Add packaging directory
[platform/upstream/neard.git] / src / ndef.c
1 /*
2  *
3  *  neard - Near Field Communication manager
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30
31 #include <glib.h>
32
33 #include <gdbus.h>
34
35 #include "near.h"
36
37 enum record_tnf {
38         RECORD_TNF_EMPTY     = 0x00,
39         RECORD_TNF_WELLKNOWN = 0x01,
40         RECORD_TNF_MIME      = 0x02,
41         RECORD_TNF_URI       = 0x03,
42         RECORD_TNF_EXTERNAL  = 0x04,
43         RECORD_TNF_UNKNOWN   = 0x05,
44         RECORD_TNF_UNCHANGED = 0x06,
45 };
46
47 #define RECORD_ACTION_DO   0x00
48 #define RECORD_ACTION_SAVE 0x01
49 #define RECORD_ACTION_EDIT 0x02
50
51 #define RECORD_MB_BIT(val)  ((val & 0x80) >> 7)
52 #define RECORD_ME_BIT(val)  ((val & 0x40) >> 6)
53 #define RECORD_CF_BIT(val)  ((val & 0x20) >> 5)
54 #define RECORD_SR_BIT(val)  ((val & 0x10) >> 4)
55 #define RECORD_IL_BIT(val)  ((val & 0x8)  >> 3)
56 #define RECORD_TNF_BIT(val) (val & 0x7)
57
58 #define NDEF_MSG_MIN_LENGTH 0x03
59 #define NDEF_PAYLOAD_LENGTH_OFFSET 0x02
60
61 #define RECORD_MB    0x80
62 #define RECORD_ME    0x40
63 #define RECORD_CF    0x20
64 #define RECORD_SR    0x10
65 #define RECORD_IL    0x08
66 #define RECORD_TNF_EMPTY_SET(val)     ((val & ~0x7) | RECORD_TNF_EMPTY)
67 #define RECORD_TNF_WKT_SET(val)       ((val & ~0x7) | RECORD_TNF_WELLKNOWN)
68 #define RECORD_TNF_MIME_SET(val)      ((val & ~0x7) | RECORD_TNF_MIME)
69 #define RECORD_TNF_URI_SET(val)       ((val & ~0x7) | RECORD_TNF_URI)
70 #define RECORD_TNF_EXTERNAL_SET(val)  ((val & ~0x7) | RECORD_TNF_EXTERNAL)
71 #define RECORD_TNF_UKNOWN_SET(val)    ((val & ~0x7) | RECORD_TNF_UNKNOWN)
72 #define RECORD_TNF_UNCHANGED_SET(val) ((val & ~0x7) | RECORD_TNF_UNCHANGED)
73
74 #define NDEF_MSG_SHORT_RECORD_MAX_LENGTH 0xFF
75 #define NDEF_TEXT_RECORD_TYPE_NAME_HEX_VALUE 0x54
76 #define NDEF_TEXT_RECORD_UTF16_STATUS 0x80
77
78 #define AC_CPS_MASK 0x03
79
80 enum record_type {
81         RECORD_TYPE_WKT_SMART_POSTER          =   0x01,
82         RECORD_TYPE_WKT_URI                   =   0x02,
83         RECORD_TYPE_WKT_TEXT                  =   0x03,
84         RECORD_TYPE_WKT_SIZE                  =   0x04,
85         RECORD_TYPE_WKT_TYPE                  =   0x05,
86         RECORD_TYPE_WKT_ACTION                =   0x06,
87         RECORD_TYPE_WKT_HANDOVER_REQUEST      =   0x07,
88         RECORD_TYPE_WKT_HANDOVER_SELECT       =   0x08,
89         RECORD_TYPE_WKT_HANDOVER_CARRIER      =   0x09,
90         RECORD_TYPE_WKT_ALTERNATIVE_CARRIER   =   0x0a,
91         RECORD_TYPE_WKT_COLLISION_RESOLUTION  =   0x0b,
92         RECORD_TYPE_WKT_ERROR                 =   0x0c,
93         RECORD_TYPE_MIME_TYPE                 =   0x0d,
94         RECORD_TYPE_EXT_AAR                   =   0x0e,
95         RECORD_TYPE_UNKNOWN                   =   0xfe,
96         RECORD_TYPE_ERROR                     =   0xff
97 };
98
99 #define RECORD_TYPE_WKT "urn:nfc:wkt:"
100 #define RECORD_TYPE_EXTERNAL "urn:nfc:ext:"
101 #define AAR_STRING "android.com:pkg"
102
103 struct near_ndef_record_header {
104         uint8_t mb;
105         uint8_t me;
106         uint8_t cf;
107         uint8_t sr;
108         uint8_t il;
109         uint8_t tnf;
110         uint8_t il_length;
111         uint8_t *il_field;
112         uint32_t payload_len;
113         uint32_t offset;
114         uint8_t type_len;
115         enum record_type rec_type;
116         char *type_name;
117         uint32_t header_len;
118 };
119
120 struct near_ndef_text_payload {
121         char *encoding;
122         char *language_code;
123         char *data;
124 };
125
126 struct near_ndef_uri_payload {
127         uint8_t identifier;
128
129         uint32_t  field_length;
130         uint8_t  *field;
131 };
132
133 struct near_ndef_sp_payload {
134         struct near_ndef_uri_payload *uri;
135
136         uint8_t number_of_title_records;
137         struct near_ndef_text_payload **title_records;
138
139         uint32_t size; /* from Size record*/
140         char *type;    /* from Type record*/
141         char *action;
142         /* TODO add icon and other records fields*/
143 };
144
145 struct near_ndef_mime_payload {
146         char *type;
147
148         struct {
149                 enum handover_carrier carrier_type;
150                 uint16_t properties;    /* e.g.: NO_PAIRING_KEY */
151         } handover;
152 };
153
154 /* Handover record definitions */
155
156 /* alternative record (AC) length based on cdr length without adata */
157 #define AC_RECORD_PAYLOAD_LEN(cdr_len) (3 + cdr_len)
158
159 struct near_ndef_ac_payload {
160         enum carrier_power_state cps;   /* carrier power state */
161
162         uint8_t cdr_len;        /* carrier data reference length */
163         uint8_t *cdr;           /* carrier data reference */
164         uint8_t adata_refcount; /* auxiliary data reference count */
165
166         /* !: if adata_refcount == 0, then there's no data reference */
167         uint16_t **adata;       /* auxiliary data reference */
168 };
169
170 /* Default Handover version */
171 #define HANDOVER_VERSION        0x12
172 #define HANDOVER_MAJOR(version) (((version) >> 4) & 0xf)
173 #define HANDOVER_MINOR(version) ((version) & 0xf)
174
175
176 /* General Handover Request/Select record */
177 struct near_ndef_ho_payload {
178         uint8_t version;                /* version id */
179         uint16_t collision_record;      /* collision record */
180
181         uint8_t number_of_ac_payloads;  /* At least 1 ac is needed */
182         struct near_ndef_ac_payload **ac_payloads;
183
184         /* Optional records */
185         uint16_t *err_record;   /* not NULL if present */
186
187         uint8_t number_of_cfg_payloads; /* extra NDEF records */
188         struct near_ndef_mime_payload **cfg_payloads;
189 };
190
191 struct near_ndef_aar_payload {
192         char *package;
193 };
194
195 struct near_ndef_record {
196         char *path;
197
198         struct near_ndef_record_header *header;
199
200         /* specific payloads */
201         struct near_ndef_text_payload *text;
202         struct near_ndef_uri_payload  *uri;
203         struct near_ndef_sp_payload   *sp;
204         struct near_ndef_mime_payload *mime;
205         struct near_ndef_ho_payload   *ho;      /* handover payload */
206         struct near_ndef_aar_payload  *aar;
207
208         char *type;
209
210         uint8_t *data;
211         size_t data_len;
212 };
213
214 static DBusConnection *connection = NULL;
215
216 static inline void fillb8(uint8_t *ptr, uint32_t len)
217 {
218         (*(uint8_t *)(ptr)) = ((uint8_t)(len));
219 }
220
221 static inline void fillb16(uint8_t *ptr, uint32_t len)
222 {
223         fillb8((ptr), (uint16_t)(len) >> 8);
224         fillb8((uint8_t *)(ptr) + 1, len);
225 }
226
227 static inline void fillb32(uint8_t *ptr, uint32_t len)
228 {
229         fillb16((ptr), (uint32_t)(len) >> 16);
230         fillb16((uint8_t *)(ptr) + 2, (uint32_t)(len));
231 }
232
233 char *__near_ndef_record_get_path(struct near_ndef_record *record)
234 {
235         return record->path;
236 }
237
238 char *__near_ndef_record_get_type(struct near_ndef_record *record)
239 {
240         return record->type;
241 }
242
243 uint8_t *__near_ndef_record_get_data(struct near_ndef_record *record,
244                                                                 size_t *len)
245 {
246         *len = record->data_len;
247
248         return record->data;
249 }
250
251 uint8_t *__near_ndef_record_get_payload(struct near_ndef_record *record,
252                                                                 size_t *len)
253 {
254         *len = record->header->payload_len;
255
256         return record->data + record->header->header_len;
257 }
258
259 void __near_ndef_append_records(DBusMessageIter *iter, GList *records)
260 {
261         GList *list;
262
263         DBG("");
264
265         for (list = records; list; list = list->next) {
266                 struct near_ndef_record *record = list->data;
267                 uint8_t *data;
268                 size_t data_len;
269
270                 data = __near_ndef_record_get_data(record, &data_len);
271                 if (!data)
272                         continue;
273
274                 dbus_message_iter_append_fixed_array(iter, DBUS_TYPE_BYTE,
275                                                         &data, data_len);
276         }
277 }
278
279 static const char *uri_prefixes[NFC_MAX_URI_ID + 1] = {
280         "",
281         "http://www.",
282         "https://www.",
283         "http://",
284         "https://",
285         "tel:",
286         "mailto:",
287         "ftp://anonymous:anonymous@",
288         "ftp://ftp.",
289         "ftps://",
290         "sftp://",
291         "smb://",
292         "nfs://",
293         "ftp://",
294         "dav://",
295         "news:",
296         "telnet://",
297         "imap:",
298         "rstp://",
299         "urn:",
300         "pop:",
301         "sip:",
302         "sips:",
303         "tftp:",
304         "btspp://",
305         "btl2cap://",
306         "btgoep://",
307         "tcpobex://",
308         "irdaobex://",
309         "file://",
310         "urn:epc:id:",
311         "urn:epc:tag:",
312         "urn:epc:pat:",
313         "urn:epc:raw:",
314         "urn:epc:",
315         "urn:nfc:",
316 };
317
318 const char *__near_ndef_get_uri_prefix(uint8_t id)
319 {
320         if (id > NFC_MAX_URI_ID)
321                 return NULL;
322
323         return uri_prefixes[id];
324 }
325
326 static gboolean property_get_type(const GDBusPropertyTable *property,
327                                         DBusMessageIter *iter, void *user_data)
328 {
329         struct near_ndef_record *record = user_data;
330         const char *type;
331
332         DBG("");
333
334         switch (record->header->rec_type) {
335         case RECORD_TYPE_WKT_SIZE:
336         case RECORD_TYPE_WKT_TYPE:
337         case RECORD_TYPE_WKT_ACTION:
338         case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
339         case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
340         case RECORD_TYPE_WKT_ERROR:
341         case RECORD_TYPE_UNKNOWN:
342         case RECORD_TYPE_ERROR:
343                 type = NULL;
344                 break;
345
346         case RECORD_TYPE_WKT_TEXT:
347                 type = "Text";
348                 break;
349
350         case RECORD_TYPE_WKT_URI:
351                 type = "URI";
352                 break;
353
354         case RECORD_TYPE_WKT_SMART_POSTER:
355                 type = "SmartPoster";
356                 break;
357
358         case RECORD_TYPE_WKT_HANDOVER_REQUEST:
359                 type = "HandoverRequest";
360                 break;
361
362         case RECORD_TYPE_WKT_HANDOVER_SELECT:
363                 type = "HandoverSelect";
364                 break;
365
366         case RECORD_TYPE_WKT_HANDOVER_CARRIER:
367                 type = "HandoverCarrier";
368                 break;
369
370         case RECORD_TYPE_MIME_TYPE:
371                 type = "MIME";
372                 break;
373
374         case RECORD_TYPE_EXT_AAR:
375                 type = "AAR";
376                 break;
377         }
378         
379         if (!type)
380                 return FALSE;
381
382         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type);
383
384         return TRUE;
385 }
386
387 static gboolean text_exists(const GDBusPropertyTable *property, void *data)
388 {
389         struct near_ndef_record *record = data;
390
391         DBG("");
392
393         if (record->text)
394                 return TRUE;
395
396         if (record->sp && record->sp->title_records)
397                 return TRUE;
398
399         DBG("No text");
400
401         return FALSE;
402 }
403
404 static const char *get_text_payload(const GDBusPropertyTable *property,
405                                         struct near_ndef_text_payload *text)
406 {
407         if (!strcmp(property->name, "Encoding"))
408                 return text->encoding;
409         else if (!strcmp(property->name, "Language"))
410                 return text->language_code;
411         else if (!strcmp(property->name, "Representation"))
412                 return text->data;
413         else
414                 return NULL;
415 }
416
417 static gboolean property_get_text(const GDBusPropertyTable *property,
418                                         DBusMessageIter *iter, void *user_data)
419 {
420         struct near_ndef_record *record = user_data;
421         const char *text;
422
423         DBG("");
424
425         if (record->text) {
426                 text = get_text_payload(property, record->text);
427                 if (!text)
428                         return FALSE;
429
430                 DBG("text %s", text);
431
432                 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &text);
433
434                 return TRUE;
435         }
436
437         if (record->sp && record->sp->title_records) {
438                 int i;
439
440                 for (i = 0; i < record->sp->number_of_title_records; i++) {
441                         text = get_text_payload(property,
442                                                 record->sp->title_records[i]);
443                         if (!text)
444                                 continue;
445
446                         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
447                                                                         &text);
448                 }
449
450                 return TRUE;
451         }
452
453         return FALSE;
454 }
455
456 static gboolean uri_exists(const GDBusPropertyTable *property, void *data)
457 {
458         struct near_ndef_record *record = data;
459
460         DBG("");
461
462         if (record->uri)
463                 return TRUE;
464
465         if (record->sp && record->sp->uri)
466                 return TRUE;
467
468         DBG("No URI");
469
470         return FALSE;
471 }
472
473 static gboolean property_get_uri(const GDBusPropertyTable *property,
474                                         DBusMessageIter *iter, void *user_data)
475 {
476         struct near_ndef_record *record = user_data;
477         struct near_ndef_uri_payload *uri;
478         char *value;
479         const char *prefix = NULL;
480
481         DBG("");
482
483         if (record->uri)
484                 uri = record->uri;
485         else if (record->sp && record->sp->uri)
486                 uri = record->sp->uri;
487         else
488                 return FALSE;
489
490         if (uri->identifier > NFC_MAX_URI_ID) {
491                 near_error("Invalid URI identifier 0x%x", uri->identifier);
492                 return FALSE;
493         }
494
495         prefix = uri_prefixes[uri->identifier];
496
497         DBG("URI prefix %s", prefix);
498
499         value = g_strdup_printf("%s%.*s", prefix, uri->field_length,
500                                                          uri->field);
501
502         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &value);
503
504         g_free(value);
505
506         return TRUE;
507 }
508
509 static gboolean sp_action_exists(const GDBusPropertyTable *property,
510                                                                 void *data)
511 {
512         struct near_ndef_record *record = data;
513
514         DBG("");
515
516         if (record->sp && record->sp->action)
517                 return TRUE;
518
519         DBG("No SmartPoster action");
520
521         return FALSE;
522 }
523
524 static gboolean sp_mime_exists(const GDBusPropertyTable *property, void *data)
525 {
526         struct near_ndef_record *record = data;
527
528         DBG("");
529
530         if (record->sp && record->sp->type)
531                 return TRUE;
532
533         DBG("No SmartPoster MIME type");
534
535         return FALSE;
536 }
537
538 static gboolean sp_size_exists(const GDBusPropertyTable *property, void *data)
539 {
540         struct near_ndef_record *record = data;
541
542         DBG("");
543
544         if (record->sp && record->sp->size)
545                 return TRUE;
546
547         DBG("No SmartPoster size");
548
549         return FALSE;
550 }
551
552 static gboolean property_get_action(const GDBusPropertyTable *property,
553                                         DBusMessageIter *iter, void *user_data)
554 {
555         struct near_ndef_record *record = user_data;
556
557         DBG("%s", record->sp->action);
558
559         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->sp->action);
560
561         return TRUE;
562 }
563
564 static gboolean property_get_mime_type(const GDBusPropertyTable *property,
565                                         DBusMessageIter *iter, void *user_data)
566 {
567         struct near_ndef_record *record = user_data;
568
569         DBG("%s", record->sp->type);
570
571         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->sp->type);
572
573         return TRUE;
574 }
575
576 static gboolean property_get_size(const GDBusPropertyTable *property,
577                                         DBusMessageIter *iter, void *user_data)
578 {
579         struct near_ndef_record *record = user_data;
580
581         DBG("%d", record->sp->size);
582
583         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &record->sp->size);
584
585         return TRUE;
586 }
587
588 static gboolean mime_exists(const GDBusPropertyTable *property, void *data)
589 {
590         struct near_ndef_record *record = data;
591
592         DBG("");
593
594         if (record->mime)
595                 return TRUE;
596
597         DBG("No MIME");
598
599         return FALSE;
600 }
601
602 static gboolean property_get_mime(const GDBusPropertyTable *property,
603                                         DBusMessageIter *iter, void *user_data)
604 {
605         struct near_ndef_record *record = user_data;
606
607         DBG("");
608
609         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->mime->type);
610
611         return TRUE;
612 }
613
614 static gboolean aar_exists(const GDBusPropertyTable *property, void *data)
615 {
616         struct near_ndef_record *record = data;
617
618         DBG("");
619
620         if (record->aar)
621                 return TRUE;
622
623         DBG("No AAR");
624
625         return FALSE;
626 }
627
628 static gboolean property_get_aar(const GDBusPropertyTable *property,
629                                         DBusMessageIter *iter, void *user_data)
630 {
631         struct near_ndef_record *record = user_data;
632
633         DBG("");
634
635         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->aar->package);
636
637         return TRUE;
638 }
639
640 static const GDBusPropertyTable record_properties[] = {
641
642         { "Type", "s", property_get_type },
643         { "Encoding", "s", property_get_text, NULL, text_exists },
644         { "Language", "s", property_get_text, NULL, text_exists },
645         { "Representation", "s", property_get_text, NULL, text_exists},
646         { "URI", "s", property_get_uri, NULL, uri_exists },
647         { "Action", "s", property_get_action, NULL, sp_action_exists },
648         { "MIMEType", "s", property_get_mime_type, NULL, sp_mime_exists },
649         { "Size", "u", property_get_size, NULL, sp_size_exists },
650         { "MIME", "s", property_get_mime, NULL, mime_exists },
651         { "AAR", "s", property_get_aar, NULL, aar_exists },
652         { }
653 };
654
655 static void free_text_payload(struct near_ndef_text_payload *text)
656 {
657         if (!text)
658                 return;
659
660         g_free(text->encoding);
661         g_free(text->language_code);
662         g_free(text->data);
663         g_free(text);
664 }
665
666 static void free_uri_payload(struct near_ndef_uri_payload *uri)
667 {
668         if (!uri)
669                 return;
670
671         g_free(uri->field);
672         g_free(uri);
673 }
674
675 static void free_sp_payload(struct near_ndef_sp_payload *sp)
676 {
677         uint8_t i;
678
679         if (!sp)
680                 return;
681
682         free_uri_payload(sp->uri);
683
684         if (sp->title_records) {
685                 for (i = 0; i < sp->number_of_title_records; i++)
686                         free_text_payload(sp->title_records[i]);
687         }
688
689         g_free(sp->title_records);
690         g_free(sp->type);
691         g_free(sp->action);
692         g_free(sp);
693 }
694
695 static void free_mime_payload(struct near_ndef_mime_payload *mime)
696 {
697         if (!mime)
698                 return;
699
700         g_free(mime->type);
701         g_free(mime);
702 }
703
704 static void free_ac_payload(struct near_ndef_ac_payload *ac)
705 {
706         if (!ac)
707                 return;
708
709         g_free(ac->cdr);
710         g_free(ac->adata);
711         g_free(ac);
712 }
713
714 static void free_ho_payload(struct near_ndef_ho_payload *ho)
715 {
716         int i;
717
718         if (!ho)
719                 return;
720
721         if (ho->ac_payloads) {
722                 for (i = 0; i < ho->number_of_ac_payloads; i++)
723                         free_ac_payload(ho->ac_payloads[i]);
724         }
725
726         g_free(ho->ac_payloads);
727         g_free(ho);
728 }
729
730 static void free_aar_payload(struct near_ndef_aar_payload *aar)
731 {
732         if (!aar)
733                 return;
734
735         g_free(aar->package);
736         g_free(aar);
737 }
738
739 static void free_ndef_record(struct near_ndef_record *record)
740 {
741         if (!record)
742                 return;
743
744         g_free(record->path);
745
746         if (record->header) {
747
748                 switch (record->header->rec_type) {
749                 case RECORD_TYPE_WKT_SIZE:
750                 case RECORD_TYPE_WKT_TYPE:
751                 case RECORD_TYPE_WKT_ACTION:
752                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
753                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
754                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
755                 case RECORD_TYPE_WKT_ERROR:
756                 case RECORD_TYPE_UNKNOWN:
757                 case RECORD_TYPE_ERROR:
758                         break;
759
760                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
761                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
762                         free_ho_payload(record->ho);
763                         break;
764
765                 case RECORD_TYPE_WKT_TEXT:
766                         free_text_payload(record->text);
767                         break;
768
769                 case RECORD_TYPE_WKT_URI:
770                         free_uri_payload(record->uri);
771                         break;
772
773                 case RECORD_TYPE_WKT_SMART_POSTER:
774                         free_sp_payload(record->sp);
775                         break;
776
777                 case RECORD_TYPE_MIME_TYPE:
778                         free_mime_payload(record->mime);
779                         break;
780
781                 case RECORD_TYPE_EXT_AAR:
782                         free_aar_payload(record->aar);
783                         break;
784                 }
785
786                 g_free(record->header->il_field);
787                 g_free(record->header->type_name);
788         }
789
790         g_free(record->header);
791         g_free(record->type);
792         g_free(record->data);
793         g_free(record);
794 }
795
796 static void free_ndef_message(struct near_ndef_message *msg)
797 {
798         if (!msg)
799                 return;
800
801         g_free(msg->data);
802         g_free(msg);
803 }
804
805 void __near_ndef_record_free(struct near_ndef_record *record)
806 {
807         g_dbus_unregister_interface(connection, record->path,
808                                                 NFC_RECORD_INTERFACE);
809
810         free_ndef_record(record);
811 }
812
813 static char *action_to_string(uint8_t action)
814 {
815         switch (action) {
816         case RECORD_ACTION_DO:
817                 return "Do";
818         case RECORD_ACTION_SAVE:
819                 return "Save";
820         case RECORD_ACTION_EDIT:
821                 return "Edit";
822         default:
823                 near_error("Unknown action 0x%x", action);
824                 return NULL;
825         }
826 }
827
828 static enum record_type get_external_record_type(uint8_t *type,
829                                                 size_t type_length)
830 {
831         DBG("");
832
833         if (strncmp((char *) type, BT_MIME_STRING_2_0,
834                                         sizeof(BT_MIME_STRING_2_0) - 1) == 0)
835                 return RECORD_TYPE_MIME_TYPE;
836         else if (strncmp((char *) type, AAR_STRING,
837                                         sizeof(AAR_STRING) - 1) == 0)
838                 return RECORD_TYPE_EXT_AAR;
839         else
840                 return RECORD_TYPE_UNKNOWN;
841 }
842
843 static enum record_type get_record_type(enum record_tnf tnf,
844                                 uint8_t *type, size_t type_length)
845 {
846         DBG("");
847
848         switch (tnf) {
849         case RECORD_TNF_EMPTY:
850         case RECORD_TNF_URI:
851         case RECORD_TNF_UNKNOWN:
852         case RECORD_TNF_UNCHANGED:
853                 break;
854
855         case RECORD_TNF_WELLKNOWN:
856                 if (type_length == 1) {
857                         if (type[0] == 'T')
858                                 return RECORD_TYPE_WKT_TEXT;
859                         else if (type[0] == 'U')
860                                 return RECORD_TYPE_WKT_URI;
861                         else if (type[0] == 's')
862                                 return RECORD_TYPE_WKT_SIZE;
863                         else if (type[0] == 't')
864                                 return RECORD_TYPE_WKT_TYPE;
865                         else
866                                 return RECORD_TYPE_UNKNOWN;
867
868                 } else if (type_length == 2) {
869                         if (strncmp((char *)type, "Sp", 2) == 0)
870                                 return RECORD_TYPE_WKT_SMART_POSTER;
871                         else if (strncmp((char *) type, "Hr", 2) == 0)
872                                 return RECORD_TYPE_WKT_HANDOVER_REQUEST;
873                         else if (strncmp((char *) type, "Hs", 2) == 0)
874                                 return RECORD_TYPE_WKT_HANDOVER_SELECT;
875                         else if (strncmp((char *) type, "Hc", 2) == 0)
876                                 return RECORD_TYPE_WKT_HANDOVER_CARRIER;
877                         else if (strncmp((char *) type, "ac", 2) == 0)
878                                 return RECORD_TYPE_WKT_ALTERNATIVE_CARRIER;
879                         else if (strncmp((char *) type, "cr", 2) == 0)
880                                 return RECORD_TYPE_WKT_COLLISION_RESOLUTION;
881                         else
882                                 return RECORD_TYPE_UNKNOWN;
883
884                 } else if (type_length == 3) {
885                         if (strncmp((char *)type, "act", 3) == 0)
886                                 return RECORD_TYPE_WKT_ACTION;
887                         else if (strncmp((char *)type, "err", 3) == 0)
888                                 return RECORD_TYPE_WKT_ERROR;
889                         else
890                                 return RECORD_TYPE_UNKNOWN;
891
892                 }
893
894         case RECORD_TNF_MIME:
895                 return RECORD_TYPE_MIME_TYPE;
896
897         case RECORD_TNF_EXTERNAL:
898                 return get_external_record_type(type, type_length);
899
900         }
901
902         return RECORD_TYPE_UNKNOWN;
903 }
904
905 static int build_record_type_string(struct near_ndef_record *rec)
906 {
907         uint8_t tnf;
908
909         DBG("");
910
911         if (!rec || !rec->header)
912                 return -EINVAL;
913
914         tnf = rec->header->tnf;
915
916         if (rec->header->rec_type == RECORD_TYPE_WKT_SMART_POSTER) {
917                 rec->type = g_strdup_printf(RECORD_TYPE_WKT "U");
918                 return 0;
919         }
920
921         switch (tnf) {
922         case RECORD_TNF_EMPTY:
923         case RECORD_TNF_UNKNOWN:
924         case RECORD_TNF_UNCHANGED:
925                 return -EINVAL;
926
927         case RECORD_TNF_URI:
928         case RECORD_TNF_MIME:
929                 rec->type = g_strndup(rec->header->type_name,
930                                       rec->header->type_len);
931                 break;
932
933         case RECORD_TNF_WELLKNOWN:
934                 rec->type = g_strdup_printf(RECORD_TYPE_WKT "%s",
935                                       rec->header->type_name);
936                 break;
937
938         case RECORD_TNF_EXTERNAL:
939                 rec->type = g_strdup_printf(RECORD_TYPE_EXTERNAL "%s",
940                                       rec->header->type_name);
941                 break;
942         }
943
944         return 0;
945 }
946
947 static uint8_t validate_record_begin_and_end_bits(uint8_t *msg_mb,
948                                         uint8_t *msg_me, uint8_t rec_mb,
949                                         uint8_t rec_me)
950 {
951         DBG("");
952
953         if (!msg_mb || !msg_me)
954                 return 0;
955
956         /* Validating record header begin and end bits
957          * eg: Single record: [mb:1,me:1]
958          *     Two records:   [mb:1,me:0 - mb:0,me:1]
959          *     Three or more records [mb:1,me:0 - mb:0,me:0 .. mb:0,me:1]
960          **/
961
962         if (rec_mb == 1) {
963                 if (*msg_mb != 1)
964                         *msg_mb = rec_mb;
965                 else
966                         return -EINVAL;
967
968         }
969
970         if (rec_me == 1) {
971                 if (*msg_me != 1) {
972                         if (*msg_mb == 1)
973                                 *msg_me = rec_me;
974                         else
975                                 return -EINVAL;
976
977                 } else
978                         return -EINVAL;
979
980         }
981
982         return 0;
983 }
984
985 /*
986  * Parse the ndef record header and cache the begin, end, chunkflag,
987  * short-record and type-name-format bits. ID length and field, record
988  * type, payload length and offset (where payload byte starts in input
989  * parameter). Validate offset for every step forward against total
990  * available length.
991  */
992 static struct near_ndef_record_header *parse_record_header(uint8_t *rec,
993                                         uint32_t offset, uint32_t length)
994 {
995         struct near_ndef_record_header *rec_header = NULL;
996         uint8_t *type = NULL;
997         uint32_t header_len = 0;
998
999         DBG("length %d", length);
1000
1001         if (!rec || offset >= length)
1002                 return NULL;
1003
1004         /* This check is for empty record. */
1005         if ((length - offset) < NDEF_MSG_MIN_LENGTH)
1006                 return NULL;
1007
1008         rec_header = g_try_malloc0(sizeof(struct near_ndef_record_header));
1009         if (!rec_header)
1010                 return NULL;
1011
1012         rec_header->mb = RECORD_MB_BIT(rec[offset]);
1013         rec_header->me = RECORD_ME_BIT(rec[offset]);
1014         rec_header->sr = RECORD_SR_BIT(rec[offset]);
1015         rec_header->il = RECORD_IL_BIT(rec[offset]);
1016         rec_header->tnf = RECORD_TNF_BIT(rec[offset]);
1017
1018         DBG("mb %d me %d sr %d il %d tnf %d",
1019                 rec_header->mb, rec_header->me, rec_header->sr,
1020                 rec_header->il, rec_header->tnf);
1021
1022         offset++;
1023         rec_header->type_len = rec[offset++];
1024         header_len = 2; /* type length + header bits */
1025
1026         if (rec_header->sr == 1) {
1027                 rec_header->payload_len = rec[offset++];
1028                 header_len++;
1029         } else {
1030                 rec_header->payload_len = near_get_be32(rec + offset);
1031                 offset += 4;
1032                 header_len += 4;
1033
1034                 if ((offset + rec_header->payload_len) > length)
1035                         goto fail;
1036         }
1037
1038         DBG("payload length %d", rec_header->payload_len);
1039
1040         if (rec_header->il == 1) {
1041                 rec_header->il_length = rec[offset++];
1042                 header_len++;
1043
1044                 if ((offset + rec_header->payload_len) > length)
1045                         goto fail;
1046         }
1047
1048         if (rec_header->type_len > 0) {
1049                 if ((offset + rec_header->type_len) > length)
1050                         goto fail;
1051
1052                 type = g_try_malloc0(rec_header->type_len);
1053                 if (!type)
1054                         goto fail;
1055
1056                 memcpy(type, rec + offset, rec_header->type_len);
1057                 offset += rec_header->type_len;
1058                 header_len += rec_header->type_len;
1059
1060                 if ((offset + rec_header->payload_len) > length)
1061                         goto fail;
1062         }
1063
1064         if (rec_header->il_length > 0) {
1065                 if ((offset + rec_header->il_length) > length)
1066                         goto fail;
1067
1068                 rec_header->il_field = g_try_malloc0(rec_header->il_length);
1069                 if (!rec_header->il_field)
1070                         goto fail;
1071
1072                 memcpy(rec_header->il_field, rec + offset,
1073                                         rec_header->il_length);
1074                 offset += rec_header->il_length;
1075                 header_len += rec_header->il_length;
1076
1077                 if ((offset + rec_header->payload_len) > length)
1078                         goto fail;
1079         }
1080
1081         rec_header->rec_type = get_record_type(rec_header->tnf, type,
1082                                                         rec_header->type_len);
1083         rec_header->offset = offset;
1084         rec_header->header_len = header_len;
1085         rec_header->type_name = g_strndup((char *) type, rec_header->type_len);
1086
1087         g_free(type);
1088
1089         return rec_header;
1090
1091 fail:
1092         near_error("parsing record header failed");
1093
1094         g_free(type);
1095         g_free(rec_header->il_field);
1096         g_free(rec_header->type_name);
1097         g_free(rec_header);
1098
1099         return NULL;
1100 }
1101
1102 static struct near_ndef_text_payload *
1103 parse_text_payload(uint8_t *payload, uint32_t length)
1104 {
1105         struct near_ndef_text_payload *text_payload = NULL;
1106         uint8_t status, lang_length;
1107         uint32_t offset;
1108
1109         DBG("");
1110
1111         if (!payload)
1112                 return NULL;
1113
1114         offset = 0;
1115         text_payload = g_try_malloc0(sizeof(struct near_ndef_text_payload));
1116         if (!text_payload)
1117                 return NULL;
1118
1119         /* 0x80 is used to get 7th bit value (0th bit is LSB) */
1120         status = ((payload[offset] & 0x80) >> 7);
1121
1122         text_payload->encoding = (status == 0) ?
1123                                         g_strdup("UTF-8") : g_strdup("UTF-16");
1124
1125         /* 0x3F is used to get 5th-0th bits value (0th bit is LSB) */
1126         lang_length = (payload[offset] & 0x3F);
1127         offset++;
1128
1129         if (lang_length > 0) {
1130                 if ((offset + lang_length) >= length)
1131                         goto fail;
1132
1133                 text_payload->language_code = g_strndup(
1134                                                 (char *)(payload + offset),
1135                                                 lang_length);
1136         } else {
1137                 text_payload->language_code = NULL;
1138         }
1139
1140         offset += lang_length;
1141
1142         if ((length - lang_length - 1) > 0) {
1143                 text_payload->data = g_strndup((char *)(payload + offset),
1144                                         length - lang_length - 1);
1145         } else {
1146                 text_payload->data = NULL;
1147         }
1148
1149         if (offset >= length)
1150                 goto fail;
1151
1152         DBG("Encoding  '%s'", text_payload->encoding);
1153         DBG("Language Code  '%s'", text_payload->language_code);
1154         DBG("Data  '%s'", text_payload->data);
1155
1156         return text_payload;
1157
1158 fail:
1159         near_error("text payload parsing failed");
1160         free_text_payload(text_payload);
1161
1162         return NULL;
1163 }
1164
1165 static struct near_ndef_uri_payload *
1166 parse_uri_payload(uint8_t *payload, uint32_t length)
1167 {
1168         struct near_ndef_uri_payload *uri_payload = NULL;
1169         uint32_t index, offset;
1170
1171         DBG("");
1172
1173         if (!payload)
1174                 return NULL;
1175
1176         offset = 0;
1177         uri_payload = g_try_malloc0(sizeof(struct near_ndef_uri_payload));
1178         if (!uri_payload)
1179                 return NULL;
1180
1181         uri_payload->identifier = payload[offset];
1182         offset++;
1183
1184         uri_payload->field_length = length - 1;
1185
1186         if (uri_payload->field_length > 0) {
1187                 uri_payload->field = g_try_malloc0(uri_payload->field_length);
1188                 if (!uri_payload->field)
1189                         goto fail;
1190
1191                 memcpy(uri_payload->field, payload + offset,
1192                                 uri_payload->field_length);
1193
1194                 for (index = 0; index < uri_payload->field_length; index++) {
1195                         /* URI Record Type Definition 1.0 [3.2.3]
1196                          * Any character value within the URI between
1197                          * (and including) 0 and 31 SHALL be recorded as
1198                          * an error, and the URI record to be discarded */
1199                         if (uri_payload->field[index] <= 31)
1200                                 goto fail;
1201                 }
1202
1203         }
1204
1205         DBG("Identifier  '0X%X'", uri_payload->identifier);
1206         DBG("Field  '%.*s'", uri_payload->field_length, uri_payload->field);
1207
1208         return uri_payload;
1209
1210 fail:
1211         near_error("uri payload parsing failed");
1212         free_uri_payload(uri_payload);
1213
1214         return NULL;
1215 }
1216
1217 /*
1218  * Validate titles records language code in Smartposter.
1219  * There must not be two or more records with the same language identifier.
1220  */
1221 static int8_t validate_language_code_in_sp_record(GSList *titles)
1222 {
1223         uint8_t i, j, length;
1224         struct near_ndef_text_payload *title1, *title2;
1225
1226         DBG("");
1227
1228         if (!titles)
1229                 return -EINVAL;
1230
1231         length = g_slist_length(titles);
1232
1233         for (i = 0; i < length; i++) {
1234                 title1 = g_slist_nth_data(titles, i);
1235
1236                 for (j = i + 1; j < length; j++) {
1237                         title2 = g_slist_nth_data(titles, j);
1238
1239                         if ((!title1->language_code) &&
1240                                         (!title2->language_code))
1241                                 continue;
1242
1243                         if (g_strcmp0(title1->language_code,
1244                                         title2->language_code) == 0)
1245                                 return -EINVAL;
1246                 }
1247         }
1248
1249         return 0;
1250 }
1251
1252 static struct near_ndef_sp_payload *
1253 parse_sp_payload(uint8_t *payload, uint32_t length)
1254 {
1255         struct near_ndef_sp_payload *sp_payload = NULL;
1256         struct near_ndef_record_header *rec_header = NULL;
1257         uint8_t mb = 0, me = 0, i;
1258         uint32_t offset;
1259         GSList *titles = NULL, *temp;
1260
1261         DBG("");
1262
1263         if (!payload)
1264                 return NULL;
1265
1266         offset = 0;
1267         sp_payload = g_try_malloc0(sizeof(struct near_ndef_sp_payload));
1268         if (!sp_payload)
1269                 return NULL;
1270
1271         while (offset < length) {
1272
1273                 DBG("Record header : 0x%x", payload[offset]);
1274
1275                 rec_header = parse_record_header(payload, offset, length);
1276                 if (!rec_header)
1277                         goto fail;
1278
1279                 if (validate_record_begin_and_end_bits(&mb, &me,
1280                                         rec_header->mb, rec_header->me) != 0) {
1281                         DBG("validate mb me failed");
1282                         goto fail;
1283                 }
1284
1285                 offset = rec_header->offset;
1286
1287                 switch (rec_header->rec_type) {
1288                 case RECORD_TYPE_WKT_SMART_POSTER:
1289                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
1290                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
1291                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
1292                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
1293                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
1294                 case RECORD_TYPE_MIME_TYPE:
1295                 case RECORD_TYPE_WKT_ERROR:
1296                 case RECORD_TYPE_EXT_AAR:
1297                 case RECORD_TYPE_UNKNOWN:
1298                 case RECORD_TYPE_ERROR:
1299                         break;
1300
1301                 case RECORD_TYPE_WKT_URI:
1302                         /* URI record should be only one. */
1303                         if (sp_payload->uri)
1304                                 goto fail;
1305
1306                         sp_payload->uri = parse_uri_payload(payload + offset,
1307                                                 rec_header->payload_len);
1308                         if (!sp_payload->uri)
1309                                 goto fail;
1310
1311                         break;
1312
1313                 case RECORD_TYPE_WKT_TEXT:
1314                         /*
1315                          * Title records can zero or more. First fill the
1316                          * records in list and validate language identifier
1317                          * and then cache them into sp record structure.
1318                          */
1319                         {
1320                         struct near_ndef_text_payload *title;
1321                         title = parse_text_payload(payload + offset,
1322                                                 rec_header->payload_len);
1323                         if (!title)
1324                                 goto fail;
1325
1326                         titles = g_slist_append(titles, title);
1327                         }
1328                         break;
1329
1330                 case RECORD_TYPE_WKT_SIZE:
1331                         /*
1332                          * If payload length is not exactly 4 bytes
1333                          * then record is wrong.
1334                          */
1335                         if (rec_header->payload_len != 4)
1336                                 goto fail;
1337
1338                         sp_payload->size = near_get_be32(payload + offset);
1339                         break;
1340
1341                 case RECORD_TYPE_WKT_TYPE:
1342
1343                         if (rec_header->payload_len > 0) {
1344                                 sp_payload->type = g_try_malloc0(
1345                                                 rec_header->payload_len);
1346                                 if (!sp_payload->type)
1347                                         goto fail;
1348
1349                                 sp_payload->type = g_strndup(
1350                                                 (char *) payload + offset,
1351                                                 rec_header->payload_len);
1352                         }
1353
1354                         break;
1355
1356                 case RECORD_TYPE_WKT_ACTION:
1357                         /*
1358                          * If the action record exists, payload should be
1359                          * single byte, otherwise consider it as error.
1360                          */
1361                         if (rec_header->payload_len != 1)
1362                                 goto fail;
1363
1364                         sp_payload->action =
1365                                 g_strdup(action_to_string(payload[offset]));
1366
1367                         break;
1368                 }
1369
1370                 offset += rec_header->payload_len;
1371                 g_free(rec_header->il_field);
1372                 g_free(rec_header->type_name);
1373                 g_free(rec_header);
1374                 rec_header = NULL;
1375         }
1376
1377         /*
1378          * Code to fill smart poster record structure from
1379          * 'titles' list.
1380          */
1381         if (!titles)
1382                 return sp_payload;
1383
1384         if (validate_language_code_in_sp_record(titles) != 0) {
1385                 DBG("language code validation failed");
1386                 goto fail;
1387         }
1388
1389         temp = titles;
1390         sp_payload->number_of_title_records = g_slist_length(temp);
1391         sp_payload->title_records = g_try_malloc0(
1392                                 sp_payload->number_of_title_records *
1393                                  sizeof(struct near_ndef_text_payload *));
1394         if (!sp_payload->title_records)
1395                 goto fail;
1396
1397         for (i = 0; i < sp_payload->number_of_title_records; i++) {
1398                 sp_payload->title_records[i] = temp->data;
1399                 temp = temp->next;
1400         }
1401
1402         g_slist_free(titles);
1403         titles = NULL;
1404
1405         return sp_payload;
1406
1407 fail:
1408         near_error("smart poster payload parsing failed");
1409
1410         if (rec_header) {
1411                 g_free(rec_header->type_name);
1412                 g_free(rec_header->il_field);
1413                 g_free(rec_header);
1414         }
1415
1416         free_sp_payload(sp_payload);
1417         g_slist_free(titles);
1418
1419         return NULL;
1420 }
1421
1422 static void correct_eir_len(struct carrier_data *data)
1423 {
1424         /*
1425          * Android 4.1 BUG - OOB EIR length should be in LE, but is in BE.
1426          * Fortunately payload length is 1 byte so this can be detected and
1427          * corrected before sending it to handover agent.
1428          */
1429         if (data->data[0] == 0) {
1430                 DBG("EIR length in BE");
1431                 data->data[0] = data->data[1];
1432                 data->data[1] = 0;
1433         }
1434
1435         /*
1436          * Some Nokia BH-505 report total OOB block length without length field
1437          * size.
1438          */
1439         if (data->data[0] == data->size - 2) {
1440                 DBG("EIR length without length field size");
1441                 data->data[0] += 2;
1442         }
1443 }
1444
1445 static int process_mime_type(struct near_ndef_mime_payload *mime,
1446                                         struct carrier_data *c_data)
1447 {
1448         int err = -EINVAL;
1449
1450         DBG("");
1451
1452         if (!mime || !c_data)
1453                 return -EINVAL;
1454
1455         switch (mime->handover.carrier_type) {
1456         case NEAR_CARRIER_BLUETOOTH:
1457                 err = __near_agent_handover_push_data(HO_AGENT_BT, c_data);
1458                 if (err == -ESRCH)
1459                         err = __near_bluetooth_parse_oob_record(c_data,
1460                                         &mime->handover.properties, true);
1461                 break;
1462
1463         case NEAR_CARRIER_WIFI:
1464                 err = __near_agent_handover_push_data(HO_AGENT_WIFI, c_data);
1465                 break;
1466
1467         case NEAR_CARRIER_EMPTY:
1468         case NEAR_CARRIER_UNKNOWN:
1469                 break;
1470         }
1471
1472         return err;
1473 }
1474
1475 static struct near_ndef_mime_payload *parse_mime_type(
1476                         struct near_ndef_record *record, uint8_t *ndef_data,
1477                         size_t ndef_length, size_t offset,
1478                         uint32_t payload_length, struct carrier_data **c_data)
1479 {
1480         struct near_ndef_mime_payload *mime;
1481         struct carrier_data *c_temp;
1482
1483         DBG("");
1484
1485         if (!c_data || !ndef_data ||
1486                         ((offset + payload_length) > ndef_length))
1487                 return NULL;
1488
1489         mime = g_try_malloc0(sizeof(struct near_ndef_mime_payload));
1490         if (!mime)
1491                 return NULL;
1492
1493         c_temp = g_try_malloc0(sizeof(struct carrier_data));
1494         if (!c_temp) {
1495                 g_free(mime);
1496                 return NULL;
1497         }
1498
1499         mime->type = g_strdup(record->header->type_name);
1500
1501         DBG("MIME Type '%s'", mime->type);
1502         if (strcmp(mime->type, BT_MIME_STRING_2_1) == 0) {
1503                 mime->handover.carrier_type = NEAR_CARRIER_BLUETOOTH;
1504                 c_temp->type = BT_MIME_V2_1;
1505                 c_temp->size = record->header->payload_len;
1506                 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1507                 correct_eir_len(c_temp);
1508         } else if (strcmp(mime->type, BT_MIME_STRING_2_0) == 0) {
1509                 mime->handover.carrier_type = NEAR_CARRIER_BLUETOOTH;
1510                 c_temp->type = BT_MIME_V2_0;
1511                 c_temp->size = record->header->payload_len;
1512                 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1513         } else if (strcmp(mime->type, WIFI_WSC_MIME_STRING) == 0) {
1514                 mime->handover.carrier_type = NEAR_CARRIER_WIFI;
1515                 c_temp->type = WIFI_WSC_MIME;
1516                 c_temp->size = record->header->payload_len;
1517                 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1518         } else {
1519                 g_free(c_temp);
1520                 c_temp = NULL;
1521                 *c_data = NULL;
1522                 return mime;
1523         }
1524
1525         *c_data = c_temp;
1526
1527         return mime;
1528 }
1529
1530 /* Set the MB bit in message header */
1531 static uint8_t near_ndef_set_mb(uint8_t *hdr, bool first_rec)
1532 {
1533         /* Reset bits 0x40 */
1534         *hdr &= (0xFF & (~RECORD_MB));
1535
1536         /* Set if needed */
1537         if (first_rec)
1538                 *hdr |= RECORD_MB;
1539
1540         return *hdr;
1541 }
1542
1543 /* Set the MB/ME bit in message header */
1544 static uint8_t near_ndef_set_me(uint8_t *hdr, bool last_rec)
1545 {
1546         /* Reset bits 0x80 */
1547         *hdr &= (0xFF & (~RECORD_ME));
1548
1549         /* Set if needed */
1550         if (last_rec)
1551                 *hdr |= RECORD_ME;
1552
1553         return *hdr;
1554 }
1555
1556 /* Set the MB/ME bit in message header */
1557 static uint8_t near_ndef_set_mb_me(uint8_t *hdr, bool first_rec,
1558                                                 bool last_rec)
1559 {
1560         near_ndef_set_mb(hdr, first_rec);
1561         return near_ndef_set_me(hdr, last_rec);
1562 }
1563
1564 /* Caller should put own payload starting from offset value */
1565 static struct near_ndef_message *ndef_message_alloc_complete(char *type_name,
1566                 uint32_t payload_len,
1567                 char *payload_id,
1568                 uint8_t payload_id_len,
1569                 enum record_tnf tnf,
1570                 bool first_rec,
1571                 bool last_rec)
1572 {
1573         struct near_ndef_message *msg;
1574         uint8_t hdr = 0, type_len, sr_bit, il_bit, id_len;
1575
1576         msg = g_try_malloc0(sizeof(struct near_ndef_message));
1577         if (!msg)
1578                 return NULL;
1579
1580         msg->length = 0;
1581         msg->offset = 0;
1582         msg->length++; /* record header*/
1583         msg->length++; /* type name length byte*/
1584
1585         type_len = (type_name) ? strlen(type_name) : 0;
1586         id_len = (payload_id) ? payload_id_len : 0;
1587         sr_bit =  (payload_len <= NDEF_MSG_SHORT_RECORD_MAX_LENGTH)
1588                                         ? TRUE : FALSE;
1589
1590         il_bit = (payload_id) ? TRUE : FALSE;
1591
1592         msg->length += (sr_bit) ? 1 : 4;
1593         msg->length += (il_bit) ? 1 : 0;
1594         msg->length += type_len;
1595         msg->length += payload_len;
1596         msg->length += id_len;
1597
1598         msg->data = g_try_malloc0(msg->length);
1599         if (!msg->data)
1600                 goto fail;
1601
1602         /* Set MB ME bits */
1603         hdr = near_ndef_set_mb_me(&hdr, first_rec, last_rec);
1604
1605         if (sr_bit)
1606                 hdr |= RECORD_SR;
1607
1608         hdr = RECORD_TNF_WKT_SET(hdr);
1609         if (il_bit)
1610                 hdr |= RECORD_IL;
1611
1612         switch (tnf) {
1613         case RECORD_TNF_EMPTY:
1614                 hdr = RECORD_TNF_EMPTY_SET(hdr);
1615                 break;
1616
1617         case RECORD_TNF_URI:
1618                 hdr = RECORD_TNF_URI_SET(hdr);
1619                 break;
1620
1621         case RECORD_TNF_EXTERNAL:
1622                 hdr = RECORD_TNF_EXTERNAL_SET(hdr);
1623                 break;
1624         case RECORD_TNF_UNKNOWN:
1625                 hdr = RECORD_TNF_UKNOWN_SET(hdr);
1626                 break;
1627
1628         case RECORD_TNF_UNCHANGED:
1629                 hdr = RECORD_TNF_UNCHANGED_SET(hdr);
1630                 break;
1631
1632         case RECORD_TNF_WELLKNOWN:
1633                 hdr = RECORD_TNF_WKT_SET(hdr);
1634                 break;
1635
1636         case RECORD_TNF_MIME:
1637                 hdr = RECORD_TNF_MIME_SET(hdr);
1638                 break;
1639         }
1640
1641         msg->data[msg->offset++] = hdr;
1642         msg->data[msg->offset++] = type_len;
1643
1644         if (sr_bit) {
1645                 msg->data[msg->offset++] = payload_len;
1646         } else {
1647                 fillb32((msg->data + msg->offset), payload_len);
1648                 msg->offset += 4;
1649         }
1650
1651         if (il_bit)
1652                 msg->data[msg->offset++] = payload_id_len;
1653
1654         if (type_name) {
1655                 memcpy(msg->data + msg->offset, type_name, type_len);
1656                 msg->offset += type_len;
1657         }
1658
1659         if (il_bit) {
1660                 memcpy(msg->data + msg->offset, payload_id, payload_id_len);
1661                 msg->offset += payload_id_len;
1662         }
1663
1664         return msg;
1665
1666 fail:
1667         near_error("ndef message struct allocation failed");
1668         free_ndef_message(msg);
1669
1670         return NULL;
1671 }
1672
1673 /*
1674  *  This is a wrapper to ndef_message_alloc, as, in most cases,
1675  *  there's no payload id, and MB=TRUE and ME=TRUE. Default type name format
1676  *  is also set to RECORD_TNF_WELLKNOWN
1677  *
1678  */
1679 static struct near_ndef_message *ndef_message_alloc(char *type_name,
1680                                                         uint32_t payload_len)
1681 {
1682         return ndef_message_alloc_complete(type_name, payload_len,
1683                         NULL, 0,
1684                         RECORD_TNF_WELLKNOWN,
1685                         true, true);
1686 }
1687
1688 static enum carrier_power_state get_cps(uint8_t data)
1689 {
1690         /* enum carrier_power_state values match binary format */
1691         return data & AC_CPS_MASK;
1692 }
1693
1694 static struct near_ndef_ac_payload *parse_ac_payload(uint8_t *payload,
1695                                                 uint32_t length)
1696 {
1697         struct near_ndef_ac_payload *ac_payload = NULL;
1698         uint32_t offset;
1699
1700         DBG("");
1701
1702         if (!payload)
1703                 return NULL;
1704
1705         offset = 0;
1706         ac_payload = g_try_malloc0(sizeof(struct near_ndef_ac_payload));
1707         if (!ac_payload)
1708                 goto fail;
1709
1710         /* Carrier flag */
1711         ac_payload->cps = get_cps(payload[offset]);
1712         offset++;
1713
1714         /* Carrier data reference length */
1715         ac_payload->cdr_len = payload[offset];
1716         offset++;
1717
1718         if (ac_payload->cdr_len == 0)
1719                 goto fail;
1720
1721         /* Carrier data reference */
1722         ac_payload->cdr = g_try_malloc0(ac_payload->cdr_len + 1);
1723         if (!ac_payload->cdr)
1724                 goto fail;
1725
1726         memcpy(ac_payload->cdr, payload + offset, ac_payload->cdr_len);
1727         offset = offset + ac_payload->cdr_len;
1728
1729         /* Auxiliary data reference count */
1730         ac_payload->adata_refcount = payload[offset];
1731         offset++;
1732
1733         if (ac_payload->adata_refcount == 0)
1734                 return ac_payload;
1735
1736         /* save the auxiliary data reference */
1737         ac_payload->adata = g_try_malloc0(
1738                         ac_payload->adata_refcount * sizeof(uint16_t));
1739         if (!ac_payload->adata)
1740                 goto fail;
1741
1742         memcpy(ac_payload->adata, payload + offset,
1743                         ac_payload->adata_refcount * sizeof(uint16_t));
1744
1745         /* and leave */
1746         return ac_payload;
1747
1748 fail:
1749         near_error("ac payload parsing failed");
1750         free_ac_payload(ac_payload);
1751
1752         return NULL;
1753 }
1754
1755 /* carrier power state & carrier reference */
1756 static struct near_ndef_message *near_ndef_prepare_ac_message(uint8_t cps,
1757                                                                 char *cdr,
1758                                                                 uint8_t cdr_len)
1759 {
1760         struct near_ndef_message *ac_msg;
1761
1762         /* alloc "ac" message minus adata*/
1763         ac_msg = ndef_message_alloc_complete("ac",
1764                                                 AC_RECORD_PAYLOAD_LEN(cdr_len),
1765                                                 NULL, 0,
1766                                                 RECORD_TNF_WELLKNOWN,
1767                                                 true, true);
1768         if (!ac_msg)
1769                 return NULL;
1770
1771         /* Prepare ac message */
1772         ac_msg->data[ac_msg->offset++] = cps;
1773
1774         ac_msg->data[ac_msg->offset++] = cdr_len;
1775         memcpy(ac_msg->data + ac_msg->offset, cdr, cdr_len); /* cdr */
1776         ac_msg->offset += cdr_len;
1777
1778         ac_msg->data[ac_msg->offset] = 0; /* adata ref count */
1779
1780         /* Check if we want an empty record */
1781         if (*cdr == 0x00)
1782                 ac_msg->length = 0;
1783
1784         return ac_msg;
1785 }
1786
1787 /* Collision Record message */
1788 static struct near_ndef_message *near_ndef_prepare_cr_message(uint16_t cr_id)
1789 {
1790         struct near_ndef_message *cr_msg;
1791
1792         cr_msg = ndef_message_alloc_complete("cr", sizeof(uint16_t),
1793                                                 NULL, 0,
1794                                                 RECORD_TNF_WELLKNOWN,
1795                                                 true, true);
1796         if (!cr_msg)
1797                 return NULL;
1798
1799         /* Prepare ac message */
1800         near_put_be16(cr_id, cr_msg->data + cr_msg->offset);
1801
1802         return cr_msg;
1803 }
1804
1805 static struct near_ndef_message *near_ndef_prepare_cfg_message(char *mime_type,
1806                                         uint8_t *data, int data_len,
1807                                         char *cdr, uint8_t cdr_len)
1808 {
1809         struct near_ndef_message *msg = NULL;
1810
1811         DBG(" %s", mime_type);
1812
1813         if (!mime_type)
1814                 return NULL;
1815
1816         msg = ndef_message_alloc_complete(mime_type, data_len, cdr, cdr_len,
1817                                                 RECORD_TNF_MIME, true, true);
1818         if (!msg)
1819                 return NULL;
1820
1821         /* store data */
1822         if (data)
1823                 memcpy(msg->data + msg->offset, data, data_len);
1824
1825         return msg;
1826 }
1827
1828 /*
1829  * Prepare alternative carrier and configuration records
1830  * (e.g. bluetooth or wifi or Hc)
1831  */
1832 static int near_ndef_prepare_ac_and_cfg_records(enum record_type type,
1833                                         enum handover_carrier carrier,
1834                                         struct near_ndef_message **ac,
1835                                         struct near_ndef_message **cfg,
1836                                         struct near_ndef_mime_payload *mime,
1837                                         struct carrier_data *remote_carrier)
1838 {
1839         struct carrier_data *local_carrier;
1840         char cdr;
1841         char *mime_type, *carrier_string;
1842         uint16_t prop;
1843
1844         DBG("");
1845
1846         if (!ac || !cfg)
1847                 return -EINVAL;
1848
1849         switch (carrier) {
1850         case NEAR_CARRIER_BLUETOOTH:
1851                 cdr = '0';
1852                 carrier_string = "Bluetooth";
1853                 mime_type = BT_MIME_STRING_2_1;
1854                 local_carrier = __near_agent_handover_request_data(
1855                                         HO_AGENT_BT, remote_carrier);
1856                 if (local_carrier)
1857                         break;
1858
1859                 prop = (mime) ? mime->handover.properties :
1860                                                         OOB_PROPS_EMPTY;
1861                 local_carrier = __near_bluetooth_local_get_properties(prop);
1862
1863                 break;
1864
1865         case NEAR_CARRIER_WIFI:
1866                 cdr = '1';
1867                 carrier_string = "WiFi-WSC";
1868                 mime_type = WIFI_WSC_MIME_STRING;
1869                 local_carrier = __near_agent_handover_request_data(
1870                                                 HO_AGENT_WIFI, remote_carrier);
1871                 break;
1872
1873         case NEAR_CARRIER_EMPTY:
1874         case NEAR_CARRIER_UNKNOWN:
1875         default:
1876                 return -EINVAL;
1877         }
1878
1879         /*
1880          * WiFi has to be handled a bit differently when we're trying
1881          * to send the first Hr or Hs (i.e. remote_carrier == NULL).
1882          * There are 2 invalid combinations:
1883          *      a) AP mode and sending an Hr, as we won't be able to
1884          *         initiate the association.
1885          *      b) STA mode and sending an Hs, as the AP won't be able
1886          *         initiate the association.
1887          *
1888          * a) is detected when local_carrier != NULL and record_type is
1889          * Handover Request.
1890          * b) is detected when local_carrier == NULL and record_type is
1891          * Handover Select.
1892          * In those 2 cases we return an error.
1893          */
1894         if (carrier == NEAR_CARRIER_WIFI && !remote_carrier) {
1895                 if (local_carrier &&
1896                                 type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
1897                         g_free(local_carrier);
1898                         return -EINVAL;
1899                 }
1900
1901                 if (!local_carrier &&
1902                                 type == RECORD_TYPE_WKT_HANDOVER_SELECT)
1903                         return -EINVAL;
1904
1905                 if (!local_carrier &&
1906                                 type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
1907                         *cfg = near_ndef_prepare_cfg_message(mime_type,
1908                                                         NULL, 0,
1909                                                         &cdr, sizeof(cdr));
1910                         *ac = near_ndef_prepare_ac_message(CPS_UNKNOWN, &cdr,
1911                                                                 sizeof(cdr));
1912
1913                         return 0;
1914                 }
1915         }
1916
1917         if (!local_carrier) {
1918                 DBG("Unable to retrieve local carrier %s data", carrier_string);
1919                 return -ESRCH;
1920         }
1921
1922         *cfg = near_ndef_prepare_cfg_message(mime_type, local_carrier->data,
1923                                                         local_carrier->size,
1924                                                         &cdr, sizeof(cdr));
1925         *ac = near_ndef_prepare_ac_message(local_carrier->state,
1926                                                         &cdr, sizeof(cdr));
1927
1928         g_free(local_carrier);
1929
1930         if (!*cfg || !*ac) {
1931                 free_ndef_message(*ac);
1932                 free_ndef_message(*cfg);
1933
1934                 return -ENOMEM;
1935         }
1936
1937         return 0;
1938 }
1939
1940 static void free_ndef_list(gpointer data)
1941 {
1942         struct near_ndef_message *msg = data;
1943
1944         free_ndef_message(msg);
1945 }
1946
1947 static struct near_ndef_message *prepare_handover_message_header(char *type,
1948                                         uint32_t msg_len, uint32_t payload_len)
1949 {
1950         struct near_ndef_message *ho_msg;
1951
1952         ho_msg = ndef_message_alloc(type, msg_len);
1953         if (!ho_msg)
1954                 return NULL;
1955
1956         /*
1957          * The handover payload length is not the *real* length.
1958          * The PL refers to the NDEF record, not the extra ones.
1959          * So, we have to fix the payload length in the header.
1960          */
1961         ho_msg->data[NDEF_PAYLOAD_LENGTH_OFFSET] = payload_len;
1962         near_ndef_set_mb_me(ho_msg->data, true, false);
1963
1964         /* Add version */
1965         ho_msg->data[ho_msg->offset++] = HANDOVER_VERSION;
1966
1967         return ho_msg;
1968 }
1969
1970 static uint32_t ndef_message_list_length(GList *list)
1971 {
1972         struct near_ndef_message *msg;
1973         uint32_t length = 0;
1974
1975         if (!list)
1976                 return 0;
1977
1978         while (list) {
1979                 msg = list->data;
1980                 length += msg->length;
1981                 list = list->next;
1982         }
1983
1984         return length;
1985 }
1986
1987 static void copy_ac_records(struct near_ndef_message *ho, GList *acs)
1988 {
1989         GList *temp = acs;
1990         struct near_ndef_message *ac;
1991
1992         if (!ho || !temp)
1993                 return;
1994
1995         while (temp) {
1996                 ac = temp->data;
1997                 memcpy(ho->data + ho->offset, ac->data, ac->length);
1998                 /*
1999                  * AC records are part of handover message payload,
2000                  * so modifying offset.
2001                  */
2002                 ho->offset += ac->length;
2003                 temp = temp->next;
2004         }
2005 }
2006
2007 static void copy_cfg_records(struct near_ndef_message *ho, GList *cfgs)
2008 {
2009         GList *temp = cfgs;
2010         struct near_ndef_message *cfg;
2011         uint32_t offset;
2012
2013         if (!ho || !temp)
2014                 return;
2015
2016         offset = ho->offset;
2017
2018         while (temp) {
2019                 cfg = temp->data;
2020                 memcpy(ho->data + offset, cfg->data, cfg->length);
2021                 /*
2022                  * Configuration records (e.g. bt or wifi) records are not part
2023                  * of handover payload, they are consecutive ndef msgs. So
2024                  * here we are not modifying ho->offset.
2025                  */
2026                 offset += cfg->length;
2027                 temp = temp->next;
2028         }
2029 }
2030
2031 static void set_mb_me_to_false(gpointer data, gpointer user_data)
2032 {
2033         struct near_ndef_message *msg = data;
2034
2035         near_ndef_set_mb_me(msg->data, false, false);
2036 }
2037
2038 static struct near_ndef_message *near_ndef_prepare_empty_hs_message(void)
2039 {
2040         struct near_ndef_message *hs_msg;
2041         struct near_ndef_message *ac_msg;
2042         char cdr = 0x00;
2043         uint32_t hs_length;
2044
2045         DBG("");
2046
2047         ac_msg = near_ndef_prepare_ac_message(CPS_UNKNOWN, &cdr, sizeof(cdr));
2048         if (!ac_msg)
2049                 return NULL;
2050
2051         hs_length = 1;
2052         hs_length += ac_msg->length;
2053
2054         hs_msg = prepare_handover_message_header("Hs", hs_length, hs_length);
2055         if (!hs_msg)
2056                 goto fail;
2057
2058         near_ndef_set_mb_me(hs_msg->data, true, true);
2059         memcpy(hs_msg->data + hs_msg->offset, ac_msg->data, ac_msg->length);
2060         hs_msg->offset += ac_msg->length;
2061
2062         if (hs_msg->offset > hs_msg->length)
2063                 goto fail;
2064
2065         free_ndef_message(ac_msg);
2066
2067         return hs_msg;
2068
2069 fail:
2070         free_ndef_message(ac_msg);
2071         free_ndef_message(hs_msg);
2072
2073         return NULL;
2074 }
2075
2076 static struct near_ndef_message *near_ndef_prepare_hs_reply(
2077                                         GSList *remote_mimes,
2078                                         GSList *remote_cfgs)
2079 {
2080         struct near_ndef_message *hs_msg = NULL;
2081         struct near_ndef_message *ac_msg;
2082         struct near_ndef_message *cfg_msg;
2083         struct near_ndef_mime_payload *remote_mime;
2084         struct carrier_data *remote_cfg;
2085         GList *ac_msgs = NULL, *cfg_msgs = NULL, *temp;
2086         GSList *mime_iter, *cfg_iter;
2087         uint8_t hs_length, hs_pl_length, num_of_carriers;
2088         int ret = -EINVAL;
2089
2090         DBG("");
2091
2092         /*
2093          * Preparing empty Hs message in case remote devices has zero
2094          * alternative carries or unknown mime types or unknown
2095          * configuration data.
2096          */
2097         if ((!remote_mimes || !remote_cfgs))
2098                 return near_ndef_prepare_empty_hs_message();
2099
2100         mime_iter = remote_mimes;
2101         cfg_iter  = remote_cfgs;
2102
2103         while (mime_iter) {
2104                 remote_mime = mime_iter->data;
2105                 remote_cfg  = cfg_iter->data;
2106                 if (!remote_mime || !remote_cfg)
2107                         goto fail;
2108
2109                 ret = near_ndef_prepare_ac_and_cfg_records(
2110                                         RECORD_TYPE_WKT_HANDOVER_SELECT,
2111                                         remote_mime->handover.carrier_type,
2112                                         &ac_msg, &cfg_msg,
2113                                         remote_mime, remote_cfg);
2114                 if (ret == 0) {
2115                         ac_msgs  = g_list_append(ac_msgs, ac_msg);
2116                         cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
2117                 }
2118
2119                 mime_iter = mime_iter->next;
2120                 cfg_iter  = cfg_iter->next;
2121         }
2122
2123         if (g_list_length(ac_msgs) == 0) {
2124                 DBG("no alternative carriers, so preparing empty Hs message");
2125                 return near_ndef_prepare_empty_hs_message();
2126         }
2127
2128         /* Prepare Hs message */
2129         hs_pl_length = 1;
2130         /* Alternative carriers are part of handover record payload length */
2131         hs_pl_length += ndef_message_list_length(ac_msgs);
2132
2133         hs_length = hs_pl_length;
2134         /* Configuration records are part of handover message length */
2135         hs_length += ndef_message_list_length(cfg_msgs);
2136
2137         hs_msg = prepare_handover_message_header("Hs", hs_length, hs_pl_length);
2138         if (!hs_msg)
2139                 goto fail;
2140
2141         num_of_carriers = g_list_length(ac_msgs);
2142
2143         if (num_of_carriers == 1) {
2144                 /* only one message */
2145                 ac_msg = ac_msgs->data;
2146                 near_ndef_set_mb_me(ac_msg->data, true, true);
2147         } else if (num_of_carriers > 1) {
2148                 g_list_foreach(ac_msgs, set_mb_me_to_false, NULL);
2149                 /* first message */
2150                 temp = g_list_first(ac_msgs);
2151                 ac_msg = temp->data;
2152                 near_ndef_set_mb_me(ac_msg->data, true, false);
2153                 /* last message */
2154                 temp = g_list_last(ac_msgs);
2155                 ac_msg = temp->data;
2156                 near_ndef_set_mb_me(ac_msg->data, false, true);
2157         }
2158
2159         g_list_foreach(cfg_msgs, set_mb_me_to_false, NULL);
2160         temp = g_list_last(cfg_msgs);
2161         cfg_msg = temp->data;
2162         near_ndef_set_mb_me(cfg_msg->data, false, true);
2163
2164         /* copy acs */
2165         copy_ac_records(hs_msg, ac_msgs);
2166         if (hs_msg->offset > hs_msg->length)
2167                 goto fail;
2168
2169         /*
2170          * copy cfgs, cfg (associated to the ac) records length
2171          * (bt or wifi) is not part of Hs initial size.
2172          */
2173         copy_cfg_records(hs_msg, cfg_msgs);
2174
2175         DBG("Hs message preparation is done");
2176
2177         g_list_free_full(ac_msgs, free_ndef_list);
2178         g_list_free_full(cfg_msgs, free_ndef_list);
2179
2180         return hs_msg;
2181
2182 fail:
2183         near_error("handover Hs message preparation failed");
2184
2185         g_list_free_full(ac_msgs, free_ndef_list);
2186         g_list_free_full(cfg_msgs, free_ndef_list);
2187
2188         free_ndef_message(hs_msg);
2189
2190         return NULL;
2191 }
2192
2193 static enum handover_carrier string2carrier(char *carrier)
2194 {
2195         if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_BLUETOOTH) == 0)
2196                 return NEAR_CARRIER_BLUETOOTH;
2197
2198         if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_WIFI) == 0)
2199                 return NEAR_CARRIER_WIFI;
2200
2201         return NEAR_CARRIER_UNKNOWN;
2202 }
2203
2204 static struct near_ndef_message *
2205 near_ndef_prepare_ho_message(enum record_type type, GSList *carriers)
2206 {
2207         struct near_ndef_message *ho_msg = NULL;
2208         struct near_ndef_message *cr_msg = NULL;
2209         struct near_ndef_message *ac_msg;
2210         struct near_ndef_message *cfg_msg;
2211         GList *ac_msgs = NULL, *cfg_msgs = NULL, *temp;
2212         uint16_t collision;
2213         uint8_t ho_length, ho_pl_length;
2214         int ret = -EINVAL;
2215         char *str_type;
2216
2217         DBG("");
2218
2219         switch (type) {
2220         case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2221                 str_type = "Hr";
2222                 break;
2223
2224         case RECORD_TYPE_WKT_HANDOVER_SELECT:
2225                 str_type = "Hs";
2226                 break;
2227
2228         default:
2229                 return NULL;
2230         }
2231
2232         /* Hr message should have at least one carrier */
2233         while (carriers) {
2234                 ret = near_ndef_prepare_ac_and_cfg_records(
2235                                 type,
2236                                 string2carrier(carriers->data),
2237                                 &ac_msg, &cfg_msg, NULL, NULL);
2238                 if (ret == 0) {
2239                         ac_msgs  = g_list_append(ac_msgs, ac_msg);
2240                         cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
2241                 }
2242
2243                 carriers = carriers->next;
2244         }
2245
2246         if (g_list_length(ac_msgs) == 0) {
2247                 DBG("no alternative carriers to prepare Hr message");
2248                 goto fail;
2249         }
2250
2251         /* Prepare Hr message */
2252         ho_pl_length = 1;
2253
2254         /* Prepare collision resolution record MB=1 ME=0, only for Hr */
2255         if (type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
2256                 collision = GUINT16_TO_BE(g_random_int_range(0, G_MAXUINT16 + 1));
2257                 cr_msg = near_ndef_prepare_cr_message(collision);
2258                 if (!cr_msg)
2259                         goto fail;
2260
2261                 near_ndef_set_mb_me(cr_msg->data, true, false);
2262
2263                 ho_pl_length += cr_msg->length;
2264         }
2265
2266         /* Alternative carriers are part of handover record payload length */
2267         ho_pl_length += ndef_message_list_length(ac_msgs);
2268
2269         ho_length = ho_pl_length;
2270         /* Configuration records are part of handover message length */
2271         ho_length += ndef_message_list_length(cfg_msgs);
2272
2273         ho_msg = prepare_handover_message_header(str_type,
2274                                                 ho_length, ho_pl_length);
2275         if (!ho_msg)
2276                 goto fail;
2277
2278         g_list_foreach(ac_msgs, set_mb_me_to_false, NULL);
2279         /* last message */
2280         temp = g_list_last(ac_msgs);
2281         ac_msg = temp->data;
2282         near_ndef_set_mb_me(ac_msg->data, false, true);
2283
2284         /*
2285          * Hs record payloads do not have collision recore, the first record
2286          * will be the first ac record.
2287          */
2288         if (type == RECORD_TYPE_WKT_HANDOVER_SELECT) {
2289                 temp = g_list_first(ac_msgs);
2290                 ac_msg = temp->data;
2291                 near_ndef_set_mb_me(ac_msg->data, true, false);
2292         }
2293
2294         g_list_foreach(cfg_msgs, set_mb_me_to_false, NULL);
2295         temp = g_list_last(cfg_msgs);
2296         cfg_msg = temp->data;
2297         near_ndef_set_mb_me(cfg_msg->data, false, true);
2298
2299         if (type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
2300                 /* copy cr */
2301                 memcpy(ho_msg->data + ho_msg->offset,
2302                                 cr_msg->data, cr_msg->length);
2303                 ho_msg->offset += cr_msg->length;
2304
2305                 if (ho_msg->offset > ho_msg->length)
2306                         goto fail;
2307         }
2308
2309         /* copy acs */
2310         copy_ac_records(ho_msg, ac_msgs);
2311         if (ho_msg->offset > ho_msg->length)
2312                 goto fail;
2313
2314         /*
2315          * copy cfgs, cfg (associated to the ac) records length
2316          * (bt or wifi) is not part of Hr initial size.
2317          */
2318         copy_cfg_records(ho_msg, cfg_msgs);
2319
2320         DBG("Handover message preparation is done");
2321
2322         free_ndef_message(cr_msg);
2323         g_list_free_full(ac_msgs, free_ndef_list);
2324         g_list_free_full(cfg_msgs, free_ndef_list);
2325
2326         return ho_msg;
2327
2328 fail:
2329         near_error("handover record preparation failed");
2330
2331         g_list_free_full(ac_msgs, free_ndef_list);
2332         g_list_free_full(cfg_msgs, free_ndef_list);
2333         free_ndef_message(cr_msg);
2334         free_ndef_message(ho_msg);
2335
2336         return NULL;
2337 }
2338
2339 /* Code to fill hr record structure from acs and mimes lists */
2340 static int near_fill_ho_payload(struct near_ndef_ho_payload *ho,
2341                                         GSList *acs, GSList *mimes)
2342 {
2343         int rec_count;
2344         int i;
2345         GSList *temp;
2346
2347         rec_count = g_slist_length(acs);
2348         ho->ac_payloads = g_try_malloc0(rec_count *
2349                         sizeof(struct near_ndef_ac_payload *));
2350         if (!ho->ac_payloads)
2351                 goto fail;
2352         temp = acs;
2353         for (i = 0; i < rec_count; i++) {
2354                 ho->ac_payloads[i] = temp->data;
2355                 temp = temp->next;
2356         }
2357         ho->number_of_ac_payloads = rec_count;
2358         g_slist_free(acs);
2359
2360         /* Same process for cfg mimes */
2361         rec_count = g_slist_length(mimes);
2362         ho->cfg_payloads = g_try_malloc0(rec_count *
2363                         sizeof(struct near_ndef_mime_payload *));
2364         if (!ho->cfg_payloads)
2365                 goto fail;
2366         temp = mimes;
2367         for (i = 0; i < rec_count; i++) {
2368                 ho->cfg_payloads[i] = temp->data;
2369                 temp = temp->next;
2370         }
2371
2372         ho->number_of_cfg_payloads = rec_count;
2373         g_slist_free(mimes);
2374
2375         return 0;
2376 fail:
2377         g_free(ho->ac_payloads);
2378         g_free(ho->cfg_payloads);
2379         ho->ac_payloads = NULL;
2380         ho->cfg_payloads = NULL;
2381         return -ENOMEM;
2382 }
2383
2384 /*
2385  * This function will parse an handover record payload, retrieving sub records
2386  * like (ac, cr, er) but it  will also get the associated ndefs
2387  * (eg: handover carrier record, mime type for BT)
2388  * In a handover frame, only the following types are expected:
2389  *     RECORD_TYPE_WKT_HANDOVER_CARRIER:
2390  *     RECORD_TYPE_WKT_COLLISION_RESOLUTION
2391  *     RECORD_TYPE_MIME_TYPE
2392  *     RECORD_TYPE_WKT_ALTERNATIVE_CARRIER
2393  */
2394 static struct near_ndef_ho_payload *parse_ho_payload(enum record_type rec_type,
2395                 uint8_t *payload, uint32_t ho_length, size_t frame_length,
2396                 uint8_t ho_mb, uint8_t ho_me, struct near_ndef_message **reply)
2397 {
2398         struct near_ndef_ho_payload *ho_payload = NULL;
2399         struct near_ndef_ac_payload *ac = NULL;
2400         struct near_ndef_mime_payload *mime = NULL;
2401         struct carrier_data *c_data;
2402         struct near_ndef_record *trec = NULL;
2403         GSList *acs = NULL, *mimes = NULL, *c_datas = NULL;
2404         uint8_t mb = 0, me = 0, i;
2405         uint32_t offset;
2406         int16_t count_ac = 0;
2407         bool action = false, status;
2408
2409         DBG("");
2410
2411         if (!payload)
2412                 return NULL;
2413         offset = 0;
2414
2415         /* Create the handover record payload */
2416         ho_payload = g_try_malloc0(sizeof(struct near_ndef_ho_payload));
2417         if (!ho_payload)
2418                 return NULL;
2419
2420         /* Version is the first mandatory field of hr payload */
2421         ho_payload->version = payload[offset];
2422
2423         /* If major is different, reply with an empty Hs */
2424         if (HANDOVER_MAJOR(ho_payload->version) !=
2425             HANDOVER_MAJOR(HANDOVER_VERSION)) {
2426                 near_error("Unsupported version (%d)", ho_payload->version);
2427                 /* Skip parsing and return an empty record */
2428                 if (reply)
2429                         *reply = near_ndef_prepare_empty_hs_message();
2430
2431                 return ho_payload;
2432         }
2433
2434         offset = offset + 1;
2435
2436         /* We should work on the whole frame */
2437         ho_length = frame_length;
2438
2439         while (offset < ho_length) {
2440                 /* Create local record for mime parsing */
2441                 trec = g_try_malloc0(sizeof(struct near_ndef_record));
2442                 if (!trec)
2443                         return NULL;
2444
2445                 trec->header = parse_record_header(payload, offset, ho_length);
2446
2447                 if (!trec->header)
2448                         goto fail;
2449
2450                 offset = trec->header->offset;
2451
2452                 switch (trec->header->rec_type) {
2453                 case RECORD_TYPE_WKT_SMART_POSTER:
2454                 case RECORD_TYPE_WKT_SIZE:
2455                 case RECORD_TYPE_WKT_TEXT:
2456                 case RECORD_TYPE_WKT_TYPE:
2457                 case RECORD_TYPE_WKT_ACTION:
2458                 case RECORD_TYPE_WKT_URI:
2459                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2460                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2461                 case RECORD_TYPE_WKT_ERROR:
2462                 case RECORD_TYPE_EXT_AAR:
2463                 case RECORD_TYPE_UNKNOWN:
2464                 case RECORD_TYPE_ERROR:
2465                         break;
2466
2467                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2468                         DBG("HANDOVER_CARRIER");
2469                         /*
2470                          * TODO process Hc record too !!!
2471                          * Used for Wifi session
2472                          */
2473                         break;
2474
2475                 case RECORD_TYPE_MIME_TYPE:
2476                         DBG("TYPE_MIME_TYPE");
2477
2478                         /* check mb/me bits */
2479                         if (validate_record_begin_and_end_bits(&ho_mb, &ho_me,
2480                                 trec->header->mb, trec->header->me) != 0) {
2481                                 DBG("validate mb me failed");
2482                                 goto fail;
2483                         }
2484
2485                         /*
2486                          * In Handover, the mime type gives bluetooth handover
2487                          * or WiFi configuration data.
2488                          * If we initiated the session, the received Hs frame
2489                          * is the signal to launch the pairing.
2490                          */
2491                         if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT)
2492                                 action = true;
2493                         else
2494                                 action = false;
2495
2496                         /* HO payload for reply creation */
2497                         trec->ho = ho_payload;
2498
2499                         mime = parse_mime_type(trec, payload, frame_length,
2500                                         offset, trec->header->payload_len,
2501                                         &c_data);
2502                         trec->ho = NULL;
2503
2504                         if (!mime || !c_data)
2505                                 goto fail;
2506
2507                         /* add the mime to the list */
2508                         mimes = g_slist_append(mimes, mime);
2509                         /* add the carrier data to the list */
2510                         c_datas = g_slist_append(c_datas, c_data);
2511
2512                         count_ac--;
2513                         if (count_ac == 0)
2514                                 offset = ho_length;
2515                         break;
2516
2517                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2518                         DBG("COLLISION_RESOLUTION");
2519
2520                         /* check nested mb/me bits */
2521                         if (validate_record_begin_and_end_bits(&mb, &me,
2522                                 trec->header->mb, trec->header->me) != 0) {
2523                                 DBG("validate mb me failed");
2524                                 goto fail;
2525                         }
2526
2527                         ho_payload->collision_record =
2528                                         near_get_be16(payload + offset);
2529
2530                         break;
2531
2532                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2533                         DBG("ALTERNATIVE_CARRIER");
2534
2535                         /* check nested mb/me bits */
2536                         if (validate_record_begin_and_end_bits(&mb, &me,
2537                                 trec->header->mb, trec->header->me) != 0) {
2538                                 DBG("validate mb me failed");
2539                                 goto fail;
2540                         }
2541
2542                         ac = parse_ac_payload(payload + offset,
2543                                         trec->header->payload_len);
2544                         if (!ac)
2545                                 goto fail;
2546
2547                         acs = g_slist_append(acs, ac);
2548
2549                         /* TODO check if adata are present */
2550                         count_ac++;
2551                         break;
2552                 }
2553
2554                 offset += trec->header->payload_len;
2555                 g_free(trec->header->il_field);
2556                 g_free(trec->header->type_name);
2557                 g_free(trec->header);
2558                 trec->header = NULL;
2559
2560                 g_free(trec);
2561                 trec = NULL;
2562         }
2563
2564         /*
2565          * In case of multiple carriers, handover with any carrier
2566          * gets done then leave the loop.
2567          */
2568         if (action) {
2569                 status = false;
2570                 count_ac = g_slist_length(mimes);
2571
2572                 for (i = 0; i < count_ac; i++) {
2573                         if (process_mime_type(g_slist_nth_data(mimes, i),
2574                                         g_slist_nth_data(c_datas, i)) == 0) {
2575                                 status = true;
2576                                 break;
2577                         }
2578                 }
2579
2580                 if (!status) {
2581                         DBG("could not process alternative carriers");
2582                         goto fail;
2583                 }
2584         } else if (reply) {
2585                 /* This is a Hs with no cfg and no Ac: No reply and fail */
2586                 if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT &&
2587                                         g_slist_length(acs) == 0) {
2588                         *reply = NULL;
2589                         goto fail;
2590                 }
2591
2592                 /* Prepare Hs, it depends upon Hr message carrier types */
2593                 *reply = near_ndef_prepare_hs_reply(mimes, c_datas);
2594                 if (!*reply) {
2595                         DBG("error in preparing in HS record");
2596                         goto fail;
2597                 }
2598         }
2599
2600         if ((!acs) || (!mimes))
2601                 return ho_payload;
2602
2603         /* Save the records */
2604         if (near_fill_ho_payload(ho_payload, acs, mimes) < 0)
2605                 goto fail;
2606
2607         DBG("handover payload parsing complete");
2608
2609         g_slist_free_full(c_datas, g_free);
2610
2611         return ho_payload;
2612
2613 fail:
2614         near_error("handover payload parsing failed");
2615
2616         if (trec) {
2617                 if (trec->header) {
2618                         g_free(trec->header->type_name);
2619                         g_free(trec->header->il_field);
2620                         g_free(trec->header);
2621                 }
2622                 g_free(trec);
2623         }
2624
2625         g_slist_free_full(c_datas, g_free);
2626         free_ho_payload(ho_payload);
2627
2628         return NULL;
2629 }
2630
2631 static struct near_ndef_aar_payload *
2632 parse_aar_payload(uint8_t *payload, uint32_t length)
2633 {
2634         struct near_ndef_aar_payload *aar_payload = NULL;
2635
2636         DBG("");
2637
2638         if (!payload)
2639                 return NULL;
2640
2641         aar_payload = g_try_malloc0(sizeof(struct near_ndef_uri_payload));
2642         if (!aar_payload)
2643                 return NULL;
2644
2645         aar_payload->package = g_strndup((char *)payload, length);
2646         if (!aar_payload->package) {
2647                 near_error("AAR payload parsing failed");
2648                 free_aar_payload(aar_payload);
2649                 return NULL;
2650         }
2651
2652         DBG("AAR package %s", aar_payload->package);
2653
2654         return aar_payload;
2655 }
2656
2657 int __near_ndef_record_register(struct near_ndef_record *record, char *path)
2658 {
2659         record->path = path;
2660
2661         g_dbus_register_interface(connection, record->path,
2662                                                 NFC_RECORD_INTERFACE,
2663                                                 NULL, NULL, record_properties,
2664                                                 record, NULL);
2665
2666         return 0;
2667 }
2668
2669 /*
2670  * These functions parse a specific type record (id or mime) to find the
2671  * associated string.
2672  */
2673 bool near_ndef_record_cmp_id(struct near_ndef_record *rec1,
2674                                                 struct near_ndef_record *rec2)
2675 {
2676         DBG("");
2677
2678         if ((!rec1) || (!rec2))
2679                 return false;
2680
2681         if ((!rec1->header) || (!rec2->header))
2682                 return false;
2683
2684         /* usual checks */
2685         if ((!rec1->header->il_field) ||
2686                         (!rec2->header->il_field))
2687                 return false;
2688
2689         if (memcmp(rec1->header->il_field, rec2->header->il_field,
2690                 (rec1->header->il_length) > (rec2->header->il_length)
2691                                         ? (rec1->header->il_length) :
2692                                         (rec2->header->il_length)) != 0)
2693                 return false;
2694
2695         return true;
2696 }
2697
2698 bool near_ndef_record_cmp_mime(struct near_ndef_record *rec1,
2699                                         struct near_ndef_record *rec2)
2700 {
2701
2702         DBG("");
2703
2704         if ((!rec1) || (!rec2))
2705                 return false;
2706
2707         if ((!rec1->header) || (!rec2->header))
2708                 return false;
2709         /* usual checks */
2710         if ((!rec1->mime) || (!rec2->mime))
2711                 return false;
2712
2713         if ((!rec1->mime->type) || (!rec2->mime->type))
2714                 return false;
2715
2716         if (strlen(rec1->mime->type) != strlen(rec2->mime->type))
2717                 return false;
2718
2719         if ((g_strcmp0(rec1->mime->type, rec2->mime->type) != 0))
2720                 return false;
2721
2722         return true;
2723 }
2724
2725 /* helper to get the record data length */
2726 size_t near_ndef_data_length(struct near_ndef_record *rec)
2727 {
2728         if (!rec)
2729                 return 0;
2730         else
2731                 return rec->data_len;
2732 }
2733
2734 /* helper to get the record data pointer */
2735 uint8_t *near_ndef_data_ptr(struct near_ndef_record *rec)
2736 {
2737         if (!rec)
2738                 return NULL;
2739         else
2740                 return rec->data;
2741 }
2742
2743 GList *near_ndef_parse_msg(uint8_t *ndef_data, size_t ndef_length,
2744                                 struct near_ndef_message **reply)
2745 {
2746         GList *records;
2747         uint8_t p_mb = 0, p_me = 0, *record_start;
2748         size_t offset = 0;
2749         struct near_ndef_record *record = NULL;
2750         struct carrier_data *c_data;
2751
2752         DBG("");
2753
2754         records = NULL;
2755
2756         if (!ndef_data ||
2757                 ndef_length < NDEF_MSG_MIN_LENGTH)
2758                         goto fail;
2759
2760         while (offset < ndef_length) {
2761
2762                 DBG("Record Header : 0x%X", ndef_data[offset]);
2763
2764                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2765                 if (!record)
2766                         goto fail;
2767
2768                 record->header = parse_record_header(ndef_data, offset,
2769                                                         ndef_length);
2770                 if (!record->header)
2771                         goto fail;
2772
2773                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2774                                         record->header->mb,
2775                                         record->header->me) != 0) {
2776                         DBG("validate mb me failed");
2777                         goto fail;
2778                 }
2779
2780                 record_start = ndef_data + offset;
2781                 offset = record->header->offset;
2782
2783                 switch (record->header->rec_type) {
2784                 case RECORD_TYPE_WKT_SIZE:
2785                 case RECORD_TYPE_WKT_TYPE:
2786                 case RECORD_TYPE_WKT_ACTION:
2787                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2788                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2789                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2790                 case RECORD_TYPE_WKT_ERROR:
2791                 case RECORD_TYPE_UNKNOWN:
2792                 case RECORD_TYPE_ERROR:
2793                         break;
2794
2795                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2796                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2797                         /*
2798                          * Handover frame are a little bit special as the NDEF
2799                          * length (specified in the header) is not the real
2800                          * frame size. The complete frame includes extra NDEF
2801                          * following the initial handover NDEF
2802                          */
2803                         record->ho = parse_ho_payload(record->header->rec_type,
2804                                         ndef_data + offset,
2805                                         record->header->payload_len,
2806                                         ndef_length - offset,
2807                                         record->header->mb, record->header->me,
2808                                         reply);
2809                         if (!record->ho)
2810                                 goto fail;
2811
2812                         /* the complete frame is processed, break the loop */
2813                         record->header->payload_len = ndef_length;
2814                         break;
2815
2816                 case RECORD_TYPE_WKT_TEXT:
2817                         record->text = parse_text_payload(ndef_data + offset,
2818                                                 record->header->payload_len);
2819
2820                         if (!record->text)
2821                                 goto fail;
2822
2823                         break;
2824
2825                 case RECORD_TYPE_WKT_URI:
2826                         record->uri = parse_uri_payload(ndef_data + offset,
2827                                                 record->header->payload_len);
2828
2829                         if (!record->uri)
2830                                 goto fail;
2831
2832                         break;
2833
2834                 case RECORD_TYPE_WKT_SMART_POSTER:
2835                         record->sp = parse_sp_payload(
2836                                                 ndef_data + offset,
2837                                                 record->header->payload_len);
2838
2839                         if (!record->sp)
2840                                 goto fail;
2841
2842                         break;
2843
2844                 case RECORD_TYPE_MIME_TYPE:
2845                         record->mime = parse_mime_type(record, ndef_data,
2846                                                 ndef_length, offset,
2847                                                 record->header->payload_len,
2848                                                 &c_data);
2849                         if (!record->mime)
2850                                 goto fail;
2851
2852                         /* No carrier data, move on */
2853                         if (!c_data)
2854                                 break;
2855
2856                         if (process_mime_type(record->mime, c_data) < 0) {
2857                                 g_free(c_data);
2858                                 c_data = NULL;
2859                                 goto fail;
2860                         }
2861
2862                         g_free(c_data);
2863                         c_data = NULL;
2864                         break;
2865
2866                 case RECORD_TYPE_EXT_AAR:
2867                         record->aar = parse_aar_payload(ndef_data + offset,
2868                                                 record->header->payload_len);
2869
2870                         if (!record->aar)
2871                                 goto fail;
2872
2873                         break;
2874                 }
2875
2876                 record->data_len = record->header->header_len +
2877                                         record->header->payload_len;
2878
2879                 record->data = g_try_malloc0(record->data_len);
2880                 if (!record->data)
2881                         goto fail;
2882
2883                 memcpy(record->data, record_start, record->data_len);
2884
2885                 records = g_list_append(records, record);
2886
2887                 build_record_type_string(record);
2888
2889                 offset += record->header->payload_len;
2890         }
2891
2892         return records;
2893
2894 fail:
2895         near_error("ndef parsing failed");
2896         free_ndef_record(record);
2897
2898         return records;
2899 }
2900
2901 void near_ndef_records_free(GList *records)
2902 {
2903         GList *list;
2904
2905         for (list = records; list; list = list->next) {
2906                 struct near_ndef_record *record = list->data;
2907
2908                 __near_ndef_record_free(record);
2909         }
2910
2911         g_list_free(records);
2912 }
2913
2914 /*
2915  * Compute ndef records length, even though the submitted frame is incomplete.
2916  * This code is used in the handover read function, as we have to "guess" the
2917  * final frame size.
2918  *
2919  * Message size for SR=1 is:
2920  *  1 : ndef rec header (offset 0)
2921  *  x : record type length (offset 1)
2922  *  y : payload length (offset 2) 1 byte ONLY if SR=1
2923  *      if SR=0: (4bytes) 32 bits
2924  *  z : payload id length (offset 3) ONLY if il_length=1
2925  * */
2926 int near_ndef_record_length(uint8_t *ndef_in, size_t ndef_in_length)
2927 {
2928         int ndef_size;   /* default size for NDEF hdr + rec typ len + payl */
2929         size_t offset;
2930         uint8_t hdr;
2931
2932         DBG("");
2933
2934         if (ndef_in_length < 3)
2935                 return -EINVAL;
2936
2937         ndef_size = 3;
2938         offset = 0;
2939
2940         /* save header byte */
2941         hdr = ndef_in[offset];
2942         offset++;
2943
2944         /* header->type_len */
2945         ndef_size += ndef_in[offset++];
2946
2947         /* header->payload_len */
2948         if (RECORD_SR_BIT(hdr) == 1) {
2949                 ndef_size += ndef_in[offset++];
2950         } else {
2951                 ndef_size += near_get_be32(ndef_in + offset);
2952                 offset += 4;
2953
2954                 if (offset >= ndef_in_length)
2955                         return -ERANGE;
2956         }
2957
2958         /* header->il */
2959         ndef_size += RECORD_IL_BIT(hdr);
2960
2961         /* header->il_length */
2962         if (RECORD_IL_BIT(hdr) == 1)
2963                 ndef_size += ndef_in[offset++];
2964
2965         DBG("near_ndef_message_length is %d", ndef_size);
2966
2967         return ndef_size;
2968 }
2969
2970 int near_ndef_count_records(uint8_t *ndef_in, size_t ndef_in_length,
2971                         uint8_t record_type)
2972 {
2973         uint8_t p_mb = 0, p_me = 0;
2974         int err;
2975         size_t offset;
2976         struct near_ndef_record *record = NULL;
2977         int counted_records = 0 ;
2978
2979         DBG("");
2980
2981         offset = 0;
2982
2983         if (!ndef_in || ndef_in_length < NDEF_MSG_MIN_LENGTH) {
2984                 err = -EINVAL;
2985                 goto fail;
2986         }
2987
2988         while (offset < ndef_in_length) {
2989                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2990                 if (!record) {
2991                         err = -ENOMEM;
2992                         goto fail;
2993                 }
2994
2995                 /* Create a record */
2996                 record->header = parse_record_header(ndef_in, offset,
2997                                                         ndef_in_length);
2998                 if (!record->header) {
2999                         err = -EINVAL;
3000                         goto fail;
3001                 }
3002
3003                 /* Validate MB ME */
3004                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
3005                                         record->header->mb,
3006                                         record->header->me) != 0) {
3007                         DBG("validate mb me failed");
3008                         err = -EINVAL;
3009                         goto fail;
3010                 }
3011
3012                 /* Is this what we want ? */
3013                 if (record->header->rec_type == record_type)
3014                         counted_records++;
3015
3016                 /* Jump to the next record */
3017                 offset = record->header->offset + record->header->payload_len;
3018
3019                 free_ndef_record(record);
3020         }
3021
3022         DBG("Type %d Records found: %d", record_type, counted_records);
3023
3024         return counted_records;
3025
3026 fail:
3027         near_error("ndef counting failed");
3028         free_ndef_record(record);
3029         return err;
3030 }
3031
3032 /* Possible encoding "UTF-8" or "UTF-16" */
3033 struct near_ndef_message *near_ndef_prepare_text_record(char *encoding,
3034                                                 char *language_code, char *text)
3035 {
3036         struct near_ndef_message *msg;
3037         uint32_t text_len, payload_length;
3038         uint8_t  code_len, status = 0;
3039
3040         DBG("");
3041
3042         /* Validate input parameters*/
3043         if (((g_strcmp0(encoding, "UTF-8") != 0) &&
3044                  (g_strcmp0(encoding, "UTF-16") != 0)) ||
3045                  (!language_code) ||
3046                  (!text)) {
3047                 return NULL;
3048         }
3049
3050         code_len = strlen(language_code);
3051         text_len = strlen(text);
3052         payload_length = 1 + code_len + text_len;
3053
3054         msg = ndef_message_alloc("T", payload_length);
3055         if (!msg)
3056                 return NULL;
3057
3058         if (g_strcmp0(encoding, "UTF-16") == 0)
3059                 status |= NDEF_TEXT_RECORD_UTF16_STATUS;
3060
3061         status = status | code_len;
3062         msg->data[msg->offset++] = status;
3063
3064         if (code_len > 0)
3065                 memcpy(msg->data + msg->offset, language_code, code_len);
3066
3067         msg->offset += code_len;
3068
3069         if (text_len > 0)
3070                 memcpy(msg->data + msg->offset, text, text_len);
3071
3072         msg->offset += text_len;
3073
3074         if (msg->offset > msg->length)
3075                 goto fail;
3076
3077         return msg;
3078
3079 fail:
3080         near_error("text record preparation failed");
3081         free_ndef_message(msg);
3082
3083         return NULL;
3084 }
3085
3086 struct near_ndef_message *near_ndef_prepare_uri_record(uint8_t identifier,
3087                                         uint32_t field_length, uint8_t *field)
3088 {
3089         struct near_ndef_message *msg = NULL;
3090         uint32_t payload_length;
3091
3092         DBG("");
3093
3094         /* Validate input parameters*/
3095         if ((field_length == 0 && field) ||
3096                 (field_length != 0 && !field)) {
3097                 return NULL;
3098         }
3099
3100         payload_length = field_length + 1;
3101
3102         msg = ndef_message_alloc("U", payload_length);
3103         if (!msg)
3104                 return NULL;
3105
3106         msg->data[msg->offset++] = identifier;
3107
3108         if (field_length > 0) {
3109                 memcpy(msg->data + msg->offset, field, field_length);
3110                 msg->offset += field_length;
3111         }
3112
3113         if (msg->offset > msg->length)
3114                 goto fail;
3115
3116         return msg;
3117
3118 fail:
3119         near_error("uri record preparation failed");
3120         free_ndef_message(msg);
3121
3122         return NULL;
3123 }
3124
3125 struct near_ndef_message *
3126 near_ndef_prepare_smartposter_record(uint8_t uri_identifier,
3127                                         uint32_t uri_field_length,
3128                                         uint8_t *uri_field)
3129 {
3130         struct near_ndef_message *msg = NULL, *uri = NULL;
3131
3132         /* URI is mandatory in Smartposter */
3133         uri = near_ndef_prepare_uri_record(uri_identifier, uri_field_length,
3134                                                                 uri_field);
3135         if (!uri)
3136                 goto fail;
3137
3138         /* URI record length is equal to payload length of Sp record */
3139         msg = ndef_message_alloc("Sp", uri->length);
3140         if (!msg)
3141                 goto fail;
3142
3143         memcpy(msg->data + msg->offset, uri->data, uri->length);
3144         msg->offset += uri->length;
3145
3146         if (msg->offset > msg->length)
3147                 goto fail;
3148
3149         free_ndef_message(uri);
3150
3151         return msg;
3152
3153 fail:
3154         near_error("smartposter record preparation failed");
3155
3156         free_ndef_message(uri);
3157         free_ndef_message(msg);
3158
3159         return NULL;
3160 }
3161
3162 static char *get_text_field(DBusMessage *msg, char *text)
3163 {
3164         DBusMessageIter iter, arr_iter;
3165         char *uri = NULL;
3166
3167         DBG("");
3168
3169         if (!text)
3170                 return NULL;
3171
3172         dbus_message_iter_init(msg, &iter);
3173         dbus_message_iter_recurse(&iter, &arr_iter);
3174
3175         while (dbus_message_iter_get_arg_type(&arr_iter) !=
3176                                         DBUS_TYPE_INVALID) {
3177                 const char *key;
3178                 DBusMessageIter ent_iter;
3179                 DBusMessageIter var_iter;
3180
3181                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3182                 dbus_message_iter_get_basic(&ent_iter, &key);
3183                 dbus_message_iter_next(&ent_iter);
3184                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3185
3186                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3187                 case DBUS_TYPE_STRING:
3188                         if (g_strcmp0(key, text) == 0)
3189                                 dbus_message_iter_get_basic(&var_iter, &uri);
3190
3191                         break;
3192                 }
3193
3194                 dbus_message_iter_next(&arr_iter);
3195         }
3196
3197         return uri;
3198 }
3199
3200 static inline char *get_uri_field(DBusMessage *msg)
3201 {
3202         return get_text_field(msg, "URI");
3203 }
3204
3205 static GSList *get_carrier_field(DBusMessage *msg)
3206 {
3207         char *carrier;
3208         char **arr;
3209         GSList *carriers = NULL;
3210         uint8_t num_of_carriers, i;
3211
3212         DBG("");
3213
3214         carrier = get_text_field(msg, "Carrier");
3215         if (!carrier)
3216                 return NULL;
3217
3218         arr = g_strsplit(carrier, ",", NEAR_CARRIER_MAX);
3219         num_of_carriers = g_strv_length(arr);
3220
3221         for (i = 0; i < num_of_carriers; i++)
3222                 carriers = g_slist_append(carriers, g_strdup(arr[i]));
3223
3224         g_strfreev(arr);
3225
3226         return carriers;
3227 }
3228
3229 static struct near_ndef_message *build_text_record(DBusMessage *msg)
3230 {
3231         DBusMessageIter iter, arr_iter;
3232         char *cod = NULL, *lang = NULL, *rep = NULL;
3233
3234         DBG("");
3235
3236         dbus_message_iter_init(msg, &iter);
3237         dbus_message_iter_recurse(&iter, &arr_iter);
3238
3239         while (dbus_message_iter_get_arg_type(&arr_iter) !=
3240                                         DBUS_TYPE_INVALID) {
3241                 const char *key;
3242                 DBusMessageIter ent_iter;
3243                 DBusMessageIter var_iter;
3244
3245                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3246                 dbus_message_iter_get_basic(&ent_iter, &key);
3247                 dbus_message_iter_next(&ent_iter);
3248                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3249
3250                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3251                 case DBUS_TYPE_STRING:
3252                         if (g_strcmp0(key, "Encoding") == 0)
3253                                 dbus_message_iter_get_basic(&var_iter, &cod);
3254                         else if (g_strcmp0(key, "Language") == 0)
3255                                 dbus_message_iter_get_basic(&var_iter, &lang);
3256                         else if (g_strcmp0(key, "Representation") == 0)
3257                                 dbus_message_iter_get_basic(&var_iter, &rep);
3258
3259                         break;
3260                 }
3261
3262                 dbus_message_iter_next(&arr_iter);
3263         }
3264
3265         return near_ndef_prepare_text_record(cod, lang, rep);
3266 }
3267
3268 static struct near_ndef_message *build_uri_record(DBusMessage *msg)
3269 {
3270         char *uri = NULL;
3271         const char *uri_prefix = NULL;
3272         uint8_t id_len, i, id;
3273         uint32_t uri_len;
3274
3275         DBG("");
3276
3277         uri = get_uri_field(msg);
3278         if (!uri)
3279                 return NULL;
3280
3281         id = 0;
3282         id_len = 0;
3283
3284         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3285                 uri_prefix = __near_ndef_get_uri_prefix(i);
3286
3287                 if (uri_prefix &&
3288                     g_str_has_prefix(uri, uri_prefix)) {
3289                         id = i;
3290                         id_len = strlen(uri_prefix);
3291                         break;
3292                 }
3293         }
3294
3295         DBG("%d %d\n", i, id_len);
3296
3297         uri_len = strlen(uri) - id_len;
3298         return near_ndef_prepare_uri_record(id, uri_len,
3299                                                 (uint8_t *)(uri + id_len));
3300 }
3301
3302 static struct near_ndef_message *build_sp_record(DBusMessage *msg)
3303 {
3304         char *uri = NULL;
3305         const char *uri_prefix;
3306         uint8_t id_len, i;
3307         uint32_t uri_len;
3308
3309         DBG("");
3310
3311         /*
3312          * Currently this function supports only mandatory URI record,
3313          * TODO: Other records support.
3314          */
3315         uri = get_uri_field(msg);
3316         if (!uri)
3317                 return NULL;
3318
3319         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3320                 uri_prefix = __near_ndef_get_uri_prefix(i);
3321
3322                 if (uri_prefix &&
3323                                 g_str_has_prefix(uri, uri_prefix))
3324                         break;
3325         }
3326
3327         if (!uri_prefix) {
3328                 i = 0;
3329                 id_len = 0;
3330         } else
3331                 id_len = strlen(uri_prefix);
3332
3333         uri_len = strlen(uri) - id_len;
3334         return near_ndef_prepare_smartposter_record(i, uri_len,
3335                                                 (uint8_t *)(uri + id_len));
3336 }
3337
3338 static struct near_ndef_message *build_ho_record(enum record_type type,
3339                                                         DBusMessage *msg)
3340 {
3341         struct near_ndef_message *ho;
3342         GSList *carriers;
3343
3344         DBG("");
3345
3346         carriers = get_carrier_field(msg);
3347         ho = near_ndef_prepare_ho_message(type, carriers);
3348         g_slist_free_full(carriers, g_free);
3349
3350         return ho;
3351 }
3352
3353 static int fill_wifi_wsc_data(uint8_t *tlv, uint16_t id,
3354                                 uint16_t data_len, uint8_t *data)
3355 {
3356         int offset = 0;
3357
3358         if (!tlv || !data)
3359                 return 0;
3360
3361         fillb16(tlv, id);
3362         offset += WIFI_WSC_ID_LENGTH;
3363
3364         fillb16(tlv + offset, data_len);
3365         offset += WIFI_WSC_ID_DATA_LENGTH;
3366
3367         memcpy(tlv + offset, data, data_len);
3368         offset += data_len;
3369
3370         return offset;
3371 }
3372
3373 static void get_wsc_data(DBusMessageIter iter, char **ssid, char **pass)
3374 {
3375         DBG("");
3376
3377         *ssid = NULL;
3378         *pass = NULL;
3379
3380         while (dbus_message_iter_get_arg_type(&iter) !=
3381                                         DBUS_TYPE_INVALID) {
3382                 const char *key;
3383                 DBusMessageIter ent_iter;
3384                 DBusMessageIter var_iter;
3385
3386                 dbus_message_iter_recurse(&iter, &ent_iter);
3387                 dbus_message_iter_get_basic(&ent_iter, &key);
3388                 dbus_message_iter_next(&ent_iter);
3389                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3390
3391                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3392                 case DBUS_TYPE_STRING:
3393                         if (g_strcmp0(key, "SSID") == 0)
3394                                 dbus_message_iter_get_basic(&var_iter, ssid);
3395                         else if (g_strcmp0(key, "Passphrase") == 0)
3396                                 dbus_message_iter_get_basic(&var_iter, pass);
3397
3398                         break;
3399                 }
3400
3401                 dbus_message_iter_next(&iter);
3402         }
3403 }
3404
3405 struct near_ndef_message *near_ndef_prepare_wsc_record(char *ssid,
3406                                                         char *passphrase)
3407 {
3408         uint16_t ssid_len, pass_len, key_type;
3409         uint8_t temp_key[2];
3410         uint8_t *tlv;
3411         uint32_t tlv_len, offset;
3412         struct near_ndef_message *mime;
3413
3414         /* At least SSID is required in case of open network */
3415         if (!ssid)
3416                 return NULL;
3417
3418         DBG("SSID %s Passphrase %s", ssid, passphrase);
3419
3420         /* Prepare TLV from ssid and passphrasse */
3421         ssid_len = strlen(ssid);
3422
3423         if (passphrase) {
3424                 pass_len = strlen(passphrase);
3425                 key_type = WIFI_WSC_KEY_PSK;
3426         } else {
3427                 pass_len = 0;
3428                 key_type = WIFI_WSC_KEY_OPEN;
3429         }
3430
3431         /* add ssid length */
3432         tlv_len = WIFI_WSC_ID_LENGTH + WIFI_WSC_ID_DATA_LENGTH + ssid_len;
3433         /* add authentication type length */
3434         tlv_len += WIFI_WSC_ID_LENGTH + WIFI_WSC_ID_DATA_LENGTH + 2;
3435         /* add network key length */
3436         if (passphrase)
3437                 tlv_len += WIFI_WSC_ID_LENGTH +
3438                                 WIFI_WSC_ID_DATA_LENGTH + pass_len;
3439
3440         tlv = g_try_malloc0(tlv_len);
3441         if (!tlv)
3442                 return NULL;
3443
3444         offset = 0;
3445         /* copy SSID */
3446         offset += fill_wifi_wsc_data(tlv, WIFI_WSC_ID_SSID,
3447                                         ssid_len, (uint8_t *) ssid);
3448
3449         /*
3450          * copy authentication type
3451          * copy key type to temp key array to maintain endianess
3452          * and fill wsc data
3453          */
3454         fillb16(temp_key, key_type);
3455         offset += fill_wifi_wsc_data(tlv + offset, WIFI_WSC_ID_AUTH_TYPE,
3456                                                 WIFI_WSC_ID_DATA_LENGTH,
3457                                                 (uint8_t *) temp_key);
3458
3459         /* copy Network Key */
3460         if (passphrase)
3461                 offset += fill_wifi_wsc_data(tlv + offset, WIFI_WSC_ID_KEY,
3462                                                 pass_len,
3463                                                 (uint8_t *) passphrase);
3464
3465         mime = ndef_message_alloc_complete(WIFI_WSC_MIME_STRING, tlv_len, NULL,
3466                                                 0, RECORD_TNF_MIME, true,
3467                                            true);
3468         if (!mime) {
3469                 g_free(tlv);
3470                 return NULL;
3471         }
3472
3473         memcpy(mime->data + mime->offset, tlv, tlv_len);
3474         g_free(tlv);
3475
3476         return mime;
3477 }
3478
3479 static char *get_mime_payload_data(DBusMessageIter iter,
3480                                 char **payload, int *payload_len)
3481 {
3482         DBG("");
3483
3484         if (!payload || !payload_len) {
3485                 near_error("Payload %p payload_len %p", payload, payload_len);
3486                 return NULL;
3487         }
3488
3489         while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
3490                 const char *key;
3491                 DBusMessageIter ent_iter;
3492                 DBusMessageIter var_iter;
3493                 DBusMessageIter arr_iter;
3494
3495                 dbus_message_iter_recurse(&iter, &ent_iter);
3496                 dbus_message_iter_get_basic(&ent_iter, &key);
3497                 dbus_message_iter_next(&ent_iter);
3498                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3499
3500                 if (g_strcmp0(key, "Payload") == 0) {
3501                         if (dbus_message_iter_get_arg_type(&var_iter) ==
3502                                                         DBUS_TYPE_ARRAY &&
3503                             dbus_message_iter_get_element_type(&var_iter) ==
3504                                                         DBUS_TYPE_BYTE) {
3505                                         dbus_message_iter_recurse(&var_iter,
3506                                                                  &arr_iter);
3507                                         dbus_message_iter_get_fixed_array(
3508                                                         &arr_iter, payload,
3509                                                         payload_len);
3510                         } else {
3511                                 near_error("Unexpected payload type");
3512                                 return NULL;
3513                         }
3514                 }
3515                 dbus_message_iter_next(&iter);
3516         }
3517
3518         return *payload;
3519 }
3520
3521 static struct near_ndef_message *near_ndef_prepare_mime_payload_record(
3522                                 char *type, char *payload, int payload_len)
3523 {
3524         struct near_ndef_message *mime;
3525
3526         DBG("Payload %*s", payload_len, payload);
3527         mime = ndef_message_alloc_complete(type, payload_len, NULL, 0,
3528                                                 RECORD_TNF_MIME, true, true);
3529         if (!mime) {
3530                 near_error("Failed to alloc NDEF message");
3531                 return NULL;
3532         }
3533
3534         memcpy(mime->data + mime->offset, payload, payload_len);
3535
3536         return mime;
3537 }
3538
3539 #define DE_AUTHENTICATION_TYPE 0x1003
3540 #define DE_NETWORK_KEY 0x1027
3541 #define DE_SSID 0x1045
3542 static void parse_wsc_oob(guint8 *oob_data, guint32 oob_length,
3543                                         char **ssid, char **passphrase)
3544 {
3545         guint32 offset = 0;
3546         guint16 de_length, de_type;
3547         guint16 auth_type;
3548
3549         while (offset < oob_length) {
3550                 de_type = near_get_be16(oob_data + offset);
3551                 de_length = near_get_be16(oob_data + offset + 2);
3552
3553                 switch(de_type) {
3554                 case DE_AUTHENTICATION_TYPE:
3555                         auth_type = near_get_be16(oob_data + offset + 4);
3556                         DBG("WSC Authentication Type: 0x%02x",
3557                             auth_type);
3558                         break;
3559
3560                 case DE_SSID:
3561                         *ssid = g_try_malloc0(de_length + 1);
3562                         if (!*ssid)
3563                                 break;
3564
3565                         g_snprintf(*ssid, de_length + 1,
3566                                         "%s", oob_data + offset + 4);
3567
3568                         DBG("SSID: %s", *ssid);
3569                         break;
3570
3571                 case DE_NETWORK_KEY:
3572                         *passphrase = g_try_malloc0(de_length + 1);
3573                         if (!*passphrase)
3574                                 break;
3575
3576                         g_snprintf(*passphrase, de_length + 1,
3577                                         "%s", oob_data + offset + 4);
3578
3579                         DBG("Passphrase: %s", *passphrase);
3580                         break;
3581
3582                 default:
3583                         DBG("Unknown Data Element");
3584                         break;
3585
3586                 }
3587
3588                 offset += 4 + de_length;
3589         }
3590 }
3591
3592 static struct near_ndef_message *build_mime_record(DBusMessage *msg)
3593 {
3594         DBusMessageIter iter, arr_iter;
3595         char *key, *mime_str, *ssid, *passphrase;
3596
3597         DBG("");
3598
3599         dbus_message_iter_init(msg, &iter);
3600         dbus_message_iter_recurse(&iter, &arr_iter);
3601
3602         while (dbus_message_iter_get_arg_type(&arr_iter) !=
3603                                         DBUS_TYPE_INVALID) {
3604                 DBusMessageIter ent_iter;
3605                 DBusMessageIter var_iter;
3606
3607                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3608                 dbus_message_iter_get_basic(&ent_iter, &key);
3609
3610                 if (g_strcmp0(key, "MIME") == 0) {
3611                         dbus_message_iter_next(&ent_iter);
3612                         dbus_message_iter_recurse(&ent_iter, &var_iter);
3613                         dbus_message_iter_get_basic(&var_iter, &mime_str);
3614
3615                         if (g_strcmp0(mime_str, WIFI_WSC_MIME_STRING) == 0) {
3616                                 struct near_ndef_message *mime;
3617                                 struct carrier_data *carrier;
3618
3619                                 get_wsc_data(arr_iter, &ssid, &passphrase);
3620                                 if (ssid)
3621                                         return near_ndef_prepare_wsc_record(
3622                                                         ssid, passphrase);
3623
3624                                 /*
3625                                  * If we did not get an SSID and optionally
3626                                  * a passphrase from the DBus message, then
3627                                  * we try to get one from the WiFi-WSC agent.
3628                                  */
3629                                 carrier = __near_agent_handover_request_data(
3630                                                         HO_AGENT_WIFI, NULL);
3631                                 if (!carrier)
3632                                         return NULL;
3633
3634                                 mime = ndef_message_alloc_complete(
3635                                         WIFI_WSC_MIME_STRING, carrier->size,
3636                                         NULL, 0, RECORD_TNF_MIME, true, true);
3637                                 if (!mime) {
3638                                         g_free(carrier);
3639                                         return NULL;
3640                                 }
3641
3642                                 memcpy(mime->data + mime->offset,
3643                                         carrier->data, carrier->size);
3644
3645                                 g_free(carrier);
3646
3647                                 return mime;
3648                         } else if (g_strcmp0(mime_str, "x/nfctl") == 0) {
3649                                 struct carrier_data *carrier;
3650                                 char *ssid = NULL, *passphrase = NULL;
3651                                 char payload[128];
3652
3653                                 carrier = __near_agent_handover_request_data(
3654                                                         HO_AGENT_WIFI, NULL);
3655                                 if (!carrier)
3656                                         return NULL;
3657
3658                                 parse_wsc_oob(carrier->data, carrier->size,
3659                                                         &ssid, &passphrase);
3660                                 if (!ssid || !passphrase)
3661                                         return NULL;
3662
3663                                 g_snprintf(payload, 128,
3664                                         "enZ:wifi association;C:I4:%s:2:%s",
3665                                         ssid, passphrase);
3666                                 g_free(ssid);
3667                                 g_free(passphrase);
3668
3669                                 DBG("payload %s", payload);
3670
3671                                 return near_ndef_prepare_mime_payload_record(
3672                                         mime_str, payload, strlen(payload));
3673                         } else {
3674                                 /*
3675                                  * Expect data is set in the Payload field of
3676                                  * message.
3677                                  */
3678                                 DBusMessageIter payload_iter;
3679                                 char *payload;
3680                                 int payload_len;
3681
3682                                 DBG("mime string %s", mime_str);
3683                                 dbus_message_iter_recurse(&iter, &payload_iter);
3684                                 if (!get_mime_payload_data(payload_iter,
3685                                                         &payload, &payload_len))
3686                                         return NULL;
3687
3688                                 return near_ndef_prepare_mime_payload_record(
3689                                         mime_str, payload, payload_len);
3690                         }
3691                 }
3692
3693                 dbus_message_iter_next(&arr_iter);
3694         }
3695
3696         return NULL;
3697 }
3698
3699 static struct near_ndef_message * build_raw_ndef(DBusMessage *msg)
3700 {
3701         DBusMessageIter iter, arr_iter;
3702         struct near_ndef_message *ndef;
3703
3704         DBG("");
3705
3706         ndef = NULL;
3707
3708         dbus_message_iter_init(msg, &iter);
3709         dbus_message_iter_recurse(&iter, &arr_iter);
3710
3711         while (dbus_message_iter_get_arg_type(&arr_iter) !=
3712                                         DBUS_TYPE_INVALID) {
3713                 const char *key;
3714                 DBusMessageIter ent_iter;
3715                 DBusMessageIter var_iter;
3716
3717                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3718                 dbus_message_iter_get_basic(&ent_iter, &key);
3719                 dbus_message_iter_next(&ent_iter);
3720                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3721
3722                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3723                 case DBUS_TYPE_ARRAY:
3724                         if (g_strcmp0(key, "NDEF") == 0) {
3725                                 DBusMessageIter array;
3726                                 uint8_t *data;
3727                                 int data_size;
3728
3729                                 dbus_message_iter_recurse(&var_iter, &array);
3730                                 dbus_message_iter_get_fixed_array(&array,
3731                                                                 &data,
3732                                                                 &data_size);
3733
3734                                 ndef = g_try_malloc0(data_size);
3735                                 if (ndef == NULL)
3736                                         break;
3737
3738                                 ndef->data = g_try_malloc0(data_size);
3739                                 if (ndef->data == NULL) {
3740                                         g_free(ndef);
3741                                         break;
3742                                 }
3743
3744                                 ndef->length = data_size;
3745                                 memcpy(ndef->data, data, data_size);
3746                         }
3747
3748                         break;
3749                 }
3750
3751                 dbus_message_iter_next(&arr_iter);
3752         }
3753
3754         return ndef;
3755 }
3756
3757 struct near_ndef_message *__ndef_build_from_message(DBusMessage *msg)
3758 {
3759         DBusMessageIter iter;
3760         DBusMessageIter arr_iter;
3761         struct near_ndef_message *ndef;
3762
3763         DBG("");
3764
3765         dbus_message_iter_init(msg, &iter);
3766         dbus_message_iter_recurse(&iter, &arr_iter);
3767
3768         ndef = NULL;
3769
3770         while (dbus_message_iter_get_arg_type(&arr_iter) !=
3771                                                 DBUS_TYPE_INVALID) {
3772                 const char *key, *value;
3773                 DBusMessageIter ent_iter;
3774                 DBusMessageIter var_iter;
3775
3776                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3777                 dbus_message_iter_get_basic(&ent_iter, &key);
3778
3779                 if (g_strcmp0(key, "Type") != 0) {
3780                         dbus_message_iter_next(&arr_iter);
3781                         continue;
3782                 }
3783
3784                 dbus_message_iter_next(&ent_iter);
3785                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3786
3787                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3788                 case DBUS_TYPE_STRING:
3789                         dbus_message_iter_get_basic(&var_iter, &value);
3790
3791                         if (g_strcmp0(value, "Text") == 0) {
3792                                 ndef = build_text_record(msg);
3793                                 break;
3794                         } else if (g_strcmp0(value, "URI") == 0) {
3795                                 ndef = build_uri_record(msg);
3796                                 break;
3797                         } else if (g_strcmp0(value, "SmartPoster") == 0) {
3798                                 ndef = build_sp_record(msg);
3799                                 break;
3800                         } else if (g_strcmp0(value, "Handover") == 0) {
3801                                 ndef = build_ho_record(
3802                                         RECORD_TYPE_WKT_HANDOVER_REQUEST, msg);
3803                                 break;
3804                         } else if (g_strcmp0(value, "StaticHandover") == 0) {
3805                                 ndef = build_ho_record(
3806                                         RECORD_TYPE_WKT_HANDOVER_SELECT, msg);
3807                                 break;
3808                         } else if (g_strcmp0(value, "MIME") == 0) {
3809                                 ndef = build_mime_record(msg);
3810                                 break;
3811                         } else if (g_strcmp0(value, "Raw") == 0) {
3812                                 ndef = build_raw_ndef(msg);
3813                                 break;
3814                         } else {
3815                                 near_error("%s not supported", value);
3816                                 ndef = NULL;
3817                                 break;
3818                         }
3819
3820                         break;
3821                 }
3822
3823                 dbus_message_iter_next(&arr_iter);
3824         }
3825
3826         return ndef;
3827 }
3828
3829 int __near_ndef_init(void)
3830 {
3831         DBG("");
3832
3833         connection = near_dbus_get_connection();
3834
3835         return 0;
3836 }
3837
3838 void __near_ndef_cleanup(void)
3839 {
3840 }