Fix build break for rpm
[framework/connectivity/bluez.git] / network / server.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <errno.h>
32
33 #include <bluetooth/bluetooth.h>
34 #include <bluetooth/bnep.h>
35 #include <bluetooth/sdp.h>
36 #include <bluetooth/sdp_lib.h>
37 #include <bluetooth/uuid.h>
38 #include <netinet/in.h>
39
40 #include <glib.h>
41 #include <gdbus.h>
42
43 #include "../src/dbus-common.h"
44 #include "../src/adapter.h"
45
46 #include "log.h"
47 #include "error.h"
48 #include "sdpd.h"
49 #include "btio.h"
50
51 #include "common.h"
52 #include "server.h"
53
54 #define NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer"
55 #define SETUP_TIMEOUT           1
56
57 /* Pending Authorization */
58 struct network_session {
59         bdaddr_t        dst;            /* Remote Bluetooth Address */
60         GIOChannel      *io;            /* Pending connect channel */
61         guint           watch;          /* BNEP socket watch */
62 };
63
64 struct network_adapter {
65         struct btd_adapter *adapter;    /* Adapter pointer */
66         GIOChannel      *io;            /* Bnep socket */
67         struct network_session *setup;  /* Setup in progress */
68         GSList          *servers;       /* Server register to adapter */
69 };
70
71 /* Main server structure */
72 struct network_server {
73         bdaddr_t        src;            /* Bluetooth Local Address */
74         char            *iface;         /* DBus interface */
75         char            *name;          /* Server service name */
76         char            *bridge;        /* Bridge name */
77         uint32_t        record_id;      /* Service record id */
78         uint16_t        id;             /* Service class identifier */
79         GSList          *sessions;      /* Active connections */
80         struct network_adapter *na;     /* Adapter reference */
81         guint           watch_id;       /* Client service watch */
82 #ifdef __TIZEN_PATCH__
83         char            dev[16];        /* Interface name */
84 #endif
85 };
86
87 static DBusConnection *connection = NULL;
88 static GSList *adapters = NULL;
89 static gboolean security = TRUE;
90
91 #ifdef  __TIZEN_PATCH__
92 static gboolean server_disconnected_cb(GIOChannel *chan,
93                         GIOCondition cond, gpointer user_data);
94 #endif
95
96 static struct network_adapter *find_adapter(GSList *list,
97                                         struct btd_adapter *adapter)
98 {
99         for (; list; list = list->next) {
100                 struct network_adapter *na = list->data;
101
102                 if (na->adapter == adapter)
103                         return na;
104         }
105
106         return NULL;
107 }
108
109 static struct network_server *find_server(GSList *list, uint16_t id)
110 {
111         for (; list; list = list->next) {
112                 struct network_server *ns = list->data;
113
114                 if (ns->id == id)
115                         return ns;
116         }
117
118         return NULL;
119 }
120
121 #ifdef  __TIZEN_PATCH__
122 static struct network_session *find_session(GSList *list, GIOChannel *io)
123 {
124         GSList *l;
125
126         for (l = list; l; l = l->next) {
127                 struct network_session *session = l->data;
128
129                 if (session->io == io)
130                         return session;
131         }
132
133         return NULL;
134 }
135 #endif
136
137 static sdp_record_t *server_record_new(const char *name, uint16_t id)
138 {
139         sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
140         uuid_t root_uuid, pan, l2cap, bnep;
141         sdp_profile_desc_t profile[1];
142         sdp_list_t *proto[2];
143         sdp_data_t *v, *p;
144         uint16_t psm = BNEP_PSM, version = 0x0100;
145         uint16_t security_desc = (security ? 0x0001 : 0x0000);
146         uint16_t net_access_type = 0xfffe;
147         uint32_t max_net_access_rate = 0;
148         const char *desc = "Network service";
149         sdp_record_t *record;
150
151         record = sdp_record_alloc();
152         if (!record)
153                 return NULL;
154
155         record->attrlist = NULL;
156         record->pattern = NULL;
157
158         switch (id) {
159         case BNEP_SVC_NAP:
160                 sdp_uuid16_create(&pan, NAP_SVCLASS_ID);
161                 svclass = sdp_list_append(NULL, &pan);
162                 sdp_set_service_classes(record, svclass);
163
164                 sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
165                 profile[0].version = 0x0100;
166                 pfseq = sdp_list_append(NULL, &profile[0]);
167                 sdp_set_profile_descs(record, pfseq);
168
169                 sdp_set_info_attr(record, name, NULL, desc);
170
171                 sdp_attr_add_new(record, SDP_ATTR_NET_ACCESS_TYPE,
172                                         SDP_UINT16, &net_access_type);
173                 sdp_attr_add_new(record, SDP_ATTR_MAX_NET_ACCESSRATE,
174                                         SDP_UINT32, &max_net_access_rate);
175                 break;
176         case BNEP_SVC_GN:
177                 sdp_uuid16_create(&pan, GN_SVCLASS_ID);
178                 svclass = sdp_list_append(NULL, &pan);
179                 sdp_set_service_classes(record, svclass);
180
181                 sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID);
182                 profile[0].version = 0x0100;
183                 pfseq = sdp_list_append(NULL, &profile[0]);
184                 sdp_set_profile_descs(record, pfseq);
185
186                 sdp_set_info_attr(record, name, NULL, desc);
187                 break;
188         case BNEP_SVC_PANU:
189                 sdp_uuid16_create(&pan, PANU_SVCLASS_ID);
190                 svclass = sdp_list_append(NULL, &pan);
191                 sdp_set_service_classes(record, svclass);
192
193                 sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
194                 profile[0].version = 0x0100;
195                 pfseq = sdp_list_append(NULL, &profile[0]);
196                 sdp_set_profile_descs(record, pfseq);
197
198                 sdp_set_info_attr(record, name, NULL, desc);
199                 break;
200         default:
201                 sdp_record_free(record);
202                 return NULL;
203         }
204
205         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
206         root = sdp_list_append(NULL, &root_uuid);
207         sdp_set_browse_groups(record, root);
208
209         sdp_uuid16_create(&l2cap, L2CAP_UUID);
210         proto[0] = sdp_list_append(NULL, &l2cap);
211         p = sdp_data_alloc(SDP_UINT16, &psm);
212         proto[0] = sdp_list_append(proto[0], p);
213         apseq    = sdp_list_append(NULL, proto[0]);
214
215         sdp_uuid16_create(&bnep, BNEP_UUID);
216         proto[1] = sdp_list_append(NULL, &bnep);
217         v = sdp_data_alloc(SDP_UINT16, &version);
218         proto[1] = sdp_list_append(proto[1], v);
219
220         /* Supported protocols */
221         {
222                 uint16_t ptype[] = {
223                         0x0800,  /* IPv4 */
224                         0x0806,  /* ARP */
225                 };
226                 sdp_data_t *head, *pseq;
227                 int p;
228
229                 for (p = 0, head = NULL; p < 2; p++) {
230                         sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
231                         if (head)
232                                 sdp_seq_append(head, data);
233                         else
234                                 head = data;
235                 }
236                 pseq = sdp_data_alloc(SDP_SEQ16, head);
237                 proto[1] = sdp_list_append(proto[1], pseq);
238         }
239
240         apseq = sdp_list_append(apseq, proto[1]);
241
242         aproto = sdp_list_append(NULL, apseq);
243         sdp_set_access_protos(record, aproto);
244
245         sdp_add_lang_attr(record);
246
247         sdp_attr_add_new(record, SDP_ATTR_SECURITY_DESC,
248                                 SDP_UINT16, &security_desc);
249
250         sdp_data_free(p);
251         sdp_data_free(v);
252         sdp_list_free(apseq, NULL);
253         sdp_list_free(root, NULL);
254         sdp_list_free(aproto, NULL);
255         sdp_list_free(proto[0], NULL);
256         sdp_list_free(proto[1], NULL);
257         sdp_list_free(svclass, NULL);
258         sdp_list_free(pfseq, NULL);
259
260         return record;
261 }
262
263 static ssize_t send_bnep_ctrl_rsp(int sk, uint16_t val)
264 {
265         struct bnep_control_rsp rsp;
266
267         rsp.type = BNEP_CONTROL;
268         rsp.ctrl = BNEP_SETUP_CONN_RSP;
269         rsp.resp = htons(val);
270
271         return send(sk, &rsp, sizeof(rsp), 0);
272 }
273
274 static int server_connadd(struct network_server *ns,
275                                 struct network_session *session,
276                                 uint16_t dst_role)
277 {
278         char devname[16];
279         int err, nsk;
280
281         memset(devname, 0, sizeof(devname));
282         strcpy(devname, "bnep%d");
283
284         nsk = g_io_channel_unix_get_fd(session->io);
285         err = bnep_connadd(nsk, dst_role, devname);
286         if (err < 0)
287                 return err;
288
289         info("Added new connection: %s", devname);
290
291 #ifdef  __TIZEN_PATCH__
292         {
293                 guint watch = 0;
294
295                 bnep_if_up(devname);
296                 memcpy(ns->dev, devname, sizeof(devname));
297
298                 watch = g_io_add_watch_full(session->io, G_PRIORITY_DEFAULT,
299                                         G_IO_HUP | G_IO_ERR | G_IO_NVAL,
300                                         server_disconnected_cb, ns, NULL);
301         }
302 #else
303         if (bnep_add_to_bridge(devname, ns->bridge) < 0) {
304                 error("Can't add %s to the bridge %s: %s(%d)",
305                                 devname, ns->bridge, strerror(errno), errno);
306                 return -EPERM;
307         }
308
309         bnep_if_up(devname);
310 #endif
311
312         ns->sessions = g_slist_append(ns->sessions, session);
313
314         return 0;
315 }
316
317 static uint16_t bnep_setup_chk(uint16_t dst_role, uint16_t src_role)
318 {
319         /* Allowed PAN Profile scenarios */
320         switch (dst_role) {
321         case BNEP_SVC_NAP:
322         case BNEP_SVC_GN:
323                 if (src_role == BNEP_SVC_PANU)
324                         return 0;
325                 return BNEP_CONN_INVALID_SRC;
326         case BNEP_SVC_PANU:
327                 if (src_role == BNEP_SVC_PANU ||
328                                 src_role == BNEP_SVC_GN ||
329                                 src_role == BNEP_SVC_NAP)
330                         return 0;
331
332                 return BNEP_CONN_INVALID_SRC;
333         }
334
335         return BNEP_CONN_INVALID_DST;
336 }
337
338 static uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req,
339                                 uint16_t *dst_role, uint16_t *src_role)
340 {
341         uint8_t *dest, *source;
342
343         dest = req->service;
344         source = req->service + req->uuid_size;
345
346         switch (req->uuid_size) {
347         case 2: /* UUID16 */
348                 *dst_role = bt_get_be16(dest);
349                 *src_role = bt_get_be16(source);
350                 break;
351         case 4: /* UUID32 */
352         case 16: /* UUID128 */
353                 *dst_role = bt_get_be32(dest);
354                 *src_role = bt_get_be32(source);
355                 break;
356         default:
357                 return BNEP_CONN_INVALID_SVC;
358         }
359
360         return 0;
361 }
362
363 static void session_free(void *data)
364 {
365         struct network_session *session = data;
366
367         if (session->watch)
368                 g_source_remove(session->watch);
369
370         if (session->io)
371                 g_io_channel_unref(session->io);
372
373         g_free(session);
374 }
375
376 static void setup_destroy(void *user_data)
377 {
378         struct network_adapter *na = user_data;
379         struct network_session *setup = na->setup;
380
381         if (!setup)
382                 return;
383
384         na->setup = NULL;
385
386         session_free(setup);
387 }
388
389 #ifdef  __TIZEN_PATCH__
390 static gboolean server_disconnected_cb(GIOChannel *chan,
391                         GIOCondition cond, gpointer user_data)
392 {
393         struct network_server *ns = NULL;
394         struct network_session *session = NULL;
395         char address[20] = {0};
396         GError *gerr = NULL;
397         const char* paddr = address;
398         char *name_str = NULL;
399
400         info("server_disconnected_cb");
401
402         if (!user_data)
403                 return FALSE;
404
405         ns = (struct network_server *) user_data;
406
407         name_str = ns->dev;
408
409         bt_io_get(chan, BT_IO_L2CAP, &gerr,
410                         BT_IO_OPT_DEST, &address,
411                         BT_IO_OPT_INVALID);
412
413         g_dbus_emit_signal(connection, adapter_get_path(ns->na->adapter),
414                         NETWORK_SERVER_INTERFACE, "PeerDisconnected",
415                         DBUS_TYPE_STRING, &name_str,
416                         DBUS_TYPE_STRING, &paddr,
417                         DBUS_TYPE_INVALID);
418
419         /* Remove the session info */
420         session = find_session(ns->sessions, chan);
421         if (session) {
422                 ns->sessions = g_slist_remove(ns->sessions, session);
423                 session_free(session);
424         }
425         else {
426                 info("Session is not exist!");
427         }
428
429         if (g_slist_length(ns->sessions) == 0)
430                 bnep_if_down(ns->dev);
431
432         return FALSE;
433 }
434 #endif
435
436 static gboolean bnep_setup(GIOChannel *chan,
437                         GIOCondition cond, gpointer user_data)
438 {
439         struct network_adapter *na = user_data;
440         struct network_server *ns;
441         uint8_t packet[BNEP_MTU];
442         struct bnep_setup_conn_req *req = (void *) packet;
443         uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
444         int n, sk;
445
446         if (cond & G_IO_NVAL)
447                 return FALSE;
448
449         if (cond & (G_IO_ERR | G_IO_HUP)) {
450                 error("Hangup or error on BNEP socket");
451                 return FALSE;
452         }
453
454         sk = g_io_channel_unix_get_fd(chan);
455
456         /* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
457         n = read(sk, packet, sizeof(packet));
458         if (n < 0) {
459                 error("read(): %s(%d)", strerror(errno), errno);
460                 return FALSE;
461         }
462
463         /* Highest known Control command ID
464          * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */
465         if (req->type == BNEP_CONTROL &&
466                                 req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
467                 uint8_t pkt[3];
468
469                 pkt[0] = BNEP_CONTROL;
470                 pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
471                 pkt[2] = req->ctrl;
472
473                 send(sk, pkt, sizeof(pkt), 0);
474
475                 return FALSE;
476         }
477
478         if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
479                 return FALSE;
480
481         rsp = bnep_setup_decode(req, &dst_role, &src_role);
482         if (rsp)
483                 goto reply;
484
485         rsp = bnep_setup_chk(dst_role, src_role);
486         if (rsp)
487                 goto reply;
488
489         ns = find_server(na->servers, dst_role);
490         if (!ns) {
491                 error("Server unavailable: (0x%x)", dst_role);
492                 goto reply;
493         }
494
495         if (!ns->record_id) {
496                 error("Service record not available");
497                 goto reply;
498         }
499
500         if (!ns->bridge) {
501                 error("Bridge interface not configured");
502                 goto reply;
503         }
504
505         if (server_connadd(ns, na->setup, dst_role) < 0)
506                 goto reply;
507
508 #ifndef  __TIZEN_PATCH__
509         na->setup = NULL;
510 #endif
511
512         rsp = BNEP_SUCCESS;
513
514 #ifdef  __TIZEN_PATCH__
515 {
516 // Emit connected signal to BT application
517         const gchar* adapter_path = adapter_get_path(na->adapter);
518         const char* pdev = ns->dev;
519         char address[24] = {0};
520         char* paddr = address;
521
522         ba2str(&na->setup->dst,paddr);
523
524         na->setup = NULL;
525
526         g_dbus_emit_signal(connection, adapter_path,
527                         NETWORK_SERVER_INTERFACE, "PeerConnected",
528                         DBUS_TYPE_STRING, &pdev,
529                         DBUS_TYPE_STRING, &paddr,
530                         DBUS_TYPE_INVALID);
531 }
532 #endif
533
534 reply:
535         send_bnep_ctrl_rsp(sk, rsp);
536
537         return FALSE;
538 }
539
540 static void connect_event(GIOChannel *chan, GError *err, gpointer user_data)
541 {
542         struct network_adapter *na = user_data;
543
544         if (err) {
545                 error("%s", err->message);
546                 setup_destroy(na);
547                 return;
548         }
549
550         g_io_channel_set_close_on_unref(chan, TRUE);
551
552         na->setup->watch = g_io_add_watch_full(chan, G_PRIORITY_DEFAULT,
553                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
554                                 bnep_setup, na, setup_destroy);
555 }
556
557 static void auth_cb(DBusError *derr, void *user_data)
558 {
559         struct network_adapter *na = user_data;
560         GError *err = NULL;
561
562         if (derr) {
563                 error("Access denied: %s", derr->message);
564                 goto reject;
565         }
566
567         if (!bt_io_accept(na->setup->io, connect_event, na, NULL,
568                                                         &err)) {
569                 error("bt_io_accept: %s", err->message);
570                 g_error_free(err);
571                 goto reject;
572         }
573
574         return;
575
576 reject:
577         g_io_channel_shutdown(na->setup->io, TRUE, NULL);
578         setup_destroy(na);
579 }
580
581 static void confirm_event(GIOChannel *chan, gpointer user_data)
582 {
583         struct network_adapter *na = user_data;
584         struct network_server *ns;
585         int perr;
586         bdaddr_t src, dst;
587         char address[18];
588         GError *err = NULL;
589
590         bt_io_get(chan, BT_IO_L2CAP, &err,
591                         BT_IO_OPT_SOURCE_BDADDR, &src,
592                         BT_IO_OPT_DEST_BDADDR, &dst,
593                         BT_IO_OPT_DEST, address,
594                         BT_IO_OPT_INVALID);
595         if (err) {
596                 error("%s", err->message);
597                 g_error_free(err);
598                 goto drop;
599         }
600
601         DBG("BNEP: incoming connect from %s", address);
602
603         if (na->setup) {
604                 error("Refusing connect from %s: setup in progress", address);
605                 goto drop;
606         }
607
608         ns = find_server(na->servers, BNEP_SVC_NAP);
609         if (!ns)
610                 goto drop;
611
612         if (!ns->record_id)
613                 goto drop;
614
615         if (!ns->bridge)
616                 goto drop;
617
618         na->setup = g_new0(struct network_session, 1);
619         bacpy(&na->setup->dst, &dst);
620         na->setup->io = g_io_channel_ref(chan);
621
622         perr = btd_request_authorization(&src, &dst, BNEP_SVC_UUID,
623                                         auth_cb, na);
624         if (perr < 0) {
625                 error("Refusing connect from %s: %s (%d)", address,
626                                 strerror(-perr), -perr);
627                 setup_destroy(na);
628                 goto drop;
629         }
630
631         return;
632
633 drop:
634         g_io_channel_shutdown(chan, TRUE, NULL);
635 }
636
637 int server_init(DBusConnection *conn, gboolean secure)
638 {
639         security = secure;
640         connection = dbus_connection_ref(conn);
641
642         return 0;
643 }
644
645 void server_exit(void)
646 {
647         dbus_connection_unref(connection);
648         connection = NULL;
649 }
650
651 static uint32_t register_server_record(struct network_server *ns)
652 {
653         sdp_record_t *record;
654
655         record = server_record_new(ns->name, ns->id);
656         if (!record) {
657                 error("Unable to allocate new service record");
658                 return 0;
659         }
660
661         if (add_record_to_server(&ns->src, record) < 0) {
662                 error("Failed to register service record");
663                 sdp_record_free(record);
664                 return 0;
665         }
666
667         DBG("got record id 0x%x", record->handle);
668
669         return record->handle;
670 }
671
672 static void server_disconnect(DBusConnection *conn, void *user_data)
673 {
674         struct network_server *ns = user_data;
675
676         ns->watch_id = 0;
677
678         if (ns->record_id) {
679                 remove_record_from_server(ns->record_id);
680                 ns->record_id = 0;
681         }
682
683         g_free(ns->bridge);
684         ns->bridge = NULL;
685 }
686
687 static DBusMessage *register_server(DBusConnection *conn,
688                                 DBusMessage *msg, void *data)
689 {
690         struct network_server *ns = data;
691         DBusMessage *reply;
692         const char *uuid, *bridge;
693
694         if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
695                                 DBUS_TYPE_STRING, &bridge, DBUS_TYPE_INVALID))
696                 return NULL;
697
698         if (g_strcmp0(uuid, "nap"))
699                 return btd_error_failed(msg, "Invalid UUID");
700
701         if (ns->record_id)
702                 return btd_error_already_exists(msg);
703
704         reply = dbus_message_new_method_return(msg);
705         if (!reply)
706                 return NULL;
707
708         ns->record_id = register_server_record(ns);
709         if (!ns->record_id)
710                 return btd_error_failed(msg, "SDP record registration failed");
711
712         g_free(ns->bridge);
713         ns->bridge = g_strdup(bridge);
714
715 #ifndef  __TIZEN_PATCH__
716         ns->watch_id = g_dbus_add_disconnect_watch(conn,
717                                         dbus_message_get_sender(msg),
718                                         server_disconnect, ns, NULL);
719 #endif
720
721         return reply;
722 }
723
724 static DBusMessage *unregister_server(DBusConnection *conn,
725                                         DBusMessage *msg, void *data)
726 {
727         struct network_server *ns = data;
728         DBusMessage *reply;
729         const char *uuid;
730
731         if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid,
732                                                         DBUS_TYPE_INVALID))
733                 return NULL;
734
735         if (g_strcmp0(uuid, "nap"))
736                 return btd_error_failed(msg, "Invalid UUID");
737
738         reply = dbus_message_new_method_return(msg);
739         if (!reply)
740                 return NULL;
741
742         g_dbus_remove_watch(conn, ns->watch_id);
743
744         server_disconnect(conn, ns);
745
746 #ifdef  __TIZEN_PATCH__
747         /* Down the bnep interface, and disconnect all connection */
748         bnep_kill_all_connections();
749         bnep_if_down(ns->dev);
750
751         if (ns->sessions) {
752                 g_slist_foreach(ns->sessions, (GFunc) session_free, NULL);
753                 g_slist_free(ns->sessions);
754                 ns->sessions = NULL;
755         }
756 #endif
757         return reply;
758 }
759
760 static void adapter_free(struct network_adapter *na)
761 {
762         if (na->io != NULL) {
763                 g_io_channel_shutdown(na->io, TRUE, NULL);
764                 g_io_channel_unref(na->io);
765         }
766
767         setup_destroy(na);
768         btd_adapter_unref(na->adapter);
769         g_free(na);
770 }
771
772 static void server_free(struct network_server *ns)
773 {
774         if (!ns)
775                 return;
776
777         /* FIXME: Missing release/free all bnepX interfaces */
778         if (ns->record_id)
779                 remove_record_from_server(ns->record_id);
780
781         g_free(ns->iface);
782         g_free(ns->name);
783         g_free(ns->bridge);
784
785         g_slist_free_full(ns->sessions, session_free);
786
787         g_free(ns);
788 }
789
790 static void path_unregister(void *data)
791 {
792         struct network_server *ns = data;
793         struct network_adapter *na = ns->na;
794
795         DBG("Unregistered interface %s on path %s",
796                 ns->iface, adapter_get_path(na->adapter));
797
798         na->servers = g_slist_remove(na->servers, ns);
799         server_free(ns);
800
801         if (na->servers)
802                 return;
803
804         adapters = g_slist_remove(adapters, na);
805         adapter_free(na);
806 }
807
808 static const GDBusMethodTable server_methods[] = {
809         { GDBUS_METHOD("Register",
810                         GDBUS_ARGS({ "uuid", "s" }, { "bridge", "s" }), NULL,
811                         register_server) },
812         { GDBUS_METHOD("Unregister",
813                         GDBUS_ARGS({ "uuid", "s" }), NULL,
814                         unregister_server) },
815         { }
816 };
817
818 #ifdef  __TIZEN_PATCH__
819 static GDBusSignalTable server_signals[] = {
820         { GDBUS_SIGNAL("PeerConnected",
821                         GDBUS_ARGS({ "device", "s" }, { "address", "s" })) },
822         { GDBUS_SIGNAL("PeerDisconnected",
823                         GDBUS_ARGS({ "device", "s" }, { "address", "s" })) },
824         { }
825 };
826 #endif
827 static struct network_adapter *create_adapter(struct btd_adapter *adapter)
828 {
829         struct network_adapter *na;
830         GError *err = NULL;
831         bdaddr_t src;
832
833         na = g_new0(struct network_adapter, 1);
834         na->adapter = btd_adapter_ref(adapter);
835
836         adapter_get_address(adapter, &src);
837
838         na->io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event, na,
839                                 NULL, &err,
840                                 BT_IO_OPT_SOURCE_BDADDR, &src,
841                                 BT_IO_OPT_PSM, BNEP_PSM,
842                                 BT_IO_OPT_OMTU, BNEP_MTU,
843                                 BT_IO_OPT_IMTU, BNEP_MTU,
844                                 BT_IO_OPT_SEC_LEVEL,
845                                 security ? BT_IO_SEC_MEDIUM : BT_IO_SEC_LOW,
846                                 BT_IO_OPT_INVALID);
847         if (!na->io) {
848                 error("%s", err->message);
849                 g_error_free(err);
850                 adapter_free(na);
851                 return NULL;
852         }
853
854         return na;
855 }
856
857 int server_register(struct btd_adapter *adapter)
858 {
859         struct network_adapter *na;
860         struct network_server *ns;
861         const char *path;
862
863         na = find_adapter(adapters, adapter);
864         if (!na) {
865                 na = create_adapter(adapter);
866                 if (!na)
867                         return -EINVAL;
868                 adapters = g_slist_append(adapters, na);
869         }
870
871         ns = find_server(na->servers, BNEP_SVC_NAP);
872         if (ns)
873                 return 0;
874
875         ns = g_new0(struct network_server, 1);
876
877         ns->iface = g_strdup(NETWORK_SERVER_INTERFACE);
878         ns->name = g_strdup("Network service");
879
880         path = adapter_get_path(adapter);
881
882 #ifndef  __TIZEN_PATCH__
883         if (!g_dbus_register_interface(connection, path, ns->iface,
884                                         server_methods, NULL, NULL,
885                                         ns, path_unregister)) {
886                 error("D-Bus failed to register %s interface",
887                                 ns->iface);
888                 server_free(ns);
889                 return -1;
890         }
891 #else
892         if (!g_dbus_register_interface(connection, path, ns->iface,
893                                         server_methods, server_signals, NULL,
894                                         ns, path_unregister)) {
895                 error("D-Bus failed to register %s interface",
896                                 ns->iface);
897                 server_free(ns);
898                 return -1;
899         }
900 #endif
901
902         adapter_get_address(adapter, &ns->src);
903         ns->id = BNEP_SVC_NAP;
904         ns->na = na;
905         ns->record_id = 0;
906         na->servers = g_slist_append(na->servers, ns);
907
908         DBG("Registered interface %s on path %s", ns->iface, path);
909
910         return 0;
911 }
912
913 int server_unregister(struct btd_adapter *adapter)
914 {
915         struct network_adapter *na;
916         struct network_server *ns;
917         uint16_t id = BNEP_SVC_NAP;
918
919         na = find_adapter(adapters, adapter);
920         if (!na)
921                 return -EINVAL;
922
923         ns = find_server(na->servers, id);
924         if (!ns)
925                 return -EINVAL;
926
927         g_dbus_unregister_interface(connection, adapter_get_path(adapter),
928                                         ns->iface);
929
930         return 0;
931 }