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