diff --git a/libpri.h b/libpri.h index 9fea043..db55dfb 100755 --- a/libpri.h +++ b/libpri.h @@ -212,6 +212,25 @@ #define PRI_COPY_DIGITS_CALLED_NUMBER +/* Network Specific Facilities (AT&T) */ +#define PRI_NSF_NONE -1 +#define PRI_NSF_SID_PREFERRED 0xB1 +#define PRI_NSF_ANI_PREFERRED 0xB2 +#define PRI_NSF_SID_ONLY 0xB3 +#define PRI_NSF_ANI_ONLY 0xB4 +#define PRI_NSF_CALL_ASSOC_TSC 0xB9 +#define PRI_NSF_NOTIF_CATSC_CLEARING 0xBA +#define PRI_NSF_OPERATOR 0xB5 +#define PRI_NSF_PCCO 0xB6 +#define PRI_NSF_SDN 0xE1 +#define PRI_NSF_TOLL_FREE_MEGACOM 0xE2 +#define PRI_NSF_MEGACOM 0xE3 +#define PRI_NSF_ACCUNET 0xE6 +#define PRI_NSF_LONG_DISTANCE_SERVICE 0xE7 +#define PRI_NSF_INTERNATIONAL_TOLL_FREE 0xE8 +#define PRI_NSF_ATT_MULTIQUEST 0xF0 +#define PRI_NSF_CALL_REDIRECTION_SERVICE 0xF7 + typedef struct q931_call q931_call; typedef struct pri_event_generic { @@ -327,6 +346,9 @@ struct pri_sr; must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */ extern struct pri *pri_new(int fd, int nodetype, int switchtype); +/* Set Network Specific Facility for PRI */ +extern void pri_set_nsf(struct pri *pri, int nsf); + /* Set debug parameters on PRI -- see above debug definitions */ extern void pri_set_debug(struct pri *pri, int debug); diff --git a/pri.c b/pri.c index 1b9fcf1..ae59646 100755 --- a/pri.c +++ b/pri.c @@ -122,6 +122,12 @@ struct pri *pri_new(int fd, int node, int switchtype) return __pri_new(fd, node, switchtype, NULL); } +void pri_set_nsf(struct pri *pri, int nsf) +{ + if (pri) + pri->nsf = nsf; +} + char *pri_event2str(int id) { switch(id) { diff --git a/pri_internal.h b/pri_internal.h index f623b00..b7882b2 100755 --- a/pri_internal.h +++ b/pri_internal.h @@ -48,6 +48,7 @@ struct pri { int debug; /* Debug stuff */ int state; /* State of D-channel */ int switchtype; /* Switch type */ + int nsf; /* Network-Specific Facility (if any) */ int localtype; /* Local network type (unknown, network, cpe) */ int remotetype; /* Remote network type (unknown, network, cpe) */ diff --git a/q931.c b/q931.c index 2cd3ebe..14cd0f6 100755 --- a/q931.c +++ b/q931.c @@ -133,6 +133,25 @@ struct msgtype causes[] = { { PRI_CAUSE_INTERWORKING, "Interworking, unspecified" }, }; +struct msgtype facilities[] = { + { PRI_NSF_SID_PREFERRED, "CPN (SID) preferred" }, + { PRI_NSF_ANI_PREFERRED, "BN (ANI) preferred" }, + { PRI_NSF_SID_ONLY, "CPN (SID) only" }, + { PRI_NSF_ANI_ONLY, "BN (ANI) only" }, + { PRI_NSF_CALL_ASSOC_TSC, "Call Associated TSC" }, + { PRI_NSF_NOTIF_CATSC_CLEARING, "Notification of CATSC Clearing or Resource Unavailable" }, + { PRI_NSF_OPERATOR, "Operator" }, + { PRI_NSF_PCCO, "Pre-subscribed Common Carrier Operator (PCCO)" }, + { PRI_NSF_SDN, "SDN (including GSDN)" }, + { PRI_NSF_TOLL_FREE_MEGACOM, "Toll Free MEGACOM" }, + { PRI_NSF_MEGACOM, "MEGACOM" }, + { PRI_NSF_ACCUNET, "ACCUNET Switched Digital Service" }, + { PRI_NSF_LONG_DISTANCE_SERVICE, "Long Distance Service" }, + { PRI_NSF_INTERNATIONAL_TOLL_FREE, "International Toll Free Service" }, + { PRI_NSF_ATT_MULTIQUEST, "AT&T MultiQuest" }, + { PRI_NSF_CALL_REDIRECTION_SERVICE, "Call Redirection Service" } +}; + #define FLAG_PREFERRED 2 #define FLAG_EXCLUSIVE 4 @@ -1184,6 +1203,34 @@ static FUNC_DUMP(dump_facility) pri_message(" ]\n"); } +static FUNC_DUMP(dump_network_spec_fac) +{ + pri_message("%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len); + if (ie->data[0] == 0x00) { + pri_message (code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0]))); + } + else + dump_ie_data(ie->data, ie->len); + pri_message(" ]\n"); +} + +static FUNC_RECV(receive_network_spec_fac) +{ + return 0; +} + +static FUNC_SEND(transmit_network_spec_fac) +{ + if (pri->nsf != PRI_NSF_NONE) { + ie->data[0] = 0x00; + ie->data[1] = pri->nsf; + return 4; + } else { + /* Leave off */ + return 0; + } +} + char *pri_cause2str(int cause) { return code2str(cause, causes, sizeof(causes) / sizeof(causes[0])); @@ -1377,7 +1424,7 @@ struct ie ies[] = { { Q931_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state }, { Q931_CHANNEL_IDENT, "Channel Identification", dump_channel_id, receive_channel_id, transmit_channel_id }, { Q931_PROGRESS_INDICATOR, "Progress Indicator", dump_progress_indicator, receive_progress_indicator, transmit_progress_indicator }, - { Q931_NETWORK_SPEC_FAC, "Network-Specific Facilities" }, + { Q931_NETWORK_SPEC_FAC, "Network-Specific Facilities", dump_network_spec_fac, receive_network_spec_fac, transmit_network_spec_fac }, { Q931_INFORMATION_RATE, "Information Rate" }, { Q931_TRANSIT_DELAY, "End-to-End Transit Delay" }, { Q931_TRANS_DELAY_SELECT, "Transmit Delay Selection and Indication" }, @@ -2120,7 +2167,7 @@ int q931_disconnect(struct pri *pri, q931_call *c, int cause) return 0; } -static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_DISPLAY, +static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, -1 }; static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };