isdn_divert.c 26 KB

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