From 31dd84ea4c4be03ec2d7f4cdcfb3e7833bf60627 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Thu, 2 Nov 1995 10:15:35 +0100 Subject: [PATCH] isdn-18 --- DOKU | 73 +++++--- cards/capi/bintec.c | 20 +- include/isdn_3.h | 12 +- include/isdn_34.h | 7 +- isdn_2/isdn_2.c | 11 -- isdn_3/capi.c | 440 +++++++++++++++++++++++++++++--------------- isdn_3/isdn_3.c | 19 +- isdn_3/phone.c | 6 +- isdn_3/prot_ETS.c | 13 +- isdn_4/cf.c | 4 +- isdn_4/conn.c | 5 +- isdn_4/devs.c | 4 +- isdn_4/info.c | 142 ++++++++------ isdn_4/loader.c | 20 +- isdn_4/master.h | 9 +- isdn_4/match.c | 165 +++++++++++------ isdn_4/nr.c | 23 ++- isdn_4/util.c | 4 +- isdn_4/work.c | 56 ++++-- ksupport/Makefile | 2 + ksupport/log.c | 2 + 21 files changed, 672 insertions(+), 365 deletions(-) diff --git a/DOKU b/DOKU index 60a43ae..4a02333 100644 --- a/DOKU +++ b/DOKU @@ -801,11 +801,14 @@ Protokolle und Flags in der DL-Zeile: Die Reihenfolge ist wichtig. -:pp Punkt-zu-Punkt-Verbindung, feste TEI (0x00). :kl ebenfalls - angeben! +:pp Punkt-zu-Punkt-Verbindung, feste TEI (0x00). + Vorsicht: Anlagenanschluß wird vom 1TR6-Treiber nicht und vom + Euro-Treiber nur unvollständig unterstützt. :mp Verbindung am Bus, variabler TEI-Identifier. Bei manchen 1TR6- - Vermittlungen und Nebenstellenanlagen sinnvoll. -:mf Verbindung am Bus, fester TEI-Identifier. Default. + Vermittlungen und Nebenstellenanlagen notwendig, in der DSS1- + Norm vorgeschrieben. +:mq Verbindung am Bus, fester TEI-Identifier. Default, weil es an + vielen Anlagen besser funktioniert als :mp. :mt Verbindung am Bus, feste TEI(0x12). In Spezialfällen notwendig. :de Debugging, macht D-Kanal-Datenaustausch beobachtbar (mit AT/W). Vorsicht: Diese Option verlangsamt das gesamte ISDN-System, auch @@ -825,14 +828,17 @@ Die Reihenfolge ist wichtig. verwendet werden. :kl Level-2-Verbindung zur Vermittlung nicht trennen. Bei Punkt- zu-Punkt-Verbindungen und bei entsprechend konfigurierten - ISDN-Anschlüssen ("Dauerüberwachung oder sowas ähnliches") + ISDN-Anschlüssen ("Dauerüberwachung" oder sowas ähnliches) notwendig. :cl Level-2-Verbindung zur Vermittlung trennen, wenn keine Verbindung besteht. Default. - :sp 8 DSS1, Euro-ISDN. [euro] - :sp 65 1TR6, deutscher Standard. [german] Entweder :sp 8 oder :sp 65 muß angegeben werden, NICHT beides! + :sp 8 DSS1, Euro-ISDN. [euro] + :b1 an manchen Nebenstellen zur korekten Nummernerkennung notwendig. + Einschalten, wenn die Nebenstellennummer nicht mit . oder / + eingeleitet wird. + :sp 65 1TR6, deutscher Standard. [german] :ai Ankommenden Anruf mit dem ISDN-Äquivalent von "RINGING" beantworten, dann prüfen ob der Anruf angenommen werden kann. @@ -844,26 +850,27 @@ Die Reihenfolge ist wichtig. beschäftigten Rechnern und bei manchen Telefonanlagen. :td TEI beim ersten Verbindungsaufbau zuordnen lassen. Default. :pr 64 Festverbindung: kein D-Kanal. -:pr 65 Intelligente Karte mit CAPI-1.x-Schnittstelle. (Noch nicht!) +:pr 65 Intelligente Karte mit CAPI-1.x-Schnittstelle. In der Konfiguration verhält sich eine CAPI-Karte ansonsten wie - der 1TR6-Treiber, und zwar AUCH DANN WENN DAS TEIl AM EURO-ISDN + der 1TR6-Treiber, und zwar AUCH DANN WENN DAS TEIL AM EURO-ISDN HÄNGT. - :pb Verwendet die CAPI wie eine Nebenstellenanlage, d.h. ankommend - Akkumulation ankommender Ziffern, abgehend dynamisches Mapping - EAZ->Nebenstellennummer. (Teilweise implementiert: ankommend - funktioniert nur Blockwahl.) + :pb Die Karte hängt an einem Anlagenanschluß / S2M und verhält sich + wie eine Nebenstellenanlage. :sp 0 Bintec-Karte. [bintec] - Auf diese Karte muß zunächst boot.68k und dann entweder bri.68k, - bri_4.68k oder pmx.68k geladen werden (LF-Zeile). + Auf diese Karte muß zunächst boot.68k und dann entweder bri.68k + oder pmx.68k geladen werden (LF-Zeile). :sc X Die folgenden Optionen betreffen nur das Xte Interface auf der Karte. X in 1..4. :lp X X X CAPI-Bitmasken für EAZ, Service, Infos. Hexadezimal. Default: 03FF E7BF 003F. :st XXXXX Protokollstack XXXXX laden. Siehe Handbuch zur Karte. - Default ist u_dss1_pmp. - :ea N NNN EAZ N auf (lokale) Endnummer NNN mappen. + Default ist u_1tr6_pmp (wenn "german" und nicht "euro" inn + config/config-data angegeben wurde) oder u_dss1_pmp (sonst). + :ea N NNN EAZ N auf lokale Nummer (MSN) NNN mappen. Default ist die letzte Ziffer der Nummer. Nicht bei :pb verwenden. + :lw X Warte bis zu X Sekunden auf nachgewählte Ziffern. + Nur bei :pb verwenden. DP-Zeile ("Dial Prefix") @@ -896,6 +903,8 @@ DP... - MP... :nr /5 würde die Nummer 12345 wählen. +Siehe auch unten unter "Bugs anderer Leute". + R-Zeile ("Run") ------- @@ -1014,11 +1023,13 @@ Parameter. LF-Zeile ("Load File") -------- -Form: LF +Form: LF Lädt die Datei auf die (aktive) Karte. Mehrere LF-Zeilen können angegeben -werden (in der richtigen Reihenfolge!). Die maximal mögliche Segmentgröße -ist 4096. +werden (in der richtigen Reihenfolge! Doku beachten!). Die maximal mögliche +Segmentgröße ist 4096. Der Delay gibt an, wie lange das Programm nach dem +Laden dieser Datei mit dem nächsten Schritt warten soll (Karte macht +Speichertest über 8 MB, und ähnliche Feinheiten). RP-Zeile ("Run Program") @@ -1538,8 +1549,11 @@ Wie dem auch sei, die Infobits haben folgende Bedeutung: 00000008 User-User Info 00000010 Cause 00000020 Status des gerufenen Teilnehmers -00000040... -80000000 reserviert +00000040 Rufnummernübergabe (Anlagenanschluß) +00000080... +20000000 reserviert +40000000 SPVs +80000000 Festverbindungen Die EAZ-Bits: 0001 Null ("Global Call", wird aber nicht besonders behandelt) @@ -1570,3 +1584,18 @@ Ankommende Rufe, die zu diesen EAZs und Diensten passen, werden durchgereicht (und die angeforderten Informationen werden gemeldet, wenn die Vermittlung sie sendet(!)); andere Rufe werden ignoriert. + +Bugs anderer Leute +================== + +(1) +An manchen Nebenstellenanlagen werden ankommende Rufe teilweise mit, +teilweise ohne der zum Rauswählen notwendigen Null ausgeliefert. + +Das liegt an der Quelle der Anrufe; die Telekom signalisiert 1TR6-Anrufe +etwas anders als Euro-ISDN (ist aber beides legal), die Telefonanlage setzt +aber nur eine Version korrekt um. + +Workaround: Keiner. +Bugfix: Hersteller kräftig treten. + diff --git a/cards/capi/bintec.c b/cards/capi/bintec.c index 3fdca4a..621611a 100644 --- a/cards/capi/bintec.c +++ b/cards/capi/bintec.c @@ -977,11 +977,17 @@ sendone(struct _bintec *bp, int thechan) freemsg(mb); if(thechan != 0) chan->waitflow++; + if(BOARD_TYPE(bp) != BOARD_ID_PMX) { + *bp->ctrl = bp->cflag | 0x10; + *bp->ctrl = bp->cflag; + } else + CTRL_SET(bp,1); } } else if(err == -EAGAIN) { S_requeue(&chan->q_out,mb); } else { freemsg(mb); + /* TODO: Kill the board? */ } return err; } @@ -1349,8 +1355,16 @@ DoIRQ(struct _bintec *bp) if (err < 0) freemsg(mb); } else { - printf("BINTEC error: msg type %04x\n",ntohs(err)); - getflush(bp,len); + mblk_t *mb = allocb(len+2,BPRI_LO); + if(mb != NULL) { + *((ushort_t *)mb->b_wptr)++ = ntohs(err); + getmb(bp,mb,len); + log_printmsg(NULL,"BINTEC error: msgtype",mb,KERN_WARNING); + freemsg(mb); + } else { + printf("BINTEC error: msg type %04x\n",ntohs(err)); + getflush(bp,len); + } err = getend(bp); } } @@ -1436,7 +1450,7 @@ bintectimer(struct _bintec *bp) #ifdef NEW_TIMEOUT bp->timer = #endif - timeout((void *)bintectimer,bp,(bp->info.irq == 0) ? ((bp->type == BOARD_ID_PMX) ? HZ/100+1 : HZ/20+1) : HZ/2); + timeout((void *)bintectimer,bp, (bp->info.irq == 0) ? (HZ/100+1) : (HZ/2)); } #endif diff --git a/include/isdn_3.h b/include/isdn_3.h index 9d9f84b..663c758 100644 --- a/include/isdn_3.h +++ b/include/isdn_3.h @@ -405,6 +405,9 @@ long isdn3_flags(mblk_t *info, uchar_t protocol, uchar_t subprot); #define FL_POINTMASK 0300 #define FL_ANS_IMMED 0400 /* default is to delay */ +#define FL_BUG1 01000 +#define FL_BUG2 02000 +#define FL_BUG3 04000 /** * Convenience macros for handling connection timeouts. @@ -423,10 +426,13 @@ long isdn3_flags(mblk_t *info, uchar_t protocol, uchar_t subprot); #define UNTIMER(T,c,w,f) do { if((c)->timerflags & f) { untimeout(w,(c)); (c)->timerflags &=~ f; } } while(0) #define untimer(T,c) UNTIMER(T,c,T,RUN_##T) #define TIMER(T,c,w,v,f) do { if(!((c)->timerflags & f)) { if((c)->talk->state & IS_UP) timeout(w,(c),v); (c)->timerflags |= f; } } while(0) -#define timer(T,c) TIMER(T,c,T,VAL_##T,RUN_##T) +#define timer(T,c) TIMER(T,(c),T,VAL_##T,RUN_##T) +#define ntimer(T,c,n) TIMER(T,(c),T,(n),RUN_##T) #define FTIMER(T,c,w,v,f) do { if(!((c)->timerflags & f)) { timeout(w,(c),v); (c)->timerflags |= f; } } while(0) -#define ftimer(T,c) FTIMER(T,c,T,VAL_##T,RUN_##T) +#define ftimer(T,c) FTIMER(T,(c),T,VAL_##T,RUN_##T) +#define fntimer(T,c) FTIMER(T,(c),T,(n),RUN_##T) #define RTIMER(T,c,w,v,f) do { if((c)->timerflags & f) { untimeout(w,(c)); timeout(w,(c),v); } } while(0) -#define rtimer(T,c) RTIMER(T,c,T,VAL_##T,RUN_##T) +#define rtimer(T,c) RTIMER(T,(c),T,VAL_##T,RUN_##T) +#define rntimer(T,c,n) RTIMER(T,(c),T,(n),RUN_##T) #endif /* _ISDN_3 */ diff --git a/include/isdn_34.h b/include/isdn_34.h index 24fb3bb..0919637 100644 --- a/include/isdn_34.h +++ b/include/isdn_34.h @@ -138,6 +138,7 @@ #define ARG_CALLREF CHAR2 ('c','r') /* long call reference number */ #define ARG_PBX CHAR2 ('p','b') /* behave like a PBX */ #define ARG_EAZ CHAR2 ('e','a') /* map EAZ to local phone nr */ +#define ARG_LWAIT CHAR2 ('l','w') /* how long to wait for additional digits */ #define ARG_LNUMBER CHAR2 ('l','r') /* local phone nr */ #define ARG_NUMBER CHAR2 ('n','r') /* remote phone nr */ #define ARG_OUTNUMS CHAR2 ('o','m') /* outgoing, for build */ @@ -158,6 +159,7 @@ #define ARG_ERRHDR CHAR2 ('e','H') /* reported error type */ #define ARG_SPV CHAR2 ('p','v') /* semipermanent */ #define ARG_FORCETALK CHAR2 ('F','t') /* force talker */ +#define ARG_INCOMPLETE CHAR2('i','C') /* Number may be incomplete */ #define ARG_SUBPROT CHAR2 ('s','p') /* long Subprotocol to use. For SAPI 0: * "65" for calls according to 1TR6, * "0" for Q.931. */ @@ -177,7 +179,7 @@ #define ARG_POINTOPOINT CHAR2('p','p') /* point-to-point link */ #define ARG_MULTIPOINT1 CHAR2('m','p') /* multipoint link, variable ID */ -#define ARG_MULTIPOINT2 CHAR2('m','f') /* multipoint link, fixed ID */ +#define ARG_MULTIPOINT2 CHAR2('m','q') /* multipoint link, fixed ID */ #define ARG_MULTIPOINT3 CHAR2('m','t') /* multipoint link, fixed TEI */ #define ARG_ANSWER_IMMED CHAR2('a','i') /* grab the TEI on startup */ @@ -191,6 +193,9 @@ #define ARG_DEBUG CHAR2('d','e') #define ARG_EVENT CHAR2('e','v') #define ARG_SUBEVENT CHAR2('e','s') +#define ARG_BUG1 CHAR2('b','1') +#define ARG_BUG2 CHAR2('b','2') +#define ARG_BUG3 CHAR2('b','3') /* Other arguments are protocol dependent. See the appropriate include files. */ diff --git a/isdn_2/isdn_2.c b/isdn_2/isdn_2.c index ce4b358..c707595 100644 --- a/isdn_2/isdn_2.c +++ b/isdn_2/isdn_2.c @@ -2390,7 +2390,6 @@ isdn2_wsrv (queue_t *q) } #endif { -printf("m"); if (chan->card != NULL) { if((err = do_chprot(chan->card,chan->channel,mp,CHP_FROMSTACK)|CHP_TOCARD) < 0) { printf("%sChProtErr isdn_2.c %d %d\n",KERN_DEBUG,__LINE__,err); @@ -2399,14 +2398,12 @@ printf("m"); } } else { mblk_t *mb = allocb (sizeof (struct _isdn23_hdr), BPRI_MED); -printf("j"); if (mb == NULL) { printf("%sNoMemHdr isdn_2.c %d\n",KERN_DEBUG,__LINE__); putbqf (q, mp); return; } -printf("i"); hdr2 = ((isdn23_hdr) mb->b_wptr)++; hdr2->key = HDR_PROTOCMD; hdr2->seqnum = hdrseq; hdrseq += 2; @@ -2415,20 +2412,15 @@ printf("i"); hdr2->hdr_protocmd.channel = 0; hdr2->hdr_protocmd.len = dsize (mp); linkb (mb, mp); -printf("h"); do { DATA_TYPE(mp) = M_DATA; mp = mp->b_cont; } while(mp != NULL); -printf("g"); if (isdn_chan.qptr != NULL) { -printf("f"); if(isdn2_debug & 0x2000) logh_printmsg (NULL, "Up", mb); if(canput(isdn_chan.qptr->q_next)) { -printf("e"); putnext (isdn_chan.qptr, mb); } else { -printf("d"); freemsg(mb); } } else { @@ -2436,11 +2428,8 @@ printf("d"); printf ("%sHang 4\n",KERN_DEBUG); putctlx (RD (q), M_HANGUP); } -printf("c"); } -printf("b"); } -printf("a"); } break; case CASE_DATA: diff --git a/isdn_3/capi.c b/isdn_3/capi.c index b5f7d4a..b095c02 100644 --- a/isdn_3/capi.c +++ b/isdn_3/capi.c @@ -71,15 +71,18 @@ #define STATE_DEAD 255 #define RUN_CAPI_TCONN 01 -#define RUN_CAPI_TWAITEAZ 02 +#define RUN_CAPI_TWAITLOCAL 02 #define RUN_CAPI_TFOO 04 +#define RUN_CAPI_TWAITFIRSTLOCAL 010 #define VAL_CAPI_TCONN ( 40 *HZ) /* timer for delaying an ALERT response */ -#define VAL_CAPI_TWAITEAZ ( HZ/2) /* timer for waiting for the EAZ */ +#define VAL_CAPI_TWAITLOCAL ( 5 *HZ) /* wait for additional digits */ +#define VAL_CAPI_TWAITFIRSTLOCAL ( HZ/2) /* wait for the first digit */ #define VAL_CAPI_TFOO ( 10 * HZ) /* timer for waiting for teardown */ static void CAPI_TCONN (isdn3_conn conn); -static void CAPI_TWAITEAZ (isdn3_conn conn); +static void CAPI_TWAITLOCAL (isdn3_conn conn); +static void CAPI_TWAITFIRSTLOCAL (isdn3_conn conn); static void CAPI_TFOO (isdn3_conn conn); /* Connection states: @@ -118,6 +121,7 @@ struct capi_info { #define INF_SPV 01 unsigned char lnr[MAXNR]; unsigned char nr[MAXNR]; + unsigned short waitlocal; }; struct trace_timer { @@ -139,8 +143,14 @@ static void checkterm (isdn3_conn conn); static void capi_timerup (isdn3_conn conn) { + struct capi_info *info = conn->p_data; + rtimer (CAPI_TCONN, conn); - rtimer (CAPI_TWAITEAZ, conn); + rtimer (CAPI_TWAITFIRSTLOCAL, conn); + if(info == NULL) + rtimer (CAPI_TWAITLOCAL, conn); + else + rntimer(CAPI_TWAITLOCAL, conn, info->waitlocal); rtimer (CAPI_TFOO, conn); } @@ -148,6 +158,8 @@ capi_timerup (isdn3_conn conn) static void Xsetstate(unsigned int deb_line, isdn3_conn conn, uchar_t state) { + struct capi_info *info = conn->p_data; + printf ("Conn CAPI:%d %05lx: State %d --> %d\n", deb_line, conn->call_ref, conn->state, state); if(conn->state == state) @@ -156,7 +168,8 @@ printf ("Conn CAPI:%d %05lx: State %d --> %d\n", deb_line, conn->call_ref, conn- untimer(CAPI_TCONN, conn); switch(conn->state) { case 6: - untimer(CAPI_TWAITEAZ, conn); + untimer(CAPI_TWAITLOCAL, conn); + untimer(CAPI_TWAITFIRSTLOCAL, conn); break; case 99: untimer(CAPI_TFOO, conn); @@ -169,7 +182,12 @@ printf ("Conn CAPI:%d %05lx: State %d --> %d\n", deb_line, conn->call_ref, conn- switch(state) { case 6: - timer(CAPI_TWAITEAZ,conn); + if(info != NULL) { + ntimer(CAPI_TWAITLOCAL,conn,info->waitlocal); + if(info->lnr == '\0') + timer(CAPI_TWAITFIRSTLOCAL,conn); + } else + timer(CAPI_TWAITLOCAL,conn); break; case 99: timer(CAPI_TFOO,conn); @@ -196,13 +214,84 @@ printf ("Conn CAPI:%d %05lx: State %d --> %d\n", deb_line, conn->call_ref, conn- } } -static ushort_t newmsgid(isdn3_talk talk) +static ushort_t +newmsgid(isdn3_talk talk) { talk->message_id = ((talk->message_id + 1) & 0x3FFF) | 0x4000; return talk->message_id; } +static int +putnr(uchar_t *nrto, uchar_t *nrfrom) +{ + uchar_t *nrorig = nrto; + switch(*nrfrom) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + *nrto++ = 0x80; break; + case '+': /* international */ + *nrto++ = 0x91; nrfrom++; break; + case '=': /* national */ + *nrto++ = 0xA1; nrfrom++; break; + case '-': /* subscriber */ + *nrto++ = 0xC1; nrfrom++; break; + case '.': /* abbreviated */ + case '/': /* abbreviated */ + *nrto++ = 0xE1; nrfrom++; break; + default: + *nrto++ = 0x80; nrfrom++; + break; + } + while(*nrfrom) + *nrto++ = *nrfrom++; + + return (nrto - nrorig); +} + + +static int +getnr(uchar_t *nrto, uchar_t *nrfrom) +{ + uchar_t *nrorig = nrfrom; + int len = *nrfrom++; + if(*nrto == '\0') { + switch(*nrfrom & 0x70) { + case 0x00: /* unknown */ + if(nrfrom[0] == 0x00 && nrfrom[1] == 0x83) + *nrto++ = '='; /* at least one PBX is stupid */ + else if(nrfrom[0] == 0x81) + *nrto++='.'; /* the very same PBX */ + break; + case 0x10: /* international */ + *nrto++='+'; + break; + case 0x20: /* national */ + *nrto++='='; + break; + case 0x30: /* network specific */ + break; + case 0x40: /* subscriber */ + *nrto++='-'; + break; + case 0x60: /* abbreviated */ + *nrto++='.'; + break; + case 0x70: /* extension */ + *nrto++='.'; + break; + } + } else { + while(*nrto) nrto++; /* number becomes longer */ + } + while (len-- > 0 && (*nrfrom++ & 0x80) == 0) ; + while (len-- > 0) + *nrto++ = *nrfrom++; + *nrto = '\0'; + return nrfrom - nrorig; +} + + static int capi_send(isdn3_talk talk, ushort_t appl, ushort_t msgtype, mblk_t *data, ushort_t msgid) { @@ -265,16 +354,26 @@ talk_timer(struct trace_timer *tt) } static void -CAPI_TWAITEAZ(isdn3_conn conn) +CAPI_TWAITLOCAL(isdn3_conn conn) { - printf("CAPI_TWAITEAZ %05lx\n",conn->call_ref); - conn->timerflags &= ~RUN_CAPI_TWAITEAZ; + printf("CAPI_TWAITLOCAL %05lx\n",conn->call_ref); + conn->timerflags &= ~RUN_CAPI_TWAITLOCAL; if(conn->state != 6) return; setstate(conn,7); report_incoming(conn); } +static void +CAPI_TWAITFIRSTLOCAL(isdn3_conn conn) +{ + printf("CAPI_TWAITFIRSTLOCAL %05lx\n",conn->call_ref); + conn->timerflags &= ~RUN_CAPI_TWAITFIRSTLOCAL; + if(conn->state != 6) + return; + report_incoming(conn); +} + static void CAPI_TFOO(isdn3_conn conn) { @@ -294,6 +393,22 @@ CAPI_TCONN(isdn3_conn conn) send_disconnect(conn,0,0); } +static int +checknrlen(isdn3_conn conn) +{ + struct capi_info *info = conn->p_data; + + if(info == NULL) + return -ENXIO; + if(!(conn->talk->state & (1<<(info->subcard+ST_pbx)))) + return -EINVAL; + if(conn->state != 6) + return -EINVAL; + + setstate(conn,6); /* this kicks the timers */ + return report_incoming(conn); +} + static int send_setup(isdn3_conn conn) { @@ -358,51 +473,50 @@ send_open(isdn3_talk talk) #endif char profile[32] = DEFPROFILE; { /* Find correct driver name */ - int err; char skip = 0; - mblk_t *info = talk->card->info; - if(info != NULL) { - streamchar *sta = info->b_rptr; + int err; char skip = 0, subskip = 0; + mblk_t *inf = talk->card->info; + if(inf != NULL) { + streamchar *sta = inf->b_rptr; ushort_t idx; - while(m_getid(info,&idx) == 0) { + while(m_getid(inf,&idx) == 0) { long sap; switch(idx) { case ARG_PROTOCOL: - if (m_geti(info,&sap) == 0) { - skip = (sap != SAPI_CAPI); - } + if (m_geti(inf,&sap) == 0) + skip = (sap != SAPI_CAPI); break; case ARG_SUBPROT: - if (m_geti(info,&sap) == 0 && !skip) { + if (m_geti(inf,&sap) == 0 && !skip) { switch(sap) { case SAPI_CAPI_BINTEC: skip=0; break; default: /* Wrong card. TODO: Do something! */ - info->b_rptr = sta; + inf->b_rptr = sta; return -ENXIO; } } break; case ARG_SUBCARD: - if (m_geti(info,&sap) == 0 && !skip) - skip = (sap != talk->regnum+1); + if (m_geti(inf,&sap) == 0 && !skip) + subskip = (sap != talk->regnum+1); break; case ARG_STACK: - if(skip) + if(skip || subskip) break; - if((err = m_getstr(info,profile,sizeof(profile)-1)) < 0) + if((err = m_getstr(inf,profile,sizeof(profile)-1)) < 0) strcpy(profile,DEFPROFILE); break; case ARG_PBX: - if(skip) + if(skip || subskip) break; talk->state |= 1<<(talk->regnum+ST_pbx); break; } } - info->b_rptr = sta; + inf->b_rptr = sta; } } @@ -538,14 +652,21 @@ static int report_incoming (isdn3_conn conn) { int err = 0; + struct capi_info *info = conn->p_data; + mblk_t *mb; - mblk_t *mb = allocb (256, BPRI_MED); + if(info == NULL) + return -ENXIO; + mb = allocb (256, BPRI_MED); if (mb == NULL) { setstate (conn, 0); return -ENOMEM; } m_putid (mb, IND_INCOMING); + if((conn->state == 6) && !(conn->talk->state & (1<<(info->subcard+ST_pbx)))) + m_putsx(mb,ARG_INCOMPLETE); + conn_info (conn, mb); if ((err = isdn3_at_send (conn, mb, 0)) != 0) { @@ -574,7 +695,7 @@ report_nocard (isdn3_talk talk, ushort_t info) { mblk_t *mb = allocb (64, BPRI_MED); - talk->state = STATE_DEAD; + talk->tstate = STATE_DEAD; m_putid (mb, IND_NOCARD); m_putlx (mb, talk->card->id); @@ -649,8 +770,10 @@ send_disconnect(isdn3_conn conn, char do_L3, ushort_t cause) conn->msgid0)) < 0) { setstate(conn,0); freemsg(m3); - } else + } else { setstate(conn,99); + report_terminate (conn,0,cause); + } } break; case 15: @@ -709,11 +832,10 @@ send_dialout(isdn3_conn conn) struct CAPI_connect_req *c2; struct capi_info *info = conn->p_data; mblk_t *m2; - int llen = strlen(info->lnr); if(info == NULL) return -ENXIO; - m2 = allocb(sizeof(*c2)+strlen(info->nr)+1+(llen ? llen+1 : 0)+((info->flags & INF_SPV) != 0),BPRI_MED); + m2 = allocb(sizeof(*c2)+strlen(info->nr)+strlen(info->lnr)+3,BPRI_MED); if(m2 == NULL) return -ENOMEM; @@ -721,7 +843,7 @@ send_dialout(isdn3_conn conn) bzero(c2,sizeof(*c2)); c2->infomask = 0xC00000FF; { /* Find correct info mask */ - int err; char skip = 0; + int err; char skip = 0, subskip = 0; mblk_t *inf = conn->talk->card->info; if(inf != NULL) { streamchar *sta = inf->b_rptr; @@ -731,9 +853,8 @@ send_dialout(isdn3_conn conn) long sap; switch(idx) { case ARG_PROTOCOL: - if (m_geti(inf,&sap) == 0) { - skip = (sap != SAPI_CAPI); - } + if (m_geti(inf,&sap) == 0) + skip = (sap != SAPI_CAPI); break; case ARG_SUBPROT: if (m_geti(inf,&sap) == 0 && !skip) { @@ -750,13 +871,13 @@ send_dialout(isdn3_conn conn) break; case ARG_SUBCARD: if (m_geti(inf,&sap) == 0 && !skip) - skip = (sap != info->subcard); + subskip = (sap != info->subcard+1); break; case ARG_LISTEN: + if(skip || subskip) + break; { long x; - if(skip) - break; if((err = m_getx(inf,&x)) >= 0) { if((err = m_getx(inf,&x)) >= 0) { if((err = m_getx(inf,&x)) >= 0) { @@ -774,26 +895,24 @@ send_dialout(isdn3_conn conn) c2->channel = (info->bchan ? info->bchan : CAPI_ANYBCHANNEL); c2->DST_service = info->service >> 8; c2->DST_addinfo = info->service; - c2->telnolen = strlen(info->nr)+1; - *m2->b_wptr++ = 0x81; - strncpy(m2->b_wptr,info->nr,c2->telnolen); - m2->b_wptr += strlen(info->nr); + m2->b_wptr += (c2->telnolen = putnr(m2->b_wptr,info->nr)); + if(info->flags & INF_SPV) { c2->telnolen++; *m2->b_wptr++ = 'S'; } - if((llen > 0) && (conn->talk->state & (1<<(info->subcard+ST_pbx)))) { + if((*info->lnr != '\0') && (conn->talk->state & (1<<(info->subcard+ST_pbx)))) { + uchar_t *lp = m2->b_wptr++; + m2->b_wptr += (*lp = putnr(m2->b_wptr,info->lnr)); c2->SRC_eaz = 0; - if(info->lnr[0] >= '0' && info->lnr[0] <= '9') { - memcpy(m2->b_wptr+1,info->lnr,llen); - } else { - llen--; - memcpy(m2->b_wptr+1,info->lnr+1,llen); - } - *m2->b_wptr = llen; - m2->b_wptr += llen+1; - } else if(llen > 0) - c2->SRC_eaz = info->lnr[llen-1]; + c2->infomask |= 0x40; + } else { + c2->infomask &=~ 0x40; + if(*info->lnr != '\0') + c2->SRC_eaz = info->lnr[strlen(info->lnr)-1]; + else + c2->SRC_eaz = '0'; + } conn->call_ref = conn->talk->tappl[info->subcard]<<16; printf(">CONNECT_REQ "); if((err = capi_send(conn->talk,conn->talk->tappl[info->subcard],CAPI_CONNECT_REQ,m2,conn->conni[WF_CONNECT_CONF]=newmsgid(conn->talk))) < 0) @@ -931,7 +1050,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) int err = 0; isdn3_conn conn = 0; - if(talk->state == STATE_DEAD) + if(talk->tstate == STATE_DEAD) return -ENXIO; printf("CAPI: recv %d, in state %ld: ",isUI,talk->tstate); @@ -1050,6 +1169,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) isdn3_setup_conn (conn, EST_DISCONNECT); report_terminate(conn,c2->info,0); } + setstate(conn,99); { int err3 = 0; struct CAPI_disconnect_resp *c3; @@ -1064,8 +1184,6 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) if((err3 = capi_send(talk,capi->appl,CAPI_DISCONNECT_RESP,m3,capi->messid)) < 0) freemsg(m3); } - if(err == 0) - err = send_disconnect(conn,0,0); if(err == 0) err = err3; } @@ -1391,6 +1509,52 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) } } } + info->waitlocal = VAL_CAPI_TWAITLOCAL/HZ; + { /* get real wait value */ + int err; char skip = 0, subskip = 0; + mblk_t *inf = talk->card->info; + if(inf != NULL) { + streamchar *sta = inf->b_rptr; + ushort_t idx; + + while(m_getid(inf,&idx) == 0) { + long sap; + switch(idx) { + case ARG_PROTOCOL: + if (m_geti(inf,&sap) == 0) + skip = (sap != SAPI_CAPI); + break; + case ARG_SUBPROT: + if (m_geti(inf,&sap) == 0 && !skip) { + switch(sap) { + case SAPI_CAPI_BINTEC: + skip=0; + break; + default: + /* Wrong card. TODO: Do something! */ + inf->b_rptr = sta; + return -ENXIO; + } + } + break; + case ARG_SUBCARD: + if (m_geti(inf,&sap) == 0 && !skip) + subskip = (sap != info->subcard+1); + break; + case ARG_LWAIT: + if(skip || subskip) + break; + { + long x; + if((err = m_geti(inf,&x)) >= 0) + info->waitlocal = x; + } + break; + } + } + inf->b_rptr = sta; + } + } if(c2->DST_eaz) { info->lnr[0] = '/'; info->lnr[1] = c2->DST_eaz; @@ -1399,21 +1563,12 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) info->lnr[0] = '\0'; info->service = (c2->DST_service << 8) | c2->DST_addinfo; if(c2->telnolen > 1) { - int nrlen = c2->telnolen; - switch(*data->b_rptr) { - case 0x91: /* international number */ - case 0xA1: /* national number */ - data->b_rptr++; nrlen--; - if(data->b_rptr[nrlen-1] == 'S') /* SPV */ - nrlen--; - if(nrlen >= MAXNR) - nrlen = MAXNR-1; - bcopy(data->b_rptr,info->nr,nrlen); - break; - default: - err = -EINVAL; - break; - } + int nrlen; + --data->b_rptr; + data->b_rptr += getnr(info->nr,data->b_rptr); + nrlen = strlen(info->nr); + if(nrlen > 0 && (info->nr[nrlen-1] == 'S' || info->nr[nrlen-1] == 's')) + info->nr[nrlen-1] = '\0'; } conn->call_ref = (capi->appl << 16) | c2->plci; @@ -1421,7 +1576,15 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) conn->minorstate |= MS_INCOMING; if(err >= 0) { - setstate(conn,6); + if(c2->DST_eaz) { + setstate(conn,7); + report_incoming(conn); + } else if(conn->talk->state & (1<<(info->subcard+ST_pbx))) { + setstate(conn,6); /* no report yet */ + } else { + setstate(conn,6); + report_incoming(conn); + } break; } } @@ -1500,27 +1663,11 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) break; case AI_DAD: printf("DAD "); - switch(*data->b_rptr) { - case 0x81: - { - int nrlen = c2->infolen; - int haslen = strlen(info->lnr); - if(haslen == 0) { - haslen = 1; - info->lnr[0] = '/'; - } - data->b_rptr++; nrlen--; - if(nrlen >= MAXNR-haslen) - nrlen = MAXNR-haslen-1; - bcopy(data->b_rptr,info->lnr+haslen,nrlen); - info->lnr[nrlen+1]='\0'; - setstate(conn,6); - } - break; - default: - err = -EINVAL; - break; - } + --data->b_rptr; + data->b_rptr += getnr(info->lnr,data->b_rptr); + if(conn->state == 6) + checknrlen(conn); + goto empt; break; case AI_UUINFO: printf("UUINFO "); @@ -1603,44 +1750,43 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) { int dodebug = 0; { - mblk_t *info = talk->card->info; - if(info != NULL) { - streamchar *sta = info->b_rptr; + mblk_t *inf = talk->card->info; + if(inf != NULL) { + streamchar *sta = inf->b_rptr; ushort_t idx; - char skip = 0; + char skip = 0, subskip = 0; - while(m_getid(info,&idx) == 0) { + while(m_getid(inf,&idx) == 0) { long sap; switch(idx) { case ARG_PROTOCOL: - if (m_geti(info,&sap) == 0) { - skip = (sap != SAPI_CAPI); - } + if (m_geti(inf,&sap) == 0) + skip = (sap != SAPI_CAPI); break; case ARG_SUBPROT: - if (m_geti(info,&sap) == 0 && !skip) { + if (m_geti(inf,&sap) == 0 && !skip) { switch(sap) { case SAPI_CAPI_BINTEC: skip=0; break; default: /* Wrong card. Do something! */ - info->b_rptr = sta; + inf->b_rptr = sta; return -ENXIO; } } break; case ARG_SUBCARD: - if (m_geti(info,&sap) == 0 && !skip) - skip = (sap != talk->regnum+1); + if (m_geti(inf,&sap) == 0 && !skip) + subskip = (sap != talk->regnum+1); break; case ARG_DEBUG: - if(skip) + if(skip || subskip) break; dodebug = 1; break; case ARG_EAZ: - if(skip) + if(skip || subskip) break; if(talk->state & 1<<(talk->regnum+ST_pbx)) break; @@ -1650,9 +1796,9 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) mblk_t *mp; int len; - if((err = m_getc(info,&eaz)) < 0) + if((err = m_getc(inf,&eaz)) < 0) break; - if((len = m_getstrlen(info)) < 0) + if((len = m_getstrlen(inf)) < 0) break; mp = allocb(sizeof(*ce)+len, BPRI_MED); if(mp == NULL) @@ -1661,7 +1807,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) bzero(ce,sizeof(*ce)); ce->eaz = eaz; ce->telnolen = len; - if((err = m_getstr(info,mp->b_wptr,len)) < 0) { + if((err = m_getstr(inf,mp->b_wptr,len)) < 0) { freemsg(mp); break; } @@ -1675,7 +1821,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) break; /* ARG_EAZ */ } } - info->b_rptr = sta; + inf->b_rptr = sta; } } if((talk->tstate == STATE_REGISTER) && dodebug) { @@ -1709,47 +1855,46 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) c2->eaz_mask = 0x03FF; c2->service_mask = 0xE7BF; { /* Find correct masks */ - int err; char skip = 0; - mblk_t *info = talk->card->info; - if(info != NULL) { - streamchar *sta = info->b_rptr; + int err; char skip = 0, subskip = 0; + mblk_t *inf = talk->card->info; + if(inf != NULL) { + streamchar *sta = inf->b_rptr; ushort_t idx; - while(m_getid(info,&idx) == 0) { + while(m_getid(inf,&idx) == 0) { long sap; switch(idx) { case ARG_PROTOCOL: - if (m_geti(info,&sap) == 0) { - skip = (sap != SAPI_CAPI); - } + if (m_geti(inf,&sap) == 0) + skip = (sap != SAPI_CAPI); break; case ARG_SUBPROT: - if (m_geti(info,&sap) == 0 && !skip) { + if (m_geti(inf,&sap) == 0 && !skip) { switch(sap) { case SAPI_CAPI_BINTEC: skip=0; break; default: /* Wrong card. TODO: Do something! */ - info->b_rptr = sta; + inf->b_rptr = sta; return -ENXIO; } } break; case ARG_SUBCARD: - if (m_geti(info,&sap) == 0 && !skip) - skip = (sap != talk->regnum+1); + if (m_geti(inf,&sap) == 0 && !skip) + subskip = (sap != talk->regnum+1); break; case ARG_LISTEN: + if(skip || subskip) + break; { long x; - if(skip) - break; - if((err = m_getx(info,&x)) >= 0) { + if((err = m_getx(inf,&x)) >= 0) { c2->eaz_mask = x; - if((err = m_getx(info,&x)) >= 0) { + if((err = m_getx(inf,&x)) >= 0) { c2->service_mask = x; - if((err = m_getx(info,&x)) >= 0) { + if((err = m_getx(inf,&x)) >= 0) { c2->info_mask = x; } } @@ -1758,10 +1903,15 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) break; } } - info->b_rptr = sta; + inf->b_rptr = sta; } } - printf(">LISTEN_RESP "); + if(talk->state & 1<<(talk->regnum+ST_pbx)) + c2->info_mask |= 0x40; + else + c2->info_mask &=~ 0x40; + + printf(">LISTEN_REQ "); if((err = capi_send(talk,talk->tappl[talk->regnum],CAPI_LISTEN_REQ,mp,capi->messid)) < 0) { freemsg(mp); @@ -2044,7 +2194,7 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) int force = 0; uchar_t cause = 0; - if(conn->talk->state == STATE_DEAD) + if(conn->talk->tstate == STATE_DEAD) return -ENXIO; printf("CAPI: sendcmd %05lx %04x: ",conn->call_ref,id); @@ -2122,14 +2272,14 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) break; case ARG_LNUMBER: m_getskip (data); - if ((err = m_getstr (data, (char *) info->lnr, MAXNR)) != 0) { + if ((err = m_getstr (data, (uchar_t *) info->lnr, MAXNR)) != 0) { printf("GetStr LNumber: "); goto RetErr; } break; case ARG_NUMBER: m_getskip (data); - if ((err = m_getstr (data, (char *) info->nr, MAXNR)) != 0) { + if ((err = m_getstr (data, (uchar_t *) info->nr, MAXNR)) != 0) { printf("GetStr Number: "); goto RetErr; } @@ -2146,12 +2296,14 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) switch (id) { case CMD_ANSWER: { + if(conn->talk->tstate != STATE_RUNNING) + return -ENXIO; if (data == NULL) { printf("DataNull: "); conn->lockit--; return -EINVAL; } - if(conn->state != 7) { + if(conn->state != 6 && conn->state != 7) { printf("CAPI error: ANSWER in bad state!\n"); conn->lockit--; return -EINVAL; @@ -2169,6 +2321,8 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) break; case CMD_DIAL: { + if(conn->talk->tstate != STATE_RUNNING) + return -ENXIO; conn->minorstate |= MS_OUTGOING | MS_WANTCONN; isdn3_setup_conn (conn, EST_NO_CHANGE); @@ -2210,8 +2364,8 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) break; } - checkterm(conn); conn->lockit--; + checkterm(conn); return err; } @@ -2219,16 +2373,6 @@ static void report (isdn3_conn conn, mblk_t * data) { struct capi_info *info; - printf("CAPI: report %05lx: ",conn->call_ref); - { - mblk_t *mb = data; - if(mb == NULL) printf("NULL"); else - while(mb != NULL) { - dumpascii(mb->b_rptr,mb->b_wptr-mb->b_rptr); - mb = mb->b_cont; - } - } - printf("\n"); info = conn->p_data; if (info == NULL) return; @@ -2244,7 +2388,7 @@ report (isdn3_conn conn, mblk_t * data) m_putsx (data, ARG_SERVICE); m_putx (data, info->service); } - if(info->subcard != (unsigned char) ~0) { + if(info->subcard != (uchar_t) ~0) { m_putsx (data, ARG_SUBCARD); m_puti (data,info->subcard+1); } @@ -2274,7 +2418,8 @@ killconn (isdn3_conn conn, char force) conn->lockit++; if (force) { untimer (CAPI_TCONN, conn); - untimer (CAPI_TWAITEAZ, conn); + untimer (CAPI_TWAITLOCAL, conn); + untimer (CAPI_TWAITFIRSTLOCAL, conn); untimer (CAPI_TFOO, conn); } if(conn->state == 0) { @@ -2309,7 +2454,6 @@ newcard (isdn3_card card) if(card->is_up) chstate (talk, DL_ESTABLISH_CONF,0); - } static ulong_t diff --git a/isdn_3/isdn_3.c b/isdn_3/isdn_3.c index 6aac16b..404246c 100644 --- a/isdn_3/isdn_3.c +++ b/isdn_3/isdn_3.c @@ -2049,9 +2049,8 @@ printf("ErX k\n"); conn->lockit++; isdn3_setup_conn (conn, EST_NO_CHANGE); conn->lockit--; - if(conn->state == 0) { + if(conn->state == 0 && conn->id_msg == 0) isdn3_killconn(conn,0); - } } } else { if (minor == 0) { @@ -2150,9 +2149,8 @@ printf("ErX k\n"); conn->lockit++; isdn3_setup_conn (conn, EST_NO_CHANGE); conn->lockit--; - if(conn->state == 0) { - /* XXX */ - } + if(conn->state == 0 && conn->id_msg == 0) + isdn3_killconn(conn,0); } else { #if 1 printf("ErrOut 2c"); @@ -2363,7 +2361,7 @@ if(theID == CMD_OFF) printf(" D9 "); if (mb != NULL) { m_putid (mb, IND_ERR); m_putsx (mb, ARG_ERRNO); - m_puti (mb, err); + m_puti (mb, (err>0) ? err : -err); if(conn_id == 0 && conn != NULL) conn_id = conn->conn_id; if(conn_id != 0) { @@ -2634,6 +2632,15 @@ isdn3_flags(mblk_t *info, uchar_t protocol, uchar_t subprot) case ARG_L2CLOSE: flags &=~ FL_L2KEEP; break; + case ARG_BUG1: + flags |= FL_BUG1; + break; + case ARG_BUG2: + flags |= FL_BUG2; + break; + case ARG_BUG3: + flags |= FL_BUG3; + break; default: break; } diff --git a/isdn_3/phone.c b/isdn_3/phone.c index 3a38fd7..edb8c94 100644 --- a/isdn_3/phone.c +++ b/isdn_3/phone.c @@ -40,9 +40,6 @@ phone_sendback (isdn3_conn conn, uchar_t msgtype, mblk_t * data) if (data != NULL) linkb (mb, data); - *mb->b_wptr++ = conn->subprotocol; - *mb->b_wptr++ = creflen; - if (conn->subprotocol == SAPI_PHONE_DSS1) { if(conn->card == NULL || conn->card->bchans <= 2) { if (creflen < 1) @@ -53,6 +50,9 @@ phone_sendback (isdn3_conn conn, uchar_t msgtype, mblk_t * data) } } + *mb->b_wptr++ = conn->subprotocol; + *mb->b_wptr++ = creflen; + if (creflen > 0) { int clen = creflen; diff --git a/isdn_3/prot_ETS.c b/isdn_3/prot_ETS.c index f8b7451..ae830e4 100644 --- a/isdn_3/prot_ETS.c +++ b/isdn_3/prot_ETS.c @@ -675,10 +675,15 @@ get_ET_nr (isdn3_conn conn, uchar_t * data, int len, uchar_t *nrpos, uchar_t wha return 0; switch(*qd_data & 0x70) { case 0x00: /* unknown */ - if(qd_data[0] == 0x00 && qd_data[1] == 0x83) - *nrpos++ = '='; /* at least one PBX is stupid */ - else if(qd_data[0] == 0x81) - *nrpos++='.'; /* the very same PBX */ + { + long flags = isdn3_flags(conn->card->info,-1,-1); + if(flags & FL_BUG1) { + if(qd_data[0] == 0x00 && qd_data[1] == 0x83) + *nrpos++ = '='; /* at least one PBX is stupid */ + else if(qd_data[0] == 0x81) + *nrpos++='.'; /* the very same PBX */ + } + } break; case 0x10: /* international */ *nrpos++='+'; diff --git a/isdn_4/cf.c b/isdn_4/cf.c index bf386c1..7d6a9af 100644 --- a/isdn_4/cf.c +++ b/isdn_4/cf.c @@ -326,13 +326,15 @@ read_file (FILE * ffile, char *errf) if (skipsp (&li)) break; if ((c->num = atoi (li)) == 0 && li[0] != '0') break; + if (skipsp (&li)) break; + if ((c->num2 = atoi (li)) == 0 && li[0] != '0') + break; if (skipsp (&li)) break; c->arg = li; if(!skipsp (&li)) break; chkone(c); do_subclass(c); c->card = str_enter(c->card); c->arg = str_enter(c->arg); - c->num2 = ++seqnum; app (&cf_LF, c); continue; case CHAR2 ('C', 'M'): diff --git a/isdn_4/conn.c b/isdn_4/conn.c index 69e2a71..d80257d 100644 --- a/isdn_4/conn.c +++ b/isdn_4/conn.c @@ -248,7 +248,8 @@ Xsetconnstate(const char *deb_file, unsigned int deb_line,conninfo conn, CState } if(state >= c_going_up) { conn->got_id = 0; - conn->got_hd = 0; + if(state > c_going_up) + conn->got_hd = 0; } if((state == c_off) && !conn->retime && (conn->flags & F_PERMANENT)) { conn->retime = 1; @@ -421,7 +422,7 @@ try_reconn(struct conninfo *conn) /* anything else is added by startconn */ - if((xconn = startconn(cg,0,0, &ret)) == conn) { + if((xconn = startconn(cg,0,0, &ret, NULL)) == conn) { dropgrab(cg); freeb(md); return; diff --git a/isdn_4/devs.c b/isdn_4/devs.c index e24bca8..2c54523 100644 --- a/isdn_4/devs.c +++ b/isdn_4/devs.c @@ -83,7 +83,7 @@ checkdev(int dev) else sbuf[len]='\0'; pid = atoi(sbuf); - if(pid <= 0 || (kill(pid,0) == -1 && errno == -ESRCH)) { + if(pid <= 0 || (kill(pid,0) == -1 && errno == ESRCH)) { if(0)syslog(LOG_WARNING,"Checking %s: unkillable, pid %d, deleted, %m",permtt1, pid); unlink(permtt1); } @@ -104,7 +104,7 @@ checkdev(int dev) else sbuf[len]='\0'; pid = atoi(sbuf); - if(pid <= 0 || (kill(pid,0) == -1 && errno == -ESRCH)) { + if(pid <= 0 || (kill(pid,0) == -1 && errno == ESRCH)) { if(0)syslog(LOG_WARNING,"Checking %s: unkillable, pid %d, deleted, %m",permtt2, pid); unlink(permtt2); } diff --git a/isdn_4/info.c b/isdn_4/info.c index d8d77ca..48db261 100644 --- a/isdn_4/info.c +++ b/isdn_4/info.c @@ -50,6 +50,7 @@ long hdrval; char no_error; struct loader *loader; long errnum; +char incomplete; /* Take the incoming arguments and put them into their variables. */ @@ -60,6 +61,9 @@ parse_arg(void) case ARG_CAUSE: (void)m_getid(&xx,&cause); break; + case ARG_INCOMPLETE: + incomplete = 1; + break; case ARG_CHARGE: (void)m_geti(&xx,&charge); break; @@ -292,6 +296,7 @@ init_vars (void) lnr[0] = '\0'; uid = -1; connref = 0; + incomplete = 0; dialin = -1; charge = 0; cause = 0; @@ -534,7 +539,7 @@ do_cardproto(void) return 2; } - if (pushcardprot (cg, minor) == 0) { + if (pushcardprot (cg, minor, connref) == 0) { dropgrab(cg); /* Success */ return 0; @@ -611,7 +616,7 @@ do_proto(void) m_putid (&xx, CMD_CLOSE); m_putsx (&xx, ARG_MINOR); m_puti (&xx, minor); - if(conn->minor == minor) { + if(conn != NULL && conn->minor == minor) { conn->minor = 0; if(conn->pid == 0) dropconn(conn); @@ -624,7 +629,7 @@ do_proto(void) (void) strwrite (xs_mon, ans, xlen, 1); return 2; } - if (pushprot (cg, minor, ind == IND_PROTO_AGAIN) == 0) { + if (pushprot (cg, minor, conn ? conn->connref : 0, ind == IND_PROTO_AGAIN) == 0) { /* Success */ dropgrab(cg); return 0; @@ -659,12 +664,14 @@ do_incoming(void) conngrab cg = newgrab(NULL); if(cg == NULL) { resp = "OutOfMemFoo"; + incomplete = 0; goto inc_err; } cg->flags = F_INCOMING|F_DIALUP|F_PERMANENT|F_NRCOMPLETE|F_LNRCOMPLETE; cinf = allocb(len,BPRI_LO); if(cinf == NULL) { resp = "OutOfMemFoo"; + incomplete = 0; goto inc_err; } @@ -673,8 +680,12 @@ do_incoming(void) cinf->b_wptr += len; cg->par_in = cinf; cg->card = str_enter(crd); - if ((resp = findit (&cg,0)) != NULL) + if ((resp = findit (&cg,0)) != NULL) { + if(incomplete && !strncmp(resp+1,"LNrIncomp",8)) + resp = "waiting for number"; goto inc_err; + } + incomplete = 0; if (quitnow) { resp = "SHUTTING DOWN"; goto inc_err; @@ -709,7 +720,7 @@ do_incoming(void) resp = "0BUSY other"; goto inc_err; } - if(((conn = startconn(cg,fminor,connref,&resp)) != NULL) && (resp != NULL)) { + if(((conn = startconn(cg,fminor,connref,&resp, NULL)) != NULL) && (resp != NULL)) { /* An existing connection feels responsible for this. */ mblk_t *mz; if(conn->state == c_forceoff) { @@ -803,7 +814,7 @@ do_incoming(void) #if 1 /* cg->flags &=~ F_INCOMING; */ /* cg->flags |= F_OUTGOING; */ - if(startconn(cg,fminor,connref,NULL) != conn) + if(startconn(cg,fminor,connref,NULL, NULL) != conn) resp = "ClashRestart Failed"; #endif conn = malloc(sizeof(*conn)); @@ -852,60 +863,61 @@ do_incoming(void) cont: if (resp != NULL) { inc_err: - xx.b_wptr = xx.b_rptr = ans; - xx.b_datap = &db; - db.db_base = ans; - db.db_lim = ans + sizeof (ans); + if(!incomplete) { + xx.b_wptr = xx.b_rptr = ans; + xx.b_datap = &db; + db.db_base = ans; + db.db_lim = ans + sizeof (ans); - if(1)printf("Dis3 "); - m_putid (&xx, CMD_OFF); - if(connref != 0) { - m_putsx (&xx, ARG_CONNREF); - m_puti (&xx, connref); - } - - /* BUSY-if-no-channel is very ugly but unavoidable when - sharing the bus with brain-damaged devices (there are - many out there) which don't answer at all when they're busy. - Grr. The PBX should catch this case. */ - /* We send the BUSY fast if _we_re busy, else we have to send it slow - because somebody else might in fact answer... */ - m_putsx (&xx, ARG_CAUSE); - if((bchan < 0) || !strncmp(resp+1,"BUSY",4)) { - m_putsx2 (&xx, ID_N1_UserBusy); - if(!strcmp(resp+1,"BUSY") || (cg->flags & F_FASTDROP)) - m_putsx(&xx,ARG_FASTDROP); - - if(conn != NULL && (conn->flags & F_BACKCALL)) { - if(conn->want_reconn == 0) - conn->want_reconn = MAX_RECONN - (MAX_RECONN >> 1); - setconnstate(conn,conn->state); + if(1)printf("Dis3 "); + m_putid (&xx, CMD_OFF); + if(connref != 0) { + m_putsx (&xx, ARG_CONNREF); + m_puti (&xx, connref); } - } else { - if(cg->flags & F_NOREJECT) - m_putsx2 (&xx, ID_N1_NoChans); - else - m_putsx2 (&xx, ID_N1_CallRejected); - if(cg->flags & F_FASTDROP) - m_putsx(&xx,ARG_FASTDROP); - } - if(crd[0] != '\0') { - m_putsx(&xx,ARG_CARD); - m_putsz(&xx,crd); - } - if(callref != 0) { - m_putsx (&xx, ARG_CALLREF); - m_puti (&xx, callref); - } - if(cg != NULL) { - syslog (LOG_WARNING, "Got '%s' for %s/%s/%s/%s,%s", resp, cg->site, cg->protocol, cg->card, cg->cclass, nr); - } else - syslog (LOG_WARNING, "Got '%s' for ???,%s", resp, nr); - xlen = xx.b_wptr - xx.b_rptr; - DUMPW (ans, xlen); - (void) strwrite (xs_mon, ans, xlen, 1); + /* BUSY-if-no-channel is very ugly but unavoidable when + sharing the bus with brain-damaged devices (there are + many out there) which don't answer at all when they're busy. + Grr. The PBX should catch this case. */ + /* We send the BUSY fast if _we_re busy, else we have to send it slow + because somebody else might in fact answer... */ + m_putsx (&xx, ARG_CAUSE); + if((bchan < 0) || !strncmp(resp+1,"BUSY",4)) { + m_putsx2 (&xx, ID_N1_UserBusy); + if(!strcmp(resp+1,"BUSY") || (cg->flags & F_FASTDROP)) + m_putsx(&xx,ARG_FASTDROP); + if(conn != NULL && (conn->flags & F_BACKCALL)) { + if(conn->want_reconn == 0) + conn->want_reconn = MAX_RECONN - (MAX_RECONN >> 1); + setconnstate(conn,conn->state); + } + } else { + if(cg->flags & F_NOREJECT) + m_putsx2 (&xx, ID_N1_NoChans); + else + m_putsx2 (&xx, ID_N1_CallRejected); + if(cg->flags & F_FASTDROP) + m_putsx(&xx,ARG_FASTDROP); + } + if(crd[0] != '\0') { + m_putsx(&xx,ARG_CARD); + m_putsz(&xx,crd); + } + if(callref != 0) { + m_putsx (&xx, ARG_CALLREF); + m_puti (&xx, callref); + } + + if(cg != NULL) { + syslog (LOG_WARNING, "Got '%s' for %s/%s/%s/%s,%s", resp, cg->site, cg->protocol, cg->card, cg->cclass, nr); + } else + syslog (LOG_WARNING, "Got '%s' for ???,%s", resp, nr); + xlen = xx.b_wptr - xx.b_rptr; + DUMPW (ans, xlen); + (void) strwrite (xs_mon, ans, xlen, 1); + } conn = malloc(sizeof(*conn)); if(conn != NULL) { bzero(conn,sizeof(*conn)); @@ -1094,6 +1106,9 @@ do_disc(void) } } break; + case c_down: + setconnstate(conn,c_down); + break; default:; } } else { /* protocol stack isn't yet down */ @@ -1531,6 +1546,7 @@ do_wantconnect(void) } } if(conn->state < c_going_up) { + conn->got_hd = 0; setconnref(conn,0); try_reconn(conn); } @@ -1738,7 +1754,6 @@ do_atcmd(void) case 'l': /* AT/L */ case 'L': /* List connections and state changes. */ { - char buf[30]; struct conninfo *fconn; char *sp; msgbuf = malloc(10240); @@ -1798,8 +1813,7 @@ do_atcmd(void) conn->ignore = 3; conn->minor = minor; conn->next = isdn4_conn; isdn4_conn = conn; - sprintf(buf,"# Waiting %s...",conn->cardname); - resp = str_enter(buf); + sp += sprintf(sp,"# Waiting %s...",conn->cardname); return 1; } @@ -1842,7 +1856,7 @@ do_atcmd(void) } else conn->cardname = "*"; } - sprintf(buf,"# Monitoring %s...",conn->cardname);; + sprintf(buf,"# Monitoring %s...",conn->cardname); resp = str_enter(buf); return 1; } @@ -2110,11 +2124,17 @@ do_atcmd(void) dropgrab(cg); return 1; } + if(!(cg->flags & F_NRCOMPLETE)) { + freeb(md); + dropgrab(cg); + resp = "RemoteNr incomplete"; + return 1; + } cg->refs++; dropgrab(conn->cg); conn->cg = cg; setconnstate(conn,c_down); - if((conn = startconn(cg,fminor,0,NULL)) != NULL) { + if((conn = startconn(cg,fminor,0,NULL, NULL)) != NULL) { freeb(md); dropgrab(cg); break; diff --git a/isdn_4/loader.c b/isdn_4/loader.c index 65d2981..d29a8aa 100644 --- a/isdn_4/loader.c +++ b/isdn_4/loader.c @@ -15,7 +15,7 @@ struct loader { int nrfile; /* number loaded to card */ }; -/* cf_LF: num2: sequence number; num: block size */ +/* cf_LF: num2: wait after load; num: block size */ #endif static void @@ -121,17 +121,21 @@ void card_load(struct loader *ld) { cf dl,lf; - int do_again; + int do_again, thisseq; ld->timer = 0; again: do_again = 0; + thisseq = 0; + /* Now find the next applicable entry. ld->seqnum is the cf number of the + next file to load. */ for(lf = cf_LF; lf != NULL; lf = lf->next) { + thisseq++; if(!wildmatch(ld->name,lf->card)) continue; - if(ld->seqnum != 0 && ld->seqnum != lf->num2) { - if(ld->seqnum < lf->num2 && (do_again == 0 || do_again > lf->num2)) - do_again = ld->seqnum; + if(ld->seqnum != 0 && ld->seqnum != thisseq) { + if(ld->seqnum < thisseq && (do_again == 0 || do_again < thisseq)) + do_again = thisseq; continue; } break; @@ -216,11 +220,11 @@ card_load(struct loader *ld) free(buf); if(do_again) { ld->timer = 1; - timeout(card_load,ld,ld->file ? HZ : HZ*(ld->nrfile+2)); + timeout(card_load,ld,(ld->file || !lf) ? HZ : (HZ*lf->num2+HZ/3)); return; } } else { - ld->seqnum = lf->num2; + ld->seqnum = thisseq; ld->nrfile++; ld->file = fopen(lf->arg,"r"); ld->foffset = 0; @@ -229,7 +233,7 @@ card_load(struct loader *ld) goto ex_load; } ld->timer = 1; - timeout(card_load,ld,HZ*2); + timeout(card_load,ld,HZ/3); return; } diff --git a/isdn_4/master.h b/isdn_4/master.h index 727ae44..73911b1 100644 --- a/isdn_4/master.h +++ b/isdn_4/master.h @@ -403,9 +403,10 @@ void putenv2 (const char *key, const char *val); char *match_nr (char *extnr, char *locnr, char *locpref); int match_suffix(char *extsuf, char *extnr); +int match_incom(char *extsuf, char *extnr); char *build_nr (char *extnr, char *locnr, char *locpref, int islocal); char *append_nr(char *extnr, char *extext); -char *strip_nr(char *extnr); +char *strip_nr(char *extnr, int keepfirst); /** @@ -474,8 +475,8 @@ char * findit (conngrab *foo, int nobusy); mblk_t * getprot (char *protocol, char *site, char *cclass, char *suffix); #endif -int pushprot (conngrab cg, int minor, char update); -int pushcardprot (conngrab cg, int minor); +int pushprot (conngrab cg, int minor, int connref, char update); +int pushcardprot (conngrab cg, int minor, int connref); void xquit (const char *s, const char *t); @@ -483,7 +484,7 @@ EXTERN int quitnow INIT(0); void panic(const char *x, ...); -struct conninfo * startconn(conngrab cg, int fminor, int connref, char **ret); +struct conninfo * startconn(conngrab cg, int fminor, int connref, char **ret, conngrab *retcg); EXTERN struct conninfo *zzconn INIT(NULL); void dropdead(void); char * runprog (cf cfr, struct conninfo **rconn, conngrab *foo); diff --git a/isdn_4/match.c b/isdn_4/match.c index b741514..5673d04 100644 --- a/isdn_4/match.c +++ b/isdn_4/match.c @@ -49,7 +49,7 @@ pmatch1 (cf prot, conngrab *cgm) chkone(prot); chkone(cg); /* Basic preprocessing */ sit = wildmatch(cg->site, prot->site); if(sit == NULL) return "7ERR Match SITE"; - pro = wildmatch(cg->protocol,prot->protocol);if(pro == NULL) return "6ERR Match PROTOCOL"; + pro = wildmatch(cg->protocol,prot->protocol);if(pro == NULL) return "7ERR Match PROTOCOL"; car = wildmatch(cg->card, prot->card); if(car == NULL) return "6ERR Match CARD"; cla =classmatch(cg->cclass, prot->cclass); if(cla == NULL) return "6ERR Match CLASS"; sub = maskmatch(cg->mask, prot->mask); if(sub == 0) return "6ERR Match SUBCARD"; @@ -104,7 +104,7 @@ pmatch1 (cf prot, conngrab *cgm) return "0OUT of MEMORY"; } } -#define DG(str) { if(first) { Xbreak(); dropgrab(cgc); dropgrab(cg); return str; } goto Ex; } +#define DG(str) do { if(first) { dropgrab(cgc); dropgrab(cg); return str; } goto Ex; } while(0) /* Remember pointers into the parameter strings. */ mbs_in = ((cgc->par_in !=NULL)? cgc->par_in->b_rptr : NULL); @@ -162,8 +162,8 @@ pmatch1 (cf prot, conngrab *cgm) /* Put it all together. */ #define CHK(_what,_t) { \ - if((nrt & ARG_OUT)&& (cgc->par_out!= NULL)) CHKO(_what,_t); \ - if((nrt & ARG_IN) && (cgc->par_in != NULL)) CHKI(_what,_t); } break + if((nrt & ARG_OUT)&& (cgc->flags & F_OUTGOING) && (cgc->par_out!= NULL)) CHKO(_what,_t); \ + if((nrt & ARG_IN) && (cgc->flags & F_INCOMING) && (cgc->par_in != NULL)) CHKI(_what,_t); } break /* Same as above, but for vectorized parameters with optional bitmasks. */ /* You are not supposed to understand this code. */ @@ -235,8 +235,8 @@ pmatch1 (cf prot, conngrab *cgm) ex:; }) /**/ #define CHKV() { \ - if((nrt & ARG_OUT)&& (cgc->par_out!= NULL)) CHKVO(); \ - if((nrt & ARG_IN) && (cgc->par_in != NULL)) CHKVI(); } break + if((nrt & ARG_OUT)&& (cgc->flags & F_OUTGOING) && (cgc->par_out!= NULL)) CHKVO(); \ + if((nrt & ARG_IN) && (cgc->flags & F_INCOMING) && (cgc->par_in != NULL)) CHKVI(); } break /* Simple one-shot labels that can't be undone (and don't need to be). */ #define CHKX() \ @@ -284,20 +284,28 @@ pmatch1 (cf prot, conngrab *cgm) if (m_getstr (cand, yy, MAXNR) != 0) break; - if ((nrt & ARG_IN) && (cgc->nrsuf != NULL)) { - if(0)printf("MatchSuffix %s and %s\n",cgc->nrsuf,yy); - if(!match_suffix(cgc->nrsuf,yy)) { if(cgc->flags & F_OUTGOING) { printf(" SuffixBadness "); Xbreak(); } else DG("2WrongNrSuffix 2") } - } else if((nrt & ARG_OUT) && (cgc->nrsuf == NULL)) - cgc->nrsuf = str_enter(yy); - if((cgc->nr != NULL) && (nrt & ARG_OUT) && !(cgc->flags & F_NRCOMPLETE)) { - char *foo = append_nr(cgc->nr,yy); - if(0)printf("Append1 %s,%s -> %s\n",cgc->nr,yy,foo); - cgc->nr = foo; - if(cgc->nr != NULL) { - if(0)printf("Strip1 %s -> %s\n",cg->nr,strip_nr(cg->nr)); - if(strip_nr(cgc->nr) != NULL) - cgc->flags |= F_NRCOMPLETE; - } else { if(cgc->flags & F_OUTGOING) { printf(" SuffixBadness2 "); Xbreak(); } else DG("3WrongNrSuffix 1") } + if ((nrt & ARG_IN) && (cgc->flags & F_INCOMING)) { + if (cgc->nrsuf != NULL) { + if(1)printf("MatchSuffix %s and %s\n",cgc->nrsuf,yy); + if(match_suffix(cgc->nrsuf,yy) <= 0) DG("2WrongNrSuffix 2"); + } else + cgc->nrsuf = str_enter(yy); + } + if((nrt & ARG_OUT) &&(cgc->flags & F_OUTGOING)) { + if (cgc->nrsuf == NULL) + cgc->nrsuf = str_enter(yy); + else if(match_suffix(cgc->nrsuf,yy) <= 0) + DG("4NrOutMatch"); + if((cgc->nr != NULL) && !(cgc->flags & F_NRCOMPLETE)) { + char *foo = append_nr(cgc->nr,yy); + if(1)printf("Append1 %s,%s -> %s\n",cgc->nr,yy,foo); + cgc->nr = foo; + if(cgc->nr != NULL) { + if(0)printf("Strip1 %s -> %s\n",cg->nr,strip_nr(cg->nr,0)); + if(strip_nr(cgc->nr,0) != NULL) + cgc->flags |= F_NRCOMPLETE; + } else DG("3WrongNrSuffix 1"); + } } } break; @@ -306,23 +314,39 @@ pmatch1 (cf prot, conngrab *cgm) case ARG_LNUMBER: { char yy[MAXNR + 2]; + int suf; if (m_getstr (cand, yy, MAXNR) != 0) break; - if ((nrt & ARG_IN) && (cgc->lnrsuf != NULL)) { - if(0)printf("MatchLSuffix %s and %s\n",cgc->lnrsuf,yy); - if(!match_suffix(cgc->lnrsuf,yy)) { if(cgc->flags & F_OUTGOING) { printf(" SuffixBadness3 "); Xbreak(); } else DG("3WrongLNrSuffix 2") } - } else if((nrt & ARG_OUT) && (cgc->lnrsuf == NULL)) - cgc->lnrsuf = str_enter(yy); - if((cgc->lnr != NULL) && (nrt & ARG_OUT) && !(cgc->flags & F_LNRCOMPLETE)) { - char *foo = append_nr(cgc->lnr,yy); - if(0)printf("Append2 %s,%s -> %s\n",cgc->lnr,yy,foo); - cgc->lnr = foo; - if(cgc->lnr != NULL) { - if(0)printf("Strip2 %s -> %s\n",cg->lnr,strip_nr(cg->lnr)); - if(strip_nr(cgc->lnr) != NULL) - cgc->flags |= F_LNRCOMPLETE; - } else { if(cgc->flags & F_OUTGOING) { printf(" SuffixBadness4 "); Xbreak(); } else DG("3WrongLNrSuffix 1") } + if ((nrt & ARG_IN) && (cgc->flags & F_INCOMING)) { + if(cgc->lnrsuf != NULL) { + if(1)printf("MatchLSuffix %s and %s\n",cgc->lnrsuf,yy); + if((suf = match_suffix(cgc->lnrsuf,yy)) <= 0) + DG(suf ? "3LNrIncompSuffix 2" : "3WrongLNrSuffix 2"); + } else + DG("4LNrIncompSuffix 3"); + } + if((nrt & ARG_OUT) && (cgc->flags & F_OUTGOING)) { + if(cgc->lnrsuf == NULL) + cgc->lnrsuf = str_enter(yy); + else if(match_suffix(cgc->lnrsuf,yy) <= 0) + DG("4LNrOutMatch"); + + if((cgc->lnr != NULL) && !(cgc->flags & F_LNRCOMPLETE)) { + char *foo = append_nr(cgc->lnr,yy); + if(1)printf("Append2 %s,%s -> %s\n",cgc->lnr,yy,foo); + cgc->lnr = foo; + if(cgc->lnr != NULL) { + if(0)printf("Strip2 %s -> %s\n",cg->lnr,strip_nr(cg->lnr,1)); + if(strip_nr(cgc->lnr,1) != NULL) + cgc->flags |= F_LNRCOMPLETE; + } else { + if((cgc->lnrsuf != 0) && (match_suffix(cgc->lnrsuf,yy) < 0)) + DG("3LNrIncompSuffix 4"); + else + DG("3WrongLNrSuffix 4"); + } + } } } break; @@ -411,7 +435,7 @@ findsite (conngrab *foo, int ignbusy) cf dp = NULL; cf dl = NULL; cf d = NULL; - char *errstr = "8ERR FIND"; + char *errstr = "8No matching ISDN card / DL entry"; char *errstrx; int numwrap = 1; conngrab cg = *foo; @@ -443,12 +467,12 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ break; } if (dp == NULL) { - errstr = "9CARD UNKNOWN"; + errstr = "9No matching DP entry"; continue; } matcrd = crd; matsub = sub; - } /* if everybody had DSS1, we could skip the prefix nonsense... */ + } /* Now find a site to call out to. */ /* The numwrap stuff makes sure that we restart where we left off last @@ -487,10 +511,8 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ if((matsit = wildmatch(cg->site,d->site)) == NULL) continue; if((matpro = wildmatch(cg->protocol,d->protocol)) == NULL) continue; if((matcar = wildmatch(matcrd,d->card)) == NULL) continue; - if((matcla = classmatch(cg->cclass,d->cclass)) == NULL) continue; - if((matcla = classmatch(matcla,matclass)) == NULL) continue; + if((matcla = classmatch(matclass,d->cclass)) == NULL) continue; if((matsub = maskmatch(cg->mask,d->mask)) == 0) continue; - if((matsub = maskmatch(matsub,matsub)) == 0) continue; if(!matchflag(cg->flags,d->type)) continue; /* Preliminary match OK, remember the data so far. */ @@ -501,7 +523,6 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ cg->site = matsit; cg->cclass = matcla; cg->card = matcar; cg->protocol = matpro; cg->mask = matsub; - if(0)printf("%s...",matsit); if(!(cg->flags & F_LEASED)) { /* Now figure out the numbers... */ @@ -536,8 +557,8 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ } continue; } - } else if(0) { /* Hmmm... */ - cg->lnr = build_nr(dl->arg,dl->arg,((cg->flags&F_INCOMING) && (dp->args != NULL)) ? dp->args : dp->arg, 0); + } else if(!(cg->flags & F_INCOMING)) { /* Hmmm... */ + cg->lnr = build_nr(dl->arg,dl->arg,((cg->flags&F_INCOMING) && (dp->args != NULL)) ? dp->args : dp->arg, 2); if(cg->lnr == NULL) { if(*errstr > '4') { dropgrab(errcg); errcg = cg; cg->refs++; @@ -550,10 +571,33 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ /* Do we have a matching P line? */ if ((errstrx = pmatch (&cg)) == NULL) { - /* We have what we need. Now figure out if we can use it. */ + /* We should have what we need. Now figure out if we can use it... */ cf cl = NULL; int nrbchan = 0; + if(cg->nr != NULL && (cg->flags & (F_INCOMING|F_OUTGOING)) && !(cg->flags & F_NRCOMPLETE)) { + if(strip_nr(cg->nr,0) != NULL) + cg->flags |= F_NRCOMPLETE; + else { + if(*errstr > '3') { + errstr = "3RemoteNr incomplete"; + errcg = cg; cg->refs++; + } + continue; + } + } + if(cg->lnr != NULL && (cg->flags & (F_INCOMING|F_OUTGOING)) && !(cg->flags & F_LNRCOMPLETE)) { + if(strip_nr(cg->lnr,1) != NULL) + cg->flags |= F_LNRCOMPLETE; + else { + if(*errstr > '3') { + errstr = "3LocalNr incomplete"; + errcg = cg; cg->refs++; + } + continue; + } + } + /* Check if we know how many B channels the card has */ { struct isdncard *ca; @@ -660,8 +704,7 @@ findit (conngrab *foo, int ignbusy) char *errstr = "9NO CARD"; char *errstrx; struct isdncard *c; - char *card; - conngrab cg = newgrab(*foo); + conngrab cg = newgrab(*foo), cgc = NULL; conngrab errcg = NULL; int cardlim; @@ -673,12 +716,10 @@ findit (conngrab *foo, int ignbusy) return "0Not Now"; } p = cg->par_in; - card = cg->card; if(p != NULL) { streamchar *olds = p->b_rptr; char st[MAXNR + 2]; - char *card; long x; while (m_getsx (p, &id) == 0) { @@ -697,7 +738,7 @@ findit (conngrab *foo, int ignbusy) break; case ARG_CARD: m_getstr (p, st, 4); - if((card = wildmatch(st,cg->card)) == NULL) { + if((cg->card = wildmatch(str_enter(st),cg->card)) == NULL) { dropgrab(cg); return "0CARD MISMATCH"; } @@ -721,39 +762,43 @@ findit (conngrab *foo, int ignbusy) c = isdn4_card; cardidx %= cardlim; } - if(!wildmatch(card,c->name)) { + if(!wildmatch(cg->card,c->name)) { cardlim += c->nrdchan; continue; } - cg->card = c->name; cg->mask = 1; redo: + dropgrab(cgc); + cgc = newgrab(cg); + if(cgc == NULL) return "0NoMemFind"; + cardlim++; - if(cg->flags & F_INCOMING) /* never skip */ + cgc->card = c->name; + if(cgc->flags & F_INCOMING) /* never skip */ cardidx = 1; if(cardlim >= cardidx) { - if ((errstrx = findsite (&cg,ignbusy)) == NULL) { /* Found it */ + if ((errstrx = findsite (&cgc,ignbusy)) == NULL) { /* Found it */ cf crd; cardidx++; - cg->flags |= F_OUTCOMPLETE; + cgc->flags |= F_OUTCOMPLETE; if(c->cap & CHM_INTELLIGENT) { - dropgrab(*foo); - *foo = cg; + dropgrab(*foo); dropgrab(cg); + *foo = cgc; return NULL; } for (crd = cf_CM; crd != NULL; crd = crd->next) { if (!wildmatch (c->name, crd->card)) continue; - dropgrab(*foo); - *foo = cg; + dropgrab(*foo); dropgrab(cg); + *foo = cgc; return NULL; } errstrx = "0CM line missing"; } if(*errstrx < *errstr) { errstr = errstrx; - dropgrab(errcg); errcg = cg; + dropgrab(errcg); errcg = cgc; errcg->refs++; } } @@ -771,7 +816,7 @@ findit (conngrab *foo, int ignbusy) dropgrab(*foo); *foo = errcg; } - dropgrab(cg); + dropgrab(cg); dropgrab(cgc); return errstr; } diff --git a/isdn_4/nr.c b/isdn_4/nr.c index f561bfd..d2fba41 100644 --- a/isdn_4/nr.c +++ b/isdn_4/nr.c @@ -8,7 +8,6 @@ #include "master.h" - /** ** Number String Stuff **/ @@ -74,11 +73,11 @@ char *match_nr (char *extnr, char *locnr, char *locpref) if(*extpos == '\0') return ""; if(!isdigit(*extpos)) { - if(strcmp(extpos,locpos+1) && !wildmat(extpos,locpos+1)) + if(strcmp(extpos,locpos+1) && wildmat(extpos,locpos+1) <= 0) return NULL; } } else { - if(locpos[1] != '\0' && !wildmat(extpos,locpos+1)) + if(locpos[1] != '\0' && wildmat(extpos,locpos+1) <= 0) return NULL; } *destpos++=*locpos; @@ -117,7 +116,7 @@ int match_suffix(char *extsuf, char *extnr) if(*extsuf=='\0') return 1; extsuf++; extnr++; - return (wildmatch(extsuf,extnr) != NULL); + return (wildmat(extsuf,extnr)); } char *build_nr (char *extnr, char *locnr, char *locpref, int islocal) @@ -155,17 +154,20 @@ char *build_nr (char *extnr, char *locnr, char *locpref, int islocal) } if(lastprefpos==NULL) return NULL; - if(*prefpos == '\0' && islocal) { + if(*prefpos == '\0' && (islocal & 1)) { char *xextpos = strchr(extnr,'/'); char *xlocpos = strchr(locnr,'/'); if(xextpos != NULL && xlocpos != NULL && - (!strcmp(xextpos,xlocpos) || wildmatch(xextpos+1,xlocpos+1))) + (!strcmp(xextpos,xlocpos) || wildmatch(xextpos+1,xlocpos+1) > 0)) lastprefpos="/"; } locpos=strchr(locnr,*lastprefpos); extpos=strchr(extnr,*lastprefpos); - lastprefpos++; + if(islocal & 2) + *destpos++ = *lastprefpos++; + else + lastprefpos++; while(*lastprefpos != '\0' && isdigit(*lastprefpos)) { *destpos++ = *lastprefpos; lastprefpos++; @@ -197,7 +199,7 @@ char *append_nr(char *extnr, char *extext) return NULL; if((extpos = strchr(extnr,*extext)) == NULL) return NULL; - if(extpos[1] != '\0' && !wildmatch(extpos,extext)) + if(extpos[1] != '\0' && wildmatch(extpos,extext) <= 0) return NULL; while(extnr != extpos) *destpos++ = *extnr++; @@ -208,7 +210,7 @@ char *append_nr(char *extnr, char *extext) return str_enter(destnr); } -char *strip_nr(char *extnr) +char *strip_nr(char *extnr, int keepfirst) /* entfernt die Spezialzeichen aus einer vollständigen Nummer, zwecks Dialout; NULL wenn die Nummer unvollständig ist */ /* 123.45 -> 12345 */ @@ -219,7 +221,8 @@ char *strip_nr(char *extnr) char *destpos = destnr; int lastspc=1; - + if(keepfirst && (*extnr != '\0')) + *destpos++ = *extnr++; while(*extnr != '\0') { if(isdigit(*extnr)) { lastspc=0; diff --git a/isdn_4/util.c b/isdn_4/util.c index 125a857..936753f 100644 --- a/isdn_4/util.c +++ b/isdn_4/util.c @@ -52,9 +52,9 @@ char *wildmatch(char *a, char *b) return b; else if(b == NULL) return a; - else if(wildmat(a,b)) + else if(wildmat(a,b) > 0) return a; - else if(wildmat(b,a)) + else if(wildmat(b,a) > 0) return b; else return NULL; diff --git a/isdn_4/work.c b/isdn_4/work.c index d6097f1..4ad15d0 100644 --- a/isdn_4/work.c +++ b/isdn_4/work.c @@ -72,7 +72,7 @@ deadkid (void) /* Push protocols onto stream */ int -pushprot (conngrab cg, int minor, char update) +pushprot (conngrab cg, int minor, int connref, char update) { cf prot; char *mods = NULL; @@ -108,6 +108,14 @@ pushprot (conngrab cg, int minor, char update) m_putid (mj, PROTO_UPDATEMODLIST); else m_putid (mj, PROTO_MODLIST); + if(cg != NULL && cg->card != NULL && strcmp(cg->card,"*") != 0) { + m_putsx(mj,ARG_CARD); + m_putsz(mj,cg->card); + } + if(connref) { + m_putsx (mj, ARG_CONNREF); + m_puti(mj,connref); + } m_putsx (mj, ARG_MODE); /* set card mode */ m_putsz (mj, prot->arg); m_putdelim (mj); @@ -236,7 +244,7 @@ pushprot (conngrab cg, int minor, char update) /* Set ISDN card mode */ int -pushcardprot (conngrab cg, int minor) +pushcardprot (conngrab cg, int minor, int connref) { cf prot; cf cmod = NULL; @@ -276,7 +284,7 @@ pushcardprot (conngrab cg, int minor) return -ENOENT; if (minor != 0) { - mblk_t *mj = allocb (32, BPRI_LO); + mblk_t *mj = allocb (64, BPRI_LO); int len; if (mj == NULL) @@ -284,6 +292,14 @@ pushcardprot (conngrab cg, int minor) m_putid (mj, CMD_CARDSETUP); m_putsx (mj, ARG_MINOR); m_puti (mj, minor); + if(cg != NULL && cg->card != NULL && strcmp(cg->card,"*") != 0) { + m_putsx(mj,ARG_CARD); + m_putsz(mj,cg->card); + } + if(connref != 0) { + m_putsx (mj, ARG_CONNREF); + m_puti (mj, connref); + } m_putdelim (mj); m_putc (mj, PROTO_MODE); m_puti (mj, num); @@ -299,7 +315,7 @@ pushcardprot (conngrab cg, int minor) /* Startup a connection... */ struct conninfo * -startconn(conngrab cg, int fminor, int connref, char **ret) +startconn(conngrab cg, int fminor, int connref, char **ret, conngrab *retcg) { struct iovec io[3]; int iovlen = 0; @@ -308,6 +324,7 @@ startconn(conngrab cg, int fminor, int connref, char **ret) struct datab db; struct conninfo *conn; char *str; + conngrab rcg = NULL; yy.b_rptr = data; yy.b_wptr = data; @@ -317,6 +334,8 @@ startconn(conngrab cg, int fminor, int connref, char **ret) if(ret == NULL) ret = &str; + if(retcg == NULL) + retcg = &rcg; if(cg->mask == 0) { *ret = "Internal error: bad mask"; return NULL; @@ -408,7 +427,8 @@ startconn(conngrab cg, int fminor, int connref, char **ret) printf("Start: %s:%s #%s...",cg->site,cg->protocol,cg->nr); if(((*ret) = findit (&cg,0)) != NULL) { - dropgrab(cg); + *retcg = cg; + dropgrab(rcg); chkall(); return NULL; } @@ -461,13 +481,20 @@ printf("Start: %s:%s #%s...",cg->site,cg->protocol,cg->nr); m_puti (&yy, connref ? connref : conn->connref); } - if (cg->lnrsuf != NULL) { - char *s = cg->lnrsuf; - m_putsx (&yy, ARG_LNUMBER); - m_putsz (&yy, s); + if (cg->lnr != NULL) { + char *s = strip_nr(cg->lnr,1); + printf("Strip3 %s -> %s\n",cg->lnr,s); + if(s == NULL && cg->lnrsuf != NULL) { + s = append_nr(cg->lnr,cg->lnrsuf); + printf("Append3 %s,%s -> %s\n",cg->lnr,cg->lnrsuf,s); + } + if(s != NULL) { + m_putsx (&yy, ARG_LNUMBER); + m_putsz (&yy, s); + } } if (cg->nr != NULL) { - char *s = strip_nr(cg->nr); + char *s = strip_nr(cg->nr,0); printf("Strip3 %s -> %s\n",cg->nr,s); if(s == NULL && cg->nrsuf != NULL) { s = append_nr(cg->nr,cg->nrsuf); @@ -621,6 +648,7 @@ runprog (cf cfr, struct conninfo **rconn, conngrab *foo) conn->seqnum = ++connseq; conn->state = c_down; conn->cause = 999999; + conn->got_hd = 1; conn->next = isdn4_conn; isdn4_conn = conn; } cg->refs++; @@ -814,7 +842,7 @@ runprog (cf cfr, struct conninfo **rconn, conngrab *foo) strncpy (ut.ut_id, sdevname (dev), sizeof (ut.ut_id)); strncpy (ut.ut_line, mdevname (dev), sizeof (ut.ut_line)); #ifndef M_UNIX - strncpy (ut.ut_host, cfr->protocol, sizeof (ut.ut_host)); + strncpy (ut.ut_host, cfr->site, sizeof (ut.ut_host)); #endif ut.ut_pid = getpid (); ut.ut_type = LOGIN_PROCESS; @@ -1035,14 +1063,14 @@ runprog (cf cfr, struct conninfo **rconn, conngrab *foo) else cg->delay = 0; } - if(startconn(conn->cg,0,0, &msg) != conn) { + if(startconn(conn->cg,0,0, &msg, NULL) != conn) { syslog(LOG_CRIT,"Bug in runprog->startconn (%s) for %s:%s",msg ? msg : "(unknown reason)", cg->site,cg->protocol); dropgrab(conn->cg); conn->cg = NULL; chkone(conn); } } else { - int err = pushprot (conn->cg, conn->minor, 0); + int err = pushprot (conn->cg, conn->minor, conn->connref, 0); if(err != 0) { printf("NoProtoEnable NotPushprot\n"); m_putid (&yy, CMD_CLOSE); @@ -1248,7 +1276,7 @@ printf("FAIL %s\n",err); } else { printf("exist %s:%s\n",conn->cg->site,conn->cg->protocol); if(conn->cg != NULL && conn->minor != 0 && conn->pid != 0) - pushprot(conn->cg,conn->minor,1); + pushprot(conn->cg,conn->minor,conn->connref,1); } } } diff --git a/ksupport/Makefile b/ksupport/Makefile index bb44466..4206657 100644 --- a/ksupport/Makefile +++ b/ksupport/Makefile @@ -1,4 +1,6 @@ KERNEL=1 TOPDIR=.. +SOURCES= streamlib.c smallq.c dump.c log.c logh.c proto.c x75lib.c qinfo.c count.c + include $(TOPDIR)/Make.rules diff --git a/ksupport/log.c b/ksupport/log.c index 8a81f84..ff28a7a 100644 --- a/ksupport/log.c +++ b/ksupport/log.c @@ -269,12 +269,14 @@ log_printmsg (void *xlog, const char *text, mblk_t * mp, const char *prefix) int l = (uchar_t *) mp1->b_wptr - dp; printf ("%s%03x ",pprefix,i); +#if 0 if(i >= 2*BLOCKSIZE && l > 3*BLOCKSIZE) { /* Skip the stuff in the middle */ l -= 2*BLOCKSIZE + (l % BLOCKSIZE); printf("[... %d bytes (0x%x) skipped ...]\n",l,l); dp += l; i += l; continue; } +#endif for (k = 0; k < BLOCKSIZE && k < l; k++) printf ("%c%c ", ctab[dp[k] >> 4], ctab[dp[k] & 0x0F]); i += k;