PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/bridge/bridge.c

https://github.com/xrg/misdnuser
C | 957 lines | 771 code | 93 blank | 93 comment | 102 complexity | 7efb38afdbc41f1c54af2cc6cd5d774e MD5 | raw file
Possible License(s): LGPL-2.0
  1. /*****************************************************************************\
  2. ** **
  3. ** isdnbridge **
  4. ** **
  5. **---------------------------------------------------------------------------**
  6. ** Copyright: Andreas Eversberg (GPL) **
  7. ** **
  8. ** user space utility to bridge two mISDN ports. **
  9. ** **
  10. \*****************************************************************************/
  11. #include <stdio.h>
  12. #include <signal.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. //#include <poll.h>
  17. #include <errno.h>
  18. //#include <sys/ioctl.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <fcntl.h>
  22. #include <mISDNlib.h>
  23. #define ISDN_PID_L4_B_USER 0x440000ff
  24. /* used for udevice */
  25. int entity = 0;
  26. /* the device handler and port list */
  27. int mISDNdevice = -1;
  28. int portcount = 0; /* counts all open ports for finding pair */
  29. /* quit flag */
  30. int quit = 0;
  31. /* option stuff */
  32. int nooutput = 0;
  33. int traffic = 0;
  34. int debug = 0;
  35. pid_t dsp_pid = 0;
  36. /* mISDN port structure list */
  37. struct mISDNport {
  38. struct mISDNport *next, *prev;
  39. int count; /* port count */
  40. int portnum; /* port number */
  41. int l1link; /* if l1 is available (only works with nt-mode) */
  42. time_t l1establish; /* time until establishing after link failure */
  43. int ntmode; /* is TRUE if port is nt mode */
  44. int pri; /* is TRUE if port is a primary rate interface */
  45. int upper_id; /* id to transfer data down */
  46. int lower_id; /* id to transfer data up */
  47. int d_stid;
  48. int b_num; /* number of ports */
  49. int b_stid[256];
  50. int b_addr[256];
  51. int b_state[256]; /* state 0 = IDLE */
  52. unsigned char que_frm[2048]; /* queue while layer 1 is down */
  53. int que_len;
  54. };
  55. struct mISDNport *mISDNport_first = NULL;
  56. enum { B_STATE_IDLE, B_STATE_ACTIVATING, B_STATE_ACTIVE, B_STATE_DEACTIVATING };
  57. /*
  58. * show state
  59. */
  60. static void show_state(struct mISDNport *m1)
  61. {
  62. struct mISDNport *m2 = m1;
  63. if (nooutput)
  64. return;
  65. if (m1->count & 1)
  66. m1 = m1->prev;
  67. else
  68. m2 = m2->next;
  69. printf("Port %2d %s <-> Port %2d %s\n", m1->portnum, (m1->l1link)?"ACTIVE":"inactive", m2->portnum, (m2->l1link)?"ACTIVE":"inactive");
  70. }
  71. /*
  72. * show traffic
  73. */
  74. static void show_traffic(struct mISDNport *m1, unsigned char *data, int len)
  75. {
  76. struct mISDNport *m2 = m1;
  77. int right, i;
  78. if (nooutput)
  79. return;
  80. if (m1->count & 1)
  81. {
  82. m1 = m1->prev;
  83. right = 0;
  84. } else
  85. {
  86. m2 = m2->next;
  87. right = 1;
  88. }
  89. printf("Port %2d %s Port %2d :", m1->portnum, right?"-->":"<--", m2->portnum);
  90. i = 0;
  91. while(i < len)
  92. {
  93. printf(" %02x", data[i]);
  94. i++;
  95. }
  96. printf("\n");
  97. }
  98. /*
  99. * debug output
  100. */
  101. #define PDEBUG(fmt, arg...) _printdebug(__FUNCTION__, __LINE__, fmt, ## arg)
  102. static void _printdebug(const char *function, int line, const char *fmt, ...)
  103. {
  104. char buffer[4096];
  105. va_list args;
  106. if (!debug || nooutput)
  107. return;
  108. va_start(args,fmt);
  109. vsnprintf(buffer, sizeof(buffer)-1, fmt, args);
  110. buffer[sizeof(buffer)-1]=0;
  111. va_end(args);
  112. printf("%s, line %d: %s", function, line, buffer);
  113. }
  114. /*
  115. * signal handler to interrupt main loop
  116. */
  117. static void sighandler(int sigset)
  118. {
  119. if (sigset == SIGHUP)
  120. return;
  121. if (sigset == SIGPIPE)
  122. return;
  123. fprintf(stderr, "Signal received: %d\n", sigset);
  124. if (!quit)
  125. quit = 1;
  126. }
  127. /*
  128. * send control information to the channel (dsp-module)
  129. */
  130. static void ph_control(unsigned long b_addr, int c1, int c2)
  131. {
  132. unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
  133. iframe_t *ctrl = (iframe_t *)buffer;
  134. unsigned long *d = (unsigned long *)&ctrl->data.p;
  135. ctrl->prim = PH_CONTROL | REQUEST;
  136. ctrl->addr = b_addr | FLG_MSG_DOWN;
  137. ctrl->dinfo = 0;
  138. ctrl->len = sizeof(unsigned long)*2;
  139. *d++ = c1;
  140. *d++ = c2;
  141. mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
  142. }
  143. void ph_control_block(unsigned long b_addr, int c1, void *c2, int c2_len)
  144. {
  145. unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
  146. iframe_t *ctrl = (iframe_t *)buffer;
  147. unsigned long *d = (unsigned long *)&ctrl->data.p;
  148. ctrl->prim = PH_CONTROL | REQUEST;
  149. ctrl->addr = b_addr | FLG_MSG_DOWN;
  150. ctrl->dinfo = 0;
  151. ctrl->len = sizeof(unsigned long)*2;
  152. *d++ = c1;
  153. memcpy(d, c2, c2_len);
  154. mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
  155. }
  156. /*
  157. * activate / deactivate bchannel
  158. */
  159. static void bchannel_activate(struct mISDNport *mISDNport, int i)
  160. {
  161. iframe_t act;
  162. /* we must activate if we are deactivated */
  163. if (mISDNport->b_state[i] == B_STATE_IDLE)
  164. {
  165. /* activate bchannel */
  166. PDEBUG("activating bchannel (index %d), because currently idle (address 0x%x).\n", i, mISDNport->b_addr[i]);
  167. act.prim = DL_ESTABLISH | REQUEST;
  168. act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
  169. act.dinfo = 0;
  170. act.len = 0;
  171. mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
  172. mISDNport->b_state[i] = B_STATE_ACTIVATING;
  173. return;
  174. }
  175. /* if we are active, we configure our channel */
  176. if (mISDNport->b_state[i] == B_STATE_ACTIVE)
  177. {
  178. /* it is an error if this channel is not associated with a port object */
  179. PDEBUG("during activation, we add conference to %d.\n", ((mISDNport->count&(~1)) << 23) + (i<<16) + dsp_pid);
  180. ph_control(mISDNport->b_addr[i], CMX_CONF_JOIN, ((mISDNport->count&(~1)) << 23) + (i<<16) + dsp_pid);
  181. PDEBUG("during activation, we set rxoff.\n");
  182. ph_control(mISDNport->b_addr[i], CMX_RECEIVE_OFF, 0);
  183. #if 0
  184. if (sadks->crypt)
  185. {
  186. PDEBUG("during activation, we set crypt to crypt=%d.\n", mISDNport->b_port[i]->p_m_crypt);
  187. ph_control_block(mISDNport->b_addr[i], BF_ENABLE_KEY, mISDNport->b_port[i]->p_m_crypt_key, mISDNport->b_port[i]->p_m_crypt_key_len);
  188. }
  189. #endif
  190. }
  191. }
  192. static void bchannel_deactivate(struct mISDNport *mISDNport, int i)
  193. {
  194. iframe_t dact;
  195. if (mISDNport->b_state[i] == B_STATE_ACTIVE)
  196. {
  197. ph_control(mISDNport->b_addr[i], CMX_CONF_SPLIT, 0);
  198. ph_control(mISDNport->b_addr[i], CMX_RECEIVE_ON, 0);
  199. /* deactivate bchannel */
  200. PDEBUG("deactivating bchannel (index %d), because currently active.\n", i);
  201. dact.prim = DL_RELEASE | REQUEST;
  202. dact.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
  203. dact.dinfo = 0;
  204. dact.len = 0;
  205. mISDN_write(mISDNdevice, &dact, mISDN_HEADER_LEN+dact.len, TIMEOUT_1SEC);
  206. mISDNport->b_state[i] = B_STATE_DEACTIVATING;
  207. return;
  208. }
  209. }
  210. /*
  211. * main loop for processing messages from mISDN device
  212. */
  213. int mISDN_handler(void)
  214. {
  215. iframe_t *frm;
  216. struct mISDNport *mISDNport;
  217. int i;
  218. unsigned char data[2048];
  219. int len;
  220. /* get message from kernel */
  221. len = mISDN_read(mISDNdevice, data, sizeof(data), 0);
  222. if (len < 0)
  223. {
  224. if (errno == EAGAIN)
  225. return(0);
  226. fprintf(stderr, "FATAL ERROR: failed to do mISDN_read()\n");
  227. exit(-1);
  228. }
  229. if (!len)
  230. {
  231. return(0);
  232. }
  233. frm = (iframe_t *)data;
  234. /* global prim */
  235. switch(frm->prim)
  236. {
  237. case MGR_INITTIMER | CONFIRM:
  238. case MGR_ADDTIMER | CONFIRM:
  239. case MGR_DELTIMER | CONFIRM:
  240. case MGR_REMOVETIMER | CONFIRM:
  241. return(1);
  242. }
  243. /* find the port */
  244. mISDNport = mISDNport_first;
  245. while(mISDNport)
  246. {
  247. if ((frm->addr&STACK_ID_MASK) == (unsigned int)(mISDNport->upper_id&STACK_ID_MASK))
  248. {
  249. /* d-message */
  250. switch(frm->prim)
  251. {
  252. case MGR_SHORTSTATUS | INDICATION:
  253. case MGR_SHORTSTATUS | CONFIRM:
  254. switch(frm->dinfo) {
  255. case SSTATUS_L1_ACTIVATED:
  256. PDEBUG("Received SSTATUS_L1_ACTIVATED for port %d.\n", mISDNport->portnum);
  257. goto ss_act;
  258. case SSTATUS_L1_DEACTIVATED:
  259. PDEBUG("Received SSTATUS_L1_DEACTIVATED for port %d.\n", mISDNport->portnum);
  260. goto ss_deact;
  261. }
  262. break;
  263. case PH_ACTIVATE | CONFIRM:
  264. case PH_ACTIVATE | INDICATION:
  265. PDEBUG("Received PH_ACTIVATE for port %d.\n", mISDNport->portnum);
  266. ss_act:
  267. if (!mISDNport->l1link)
  268. {
  269. mISDNport->l1link = 1;
  270. show_state(mISDNport);
  271. }
  272. if (mISDNport->que_len)
  273. {
  274. PDEBUG("Data in que, due to inactive link on port %d.\n", mISDNport->portnum);
  275. mISDN_write(mISDNdevice, mISDNport->que_frm, mISDNport->que_len, TIMEOUT_1SEC);
  276. mISDNport->que_len = 0;
  277. }
  278. break;
  279. case PH_DEACTIVATE | CONFIRM:
  280. case PH_DEACTIVATE | INDICATION:
  281. PDEBUG("Received PH_DEACTIVATE for port %d.\n", mISDNport->portnum);
  282. ss_deact:
  283. if (mISDNport->l1link)
  284. {
  285. mISDNport->l1link = 0;
  286. show_state(mISDNport);
  287. }
  288. mISDNport->que_len = 0;
  289. break;
  290. case PH_CONTROL | CONFIRM:
  291. case PH_CONTROL | INDICATION:
  292. PDEBUG("Received PH_CONTROL for port %d.\n", mISDNport->portnum);
  293. break;
  294. case PH_DATA | INDICATION:
  295. if (traffic)
  296. show_traffic(mISDNport, data + mISDN_HEADER_LEN, frm->len);
  297. PDEBUG("GOT data from %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, frm->prim, frm->dinfo, frm->addr);
  298. if (mISDNport->count & 1)
  299. {
  300. if (mISDNport->prev == NULL)
  301. {
  302. printf("soft error, no prev where expected.\n");
  303. exit (0);
  304. }
  305. /* sending to previous port */
  306. frm->prim = PH_DATA | REQUEST;
  307. frm->addr = mISDNport->prev->upper_id | FLG_MSG_DOWN;
  308. PDEBUG("sending to %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (mISDNport->prev->ntmode)?"NT":"TE", mISDNport->prev->portnum, frm->prim, frm->dinfo, frm->addr);
  309. if (mISDNport->prev->l1link)
  310. mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
  311. else {
  312. PDEBUG("layer 1 is down, so we queue and activate link.\n");
  313. memcpy(mISDNport->prev->que_frm, frm, len);
  314. mISDNport->prev->que_len = len;
  315. frm->prim = PH_ACTIVATE | REQUEST;
  316. frm->dinfo = 0;
  317. frm->len = 0;
  318. mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
  319. }
  320. } else {
  321. if (mISDNport->next == NULL)
  322. {
  323. printf("soft error, no next where expected.\n");
  324. exit (0);
  325. }
  326. /* sending to next port */
  327. frm->prim = PH_DATA | REQUEST;
  328. frm->addr = mISDNport->next->upper_id | FLG_MSG_DOWN;
  329. PDEBUG("sending to %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (mISDNport->next->ntmode)?"NT":"TE", mISDNport->next->portnum, frm->prim, frm->dinfo, frm->addr);
  330. if (mISDNport->next->l1link)
  331. mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
  332. else {
  333. PDEBUG("layer 1 is down, so we queue and activate link.\n");
  334. memcpy(mISDNport->next->que_frm, frm, len);
  335. mISDNport->next->que_len = len;
  336. frm->prim = PH_ACTIVATE | REQUEST;
  337. frm->dinfo = 0;
  338. frm->len = 0;
  339. mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
  340. }
  341. }
  342. break;
  343. case PH_DATA | CONFIRM:
  344. //PDEBUG("GOT confirm from %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, frm->prim, frm->dinfo, frm->addr);
  345. break;
  346. case PH_DATA | REQUEST:
  347. PDEBUG("GOT strange PH_DATA REQUEST from %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, frm->prim, frm->dinfo, frm->addr);
  348. break;
  349. default:
  350. break;
  351. }
  352. break;
  353. }
  354. //PDEBUG("flg:%d upper_id=%x addr=%x\n", (frm->addr&FLG_CHILD_STACK), (mISDNport->b_addr[0])&(~IF_CHILDMASK), (frm->addr)&(~IF_CHILDMASK));
  355. /* check if child, and if parent stack match */
  356. if ((frm->addr&FLG_CHILD_STACK) && (((unsigned int)(mISDNport->b_addr[0])&(~CHILD_ID_MASK)&STACK_ID_MASK) == ((frm->addr)&(~CHILD_ID_MASK)&STACK_ID_MASK)))
  357. {
  358. /* b-message */
  359. switch(frm->prim)
  360. {
  361. /* we don't care about confirms, we use rx data to sync tx */
  362. case PH_DATA | CONFIRM:
  363. case DL_DATA | CONFIRM:
  364. break;
  365. /* we receive audio data, we respond to it AND we send tones */
  366. case PH_DATA | INDICATION:
  367. case DL_DATA | INDICATION:
  368. case PH_CONTROL | INDICATION:
  369. i = 0;
  370. while(i < mISDNport->b_num)
  371. {
  372. if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
  373. break;
  374. i++;
  375. }
  376. if (i == mISDNport->b_num)
  377. {
  378. fprintf(stderr, "unhandled b-message (address 0x%x).\n", frm->addr);
  379. break;
  380. }
  381. PDEBUG("got B-channel data, this should not happen all the time. (just a few until cmx release tx-data are ok)\n");
  382. break;
  383. case PH_ACTIVATE | INDICATION:
  384. case DL_ESTABLISH | INDICATION:
  385. case PH_ACTIVATE | CONFIRM:
  386. case DL_ESTABLISH | CONFIRM:
  387. PDEBUG("DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
  388. i = 0;
  389. while(i < mISDNport->b_num)
  390. {
  391. if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
  392. break;
  393. i++;
  394. }
  395. if (i == mISDNport->b_num)
  396. {
  397. fprintf(stderr, "unhandled b-establish (address 0x%x).\n", frm->addr);
  398. break;
  399. }
  400. mISDNport->b_state[i] = B_STATE_ACTIVE;
  401. bchannel_activate(mISDNport, i);
  402. break;
  403. case PH_DEACTIVATE | INDICATION:
  404. case DL_RELEASE | INDICATION:
  405. case PH_DEACTIVATE | CONFIRM:
  406. case DL_RELEASE | CONFIRM:
  407. PDEBUG("DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
  408. i = 0;
  409. while(i < mISDNport->b_num)
  410. {
  411. if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
  412. break;
  413. i++;
  414. }
  415. if (i == mISDNport->b_num)
  416. {
  417. fprintf(stderr, "unhandled b-release (address 0x%x).\n", frm->addr);
  418. break;
  419. }
  420. mISDNport->b_state[i] = B_STATE_IDLE;
  421. break;
  422. }
  423. break;
  424. }
  425. mISDNport = mISDNport->next;
  426. }
  427. if (!mISDNport)
  428. {
  429. if (frm->prim == (MGR_TIMER | INDICATION))
  430. fprintf(stderr, "unhandled timer indication message: prim(0x%x) addr(0x%x) len(%d)\n", frm->prim, frm->addr, len);
  431. else
  432. fprintf(stderr, "unhandled message: prim(0x%x) addr(0x%x) len(%d)\n", frm->prim, frm->addr, len);
  433. }
  434. return(1);
  435. }
  436. /*
  437. * global function to add a new card (port)
  438. */
  439. struct mISDNport *mISDN_port_open(int port)
  440. {
  441. int ret;
  442. unsigned char buff[1025];
  443. iframe_t *frm = (iframe_t *)buff;
  444. stack_info_t *stinf;
  445. struct mISDNport *mISDNport, **mISDNportp, *mISDNport_prev;
  446. int i, cnt;
  447. layer_info_t li;
  448. // interface_info_t ii;
  449. mISDN_pid_t pid;
  450. int pri = 0;
  451. int nt = 0;
  452. iframe_t dact;
  453. /* open mISDNdevice if not already open */
  454. if (mISDNdevice < 0)
  455. {
  456. ret = mISDN_open();
  457. if (ret < 0)
  458. {
  459. fprintf(stderr, "cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
  460. return(0);
  461. }
  462. mISDNdevice = ret;
  463. PDEBUG("mISDN device opened.\n");
  464. /* create entity for layer 3 TE-mode */
  465. mISDN_write_frame(mISDNdevice, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
  466. ret = mISDN_read_frame(mISDNdevice, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
  467. if (ret < (int)mISDN_HEADER_LEN)
  468. {
  469. noentity:
  470. fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
  471. exit(-1);
  472. }
  473. entity = frm->dinfo & 0xffff;
  474. if (!entity)
  475. goto noentity;
  476. PDEBUG("our entity for l3-processes is %d.\n", entity);
  477. }
  478. /* query port's requirements */
  479. cnt = mISDN_get_stack_count(mISDNdevice);
  480. if (cnt <= 0)
  481. {
  482. fprintf(stderr, "Found no card. Please be sure to load card drivers.\n");
  483. return(0);
  484. }
  485. if (port>cnt || port<1)
  486. {
  487. fprintf(stderr, "Port (%d) given is out of existing port range (%d-%d)\n", port, 1, cnt);
  488. return(0);
  489. }
  490. ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
  491. if (ret < 0)
  492. {
  493. fprintf(stderr, "Cannot get stack info for port %d (ret=%d)\n", port, ret);
  494. return(0);
  495. }
  496. stinf = (stack_info_t *)&frm->data.p;
  497. switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
  498. {
  499. case ISDN_PID_L0_TE_S0:
  500. PDEBUG("TE-mode BRI S/T interface line\n");
  501. break;
  502. case ISDN_PID_L0_NT_S0:
  503. PDEBUG("NT-mode BRI S/T interface port\n");
  504. nt = 1;
  505. break;
  506. case ISDN_PID_L0_TE_E1:
  507. PDEBUG("TE-mode PRI E1 interface line\n");
  508. pri = 1;
  509. break;
  510. case ISDN_PID_L0_NT_E1:
  511. PDEBUG("LT-mode PRI E1 interface port\n");
  512. pri = 1;
  513. nt = 1;
  514. break;
  515. default:
  516. fprintf(stderr, "unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
  517. return(0);
  518. }
  519. if (stinf->pid.protocol[1] == 0)
  520. {
  521. fprintf(stderr, "Given port %d: Missing layer 1 protocol.\n", port);
  522. return(0);
  523. }
  524. if (stinf->pid.protocol[2])
  525. {
  526. fprintf(stderr, "Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for bridging layer 1.\n", port, stinf->pid.protocol[2]);
  527. return(0);
  528. }
  529. /* add mISDNport structure */
  530. mISDNport = mISDNport_first;
  531. mISDNportp = &mISDNport_first;
  532. mISDNport_prev = NULL;
  533. while(mISDNport)
  534. {
  535. mISDNport_prev=mISDNport;
  536. mISDNportp = &mISDNport->next;
  537. mISDNport = mISDNport->next;
  538. }
  539. mISDNport = (struct mISDNport *)calloc(1, sizeof(struct mISDNport));
  540. if (!mISDNport)
  541. {
  542. fprintf(stderr, "Cannot alloc mISDNport structure\n");
  543. return(0);
  544. }
  545. memset(mISDNport, 0, sizeof(mISDNport));
  546. *mISDNportp = mISDNport;
  547. mISDNport->prev = mISDNport_prev;
  548. /* allocate ressources of port */
  549. mISDNport->count = portcount++;
  550. mISDNport->portnum = port;
  551. mISDNport->ntmode = nt;
  552. mISDNport->pri = pri;
  553. mISDNport->d_stid = stinf->id;
  554. PDEBUG("d_stid = 0x%x.\n", mISDNport->d_stid);
  555. mISDNport->b_num = stinf->childcnt;
  556. PDEBUG("Port has %d b-channels.\n", mISDNport->b_num);
  557. i = 0;
  558. while(i < stinf->childcnt)
  559. {
  560. mISDNport->b_stid[i] = stinf->child[i];
  561. PDEBUG("b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
  562. i++;
  563. }
  564. memset(&li, 0, sizeof(li));
  565. strcpy(&li.name[0], "bridge l2");
  566. li.object_id = -1;
  567. li.extentions = 0;
  568. li.pid.protocol[2] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L2_LAPD;
  569. li.pid.layermask = ISDN_LAYER(2);
  570. li.st = mISDNport->d_stid;
  571. ret = mISDN_new_layer(mISDNdevice, &li);
  572. if (ret)
  573. {
  574. fprintf(stderr, "Cannot add layer 2 of port %d (ret %d)\n", port, ret);
  575. return(0);
  576. }
  577. mISDNport->upper_id = li.id;
  578. ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
  579. if (ret)
  580. {
  581. fprintf(stderr, "Cannot register layer 2 of port %d\n", port);
  582. return(0);
  583. }
  584. mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, 1);
  585. if (mISDNport->lower_id < 0)
  586. {
  587. fprintf(stderr, "Cannot get layer(1) id of port %d\n", port);
  588. return(0);
  589. }
  590. mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, 2);
  591. if (mISDNport->upper_id < 0)
  592. {
  593. fprintf(stderr, "Cannot get layer(2) id of port %d\n", port);
  594. return(0);
  595. }
  596. PDEBUG("Layer 2 of port %d added.\n", port);
  597. /* try to activate link layer 1 */
  598. {
  599. iframe_t act;
  600. /* L1 */
  601. PDEBUG("sending PH_ACTIVATE to port %d.\n", port);
  602. act.prim = PH_ACTIVATE | REQUEST;
  603. act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
  604. act.dinfo = 0;
  605. act.len = 0;
  606. mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
  607. }
  608. /* initially, we assume that the link is down */
  609. mISDNport->l1link = 0;
  610. PDEBUG("using 'mISDN_dsp.o' module\n");
  611. /* add all bchannel layers */
  612. i = 0;
  613. while(i < mISDNport->b_num)
  614. {
  615. mISDNport->b_state[i] = B_STATE_IDLE;
  616. /* create new layer */
  617. PDEBUG("creating bchannel %d (index %d).\n" , i+1+(i>=15), i);
  618. memset(&li, 0, sizeof(li));
  619. memset(&pid, 0, sizeof(pid));
  620. li.object_id = -1;
  621. li.extentions = 0;
  622. li.st = mISDNport->b_stid[i];
  623. strcpy(li.name, "B L4");
  624. li.pid.layermask = ISDN_LAYER((4));
  625. li.pid.protocol[4] = ISDN_PID_L4_B_USER;
  626. ret = mISDN_new_layer(mISDNdevice, &li);
  627. if (ret)
  628. {
  629. failed_new_layer:
  630. fprintf(stderr, "mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
  631. return(0);
  632. }
  633. mISDNport->b_addr[i] = li.id;
  634. if (!li.id)
  635. {
  636. goto failed_new_layer;
  637. }
  638. PDEBUG("new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
  639. /* create new stack */
  640. pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
  641. pid.protocol[2] = ISDN_PID_L2_B_TRANS;
  642. pid.protocol[3] = ISDN_PID_L3_B_DSP;
  643. pid.protocol[4] = ISDN_PID_L4_B_USER;
  644. pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
  645. ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
  646. if (ret)
  647. {
  648. stack_error:
  649. fprintf(stderr, "mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
  650. mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
  651. mISDNport->b_addr[i] = 0;
  652. return(0);
  653. }
  654. ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
  655. if (ret)
  656. goto stack_error;
  657. /* get layer id */
  658. mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
  659. if (!mISDNport->b_addr[i])
  660. goto stack_error;
  661. /* deactivate bchannel if already enabled due to crash */
  662. PDEBUG("deactivating bchannel (index %d) as a precaution.\n", i);
  663. dact.prim = DL_RELEASE | REQUEST;
  664. dact.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
  665. dact.dinfo = 0;
  666. dact.len = 0;
  667. mISDN_write(mISDNdevice, &dact, mISDN_HEADER_LEN+dact.len, TIMEOUT_1SEC);
  668. i++;
  669. }
  670. PDEBUG("using port %d %s %d b-channels\n", mISDNport->portnum, (mISDNport->ntmode)?"NT-mode":"TE-mode", mISDNport->b_num);
  671. return(mISDNport);
  672. }
  673. /*
  674. * global function to free ALL cards (ports)
  675. */
  676. void mISDN_port_close(void)
  677. {
  678. struct mISDNport *mISDNport, *mISDNporttemp;
  679. unsigned char buf[32];
  680. int i;
  681. /* free all ports */
  682. mISDNport = mISDNport_first;
  683. while(mISDNport)
  684. {
  685. i = 0;
  686. while(i < mISDNport->b_num)
  687. {
  688. bchannel_deactivate(mISDNport, i);
  689. PDEBUG("freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
  690. if (mISDNport->b_stid[i])
  691. {
  692. mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
  693. if (mISDNport->b_addr[i])
  694. mISDN_write_frame(mISDNdevice, buf, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
  695. }
  696. i++;
  697. }
  698. PDEBUG("freeing d-stack.\n");
  699. if (mISDNport->d_stid)
  700. {
  701. // mISDN_clear_stack(mISDNdevice, mISDNport->d_stid);
  702. if (mISDNport->lower_id)
  703. mISDN_write_frame(mISDNdevice, buf, mISDNport->lower_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
  704. }
  705. mISDNporttemp = mISDNport;
  706. mISDNport = mISDNport->next;
  707. memset(mISDNporttemp, 0, sizeof(struct mISDNport));
  708. free(mISDNporttemp);
  709. }
  710. mISDNport_first = NULL;
  711. /* close mISDNdevice */
  712. if (mISDNdevice >= 0)
  713. {
  714. /* free entity */
  715. mISDN_write_frame(mISDNdevice, buf, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
  716. /* close device */
  717. mISDN_close(mISDNdevice);
  718. mISDNdevice = -1;
  719. PDEBUG("mISDN device closed.\n");
  720. }
  721. }
  722. /*
  723. * main routine and loop
  724. */
  725. int main(int argc, char *argv[])
  726. {
  727. struct mISDNport *mISDNport_a, *mISDNport_b;
  728. int i, j;
  729. int forking = 0;
  730. if (argc <= 1)
  731. {
  732. usage:
  733. printf("Usage: %s [--<option> [...]] <port a> <port b> [<port a> <port b> [...]]\n\n", argv[0]);
  734. printf("Bridges given pairs of ports. The number of given ports must be even.\n");
  735. printf("Each pair of ports must be the same interface size (equal channel number).\n");
  736. printf("Both ports may have same mode, e.g. TE-mode, to bridge ISDN to leased line.\n");
  737. printf("Also bridging a card to ISDN over IP tunnel is possible. (L1oIP)\n");
  738. printf("Note: Ports must have layer 1 only, so layermask must be 0x3 to make it work.\n");
  739. printf("--fork will make a daemon fork.\n");
  740. printf("--traffic will show D-channel traffic.\n");
  741. printf("--debug will show debug info.\n");
  742. return(0);
  743. }
  744. if (strstr("help", argv[1]))
  745. goto usage;
  746. /* open mISDN */
  747. i = 1;
  748. while (i < argc)
  749. {
  750. usleep(200000);
  751. if (!strcmp(argv[i], "--traffic"))
  752. {
  753. traffic = 1;
  754. i++;
  755. continue;
  756. }
  757. if (!strcmp(argv[i], "--fork"))
  758. {
  759. forking = 1;
  760. i++;
  761. continue;
  762. }
  763. if (!strcmp(argv[i], "--debug"))
  764. {
  765. debug = 1;
  766. i++;
  767. continue;
  768. }
  769. /* open port a */
  770. mISDNport_a = mISDN_port_open(strtol(argv[i], NULL, 0));
  771. if (!mISDNport_a)
  772. goto error;
  773. printf("port A: #%d %s, %d b-channels\n", mISDNport_a->portnum, (mISDNport_a->ntmode)?"NT-mode":"TE-mode", mISDNport_a->b_num);
  774. i++; // two ports at the same time
  775. if (i == argc)
  776. {
  777. fprintf(stderr, "The number of ports given are not even.\nYou may only bridge two or more pairs of ports.\n\n");
  778. goto error;
  779. }
  780. mISDNport_b = mISDN_port_open(strtol(argv[i], NULL, 0));
  781. if (!mISDNport_b)
  782. goto error;
  783. /* open port b */
  784. printf("port B: #%d %s, %d b-channels\n", mISDNport_b->portnum, (mISDNport_b->ntmode)?"NT-mode":"TE-mode", mISDNport_b->b_num);
  785. i++; // two ports at the same time
  786. if (mISDNport_a->b_num != mISDNport_b->b_num)
  787. {
  788. fprintf(stderr, "The pair of ports are not compatible for bridging.\n");
  789. fprintf(stderr, "The number ob B-channels are different: port(%d)=%d, port(%d)=%d\n", mISDNport_a->portnum, mISDNport_a->b_num, mISDNport_b->portnum, mISDNport_b->b_num);
  790. mISDN_port_close();
  791. goto error;
  792. }
  793. /* opening and bridge each pair of bchannels */
  794. j = 0;
  795. while(j < mISDNport_a->b_num)
  796. {
  797. bchannel_activate(mISDNport_a, j);
  798. while(mISDN_handler())
  799. ;
  800. j++;
  801. }
  802. j = 0;
  803. while(j < mISDNport_b->b_num)
  804. {
  805. bchannel_activate(mISDNport_b, j);
  806. while(mISDN_handler())
  807. ;
  808. j++;
  809. }
  810. }
  811. printf("%s now started\n",argv[0]);
  812. /* forking */
  813. if (forking) {
  814. pid_t pid;
  815. /* do daemon fork */
  816. pid = fork();
  817. if (pid < 0)
  818. {
  819. fprintf(stderr, "Cannot fork!\n");
  820. goto free;
  821. }
  822. if (pid != 0)
  823. {
  824. exit(0);
  825. }
  826. usleep(200000);
  827. printf("\n");
  828. /* do second fork */
  829. pid = fork();
  830. if (pid < 0)
  831. {
  832. fprintf(stderr, "Cannot fork!\n");
  833. goto free;
  834. }
  835. if (pid != 0)
  836. {
  837. printf("%s: Starting daemon.\n", argv[0]);
  838. exit(0);
  839. }
  840. nooutput = 1;
  841. }
  842. dsp_pid = getpid();
  843. /* signal handlers */
  844. signal(SIGINT,sighandler);
  845. signal(SIGHUP,sighandler);
  846. signal(SIGTERM,sighandler);
  847. signal(SIGPIPE,sighandler);
  848. while(!quit)
  849. {
  850. //mISDNport_a->l1link = 1;
  851. if (!mISDN_handler())
  852. usleep(30000);
  853. }
  854. /* remove signal handler */
  855. signal(SIGINT,SIG_DFL);
  856. signal(SIGHUP,SIG_DFL);
  857. signal(SIGTERM,SIG_DFL);
  858. signal(SIGPIPE,SIG_DFL);
  859. free:
  860. mISDN_port_close();
  861. return(0);
  862. error:
  863. return(-1);
  864. }