Index: libpri.h =================================================================== RCS file: /usr/cvsroot/libpri/libpri.h,v retrieving revision 1.49 diff -u -r1.49 libpri.h --- libpri.h 6 Apr 2005 19:42:41 -0000 1.49 +++ libpri.h 21 Apr 2005 13:52:49 -0000 @@ -76,6 +76,9 @@ #define PRI_EVENT_NOTIFY 16 /* Notification received */ #define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */ #define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state */ +#define PRI_EVENT_SERVICE 19 /* NFAS Maintenance */ +#define PRI_EVENT_SERVICE_ACK 20 /* NFAS Maintenance */ + /* Simple states */ #define PRI_STATE_DOWN 0 @@ -363,6 +366,18 @@ char digits[64]; } pri_event_keypad_digit; +typedef struct pri_event_service { + int e; + int channel; + int changestatus; +} pri_event_service; + +typedef struct pri_event_service_ack { + int e; + int channel; + int changestatus; +} pri_event_service_ack; + typedef union { int e; pri_event_generic gen; /* Generic view */ @@ -378,6 +393,8 @@ pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */ pri_event_notify notify; /* Notification */ pri_event_keypad_digit digit; /* Digits that come during a call */ + pri_event_service service; /* NFAS Maintenance */ + pri_event_service_ack service_ack; /* NFAS Maintenance */ } pri_event; struct pri; @@ -473,6 +490,9 @@ extern void pri_destroycall(struct pri *pri, q931_call *call); extern int pri_reset(struct pri *pri, int channel); + +/* Handle NFAS maintenance messages for putting B-Channels (and eventually D-Channels) in and out of service */ +extern int pri_maintenance_service(struct pri *pri, int channel, int changestatus); /* Create a new call */ extern q931_call *pri_new_call(struct pri *pri); Index: pri.c =================================================================== RCS file: /usr/cvsroot/libpri/pri.c,v retrieving revision 1.34 diff -u -r1.34 pri.c --- pri.c 5 Apr 2005 03:55:58 -0000 1.34 +++ pri.c 21 Apr 2005 13:52:50 -0000 @@ -506,6 +506,13 @@ return q931_restart(pri, channel); } +int pri_maintenance_service(struct pri *pri, int channel, int changestatus) +{ + if (!pri) + return -1; + return nfas_maintenance_service(pri, channel, changestatus); +} + q931_call *pri_new_call(struct pri *pri) { if (!pri) Index: pri_internal.h =================================================================== RCS file: /usr/cvsroot/libpri/pri_internal.h,v retrieving revision 1.20 diff -u -r1.20 pri_internal.h --- pri_internal.h 6 Apr 2005 19:42:41 -0000 1.20 +++ pri_internal.h 21 Apr 2005 13:52:50 -0000 @@ -232,6 +232,7 @@ long aoc_units; /* Advice of Charge Units */ struct apdu_event *apdus; /* APDU queue for call */ + int changestatus; /* Maintenance service related */ }; extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data); Index: pri_q931.h =================================================================== RCS file: /usr/cvsroot/libpri/pri_q931.h,v retrieving revision 1.21 diff -u -r1.21 pri_q931.h --- pri_q931.h 20 Apr 2005 15:23:35 -0000 1.21 +++ pri_q931.h 21 Apr 2005 13:52:50 -0000 @@ -108,6 +108,8 @@ #define Q931_PROTOCOL_DISCRIMINATOR 0x08 #define GR303_PROTOCOL_DISCRIMINATOR 0x4f +#define NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR 0x3 +#define NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO 0x43 /* Q.931 / National ISDN Message Types */ @@ -151,12 +153,9 @@ #define Q931_SUSPEND_ACKNOWLEDGE 0x2d #define Q931_SUSPEND_REJECT 0x21 -/* Maintenance messages (codeset 0 only) */ -#define NATIONAL_SERVICE 0x0f -#define NATIONAL_SERVICE_ACKNOWLEDGE 0x07 - -/* Special codeset 0 IE */ -#define NATIONAL_CHANGE_STATUS 0x1 +/* Maintenance messages (codeset 0) */ +#define NFAS_MAINTENANCE_SERVICE 0x0f +#define NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE 0x07 /* Q.931 / National ISDN Information Elements */ #define Q931_LOCKING_SHIFT 0x90 @@ -218,6 +217,13 @@ #define Q931_IE_USER_USER 0x7E #define Q931_IE_ESCAPE_FOR_EXT 0x7F +/* For maintenance service */ +#define NFAS_IE_CHANGE_STATUS 0x05 +#define NFAS_CHANGE_STATUS_IN_SERVICE 0 +#define NFAS_CHANGE_STATUS_LOOP_BACK 1 +#define NFAS_CHANGE_STATUS_OUT_OF_SERVICE 2 +#define NFAS_CHANGE_STATUS_REQ_CONTINUITY_CHECK 3 +#define NFAS_CHANGE_STATUS_GRACEFUL_SHUTDOWN 4 /* Call state stuff */ #define Q931_CALL_STATE_NULL 0 @@ -242,6 +248,10 @@ /* EuroISDN */ #define Q931_SENDING_COMPLETE 0xa1 + +extern int nfas_maintenance_service(struct pri *pri, int channel, int changestatus); + +extern int nfas_maintenance_service_ack(struct pri *pri, q931_call *call); extern int q931_receive(struct pri *pri, q931_h *h, int len); Index: q931.c =================================================================== RCS file: /usr/cvsroot/libpri/q931.c,v retrieving revision 1.124 diff -u -r1.124 q931.c --- q931.c 6 Apr 2005 19:42:41 -0000 1.124 +++ q931.c 21 Apr 2005 13:52:54 -0000 @@ -83,10 +83,12 @@ { Q931_SUSPEND, "SUSPEND" }, { Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" }, { Q931_SUSPEND_REJECT, "SUSPEND REJECT" }, +}; +struct msgtype nfas_msgs[] = { /* Maintenance */ - { NATIONAL_SERVICE, "SERVICE" }, - { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" }, + { NFAS_MAINTENANCE_SERVICE, "SERVICE" }, + { NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" }, }; struct msgtype causes[] = { @@ -956,6 +958,27 @@ return 0; } +static FUNC_DUMP(dump_change_status) +{ + int x; + pri_message("%c Change Status Information (len=%2d) [", prefix, len); + for (x=0;xlen;x++) + pri_message(" %02x", ie->data[x] & 0x7f); + pri_message(" ]\n"); +} + +static FUNC_RECV(receive_change_status) +{ + call->changestatus = ie->data[0] & 0x7f; + return 0; +} + +static FUNC_SEND(transmit_change_status) +{ + ie->data[0] = 0x80 | call->changestatus; + return 3; +} + static char *prog2str(int prog) { static struct msgtype progs[] = { @@ -2051,7 +2074,7 @@ struct ie ies[] = { /* Codeset 0 - Common */ - { 1, NATIONAL_CHANGE_STATUS, "Change Status" }, + { 1, NFAS_IE_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status }, { 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift }, { 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability }, { 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause }, @@ -2095,7 +2118,6 @@ { 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user }, { 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" }, { 1, Q931_IE_CALL_STATUS, "Call Status" }, - { 1, Q931_IE_CHANGE_STATUS, "Change Status" }, { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number }, { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number }, { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number }, @@ -2107,7 +2129,7 @@ { 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility }, { 1, Q931_DISPLAY | Q931_CODESET(6), "Display (CS6)", dump_display, receive_display, transmit_display }, { 0, Q931_IE_GENERIC_DIGITS, "Generic Digits", dump_generic_digits, receive_generic_digits, transmit_generic_digits }, - /* Codeset 7 */ + /* Codeset 7 - User specific */ }; static char *ie2str(int ie) @@ -2179,6 +2201,15 @@ return "Unknown Message Type"; } +static char *nfas_msg2str(int msg) +{ + unsigned int x; + for (x=0;xcrlen, q931_cr(h) & 0x7FFF, q931_cr(h) & 0x7FFF, (h->crv[0] & 0x80) ? "Terminator" : "Originator"); /* Message header begins at the end of the call reference number */ mh = (q931_mh *)(h->contents + h->crlen); - pri_message("%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg); + /* Might be an NFAS message */ + if ((h->pd == NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR) || (h->pd == NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO)) + pri_message("%c Message type: %s (%d)\n", c, nfas_msg2str(mh->msg), mh->msg); + else + pri_message("%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg); /* Drop length of header, including call reference */ len -= (h->crlen + 3); codeset = cur_codeset = 0; @@ -2449,12 +2484,15 @@ return -1; } -static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len) +static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int protodisc) { /* Returns header and message header and modifies length in place */ q931_h *h = (q931_h *)buf; q931_mh * mh = (q931_mh *)(h->contents + 2); - h->pd = pri->protodisc; + if (protodisc) + h->pd = protodisc; + else + h->pd = pri->protodisc; h->x0 = 0; /* Reserved 0 */ h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */ if (call->cr || call->forceinvert) { @@ -2504,8 +2542,8 @@ memset(buf, 0, sizeof(buf)); len = sizeof(buf); - init_header(pri, c, buf, &h, &mh, &len); - mh->msg = msgtype; + init_header(pri, c, buf, &h, &mh, &len, (msgtype >> 8)); + mh->msg = msgtype & 0x00ff; x=0; codeset = 0; while(ies[x] > -1) { @@ -2544,6 +2582,29 @@ return 0; } +static int maintenance_service_ies[] = { NFAS_IE_CHANGE_STATUS, Q931_CHANNEL_IDENT, -1 }; + +int nfas_maintenance_service_ack(struct pri *pri, q931_call *c) +{ + return send_message(pri, c, (NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR << 8) | NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE, maintenance_service_ies); +} + +int nfas_maintenance_service(struct pri *pri, int channel, int changestatus) +{ + struct q931_call *c; + c = q931_getcall(pri, 0 | 0x8000); + if (!c) + return -1; + if (channel) { + c->ds1no = (channel & 0xff00) >> 8; + channel &= 0xff; + c->channelno = channel; + } + c->chanflags &= ~FLAG_PREFERRED; + c->changestatus = changestatus; + return send_message(pri, c, (NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR << 8) | NFAS_MAINTENANCE_SERVICE, maintenance_service_ies); +} + static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 }; static int q931_status(struct pri *pri, q931_call *c, int cause) @@ -3096,14 +3157,7 @@ pri->q931_rxcount++; #endif mh = (q931_mh *)(h->contents + h->crlen); - if ((h->pd == 0x3) || (h->pd == 0x43)) { - /* This is the weird maintenance stuff. We majorly - KLUDGE this by changing byte 4 from a 0xf (SERVICE) - to a 0x7 (SERVICE ACKNOWLEDGE) */ - h->raw[h->crlen + 2] -= 0x8; - q931_xmit(pri, h, len, 1); - return 0; - } else if (h->pd != pri->protodisc) { + if ((h->pd != pri->protodisc) && (h->pd != NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR) && (h->pd != NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO)) { pri_error("Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd); return 0; } @@ -3112,124 +3166,143 @@ pri_error("Unable to locate call %d\n", q931_cr(h)); return -1; } - /* Preliminary handling */ - switch(mh->msg) { - case Q931_RESTART: - if (pri->debug & PRI_DEBUG_Q931_STATE) - pri_message("-- Processing Q.931 Restart\n"); - /* Reset information */ - c->channelno = -1; - c->slotmap = -1; - c->chanflags = 0; - c->ds1no = 0; - c->ri = -1; - break; - case Q931_FACILITY: - strcpy(c->callername, ""); - break; - case Q931_SETUP: - if (pri->debug & PRI_DEBUG_Q931_STATE) - pri_message("-- Processing Q.931 Call Setup\n"); - c->channelno = -1; - c->slotmap = -1; - c->chanflags = 0; - c->ds1no = 0; - c->ri = -1; - c->transcapability = -1; - c->transmoderate = -1; - c->transmultiple = -1; - c->userl1 = -1; - c->userl2 = -1; - c->userl3 = -1; - c->rateadaption = -1; - c->calledplan = -1; - c->callerplan = -1; - c->callerpres = -1; - strcpy(c->callernum, ""); - strcpy(c->callednum, ""); - strcpy(c->callername, ""); - c->redirectingplan = -1; - c->redirectingpres = -1; - c->redirectingreason = -1; - c->origcalledplan = -1; - c->origcalledpres = -1; - c->origredirectingreason = -1; - strcpy(c->redirectingnum, ""); - strcpy(c->origcallednum, ""); - strcpy(c->redirectingname, ""); - strcpy(c->origcalledname, ""); - c->useruserprotocoldisc = -1; - strcpy(c->useruserinfo, ""); - c->complete = 0; - c->nonisdn = 0; - /* Fall through */ - case Q931_CONNECT: - case Q931_ALERTING: - case Q931_PROGRESS: - case Q931_CALL_PROCEEDING: - c->progress = -1; - c->progressmask = 0; - break; - case Q931_CONNECT_ACKNOWLEDGE: - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; - break; - case Q931_RELEASE: - case Q931_DISCONNECT: - c->cause = -1; - c->causecode = -1; - c->causeloc = -1; - c->aoc_units = -1; - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; - break; - case Q931_RELEASE_COMPLETE: - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; - case Q931_STATUS: - c->cause = -1; - c->causecode = -1; - c->causeloc = -1; - c->sugcallstate = -1; - c->aoc_units = -1; - break; - case Q931_RESTART_ACKNOWLEDGE: - c->channelno = -1; - break; - case Q931_INFORMATION: - break; - case Q931_STATUS_ENQUIRY: - break; - case Q931_SETUP_ACKNOWLEDGE: - break; - case Q931_NOTIFY: - break; - case Q931_USER_INFORMATION: - case Q931_SEGMENT: - case Q931_CONGESTION_CONTROL: - case Q931_HOLD: - case Q931_HOLD_ACKNOWLEDGE: - case Q931_HOLD_REJECT: - case Q931_RETRIEVE: - case Q931_RETRIEVE_ACKNOWLEDGE: - case Q931_RETRIEVE_REJECT: - case Q931_RESUME: - case Q931_RESUME_ACKNOWLEDGE: - case Q931_RESUME_REJECT: - case Q931_SUSPEND: - case Q931_SUSPEND_ACKNOWLEDGE: - case Q931_SUSPEND_REJECT: - pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - /* Fall through */ - default: - pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); - if (c->newcall) - q931_destroycall(pri,c->cr); - return -1; + if (h->pd == pri->protodisc) { + /* Preliminary handling */ + switch(mh->msg) { + case Q931_RESTART: + if (pri->debug & PRI_DEBUG_Q931_STATE) + pri_message("-- Processing Q.931 Restart\n"); + /* Reset information */ + c->channelno = -1; + c->slotmap = -1; + c->chanflags = 0; + c->ds1no = 0; + c->ri = -1; + break; + case Q931_FACILITY: + strcpy(c->callername, ""); + break; + case Q931_SETUP: + if (pri->debug & PRI_DEBUG_Q931_STATE) + pri_message("-- Processing Q.931 Call Setup\n"); + c->channelno = -1; + c->slotmap = -1; + c->chanflags = 0; + c->ds1no = 0; + c->ri = -1; + c->transcapability = -1; + c->transmoderate = -1; + c->transmultiple = -1; + c->userl1 = -1; + c->userl2 = -1; + c->userl3 = -1; + c->rateadaption = -1; + c->calledplan = -1; + c->callerplan = -1; + c->callerpres = -1; + strcpy(c->callernum, ""); + strcpy(c->callednum, ""); + strcpy(c->callername, ""); + c->redirectingplan = -1; + c->redirectingpres = -1; + c->redirectingreason = -1; + c->origcalledplan = -1; + c->origcalledpres = -1; + c->origredirectingreason = -1; + strcpy(c->redirectingnum, ""); + strcpy(c->origcallednum, ""); + strcpy(c->redirectingname, ""); + strcpy(c->origcalledname, ""); + c->useruserprotocoldisc = -1; + strcpy(c->useruserinfo, ""); + c->complete = 0; + c->nonisdn = 0; + /* Fall through */ + case Q931_CONNECT: + case Q931_ALERTING: + case Q931_PROGRESS: + case Q931_CALL_PROCEEDING: + c->progress = -1; + c->progressmask = 0; + break; + case Q931_CONNECT_ACKNOWLEDGE: + if (c->retranstimer) + pri_schedule_del(pri, c->retranstimer); + c->retranstimer = 0; + break; + case Q931_RELEASE: + case Q931_DISCONNECT: + c->cause = -1; + c->causecode = -1; + c->causeloc = -1; + c->aoc_units = -1; + if (c->retranstimer) + pri_schedule_del(pri, c->retranstimer); + c->retranstimer = 0; + break; + case Q931_RELEASE_COMPLETE: + if (c->retranstimer) + pri_schedule_del(pri, c->retranstimer); + c->retranstimer = 0; + case Q931_STATUS: + c->cause = -1; + c->causecode = -1; + c->causeloc = -1; + c->sugcallstate = -1; + c->aoc_units = -1; + break; + case Q931_RESTART_ACKNOWLEDGE: + c->channelno = -1; + break; + case Q931_INFORMATION: + break; + case Q931_STATUS_ENQUIRY: + break; + case Q931_SETUP_ACKNOWLEDGE: + break; + case Q931_NOTIFY: + break; + case Q931_USER_INFORMATION: + case Q931_SEGMENT: + case Q931_CONGESTION_CONTROL: + case Q931_HOLD: + case Q931_HOLD_ACKNOWLEDGE: + case Q931_HOLD_REJECT: + case Q931_RETRIEVE: + case Q931_RETRIEVE_ACKNOWLEDGE: + case Q931_RETRIEVE_REJECT: + case Q931_RESUME: + case Q931_RESUME_ACKNOWLEDGE: + case Q931_RESUME_REJECT: + case Q931_SUSPEND: + case Q931_SUSPEND_ACKNOWLEDGE: + case Q931_SUSPEND_REJECT: + pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + /* Fall through */ + default: + pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); + if (c->newcall) + q931_destroycall(pri,c->cr); + return -1; + } + } else { + /* Do the maintenance stuff */ + switch(mh->msg) { + case NFAS_MAINTENANCE_SERVICE: + case NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE: + c->channelno = -1; + c->slotmap = -1; + c->chanflags = 0; + c->ds1no = 0; + c->ri = -1; + c->changestatus = -1; + break; + default: + pri_error("!! Don't know how to pre-handle maintenance message type %s (%d)\n", nfas_msg2str(mh->msg), mh->msg); + return -1; + break; + } } memset(mandies, 0, sizeof(mandies)); missingmand = 0; @@ -3317,189 +3390,214 @@ } } - /* Post handling */ - switch(mh->msg) { - case Q931_RESTART: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - q931_destroycall(pri, c->cr); - break; - } - c->ourcallstate = Q931_CALL_STATE_RESTART; - c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST; - /* Send back the Restart Acknowledge */ - restart_ack(pri, c); - /* Notify user of restart event */ - pri->ev.e = PRI_EVENT_RESTART; - pri->ev.restart.channel = c->channelno | (c->ds1no << 8); - return Q931_RES_HAVEEVENT; - case Q931_SETUP: - if (missingmand) { - q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - break; - } - /* Must be new call */ - if (!c->newcall) { - break; - } - if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN) - c->nonisdn = 1; - c->newcall = 0; - c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT; - c->peercallstate = Q931_CALL_STATE_CALL_INITIATED; - /* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */ - c->alive = 0; - if (c->transmoderate != TRANS_MODE_64_CIRCUIT) { - q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL); - break; - } - pri->ev.e = PRI_EVENT_RING; - pri->ev.ring.channel = c->channelno | (c->ds1no << 8); - pri->ev.ring.callingpres = c->callerpres; - pri->ev.ring.callingplan = c->callerplan; - pri->ev.ring.ani2 = c->ani2; - strncpy(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum) - 1); - strncpy(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname) - 1); - pri->ev.ring.calledplan = c->calledplan; - strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); - strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); - strncpy(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname) - 1); - strncpy(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum) - 1); - strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1); - strncpy(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname) - 1); - strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1); - pri->ev.ring.redirectingreason = c->redirectingreason; - pri->ev.ring.origredirectingreason = c->origredirectingreason; - pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE); - pri->ev.ring.cref = c->cr; - pri->ev.ring.call = c; - pri->ev.ring.layer1 = c->userl1; - pri->ev.ring.complete = c->complete; - pri->ev.ring.ctype = c->transcapability; - pri->ev.ring.redirectingreason = c->redirectingreason; - pri->ev.ring.progress = c->progress; - pri->ev.ring.progressmask = c->progressmask; - return Q931_RES_HAVEEVENT; - case Q931_ALERTING: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED; - c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED; - pri->ev.e = PRI_EVENT_RINGING; - pri->ev.ringing.channel = c->channelno | (c->ds1no << 8); - pri->ev.ringing.cref = c->cr; - pri->ev.ringing.call = c; - pri->ev.ringing.progress = c->progress; - pri->ev.ringing.progressmask = c->progressmask; - return Q931_RES_HAVEEVENT; - case Q931_CONNECT: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) { - q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE); - break; - } - c->ourcallstate = Q931_CALL_STATE_ACTIVE; - c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST; - pri->ev.e = PRI_EVENT_ANSWER; - pri->ev.answer.channel = c->channelno | (c->ds1no << 8); - pri->ev.answer.cref = c->cr; - pri->ev.answer.call = c; - pri->ev.answer.progress = c->progress; - pri->ev.answer.progressmask = c->progressmask; - q931_connect_acknowledge(pri, c); - if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */ - q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING); - break; - } else + if (h->pd == pri->protodisc) { + /* Post handling */ + switch(mh->msg) { + case Q931_RESTART: + if (missingmand) { + q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + q931_destroycall(pri, c->cr); + break; + } + c->ourcallstate = Q931_CALL_STATE_RESTART; + c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST; + /* Send back the Restart Acknowledge */ + restart_ack(pri, c); + /* Notify user of restart event */ + pri->ev.e = PRI_EVENT_RESTART; + pri->ev.restart.channel = c->channelno | (c->ds1no << 8); return Q931_RES_HAVEEVENT; - case Q931_FACILITY: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - pri->ev.e = PRI_EVENT_FACNAME; - strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1); - strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1); - pri->ev.facname.channel = c->channelno | (c->ds1no << 8); - pri->ev.facname.cref = c->cr; - pri->ev.facname.call = c; + case Q931_SETUP: + if (missingmand) { + q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + break; + } + /* Must be new call */ + if (!c->newcall) { + break; + } + if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN) + c->nonisdn = 1; + c->newcall = 0; + c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT; + c->peercallstate = Q931_CALL_STATE_CALL_INITIATED; + /* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */ + c->alive = 0; + if (c->transmoderate != TRANS_MODE_64_CIRCUIT) { + q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL); + break; + } + pri->ev.e = PRI_EVENT_RING; + pri->ev.ring.channel = c->channelno | (c->ds1no << 8); + pri->ev.ring.callingpres = c->callerpres; + pri->ev.ring.callingplan = c->callerplan; + pri->ev.ring.ani2 = c->ani2; + strncpy(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum) - 1); + strncpy(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname) - 1); + pri->ev.ring.calledplan = c->calledplan; + strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); + strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); + strncpy(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname) - 1); + strncpy(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum) - 1); + strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1); + strncpy(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname) - 1); + strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1); + pri->ev.ring.redirectingreason = c->redirectingreason; + pri->ev.ring.origredirectingreason = c->origredirectingreason; + pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE); + pri->ev.ring.cref = c->cr; + pri->ev.ring.call = c; + pri->ev.ring.layer1 = c->userl1; + pri->ev.ring.complete = c->complete; + pri->ev.ring.ctype = c->transcapability; + pri->ev.ring.redirectingreason = c->redirectingreason; + pri->ev.ring.progress = c->progress; + pri->ev.ring.progressmask = c->progressmask; + return Q931_RES_HAVEEVENT; + case Q931_ALERTING: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED; + c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED; + pri->ev.e = PRI_EVENT_RINGING; + pri->ev.ringing.channel = c->channelno | (c->ds1no << 8); + pri->ev.ringing.cref = c->cr; + pri->ev.ringing.call = c; + pri->ev.ringing.progress = c->progress; + pri->ev.ringing.progressmask = c->progressmask; + return Q931_RES_HAVEEVENT; + case Q931_CONNECT: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) { + q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE); + break; + } + c->ourcallstate = Q931_CALL_STATE_ACTIVE; + c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST; + pri->ev.e = PRI_EVENT_ANSWER; + pri->ev.answer.channel = c->channelno | (c->ds1no << 8); + pri->ev.answer.cref = c->cr; + pri->ev.answer.call = c; + pri->ev.answer.progress = c->progress; + pri->ev.answer.progressmask = c->progressmask; + q931_connect_acknowledge(pri, c); + if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */ + q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING); + break; + } else + return Q931_RES_HAVEEVENT; + case Q931_FACILITY: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + pri->ev.e = PRI_EVENT_FACNAME; + strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1); + strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1); + pri->ev.facname.channel = c->channelno | (c->ds1no << 8); + pri->ev.facname.cref = c->cr; + pri->ev.facname.call = c; #if 0 - pri_message("Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum); + pri_message("Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum); #endif - return Q931_RES_HAVEEVENT; - case Q931_PROGRESS: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - q931_destroycall(pri, c->cr); - break; - } - pri->ev.e = PRI_EVENT_PROGRESS; - /* Fall through */ - case Q931_CALL_PROCEEDING: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) && - (c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) && - (c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) && - (c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) { - q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); - break; - } - pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8); - if (mh->msg == Q931_CALL_PROCEEDING) { - pri->ev.e = PRI_EVENT_PROCEEDING; - c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING; - c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING; - } - pri->ev.proceeding.progress = c->progress; - pri->ev.proceeding.progressmask = c->progressmask; - pri->ev.proceeding.cref = c->cr; - pri->ev.proceeding.call = c; - return Q931_RES_HAVEEVENT; - case Q931_CONNECT_ACKNOWLEDGE: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) { - q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); - break; - } - c->ourcallstate = Q931_CALL_STATE_ACTIVE; - c->peercallstate = Q931_CALL_STATE_ACTIVE; - break; - case Q931_STATUS: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - q931_destroycall(pri, c->cr); + return Q931_RES_HAVEEVENT; + case Q931_PROGRESS: + if (missingmand) { + q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + q931_destroycall(pri, c->cr); + break; + } + pri->ev.e = PRI_EVENT_PROGRESS; + /* Fall through */ + case Q931_CALL_PROCEEDING: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) && + (c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) && + (c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) && + (c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) { + q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); + break; + } + pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8); + if (mh->msg == Q931_CALL_PROCEEDING) { + pri->ev.e = PRI_EVENT_PROCEEDING; + c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING; + c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING; + } + pri->ev.proceeding.progress = c->progress; + pri->ev.proceeding.progressmask = c->progressmask; + pri->ev.proceeding.cref = c->cr; + pri->ev.proceeding.call = c; + return Q931_RES_HAVEEVENT; + case Q931_CONNECT_ACKNOWLEDGE: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) { + q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); + break; + } + c->ourcallstate = Q931_CALL_STATE_ACTIVE; + c->peercallstate = Q931_CALL_STATE_ACTIVE; break; - } - if (c->newcall) { - if (c->cr & 0x7fff) - q931_release_complete(pri,c,PRI_CAUSE_WRONG_CALL_STATE); + case Q931_STATUS: + if (missingmand) { + q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + q931_destroycall(pri, c->cr); + break; + } + if (c->newcall) { + if (c->cr & 0x7fff) + q931_release_complete(pri,c,PRI_CAUSE_WRONG_CALL_STATE); + break; + } + /* Do nothing */ + /* Also when the STATUS asks for the call of an unexisting reference send RELEASE_COMPL */ + if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) && + (c->cause != PRI_CAUSE_INTERWORKING)) + pri_error("Received unsolicited status: %s\n", pri_cause2str(c->cause)); + /* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */ + if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) { + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); + pri->ev.hangup.cref = c->cr; + pri->ev.hangup.cause = c->cause; + pri->ev.hangup.call = c; + /* Free resources */ + c->ourcallstate = Q931_CALL_STATE_NULL; + c->peercallstate = Q931_CALL_STATE_NULL; + if (c->alive) { + pri->ev.e = PRI_EVENT_HANGUP; + res = Q931_RES_HAVEEVENT; + c->alive = 0; + } else if (c->sendhangupack) { + res = Q931_RES_HAVEEVENT; + pri->ev.e = PRI_EVENT_HANGUP_ACK; + q931_hangup(pri, c, c->cause); + } else { + q931_hangup(pri, c, c->cause); + res = 0; + } + if (res) + return res; + } break; - } - /* Do nothing */ - /* Also when the STATUS asks for the call of an unexisting reference send RELEASE_COMPL */ - if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) && - (c->cause != PRI_CAUSE_INTERWORKING)) - pri_error("Received unsolicited status: %s\n", pri_cause2str(c->cause)); - /* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */ - if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) { + case Q931_RELEASE_COMPLETE: + c->ourcallstate = Q931_CALL_STATE_NULL; + c->peercallstate = Q931_CALL_STATE_NULL; pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); pri->ev.hangup.cref = c->cr; pri->ev.hangup.cause = c->cause; pri->ev.hangup.call = c; /* Free resources */ - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; if (c->alive) { pri->ev.e = PRI_EVENT_HANGUP; res = Q931_RES_HAVEEVENT; @@ -3507,170 +3605,166 @@ } else if (c->sendhangupack) { res = Q931_RES_HAVEEVENT; pri->ev.e = PRI_EVENT_HANGUP_ACK; - q931_hangup(pri, c, c->cause); - } else { - q931_hangup(pri, c, c->cause); + pri_hangup(pri, c, c->cause); + } else res = 0; - } if (res) return res; - } - break; - case Q931_RELEASE_COMPLETE: - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); - pri->ev.hangup.cref = c->cr; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - /* Free resources */ - if (c->alive) { + else + q931_hangup(pri,c,c->cause); + break; + case Q931_RELEASE: + if (missingmand) { + /* Force cause to be mandatory IE missing */ + c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; + } + if (c->ourcallstate == Q931_CALL_STATE_RELEASE_REQUEST) + c->peercallstate = Q931_CALL_STATE_NULL; + else { + c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST; + } + c->ourcallstate = Q931_CALL_STATE_NULL; pri->ev.e = PRI_EVENT_HANGUP; - res = Q931_RES_HAVEEVENT; - c->alive = 0; - } else if (c->sendhangupack) { - res = Q931_RES_HAVEEVENT; - pri->ev.e = PRI_EVENT_HANGUP_ACK; - pri_hangup(pri, c, c->cause); - } else - res = 0; - if (res) - return res; - else - q931_hangup(pri,c,c->cause); - break; - case Q931_RELEASE: - if (missingmand) { - /* Force cause to be mandatory IE missing */ - c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; - } - if (c->ourcallstate == Q931_CALL_STATE_RELEASE_REQUEST) - c->peercallstate = Q931_CALL_STATE_NULL; - else { - c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST; - } - c->ourcallstate = Q931_CALL_STATE_NULL; - pri->ev.e = PRI_EVENT_HANGUP; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); - pri->ev.hangup.cref = c->cr; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - pri->ev.hangup.aoc_units = c->aoc_units; - /* Don't send release complete if they send us release - while we sent it, assume a NULL state */ - if (c->newcall) - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - else - return Q931_RES_HAVEEVENT; - break; - case Q931_DISCONNECT: - if (missingmand) { - /* Still let user call release */ - c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; - } - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); + pri->ev.hangup.cref = c->cr; + pri->ev.hangup.cause = c->cause; + pri->ev.hangup.call = c; + pri->ev.hangup.aoc_units = c->aoc_units; + /* Don't send release complete if they send us release + while we sent it, assume a NULL state */ + if (c->newcall) + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + else + return Q931_RES_HAVEEVENT; + break; + case Q931_DISCONNECT: + if (missingmand) { + /* Still let user call release */ + c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; + } + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + c->ourcallstate = Q931_CALL_STATE_DISCONNECT_INDICATION; + c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST; + c->sendhangupack = 1; + /* Return such an event */ + pri->ev.e = PRI_EVENT_HANGUP_REQ; + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); + pri->ev.hangup.cref = c->cr; + pri->ev.hangup.cause = c->cause; + pri->ev.hangup.call = c; + pri->ev.hangup.aoc_units = c->aoc_units; + if (c->alive) + return Q931_RES_HAVEEVENT; + else + q931_hangup(pri,c,c->cause); break; - } - c->ourcallstate = Q931_CALL_STATE_DISCONNECT_INDICATION; - c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST; - c->sendhangupack = 1; - /* Return such an event */ - pri->ev.e = PRI_EVENT_HANGUP_REQ; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); - pri->ev.hangup.cref = c->cr; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - pri->ev.hangup.aoc_units = c->aoc_units; - if (c->alive) + case Q931_RESTART_ACKNOWLEDGE: + c->ourcallstate = Q931_CALL_STATE_NULL; + c->peercallstate = Q931_CALL_STATE_NULL; + pri->ev.e = PRI_EVENT_RESTART_ACK; + pri->ev.restartack.channel = c->channelno | (c->ds1no << 8); return Q931_RES_HAVEEVENT; - else - q931_hangup(pri,c,c->cause); - break; - case Q931_RESTART_ACKNOWLEDGE: - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; - pri->ev.e = PRI_EVENT_RESTART_ACK; - pri->ev.restartack.channel = c->channelno | (c->ds1no << 8); - return Q931_RES_HAVEEVENT; - case Q931_INFORMATION: - /* XXX We're handling only INFORMATION messages that contain - overlap dialing received digit - + the "Complete" msg which is basically an EOF on further digits - XXX */ - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if (c->ourcallstate != Q931_CALL_STATE_OVERLAP_RECEIVING) { - pri->ev.e = PRI_EVENT_KEYPAD_DIGIT; - pri->ev.digit.call = c; - pri->ev.digit.channel = c->channelno | (c->ds1no << 8); - strncpy(pri->ev.digit.digits, c->digitbuf, sizeof(pri->ev.digit.digits)); + case Q931_INFORMATION: + /* XXX We're handling only INFORMATION messages that contain + overlap dialing received digit + + the "Complete" msg which is basically an EOF on further digits + XXX */ + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if (c->ourcallstate != Q931_CALL_STATE_OVERLAP_RECEIVING) { + pri->ev.e = PRI_EVENT_KEYPAD_DIGIT; + pri->ev.digit.call = c; + pri->ev.digit.channel = c->channelno | (c->ds1no << 8); + strncpy(pri->ev.digit.digits, c->digitbuf, sizeof(pri->ev.digit.digits)); + return Q931_RES_HAVEEVENT; + } + pri->ev.e = PRI_EVENT_INFO_RECEIVED; + pri->ev.ring.call = c; + pri->ev.ring.channel = c->channelno | (c->ds1no << 8); + strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); + strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); + pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */ return Q931_RES_HAVEEVENT; - } - pri->ev.e = PRI_EVENT_INFO_RECEIVED; - pri->ev.ring.call = c; - pri->ev.ring.channel = c->channelno | (c->ds1no << 8); - strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); - strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); - pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */ - return Q931_RES_HAVEEVENT; - case Q931_STATUS_ENQUIRY: - if (c->newcall) { - q931_release_complete(pri, c, PRI_CAUSE_INVALID_CALL_REFERENCE); - } else - q931_status(pri,c, 0); - break; - case Q931_SETUP_ACKNOWLEDGE: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - c->ourcallstate = Q931_CALL_STATE_OVERLAP_SENDING; - c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING; - pri->ev.e = PRI_EVENT_SETUP_ACK; - pri->ev.setup_ack.channel = c->channelno; - - cur = c->apdus; - while (cur) { - if (!cur->sent && cur->message == Q931_FACILITY) { - q931_facility(pri, c); + case Q931_STATUS_ENQUIRY: + if (c->newcall) { + q931_release_complete(pri, c, PRI_CAUSE_INVALID_CALL_REFERENCE); + } else + q931_status(pri,c, 0); + break; + case Q931_SETUP_ACKNOWLEDGE: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } - cur = cur->next; - } + c->ourcallstate = Q931_CALL_STATE_OVERLAP_SENDING; + c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING; + pri->ev.e = PRI_EVENT_SETUP_ACK; + pri->ev.setup_ack.channel = c->channelno; + + cur = c->apdus; + while (cur) { + if (!cur->sent && cur->message == Q931_FACILITY) { + q931_facility(pri, c); + break; + } + cur = cur->next; + } - return Q931_RES_HAVEEVENT; - case Q931_NOTIFY: - pri->ev.e = PRI_EVENT_NOTIFY; - pri->ev.notify.channel = c->channelno; - pri->ev.notify.info = c->notify; - return Q931_RES_HAVEEVENT; - case Q931_USER_INFORMATION: - case Q931_SEGMENT: - case Q931_CONGESTION_CONTROL: - case Q931_HOLD: - case Q931_HOLD_ACKNOWLEDGE: - case Q931_HOLD_REJECT: - case Q931_RETRIEVE: - case Q931_RETRIEVE_ACKNOWLEDGE: - case Q931_RETRIEVE_REJECT: - case Q931_RESUME: - case Q931_RESUME_ACKNOWLEDGE: - case Q931_RESUME_REJECT: - case Q931_SUSPEND: - case Q931_SUSPEND_ACKNOWLEDGE: - case Q931_SUSPEND_REJECT: - pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - /* Fall through */ - default: - - pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); - if (c->newcall) - q931_destroycall(pri,c->cr); - return -1; + return Q931_RES_HAVEEVENT; + case Q931_NOTIFY: + pri->ev.e = PRI_EVENT_NOTIFY; + pri->ev.notify.channel = c->channelno; + pri->ev.notify.info = c->notify; + return Q931_RES_HAVEEVENT; + case Q931_USER_INFORMATION: + case Q931_SEGMENT: + case Q931_CONGESTION_CONTROL: + case Q931_HOLD: + case Q931_HOLD_ACKNOWLEDGE: + case Q931_HOLD_REJECT: + case Q931_RETRIEVE: + case Q931_RETRIEVE_ACKNOWLEDGE: + case Q931_RETRIEVE_REJECT: + case Q931_RESUME: + case Q931_RESUME_ACKNOWLEDGE: + case Q931_RESUME_REJECT: + case Q931_SUSPEND: + case Q931_SUSPEND_ACKNOWLEDGE: + case Q931_SUSPEND_REJECT: + pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + /* Fall through */ + default: + + pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); + if (c->newcall) + q931_destroycall(pri,c->cr); + return -1; + } + } else { + /* Do the maintenance stuff */ + switch(mh->msg) { + case NFAS_MAINTENANCE_SERVICE: + pri->ev.e = PRI_EVENT_SERVICE; + pri->ev.service.channel = c->channelno | (c->ds1no << 8); + pri->ev.service.changestatus = c->changestatus; + nfas_maintenance_service_ack(pri, c); + return Q931_RES_HAVEEVENT; + case NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE: + pri->ev.e = PRI_EVENT_SERVICE_ACK; + pri->ev.service_ack.channel = c->channelno | (c->ds1no << 8); + pri->ev.service_ack.changestatus = c->changestatus; + return Q931_RES_HAVEEVENT; + default: + pri_error("!! Don't know how to post-handle maintenance message type %s (%d)\n", nfas_msg2str(mh->msg), mh->msg); + return -1; + break; + } } return 0; }