bneptest.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2015 Intel Corporation
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <signal.h>
  16. #include <stdlib.h>
  17. #include <getopt.h>
  18. #include <stdbool.h>
  19. #include <errno.h>
  20. #include <unistd.h>
  21. #include <sys/ioctl.h>
  22. #include <net/if.h>
  23. #include <linux/sockios.h>
  24. #include <netinet/in.h>
  25. #include <linux/if_bridge.h>
  26. #include <glib.h>
  27. #include "lib/bluetooth.h"
  28. #include "lib/hci.h"
  29. #include "lib/hci_lib.h"
  30. #include "src/log.h"
  31. #include "src/shared/util.h"
  32. #include "btio/btio.h"
  33. #include "lib/bnep.h"
  34. #include "profiles/network/bnep.h"
  35. enum {
  36. MODE_LISTEN,
  37. MODE_CONNECT,
  38. };
  39. static GMainLoop *mloop;
  40. static GIOChannel *bnep_io;
  41. static struct bnep *session;
  42. static int mode;
  43. static bool no_close_after_disconn;
  44. static int send_frame_timeout;
  45. static bdaddr_t src_addr, dst_addr;
  46. static char iface[16];
  47. static char bridge[16];
  48. static bool send_ctrl_msg_type_set = false;
  49. static uint8_t ctrl_msg_type = 0x00;
  50. static bool send_bnep_msg_type_set = false;
  51. static uint8_t bnep_msg_type = 0x00;
  52. static int ctrl_msg_retransmition_nb = 0;
  53. static int bnep_msg_retransmission_nb = 0;
  54. static uint16_t local_role = BNEP_SVC_PANU;
  55. static uint16_t remote_role = BNEP_SVC_NAP;
  56. static uint16_t ntw_proto_down_range = 0x0000;
  57. static uint16_t ntw_proto_up_range = 0xdc05;
  58. static uint16_t ntw_proto_type = 0x0000;
  59. static uint8_t mcast_addr_down_range[6];
  60. static uint8_t mcast_addr_up_range[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  61. static uint8_t src_hw_addr[6];
  62. static uint8_t dst_hw_addr[6];
  63. static uint8_t general_frame_payload[] = "abcdef0123456789_bnep_test_data";
  64. static int set_forward_delay(int sk)
  65. {
  66. unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0, 0, 0 };
  67. struct ifreq ifr;
  68. memset(&ifr, 0, sizeof(ifr));
  69. strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
  70. ifr.ifr_data = (char *) args;
  71. if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
  72. error("setting forward delay failed: %d (%s)",
  73. errno, strerror(errno));
  74. return -1;
  75. }
  76. return 0;
  77. }
  78. static int nap_create_bridge(void)
  79. {
  80. int sk, err;
  81. sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
  82. if (sk < 0)
  83. return -EOPNOTSUPP;
  84. if (ioctl(sk, SIOCBRADDBR, bridge) < 0) {
  85. if (errno != EEXIST) {
  86. close(sk);
  87. return -EOPNOTSUPP;
  88. }
  89. }
  90. err = set_forward_delay(sk);
  91. if (err < 0) {
  92. printf("failed to set forward delay\n");
  93. ioctl(sk, SIOCBRDELBR, bridge);
  94. }
  95. close(sk);
  96. return err;
  97. }
  98. static int cleanup(void)
  99. {
  100. bnep_cleanup();
  101. if (mode == MODE_LISTEN)
  102. bnep_server_delete(bridge, iface, &dst_addr);
  103. if (bnep_io) {
  104. g_io_channel_shutdown(bnep_io, TRUE, NULL);
  105. g_io_channel_unref(bnep_io);
  106. bnep_io = NULL;
  107. }
  108. return 0;
  109. }
  110. static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
  111. gpointer user_data)
  112. {
  113. printf("%s\n", __func__);
  114. if (no_close_after_disconn)
  115. return FALSE;
  116. /* Cleanup since it's called when disconnected l2cap */
  117. if (cleanup() < 0) {
  118. printf("cleanup went wrong...\n");
  119. return FALSE;
  120. }
  121. g_main_loop_quit(mloop);
  122. return FALSE;
  123. }
  124. static ssize_t send_compressed_frame(int sk, uint8_t type)
  125. {
  126. uint8_t frame[100];
  127. printf("%s\n", __func__);
  128. if (send_frame_timeout > 0) {
  129. printf("waiting %d seconds before sending msg\n",
  130. send_frame_timeout);
  131. sleep(send_frame_timeout);
  132. }
  133. frame[0] = type;
  134. memcpy(&frame[1], dst_hw_addr, sizeof(dst_hw_addr));
  135. memcpy(&frame[7], src_hw_addr, sizeof(src_hw_addr));
  136. frame[13] = ntw_proto_type & 0xff;
  137. frame[14] = (ntw_proto_type >> 8);
  138. memcpy(&frame[15], general_frame_payload,
  139. sizeof(general_frame_payload));
  140. /* TODO - set frame payload by user */
  141. return send(sk, frame, 15 + sizeof(general_frame_payload), 0);
  142. }
  143. static ssize_t send_general_frame(int sk)
  144. {
  145. uint8_t frame[100];
  146. printf("%s\n", __func__);
  147. if (send_frame_timeout > 0) {
  148. printf("waiting %d seconds before sending msg\n",
  149. send_frame_timeout);
  150. sleep(send_frame_timeout);
  151. }
  152. frame[0] = BNEP_GENERAL;
  153. memcpy(&frame[1], dst_hw_addr, sizeof(dst_hw_addr));
  154. memcpy(&frame[7], src_hw_addr, sizeof(src_hw_addr));
  155. frame[13] = ntw_proto_type & 0xff;
  156. frame[14] = (ntw_proto_type >> 8);
  157. memcpy(&frame[15], general_frame_payload,
  158. sizeof(general_frame_payload));
  159. /* TODO - set frame payload by user */
  160. return send(sk, frame, 15 + sizeof(general_frame_payload), 0);
  161. }
  162. static ssize_t send_ctrl_frame(int sk)
  163. {
  164. /*
  165. * Max buff size = type(1byte) + ctrl(1byte) + len(2byte) +
  166. * mcast_addr_down(6byte) + mcast_addr_up(6byte)
  167. */
  168. uint8_t buff[16];
  169. struct bnep_set_filter_req *frame = (void *) buff;
  170. int err;
  171. printf("%s\n", __func__);
  172. if (send_frame_timeout > 0) {
  173. printf("waiting %d seconds before sending msg\n",
  174. send_frame_timeout);
  175. sleep(send_frame_timeout);
  176. }
  177. switch (ctrl_msg_type) {
  178. case BNEP_FILTER_NET_TYPE_SET:
  179. frame->type = BNEP_CONTROL;
  180. frame->ctrl = ctrl_msg_type;
  181. frame->len = htons(sizeof(ntw_proto_down_range) +
  182. sizeof(ntw_proto_up_range));
  183. memcpy(frame->list, &ntw_proto_down_range,
  184. sizeof(ntw_proto_down_range));
  185. memcpy(frame->list + sizeof(ntw_proto_down_range),
  186. &ntw_proto_up_range, sizeof(ntw_proto_up_range));
  187. err = send(sk, frame, sizeof(*frame) +
  188. sizeof(ntw_proto_down_range) +
  189. sizeof(ntw_proto_up_range), 0);
  190. break;
  191. case BNEP_FILTER_MULT_ADDR_SET:
  192. frame->type = BNEP_CONTROL;
  193. frame->ctrl = ctrl_msg_type;
  194. frame->len = htons(sizeof(mcast_addr_down_range) +
  195. sizeof(mcast_addr_up_range));
  196. memcpy(frame->list, mcast_addr_down_range,
  197. sizeof(mcast_addr_down_range));
  198. memcpy(frame->list + sizeof(mcast_addr_down_range),
  199. mcast_addr_up_range, sizeof(mcast_addr_up_range));
  200. err = send(sk, frame, sizeof(*frame) +
  201. sizeof(mcast_addr_down_range) +
  202. sizeof(mcast_addr_up_range), 0);
  203. break;
  204. default:
  205. err = -1;
  206. break;
  207. }
  208. return err;
  209. }
  210. static int send_bnep_frame(int sk)
  211. {
  212. int err;
  213. switch (bnep_msg_type) {
  214. case BNEP_GENERAL:
  215. err = send_general_frame(sk);
  216. break;
  217. case BNEP_COMPRESSED:
  218. err = send_compressed_frame(sk, BNEP_COMPRESSED);
  219. break;
  220. case BNEP_COMPRESSED_SRC_ONLY:
  221. err = send_compressed_frame(sk,
  222. BNEP_COMPRESSED_SRC_ONLY);
  223. break;
  224. case BNEP_COMPRESSED_DST_ONLY:
  225. err = send_compressed_frame(sk,
  226. BNEP_COMPRESSED_DST_ONLY);
  227. break;
  228. default:
  229. printf("wrong bnep_msg_type 0x%02x\n", bnep_msg_type);
  230. err = -EINVAL;
  231. break;
  232. }
  233. return err;
  234. }
  235. static void handle_bnep_msg_send(int sk)
  236. {
  237. if (send_ctrl_msg_type_set) {
  238. do {
  239. if (send_ctrl_frame(sk) < 0)
  240. printf("sending ctrl frame error: %s (%d)\n",
  241. strerror(errno), errno);
  242. } while (ctrl_msg_retransmition_nb--);
  243. }
  244. if (send_bnep_msg_type_set) {
  245. do {
  246. if (send_bnep_frame(sk) < 0)
  247. printf("sending bnep frame error: %s (%d)\n",
  248. strerror(errno), errno);
  249. } while (bnep_msg_retransmission_nb--);
  250. }
  251. }
  252. static gboolean setup_bnep_cb(GIOChannel *chan, GIOCondition cond,
  253. gpointer user_data)
  254. {
  255. uint8_t packet[BNEP_MTU];
  256. int sk, n, err;
  257. printf("%s\n", __func__);
  258. if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
  259. error("hangup or error or inval on BNEP socket");
  260. return FALSE;
  261. }
  262. sk = g_io_channel_unix_get_fd(chan);
  263. /* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
  264. n = recv(sk, packet, sizeof(packet), MSG_PEEK);
  265. if (n < 0) {
  266. error("read(): %s(%d)", strerror(errno), errno);
  267. return FALSE;
  268. }
  269. err = nap_create_bridge();
  270. if (err < 0) {
  271. error("failed to create bridge: %s (%d)", strerror(-err), err);
  272. return FALSE;
  273. }
  274. if (bnep_server_add(sk, (err < 0) ? NULL : bridge, iface, &dst_addr,
  275. packet, n) < 0) {
  276. printf("server_connadd failed\n");
  277. cleanup();
  278. return FALSE;
  279. }
  280. g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL, bnep_watchdog_cb,
  281. NULL);
  282. handle_bnep_msg_send(sk);
  283. g_io_channel_unref(bnep_io);
  284. bnep_io = NULL;
  285. return FALSE;
  286. }
  287. static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
  288. {
  289. printf("%s\n", __func__);
  290. if (err) {
  291. error("%s", err->message);
  292. return;
  293. }
  294. g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  295. setup_bnep_cb, NULL);
  296. }
  297. static void connected_client_cb(char *iface, int err, void *data)
  298. {
  299. int sk = PTR_TO_INT(data);
  300. printf("%s\n", __func__);
  301. handle_bnep_msg_send(sk);
  302. }
  303. static void disconnected_client_cb(void *data)
  304. {
  305. printf("%s\n", __func__);
  306. if (no_close_after_disconn)
  307. return;
  308. /* Cleanup since it's called when disconnected l2cap */
  309. if (cleanup() < 0) {
  310. printf("cleanup went wrong...\n");
  311. return;
  312. }
  313. g_main_loop_quit(mloop);
  314. }
  315. static void connect_client_cb(GIOChannel *chan, GError *err, gpointer user_data)
  316. {
  317. int perr;
  318. int sk;
  319. sk = g_io_channel_unix_get_fd(bnep_io);
  320. session = bnep_new(sk, local_role, remote_role, bridge);
  321. if (!session) {
  322. printf("cannot create bnep session\n");
  323. return;
  324. }
  325. perr = bnep_connect(session, connected_client_cb,
  326. disconnected_client_cb, INT_TO_PTR(sk), NULL);
  327. if (perr < 0)
  328. printf("cannot initiate bnep connection\n");
  329. }
  330. static void confirm_cb(GIOChannel *chan, gpointer data)
  331. {
  332. GError *err = NULL;
  333. char address[18];
  334. printf("%s\n", __func__);
  335. bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst_addr, BT_IO_OPT_DEST,
  336. address, BT_IO_OPT_INVALID);
  337. if (err) {
  338. error("%s", err->message);
  339. g_error_free(err);
  340. return;
  341. }
  342. printf("incoming connection from: %s\n", address);
  343. bnep_io = g_io_channel_ref(chan);
  344. g_io_channel_set_close_on_unref(bnep_io, TRUE);
  345. if (!bt_io_accept(bnep_io, connect_cb, NULL, NULL, &err)) {
  346. error("bt_io_accept: %s", err->message);
  347. g_error_free(err);
  348. g_io_channel_unref(bnep_io);
  349. }
  350. }
  351. static int bnep_server_listen(void)
  352. {
  353. GError *gerr = NULL;
  354. printf("%s\n", __func__);
  355. bnep_io = bt_io_listen(NULL, confirm_cb, NULL, NULL, &gerr,
  356. BT_IO_OPT_SOURCE_BDADDR, &src_addr,
  357. BT_IO_OPT_PSM, BNEP_PSM,
  358. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
  359. BT_IO_OPT_OMTU, BNEP_MTU,
  360. BT_IO_OPT_IMTU, BNEP_MTU,
  361. BT_IO_OPT_INVALID);
  362. if (!bnep_io) {
  363. printf("can't start server listening: err %s\n", gerr->message);
  364. g_error_free(gerr);
  365. return -1;
  366. }
  367. return 0;
  368. }
  369. static int bnep_client_connect(void)
  370. {
  371. GError *gerr = NULL;
  372. char bdastr[18];
  373. printf("%s\n", __func__);
  374. ba2str(&dst_addr, bdastr);
  375. printf("connecting %s\n", bdastr);
  376. bnep_io = bt_io_connect(connect_client_cb, NULL, NULL, &gerr,
  377. BT_IO_OPT_SOURCE_BDADDR, &src_addr,
  378. BT_IO_OPT_DEST_BDADDR, &dst_addr,
  379. BT_IO_OPT_PSM, BNEP_PSM,
  380. BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
  381. BT_IO_OPT_OMTU, BNEP_MTU,
  382. BT_IO_OPT_IMTU, BNEP_MTU,
  383. BT_IO_OPT_INVALID);
  384. if (!bnep_io) {
  385. printf("cannot connect: err %s\n", gerr->message);
  386. g_error_free(gerr);
  387. return -1;
  388. }
  389. return 0;
  390. }
  391. static void exit_handler(int sig)
  392. {
  393. printf("got sig = %d, cleaning up...\n", sig);
  394. if (cleanup() < 0)
  395. printf("cleanup failure...\n");
  396. else
  397. printf("cleanup successful - exit\n");
  398. exit(0);
  399. }
  400. static void usage(void)
  401. {
  402. printf("bneptest - BNEP testing ver %s\n", VERSION);
  403. printf("Usage:\n"
  404. "\tbneptest [-i] -b <bridge name> -n <iface name>"
  405. " <connection mode> [send_ctrl_cmd] [options]\n"
  406. "\t-i hci dev number <hci number>, def. 0\n"
  407. "\t-b bridge name <string>\n"
  408. "\t-n interface name <string>\n");
  409. printf("Connect Mode:\n"
  410. "\t-c connect <dst_addr>\n"
  411. "\t-r remote role <16 bit svc value>\n"
  412. "\t-l local role <16 bit svc valu>\n");
  413. printf("Listen Mode:\n"
  414. "\t-s start server listening\n");
  415. printf("Send control command:\n"
  416. "\t-t send message type <control msg type>, def. 0\n"
  417. "\t-e start network protocol type range <16 bit val>, def. 0\n"
  418. "\t-d end network protocol type range <16 bit val>, def. 1500\n"
  419. "\t-g start multicast addr range <xx:xx:xx:xx:xx:xx>, def. 0\n"
  420. "\t-j end multicast addr range <xx:xx:xx:xx:xx:xx>, def. f\n"
  421. "\t-y number of ctrl frame retransmission <integer>, def. 0\n"
  422. "\t-u number of bnep frame retransmission <integer>, def. 0\n");
  423. printf("Send bnep generic frame:\n"
  424. "\t-w send bnep generic frame <bnep generic type>, def. 0\n"
  425. "\t-k set src mac addr <xx:xx:xx:xx:xx:xx>, def. 0\n"
  426. "\t-f set dst mac addr <xx:xx:xx:xx:xx:xx>, def. 0\n");
  427. printf("Options:\n"
  428. "\t-T send message timeout after setup <seconds>\n"
  429. "\t-N don't close bneptest after disconnect\n");
  430. }
  431. static struct option main_options[] = {
  432. { "device", 1, 0, 'i' },
  433. { "listen", 0, 0, 's' },
  434. { "connect", 1, 0, 'c' },
  435. { "snd_ctrl_msg_type", 1, 0, 't' },
  436. { "snd_bnep_msg_type", 1, 0, 'w' },
  437. { "src_hw_addr", 1, 0, 'k' },
  438. { "dst_hw_addr", 1, 0, 'f' },
  439. { "send_timeout", 1, 0, 'T' },
  440. { "ntw_proto_down_range", 1, 0, 'd' },
  441. { "ntw_proto_up_range", 1, 0, 'e' },
  442. { "mcast_addr_down_range", 1, 0, 'g' },
  443. { "mcast_addr_up_range", 1, 0, 'j' },
  444. { "local_role", 1, 0, 'l' },
  445. { "remote_role", 1, 0, 'r' },
  446. { "bridge name", 1, 0, 'b' },
  447. { "iface name", 1, 0, 'n' },
  448. { "no_close", 0, 0, 'N' },
  449. { "retrans_ctrl_nb", 0, 0, 'y' },
  450. { "retrans_bnep_nb", 0, 0, 'u' },
  451. { "help", 0, 0, 'h' },
  452. { 0, 0, 0, 0 }
  453. };
  454. int main(int argc, char *argv[])
  455. {
  456. int opt, i;
  457. int err;
  458. bool is_set_b_name = false, is_set_i_name = false;
  459. DBG("");
  460. signal(SIGINT, exit_handler);
  461. hci_devba(0, &src_addr);
  462. bacpy(&src_addr, BDADDR_ANY);
  463. mloop = g_main_loop_new(NULL, FALSE);
  464. if (!mloop) {
  465. printf("cannot create main loop\n");
  466. exit(1);
  467. }
  468. while ((opt = getopt_long(argc, argv,
  469. "+i:c:b:n:t:T:d:e:g:j:k:f:w:l:r:y:u:Nsh",
  470. main_options, NULL)) != EOF) {
  471. switch (opt) {
  472. case 'i':
  473. if (!strncmp(optarg, "hci", 3))
  474. hci_devba(atoi(optarg + 3), &src_addr);
  475. else
  476. str2ba(optarg, &src_addr);
  477. break;
  478. case 's':
  479. mode = MODE_LISTEN;
  480. break;
  481. case 'c':
  482. str2ba(optarg, &dst_addr);
  483. mode = MODE_CONNECT;
  484. break;
  485. case 't':
  486. send_ctrl_msg_type_set = true;
  487. ctrl_msg_type = atoi(optarg);
  488. break;
  489. case 'w':
  490. send_bnep_msg_type_set = true;
  491. bnep_msg_type = atoi(optarg);
  492. break;
  493. case 'k':
  494. for (i = 0; i <= 5; i++, optarg += 3)
  495. src_hw_addr[i] = strtol(optarg, NULL, 16);
  496. break;
  497. case 'f':
  498. for (i = 0; i <= 5; i++, optarg += 3)
  499. dst_hw_addr[i] = strtol(optarg, NULL, 16);
  500. break;
  501. case 'T':
  502. send_frame_timeout = atoi(optarg);
  503. break;
  504. case 'd':
  505. ntw_proto_down_range = htons(atoi(optarg));
  506. break;
  507. case 'e':
  508. ntw_proto_up_range = htons(atoi(optarg));
  509. break;
  510. case 'g':
  511. for (i = 5; i >= 0; i--, optarg += 3)
  512. mcast_addr_down_range[i] =
  513. strtol(optarg, NULL, 16);
  514. break;
  515. case 'j':
  516. for (i = 5; i >= 0; i--, optarg += 3)
  517. mcast_addr_up_range[i] =
  518. strtol(optarg, NULL, 16);
  519. break;
  520. case 'l':
  521. local_role = atoi(optarg);
  522. break;
  523. case 'r':
  524. remote_role = atoi(optarg);
  525. break;
  526. case 'b':
  527. strncpy(bridge, optarg, 16);
  528. bridge[15] = '\0';
  529. is_set_b_name = true;
  530. break;
  531. case 'n':
  532. strncpy(iface, optarg, 14);
  533. strcat(iface, "\%d");
  534. iface[15] = '\0';
  535. is_set_i_name = true;
  536. break;
  537. case 'N':
  538. no_close_after_disconn = true;
  539. break;
  540. case 'y':
  541. ctrl_msg_retransmition_nb = atoi(optarg);
  542. break;
  543. case 'u':
  544. bnep_msg_retransmission_nb = atoi(optarg);
  545. break;
  546. case 'h':
  547. default:
  548. usage();
  549. exit(0);
  550. }
  551. }
  552. if (!is_set_b_name || !is_set_i_name) {
  553. printf("bridge, interface name must be set!\n");
  554. exit(1);
  555. }
  556. switch (mode) {
  557. case MODE_CONNECT:
  558. err = bnep_init();
  559. if (err < 0) {
  560. printf("cannot initialize bnep\n");
  561. exit(1);
  562. }
  563. err = bnep_client_connect();
  564. if (err < 0)
  565. exit(1);
  566. break;
  567. case MODE_LISTEN:
  568. err = bnep_init();
  569. if (err < 0) {
  570. printf("cannot initialize bnep\n");
  571. exit(1);
  572. }
  573. err = bnep_server_listen();
  574. if (err < 0)
  575. exit(1);
  576. break;
  577. default:
  578. printf("connect/listen mode not set, exit...\n");
  579. exit(1);
  580. }
  581. g_main_loop_run(mloop);
  582. printf("Done\n");
  583. g_main_loop_unref(mloop);
  584. return 0;
  585. }