isdn_divert.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. /* $Id: isdn_divert.c,v 1.6.6.3 2001/09/23 22:24:36 kai Exp $
  2. *
  3. * DSS1 main diversion supplementary handling for i4l.
  4. *
  5. * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de)
  6. *
  7. * This software may be used and distributed according to the terms
  8. * of the GNU General Public License, incorporated herein by reference.
  9. *
  10. */
  11. #include <linux/proc_fs.h>
  12. #include <linux/slab.h>
  13. #include <linux/timer.h>
  14. #include <linux/jiffies.h>
  15. #include "isdn_divert.h"
  16. /**********************************/
  17. /* structure keeping calling info */
  18. /**********************************/
  19. struct call_struc {
  20. isdn_ctrl ics; /* delivered setup + driver parameters */
  21. ulong divert_id; /* Id delivered to user */
  22. unsigned char akt_state; /* actual state */
  23. char deflect_dest[35]; /* deflection destination */
  24. struct timer_list timer; /* timer control structure */
  25. char info[90]; /* device info output */
  26. struct call_struc *next; /* pointer to next entry */
  27. struct call_struc *prev;
  28. };
  29. /********************************************/
  30. /* structure keeping deflection table entry */
  31. /********************************************/
  32. struct deflect_struc {
  33. struct deflect_struc *next, *prev;
  34. divert_rule rule; /* used rule */
  35. };
  36. /*****************************************/
  37. /* variables for main diversion services */
  38. /*****************************************/
  39. /* diversion/deflection processes */
  40. static struct call_struc *divert_head = NULL; /* head of remembered entrys */
  41. static ulong next_id = 1; /* next info id */
  42. static struct deflect_struc *table_head = NULL;
  43. static struct deflect_struc *table_tail = NULL;
  44. static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */
  45. DEFINE_SPINLOCK(divert_lock);
  46. /***************************/
  47. /* timer callback function */
  48. /***************************/
  49. static void deflect_timer_expire(ulong arg)
  50. {
  51. unsigned long flags;
  52. struct call_struc *cs = (struct call_struc *) arg;
  53. spin_lock_irqsave(&divert_lock, flags);
  54. del_timer(&cs->timer); /* delete active timer */
  55. spin_unlock_irqrestore(&divert_lock, flags);
  56. switch (cs->akt_state) {
  57. case DEFLECT_PROCEED:
  58. cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
  59. divert_if.ll_cmd(&cs->ics);
  60. spin_lock_irqsave(&divert_lock, flags);
  61. cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
  62. cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
  63. add_timer(&cs->timer);
  64. spin_unlock_irqrestore(&divert_lock, flags);
  65. break;
  66. case DEFLECT_ALERT:
  67. cs->ics.command = ISDN_CMD_REDIR; /* protocol */
  68. strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone));
  69. strcpy(cs->ics.parm.setup.eazmsn, "Testtext delayed");
  70. divert_if.ll_cmd(&cs->ics);
  71. spin_lock_irqsave(&divert_lock, flags);
  72. cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
  73. cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
  74. add_timer(&cs->timer);
  75. spin_unlock_irqrestore(&divert_lock, flags);
  76. break;
  77. case DEFLECT_AUTODEL:
  78. default:
  79. spin_lock_irqsave(&divert_lock, flags);
  80. if (cs->prev)
  81. cs->prev->next = cs->next; /* forward link */
  82. else
  83. divert_head = cs->next;
  84. if (cs->next)
  85. cs->next->prev = cs->prev; /* back link */
  86. spin_unlock_irqrestore(&divert_lock, flags);
  87. kfree(cs);
  88. return;
  89. } /* switch */
  90. } /* deflect_timer_func */
  91. /*****************************************/
  92. /* handle call forwarding de/activations */
  93. /* 0 = deact, 1 = act, 2 = interrogate */
  94. /*****************************************/
  95. int cf_command(int drvid, int mode,
  96. u_char proc, char *msn,
  97. u_char service, char *fwd_nr, ulong *procid)
  98. {
  99. unsigned long flags;
  100. int retval, msnlen;
  101. int fwd_len;
  102. char *p, *ielenp, tmp[60];
  103. struct call_struc *cs;
  104. if (strchr(msn, '.')) return (-EINVAL); /* subaddress not allowed in msn */
  105. if ((proc & 0x7F) > 2) return (-EINVAL);
  106. proc &= 3;
  107. p = tmp;
  108. *p++ = 0x30; /* enumeration */
  109. ielenp = p++; /* remember total length position */
  110. *p++ = 0xa; /* proc tag */
  111. *p++ = 1; /* length */
  112. *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */
  113. *p++ = 0xa; /* service tag */
  114. *p++ = 1; /* length */
  115. *p++ = service; /* service to handle */
  116. if (mode == 1) {
  117. if (!*fwd_nr) return (-EINVAL); /* destination missing */
  118. if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */
  119. fwd_len = strlen(fwd_nr);
  120. *p++ = 0x30; /* number enumeration */
  121. *p++ = fwd_len + 2; /* complete forward to len */
  122. *p++ = 0x80; /* fwd to nr */
  123. *p++ = fwd_len; /* length of number */
  124. strcpy(p, fwd_nr); /* copy number */
  125. p += fwd_len; /* pointer beyond fwd */
  126. } /* activate */
  127. msnlen = strlen(msn);
  128. *p++ = 0x80; /* msn number */
  129. if (msnlen > 1) {
  130. *p++ = msnlen; /* length */
  131. strcpy(p, msn);
  132. p += msnlen;
  133. } else
  134. *p++ = 0;
  135. *ielenp = p - ielenp - 1; /* set total IE length */
  136. /* allocate mem for information struct */
  137. if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
  138. return (-ENOMEM); /* no memory */
  139. init_timer(&cs->timer);
  140. cs->info[0] = '\0';
  141. cs->timer.function = deflect_timer_expire;
  142. cs->timer.data = (ulong) cs; /* pointer to own structure */
  143. cs->ics.driver = drvid;
  144. cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */
  145. cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */
  146. cs->ics.parm.dss1_io.proc = (mode == 1) ? 7 : (mode == 2) ? 11 : 8; /* operation */
  147. cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */
  148. cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */
  149. cs->ics.parm.dss1_io.data = tmp; /* start of buffer */
  150. spin_lock_irqsave(&divert_lock, flags);
  151. cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */
  152. spin_unlock_irqrestore(&divert_lock, flags);
  153. *procid = cs->ics.parm.dss1_io.ll_id;
  154. sprintf(cs->info, "%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
  155. (!mode) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
  156. cs->ics.parm.dss1_io.ll_id,
  157. (mode != 2) ? "" : "0 ",
  158. divert_if.drv_to_name(cs->ics.driver),
  159. msn,
  160. service & 0xFF,
  161. proc,
  162. (mode != 1) ? "" : " 0 ",
  163. (mode != 1) ? "" : fwd_nr);
  164. retval = divert_if.ll_cmd(&cs->ics); /* execute command */
  165. if (!retval) {
  166. cs->prev = NULL;
  167. spin_lock_irqsave(&divert_lock, flags);
  168. cs->next = divert_head;
  169. divert_head = cs;
  170. spin_unlock_irqrestore(&divert_lock, flags);
  171. } else
  172. kfree(cs);
  173. return (retval);
  174. } /* cf_command */
  175. /****************************************/
  176. /* handle a external deflection command */
  177. /****************************************/
  178. int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
  179. {
  180. struct call_struc *cs;
  181. isdn_ctrl ic;
  182. unsigned long flags;
  183. int i;
  184. if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */
  185. cs = divert_head; /* start of parameter list */
  186. while (cs) {
  187. if (cs->divert_id == callid) break; /* found */
  188. cs = cs->next;
  189. } /* search entry */
  190. if (!cs) return (-EINVAL); /* invalid callid */
  191. ic.driver = cs->ics.driver;
  192. ic.arg = cs->ics.arg;
  193. i = -EINVAL;
  194. if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */
  195. switch (cmd & 0x7F) {
  196. case 0: /* hangup */
  197. del_timer(&cs->timer);
  198. ic.command = ISDN_CMD_HANGUP;
  199. i = divert_if.ll_cmd(&ic);
  200. spin_lock_irqsave(&divert_lock, flags);
  201. cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
  202. cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
  203. add_timer(&cs->timer);
  204. spin_unlock_irqrestore(&divert_lock, flags);
  205. break;
  206. case 1: /* alert */
  207. if (cs->akt_state == DEFLECT_ALERT) return (0);
  208. cmd &= 0x7F; /* never wait */
  209. del_timer(&cs->timer);
  210. ic.command = ISDN_CMD_ALERT;
  211. if ((i = divert_if.ll_cmd(&ic))) {
  212. spin_lock_irqsave(&divert_lock, flags);
  213. cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
  214. cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
  215. add_timer(&cs->timer);
  216. spin_unlock_irqrestore(&divert_lock, flags);
  217. } else
  218. cs->akt_state = DEFLECT_ALERT;
  219. break;
  220. case 2: /* redir */
  221. del_timer(&cs->timer);
  222. strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone));
  223. strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
  224. ic.command = ISDN_CMD_REDIR;
  225. if ((i = divert_if.ll_cmd(&ic))) {
  226. spin_lock_irqsave(&divert_lock, flags);
  227. cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
  228. cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
  229. add_timer(&cs->timer);
  230. spin_unlock_irqrestore(&divert_lock, flags);
  231. } else
  232. cs->akt_state = DEFLECT_ALERT;
  233. break;
  234. } /* switch */
  235. return (i);
  236. } /* deflect_extern_action */
  237. /********************************/
  238. /* insert a new rule before idx */
  239. /********************************/
  240. int insertrule(int idx, divert_rule *newrule)
  241. {
  242. struct deflect_struc *ds, *ds1 = NULL;
  243. unsigned long flags;
  244. if (!(ds = kmalloc(sizeof(struct deflect_struc), GFP_KERNEL)))
  245. return (-ENOMEM); /* no memory */
  246. ds->rule = *newrule; /* set rule */
  247. spin_lock_irqsave(&divert_lock, flags);
  248. if (idx >= 0) {
  249. ds1 = table_head;
  250. while ((ds1) && (idx > 0))
  251. { idx--;
  252. ds1 = ds1->next;
  253. }
  254. if (!ds1) idx = -1;
  255. }
  256. if (idx < 0) {
  257. ds->prev = table_tail; /* previous entry */
  258. ds->next = NULL; /* end of chain */
  259. if (ds->prev)
  260. ds->prev->next = ds; /* last forward */
  261. else
  262. table_head = ds; /* is first entry */
  263. table_tail = ds; /* end of queue */
  264. } else {
  265. ds->next = ds1; /* next entry */
  266. ds->prev = ds1->prev; /* prev entry */
  267. ds1->prev = ds; /* backward chain old element */
  268. if (!ds->prev)
  269. table_head = ds; /* first element */
  270. }
  271. spin_unlock_irqrestore(&divert_lock, flags);
  272. return (0);
  273. } /* insertrule */
  274. /***********************************/
  275. /* delete the rule at position idx */
  276. /***********************************/
  277. int deleterule(int idx)
  278. {
  279. struct deflect_struc *ds, *ds1;
  280. unsigned long flags;
  281. if (idx < 0) {
  282. spin_lock_irqsave(&divert_lock, flags);
  283. ds = table_head;
  284. table_head = NULL;
  285. table_tail = NULL;
  286. spin_unlock_irqrestore(&divert_lock, flags);
  287. while (ds) {
  288. ds1 = ds;
  289. ds = ds->next;
  290. kfree(ds1);
  291. }
  292. return (0);
  293. }
  294. spin_lock_irqsave(&divert_lock, flags);
  295. ds = table_head;
  296. while ((ds) && (idx > 0)) {
  297. idx--;
  298. ds = ds->next;
  299. }
  300. if (!ds) {
  301. spin_unlock_irqrestore(&divert_lock, flags);
  302. return (-EINVAL);
  303. }
  304. if (ds->next)
  305. ds->next->prev = ds->prev; /* backward chain */
  306. else
  307. table_tail = ds->prev; /* end of chain */
  308. if (ds->prev)
  309. ds->prev->next = ds->next; /* forward chain */
  310. else
  311. table_head = ds->next; /* start of chain */
  312. spin_unlock_irqrestore(&divert_lock, flags);
  313. kfree(ds);
  314. return (0);
  315. } /* deleterule */
  316. /*******************************************/
  317. /* get a pointer to a specific rule number */
  318. /*******************************************/
  319. divert_rule *getruleptr(int idx)
  320. {
  321. struct deflect_struc *ds = table_head;
  322. if (idx < 0) return (NULL);
  323. while ((ds) && (idx >= 0)) {
  324. if (!(idx--)) {
  325. return (&ds->rule);
  326. break;
  327. }
  328. ds = ds->next;
  329. }
  330. return (NULL);
  331. } /* getruleptr */
  332. /*************************************************/
  333. /* called from common module on an incoming call */
  334. /*************************************************/
  335. static int isdn_divert_icall(isdn_ctrl *ic)
  336. {
  337. int retval = 0;
  338. unsigned long flags;
  339. struct call_struc *cs = NULL;
  340. struct deflect_struc *dv;
  341. char *p, *p1;
  342. u_char accept;
  343. /* first check the internal deflection table */
  344. for (dv = table_head; dv; dv = dv->next) {
  345. /* scan table */
  346. if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
  347. ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
  348. continue; /* call option check */
  349. if (!(dv->rule.drvid & (1L << ic->driver)))
  350. continue; /* driver not matching */
  351. if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1))
  352. continue; /* si1 not matching */
  353. if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2))
  354. continue; /* si2 not matching */
  355. p = dv->rule.my_msn;
  356. p1 = ic->parm.setup.eazmsn;
  357. accept = 0;
  358. while (*p) {
  359. /* complete compare */
  360. if (*p == '-') {
  361. accept = 1; /* call accepted */
  362. break;
  363. }
  364. if (*p++ != *p1++)
  365. break; /* not accepted */
  366. if ((!*p) && (!*p1))
  367. accept = 1;
  368. } /* complete compare */
  369. if (!accept) continue; /* not accepted */
  370. if ((strcmp(dv->rule.caller, "0")) ||
  371. (ic->parm.setup.phone[0])) {
  372. p = dv->rule.caller;
  373. p1 = ic->parm.setup.phone;
  374. accept = 0;
  375. while (*p) {
  376. /* complete compare */
  377. if (*p == '-') {
  378. accept = 1; /* call accepted */
  379. break;
  380. }
  381. if (*p++ != *p1++)
  382. break; /* not accepted */
  383. if ((!*p) && (!*p1))
  384. accept = 1;
  385. } /* complete compare */
  386. if (!accept) continue; /* not accepted */
  387. }
  388. switch (dv->rule.action) {
  389. case DEFLECT_IGNORE:
  390. return (0);
  391. break;
  392. case DEFLECT_ALERT:
  393. case DEFLECT_PROCEED:
  394. case DEFLECT_REPORT:
  395. case DEFLECT_REJECT:
  396. if (dv->rule.action == DEFLECT_PROCEED)
  397. if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
  398. return (0); /* no external deflection needed */
  399. if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
  400. return (0); /* no memory */
  401. init_timer(&cs->timer);
  402. cs->info[0] = '\0';
  403. cs->timer.function = deflect_timer_expire;
  404. cs->timer.data = (ulong) cs; /* pointer to own structure */
  405. cs->ics = *ic; /* copy incoming data */
  406. if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone, "0");
  407. if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn, "0");
  408. cs->ics.parm.setup.screen = dv->rule.screen;
  409. if (dv->rule.waittime)
  410. cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
  411. else if (dv->rule.action == DEFLECT_PROCEED)
  412. cs->timer.expires = jiffies + (HZ * extern_wait_max);
  413. else
  414. cs->timer.expires = 0;
  415. cs->akt_state = dv->rule.action;
  416. spin_lock_irqsave(&divert_lock, flags);
  417. cs->divert_id = next_id++; /* new sequence number */
  418. spin_unlock_irqrestore(&divert_lock, flags);
  419. cs->prev = NULL;
  420. if (cs->akt_state == DEFLECT_ALERT) {
  421. strcpy(cs->deflect_dest, dv->rule.to_nr);
  422. if (!cs->timer.expires) {
  423. strcpy(ic->parm.setup.eazmsn,
  424. "Testtext direct");
  425. ic->parm.setup.screen = dv->rule.screen;
  426. strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone));
  427. cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
  428. cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
  429. retval = 5;
  430. } else
  431. retval = 1; /* alerting */
  432. } else {
  433. cs->deflect_dest[0] = '\0';
  434. retval = 4; /* only proceed */
  435. }
  436. sprintf(cs->info, "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
  437. cs->akt_state,
  438. cs->divert_id,
  439. divert_if.drv_to_name(cs->ics.driver),
  440. (ic->command == ISDN_STAT_ICALLW) ? "1" : "0",
  441. cs->ics.parm.setup.phone,
  442. cs->ics.parm.setup.eazmsn,
  443. cs->ics.parm.setup.si1,
  444. cs->ics.parm.setup.si2,
  445. cs->ics.parm.setup.screen,
  446. dv->rule.waittime,
  447. cs->deflect_dest);
  448. if ((dv->rule.action == DEFLECT_REPORT) ||
  449. (dv->rule.action == DEFLECT_REJECT)) {
  450. put_info_buffer(cs->info);
  451. kfree(cs); /* remove */
  452. return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */
  453. }
  454. break;
  455. default:
  456. return (0); /* ignore call */
  457. break;
  458. } /* switch action */
  459. break;
  460. } /* scan_table */
  461. if (cs) {
  462. cs->prev = NULL;
  463. spin_lock_irqsave(&divert_lock, flags);
  464. cs->next = divert_head;
  465. divert_head = cs;
  466. if (cs->timer.expires) add_timer(&cs->timer);
  467. spin_unlock_irqrestore(&divert_lock, flags);
  468. put_info_buffer(cs->info);
  469. return (retval);
  470. } else
  471. return (0);
  472. } /* isdn_divert_icall */
  473. void deleteprocs(void)
  474. {
  475. struct call_struc *cs, *cs1;
  476. unsigned long flags;
  477. spin_lock_irqsave(&divert_lock, flags);
  478. cs = divert_head;
  479. divert_head = NULL;
  480. while (cs) {
  481. del_timer(&cs->timer);
  482. cs1 = cs;
  483. cs = cs->next;
  484. kfree(cs1);
  485. }
  486. spin_unlock_irqrestore(&divert_lock, flags);
  487. } /* deleteprocs */
  488. /****************************************************/
  489. /* put a address including address type into buffer */
  490. /****************************************************/
  491. static int put_address(char *st, u_char *p, int len)
  492. {
  493. u_char retval = 0;
  494. u_char adr_typ = 0; /* network standard */
  495. if (len < 2) return (retval);
  496. if (*p == 0xA1) {
  497. retval = *(++p) + 2; /* total length */
  498. if (retval > len) return (0); /* too short */
  499. len = retval - 2; /* remaining length */
  500. if (len < 3) return (0);
  501. if ((*(++p) != 0x0A) || (*(++p) != 1)) return (0);
  502. adr_typ = *(++p);
  503. len -= 3;
  504. p++;
  505. if (len < 2) return (0);
  506. if (*p++ != 0x12) return (0);
  507. if (*p > len) return (0); /* check number length */
  508. len = *p++;
  509. } else if (*p == 0x80) {
  510. retval = *(++p) + 2; /* total length */
  511. if (retval > len) return (0);
  512. len = retval - 2;
  513. p++;
  514. } else
  515. return (0); /* invalid address information */
  516. sprintf(st, "%d ", adr_typ);
  517. st += strlen(st);
  518. if (!len)
  519. *st++ = '-';
  520. else
  521. while (len--)
  522. *st++ = *p++;
  523. *st = '\0';
  524. return (retval);
  525. } /* put_address */
  526. /*************************************/
  527. /* report a successful interrogation */
  528. /*************************************/
  529. static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
  530. {
  531. char *src = ic->parm.dss1_io.data;
  532. int restlen = ic->parm.dss1_io.datalen;
  533. int cnt = 1;
  534. u_char n, n1;
  535. char st[90], *p, *stp;
  536. if (restlen < 2) return (-100); /* frame too short */
  537. if (*src++ != 0x30) return (-101);
  538. if ((n = *src++) > 0x81) return (-102); /* invalid length field */
  539. restlen -= 2; /* remaining bytes */
  540. if (n == 0x80) {
  541. if (restlen < 2) return (-103);
  542. if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104);
  543. restlen -= 2;
  544. } else if (n == 0x81) {
  545. n = *src++;
  546. restlen--;
  547. if (n > restlen) return (-105);
  548. restlen = n;
  549. } else if (n > restlen)
  550. return (-106);
  551. else
  552. restlen = n; /* standard format */
  553. if (restlen < 3) return (-107); /* no procedure */
  554. if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108);
  555. restlen -= 3;
  556. if (restlen < 2) return (-109); /* list missing */
  557. if (*src == 0x31) {
  558. src++;
  559. if ((n = *src++) > 0x81) return (-110); /* invalid length field */
  560. restlen -= 2; /* remaining bytes */
  561. if (n == 0x80) {
  562. if (restlen < 2) return (-111);
  563. if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112);
  564. restlen -= 2;
  565. } else if (n == 0x81) {
  566. n = *src++;
  567. restlen--;
  568. if (n > restlen) return (-113);
  569. restlen = n;
  570. } else if (n > restlen)
  571. return (-114);
  572. else
  573. restlen = n; /* standard format */
  574. } /* result list header */
  575. while (restlen >= 2) {
  576. stp = st;
  577. sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id,
  578. cnt++, divert_if.drv_to_name(ic->driver));
  579. stp += strlen(stp);
  580. if (*src++ != 0x30) return (-115); /* invalid enum */
  581. n = *src++;
  582. restlen -= 2;
  583. if (n > restlen) return (-116); /* enum length wrong */
  584. restlen -= n;
  585. p = src; /* one entry */
  586. src += n;
  587. if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
  588. stp += strlen(stp);
  589. p += n1;
  590. n -= n1;
  591. if (n < 6) continue; /* no service and proc */
  592. if ((*p++ != 0x0A) || (*p++ != 1)) continue;
  593. sprintf(stp, " 0x%02x ", (*p++) & 0xFF);
  594. stp += strlen(stp);
  595. if ((*p++ != 0x0A) || (*p++ != 1)) continue;
  596. sprintf(stp, "%d ", (*p++) & 0xFF);
  597. stp += strlen(stp);
  598. n -= 6;
  599. if (n > 2) {
  600. if (*p++ != 0x30) continue;
  601. if (*p > (n - 2)) continue;
  602. n = *p++;
  603. if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
  604. stp += strlen(stp);
  605. }
  606. sprintf(stp, "\n");
  607. put_info_buffer(st);
  608. } /* while restlen */
  609. if (restlen) return (-117);
  610. return (0);
  611. } /* interrogate_success */
  612. /*********************************************/
  613. /* callback for protocol specific extensions */
  614. /*********************************************/
  615. static int prot_stat_callback(isdn_ctrl *ic)
  616. {
  617. struct call_struc *cs, *cs1;
  618. int i;
  619. unsigned long flags;
  620. cs = divert_head; /* start of list */
  621. cs1 = NULL;
  622. while (cs) {
  623. if (ic->driver == cs->ics.driver) {
  624. switch (cs->ics.arg) {
  625. case DSS1_CMD_INVOKE:
  626. if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
  627. (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) {
  628. switch (ic->arg) {
  629. case DSS1_STAT_INVOKE_ERR:
  630. sprintf(cs->info, "128 0x%lx 0x%x\n",
  631. ic->parm.dss1_io.ll_id,
  632. ic->parm.dss1_io.timeout);
  633. put_info_buffer(cs->info);
  634. break;
  635. case DSS1_STAT_INVOKE_RES:
  636. switch (cs->ics.parm.dss1_io.proc) {
  637. case 7:
  638. case 8:
  639. put_info_buffer(cs->info);
  640. break;
  641. case 11:
  642. i = interrogate_success(ic, cs);
  643. if (i)
  644. sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT,
  645. ic->parm.dss1_io.ll_id, i);
  646. put_info_buffer(cs->info);
  647. break;
  648. default:
  649. printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc);
  650. break;
  651. }
  652. break;
  653. default:
  654. printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg);
  655. break;
  656. }
  657. cs1 = cs; /* remember structure */
  658. cs = NULL;
  659. continue; /* abort search */
  660. } /* id found */
  661. break;
  662. case DSS1_CMD_INVOKE_ABORT:
  663. printk(KERN_WARNING "dss1_divert unhandled invoke abort\n");
  664. break;
  665. default:
  666. printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n", cs->ics.arg);
  667. break;
  668. } /* switch ics.arg */
  669. cs = cs->next;
  670. } /* driver ok */
  671. }
  672. if (!cs1) {
  673. printk(KERN_WARNING "dss1_divert unhandled process\n");
  674. return (0);
  675. }
  676. if (cs1->ics.driver == -1) {
  677. spin_lock_irqsave(&divert_lock, flags);
  678. del_timer(&cs1->timer);
  679. if (cs1->prev)
  680. cs1->prev->next = cs1->next; /* forward link */
  681. else
  682. divert_head = cs1->next;
  683. if (cs1->next)
  684. cs1->next->prev = cs1->prev; /* back link */
  685. spin_unlock_irqrestore(&divert_lock, flags);
  686. kfree(cs1);
  687. }
  688. return (0);
  689. } /* prot_stat_callback */
  690. /***************************/
  691. /* status callback from HL */
  692. /***************************/
  693. static int isdn_divert_stat_callback(isdn_ctrl *ic)
  694. {
  695. struct call_struc *cs, *cs1;
  696. unsigned long flags;
  697. int retval;
  698. retval = -1;
  699. cs = divert_head; /* start of list */
  700. while (cs) {
  701. if ((ic->driver == cs->ics.driver) &&
  702. (ic->arg == cs->ics.arg)) {
  703. switch (ic->command) {
  704. case ISDN_STAT_DHUP:
  705. sprintf(cs->info, "129 0x%lx\n", cs->divert_id);
  706. del_timer(&cs->timer);
  707. cs->ics.driver = -1;
  708. break;
  709. case ISDN_STAT_CAUSE:
  710. sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num);
  711. break;
  712. case ISDN_STAT_REDIR:
  713. sprintf(cs->info, "131 0x%lx\n", cs->divert_id);
  714. del_timer(&cs->timer);
  715. cs->ics.driver = -1;
  716. break;
  717. default:
  718. sprintf(cs->info, "999 0x%lx 0x%x\n", cs->divert_id, (int)(ic->command));
  719. break;
  720. }
  721. put_info_buffer(cs->info);
  722. retval = 0;
  723. }
  724. cs1 = cs;
  725. cs = cs->next;
  726. if (cs1->ics.driver == -1) {
  727. spin_lock_irqsave(&divert_lock, flags);
  728. if (cs1->prev)
  729. cs1->prev->next = cs1->next; /* forward link */
  730. else
  731. divert_head = cs1->next;
  732. if (cs1->next)
  733. cs1->next->prev = cs1->prev; /* back link */
  734. spin_unlock_irqrestore(&divert_lock, flags);
  735. kfree(cs1);
  736. }
  737. }
  738. return (retval); /* not found */
  739. } /* isdn_divert_stat_callback */
  740. /********************/
  741. /* callback from ll */
  742. /********************/
  743. int ll_callback(isdn_ctrl *ic)
  744. {
  745. switch (ic->command) {
  746. case ISDN_STAT_ICALL:
  747. case ISDN_STAT_ICALLW:
  748. return (isdn_divert_icall(ic));
  749. break;
  750. case ISDN_STAT_PROT:
  751. if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) {
  752. if (ic->arg != DSS1_STAT_INVOKE_BRD)
  753. return (prot_stat_callback(ic));
  754. else
  755. return (0); /* DSS1 invoke broadcast */
  756. } else
  757. return (-1); /* protocol not euro */
  758. default:
  759. return (isdn_divert_stat_callback(ic));
  760. }
  761. } /* ll_callback */