diff --git a/libpri.h b/libpri.h index f2a64bc..b6035d3 100644 --- a/libpri.h +++ b/libpri.h @@ -428,7 +428,7 @@ struct pri_party_subaddress { * \note The null terminator is a convenience only since the data could be * BCD/binary and thus have a null byte as part of the contents. */ - char data[32]; + unsigned char data[32]; }; /*! \brief Information needed to identify an endpoint in a call. */ @@ -598,7 +598,7 @@ typedef struct pri_event_ring { int layer1; /* User layer 1 */ int complete; /* Have we seen "Complete" i.e. no more number? */ q931_call *call; /* Opaque call pointer */ - char callingsubaddr[256]; /* Calling parties subaddress */ + char callingsubaddr[256]; /* Calling parties subaddress, backwards compatibility */ int progress; int progressmask; char origcalledname[256]; @@ -607,6 +607,8 @@ typedef struct pri_event_ring { int origredirectingreason; int reversecharge; struct pri_subcommands *subcmds; + struct pri_party_id calling; /* Calling Party's info, initially subaddress' */ + struct pri_party_subaddress called_subaddress; /* Called party's subaddress */ } pri_event_ring; typedef struct pri_event_hangup { @@ -832,8 +834,8 @@ extern pri_event *pri_schedule_run(struct pri *pri); extern pri_event *pri_schedule_run_tv(struct pri *pri, const struct timeval *now); int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, - int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres, - char *called,int calledplan, int ulayer1); + int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres, + char *called, int calledplan, int ulayer1); struct pri_sr *pri_sr_new(void); void pri_sr_free(struct pri_sr *sr); @@ -854,6 +856,26 @@ void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *calle /*! \note Use pri_sr_set_caller_party() instead to pass more precise caller information. */ int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres); +/*! + * \brief Set the calling subaddress information in the call SETUP record. + * + * \param sr New call SETUP record. + * \param subaddress information to set. + * + * \return Nothing + */ +void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress); + +/*! + * \brief Set the called subaddress information in the call SETUP record. + * + * \param sr New call SETUP record. + * \param subaddress information to set. + * + * \return Nothing + */ +void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress); + /*! * \brief Set the redirecting information in the call SETUP record. * diff --git a/pri.c b/pri.c index a47add9..bd91b41 100644 --- a/pri.c +++ b/pri.c @@ -616,6 +616,40 @@ static void pri_copy_party_number_to_q931(struct q931_party_number *q931_number, } } +/*! + * \internal + * \brief Copy the PRI party subaddress to the Q.931 party subaddress structure. + * + * \param q931_subaddress Q.931 party subaddress structure + * \param pri_subaddress PRI party subaddress structure + * + * \return Nothing + */ +static void pri_copy_party_subaddress_to_q931(struct q931_party_subaddress *q931_subaddress, const struct pri_party_subaddress *pri_subaddress) +{ + int length; + int maxlen = sizeof(q931_subaddress->data) - 1; + + q931_party_subaddress_init(q931_subaddress); + + if (!pri_subaddress->valid) { + return; + } + + q931_subaddress->valid = 1; + q931_subaddress->type = pri_subaddress->type; + + length = pri_subaddress->length; + if (length > maxlen){ + length = maxlen; + } else { + q931_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator; + } + q931_subaddress->length = length; + memcpy(q931_subaddress->data, pri_subaddress->data, length); + q931_subaddress->data[length] = '\0'; +} + /*! * \internal * \brief Copy the PRI party id to the Q.931 party id structure. @@ -629,6 +663,7 @@ static void pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struc { pri_copy_party_name_to_q931(&q931_id->name, &pri_id->name); pri_copy_party_number_to_q931(&q931_id->number, &pri_id->number); + pri_copy_party_subaddress_to_q931(&q931_id->subaddress, &pri_id->subaddress); } int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pri_party_connected_line *connected) @@ -974,7 +1009,7 @@ int pri_setup(struct pri *pri, q931_call *c, struct pri_sr *req) int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called, - int calledplan,int ulayer1) + int calledplan, int ulayer1) { struct pri_sr req; if (!pri || !c) @@ -1206,6 +1241,11 @@ int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int numco return 0; } +void pri_sr_set_called_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress) +{ + pri_copy_party_subaddress_to_q931(&sr->called.subaddress, subaddress); +} + int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres) { q931_party_id_init(&sr->caller); @@ -1226,6 +1266,11 @@ int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int cal return 0; } +void pri_sr_set_caller_subaddress(struct pri_sr *sr, const struct pri_party_subaddress *subaddress) +{ + pri_copy_party_subaddress_to_q931(&sr->caller.subaddress, subaddress); +} + void pri_sr_set_caller_party(struct pri_sr *sr, const struct pri_party_id *caller) { pri_copy_party_id_to_q931(&sr->caller, caller); diff --git a/pri_internal.h b/pri_internal.h index 3b4676f..cc688e2 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -181,7 +181,6 @@ struct q931_party_number { /*! \brief Maximum subaddress length plus null terminator */ #define PRI_MAX_SUBADDRESS_LEN (20 + 1) -#if defined(POSSIBLE_FUTURE_SUBADDRESS_SUPPORT) struct q931_party_subaddress { /*! \brief TRUE if the subaddress information is valid/present */ unsigned char valid; @@ -205,17 +204,14 @@ struct q931_party_subaddress { * \note The null terminator is a convenience only since the data could be * BCD/binary and thus have a null byte as part of the contents. */ - char data[PRI_MAX_SUBADDRESS_LEN]; + unsigned char data[PRI_MAX_SUBADDRESS_LEN]; }; -#endif /* defined(POSSIBLE_FUTURE_SUBADDRESS_SUPPORT) */ struct q931_party_address { /*! \brief Subscriber phone number */ struct q931_party_number number; -#if defined(POSSIBLE_FUTURE_SUBADDRESS_SUPPORT) /*! \brief Subscriber subaddress */ struct q931_party_subaddress subaddress; -#endif /* defined(POSSIBLE_FUTURE_SUBADDRESS_SUPPORT) */ }; /*! \brief Information needed to identify an endpoint in a call. */ @@ -224,10 +220,8 @@ struct q931_party_id { struct q931_party_name name; /*! \brief Subscriber phone number */ struct q931_party_number number; -#if defined(POSSIBLE_FUTURE_SUBADDRESS_SUPPORT) /*! \brief Subscriber subaddress */ struct q931_party_subaddress subaddress; -#endif /* defined(POSSIBLE_FUTURE_SUBADDRESS_SUPPORT) */ }; enum Q931_REDIRECTING_STATE { @@ -489,16 +483,19 @@ void __pri_free_tei(struct pri *p); void q931_party_name_init(struct q931_party_name *name); void q931_party_number_init(struct q931_party_number *number); +void q931_party_subaddress_init(struct q931_party_subaddress *subaddr); void q931_party_address_init(struct q931_party_address *address); void q931_party_id_init(struct q931_party_id *id); void q931_party_redirecting_init(struct q931_party_redirecting *redirecting); int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right); int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right); +int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right); int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right); void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name); void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number); +void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress); void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id); void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting); diff --git a/pri_q931.h b/pri_q931.h index 6acf74b..4667d3a 100644 --- a/pri_q931.h +++ b/pri_q931.h @@ -174,8 +174,9 @@ typedef struct q931_ie { #define Q931_IE_SEGMENTED_MSG 0x00 #define Q931_IE_CHANGE_STATUS 0x01 #define Q931_IE_ORIGINATING_LINE_INFO (0x01 | Q931_CODESET(6)) -#define Q931_IE_CONNECTED_ADDR 0x0C -#define Q931_IE_CONNECTED_NUM 0x4C +#define Q931_IE_CONNECTED_ADDR 0x0c +#define Q931_IE_CONNECTED_NUM 0x4c +#define Q931_IE_CONNECTED_SUBADDR 0x4d #define Q931_IE_CALL_IDENTITY 0x10 #define Q931_IE_FACILITY 0x1c #define Q931_IE_ENDPOINT_ID 0x26 diff --git a/q931.c b/q931.c index e10c3de..a33da71 100644 --- a/q931.c +++ b/q931.c @@ -319,6 +319,22 @@ void q931_party_number_init(struct q931_party_number *number) number->str[0] = '\0'; } +/*! + * \brief Initialize the given struct q931_party_subaddress + * + * \param subaddress Structure to initialize + * + * \return Nothing + */ +void q931_party_subaddress_init(struct q931_party_subaddress *subaddress) +{ + subaddress->valid = 0; + subaddress->type = 0; + subaddress->odd_even_indicator = 0; + subaddress->length = 0; + subaddress->data[0] = '\0'; +} + /*! * \brief Initialize the given struct q931_party_address * @@ -329,6 +345,7 @@ void q931_party_number_init(struct q931_party_number *number) void q931_party_address_init(struct q931_party_address *address) { q931_party_number_init(&address->number); + q931_party_subaddress_init(&address->subaddress); } /*! @@ -342,6 +359,7 @@ void q931_party_id_init(struct q931_party_id *id) { q931_party_name_init(&id->name); q931_party_number_init(&id->number); + q931_party_subaddress_init(&id->subaddress); } /*! @@ -430,6 +448,45 @@ int q931_party_number_cmp(const struct q931_party_number *left, const struct q93 return cmp; } +/*! + * \brief Compare the left and right party subaddress. + * + * \param left Left parameter party subaddress. + * \param right Right parameter party subaddress. + * + * \retval < 0 when left < right. + * \retval == 0 when left == right. + * \retval > 0 when left > right. + */ +int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right) +{ + int cmp; + + if (!left->valid) { + if (!right->valid) { + return 0; + } + return -1; + } else if (!right->valid) { + return 1; + } + cmp = left->type - right->type; + if (cmp) { + return cmp; + } + cmp = memcmp(left->data, right->data, + (left->length < right->length) ? left->length : right->length); + if (cmp) { + return cmp; + } + cmp = left->length - right->length; + if (cmp) { + return cmp; + } + cmp = left->odd_even_indicator - right->odd_even_indicator; + return cmp; +} + /*! * \brief Compare the left and right party id. * @@ -448,6 +505,10 @@ int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_ if (cmp) { return cmp; } + cmp = q931_party_subaddress_cmp(&left->subaddress, &right->subaddress); + if (cmp) { + return cmp; + } cmp = q931_party_name_cmp(&left->name, &right->name); return cmp; } @@ -498,6 +559,42 @@ void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const st } } +/*! + * \brief Copy the Q.931 party subaddress to the PRI party subaddress structure. + * + * \param pri_subaddress PRI party subaddress structure + * \param q931_subaddress Q.931 party subaddress structure + * + * \return Nothing + */ +void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress) +{ + int length; + + /* + * The size of pri_subaddress->data[] is not the same as the size of + * q931_subaddress->data[]. + */ + + if (!q931_subaddress->valid) { + pri_subaddress->valid = 0; + pri_subaddress->type = 0; + pri_subaddress->odd_even_indicator = 0; + pri_subaddress->length = 0; + pri_subaddress->data[0] = '\0'; + return; + } + + pri_subaddress->valid = 1; + pri_subaddress->type = q931_subaddress->type; + pri_subaddress->odd_even_indicator = q931_subaddress->odd_even_indicator; + + length = q931_subaddress->length; + pri_subaddress->length = length; + memcpy(pri_subaddress->data, q931_subaddress->data, length); + pri_subaddress->data[length] = '\0'; +} + /*! * \brief Copy the Q.931 party id to the PRI party id structure. * @@ -510,6 +607,7 @@ void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_pa { q931_party_name_copy_to_pri(&pri_id->name, &q931_id->name); q931_party_number_copy_to_pri(&pri_id->number, &q931_id->number); + q931_party_subaddress_copy_to_pri(&pri_id->subaddress, &q931_id->subaddress); } /*! @@ -1390,6 +1488,93 @@ static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, num[len] = 0; } +static void q931_get_subaddr_specific(unsigned char *num, int maxlen, unsigned char *src, int len, char oddflag) +{ + /* User Specified */ + int x; + char *ptr = (char *) num; + + if (len <= 0) { + num[0] = '\0'; + return; + } + + if (((len * 2) + 1) > maxlen) { + len = (maxlen / 2) - 1; + } + + for (x = 0; x < (len - 1); ++x) { + ptr += sprintf(ptr, "%02x", src[x]); + } + + if (oddflag) { + /* ODD */ + sprintf(ptr, "%01x", (src[len - 1]) >> 4); + } else { + /* EVEN */ + sprintf(ptr, "%02x", src[len - 1]); + } +} + +static int transmit_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len, int order) +{ + size_t datalen; + + if (!q931_subaddress->valid) { + return 0; + } + + datalen = q931_subaddress->length; + if (!q931_subaddress->type) { + /* 0 = NSAP */ + /* 0 = Odd/Even indicator */ + ie->data[0] = 0x80; + } else { + /* 2 = User Specified */ + ie->data[0] = q931_subaddress->odd_even_indicator ? 0xA8 : 0xA0; + } + memcpy(ie->data + offset, q931_subaddress->data, datalen); + + return datalen + (offset + 2); +} + +static int receive_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len) +{ + if (len <= 0) { + return -1; + } + + q931_subaddress->valid = 1; + q931_subaddress->length = len; + /* type: 0 = NSAP, 2 = User Specified */ + q931_subaddress->type = ((ie->data[0] & 0x70) >> 4); + q931_subaddress->odd_even_indicator = (ie->data[0] & 0x08) ? 1 : 0; + q931_get_number(q931_subaddress->data, sizeof(q931_subaddress->data), + ie->data + offset, len); + + return 0; +} + +static void dump_subaddr_helper(int full_ie, struct pri *ctrl, q931_ie *ie, int offset, int len, int datalen, char prefix, const char *named) +{ + unsigned char cnum[256]; + + if (!(ie->data[0] & 0x70)) { + /* NSAP */ + q931_get_number(cnum, sizeof(cnum), ie->data + offset, datalen); + } else { + /* User Specified */ + q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset, datalen, + ie->data[0] & 0x08); + } + + pri_message(ctrl, + "%c %s Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", + prefix, named, len, ie->data[0] >> 7, + subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, + (ie->data[0] & 0x08) >> 3, cnum); +} + static void dump_called_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix) { unsigned char cnum[256]; @@ -1401,12 +1586,7 @@ static void dump_called_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, static void dump_called_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix) { - unsigned char cnum[256]; - q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); - pri_message(ctrl, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", - prefix, len, ie->data[0] >> 7, - subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, - (ie->data[0] & 0x08) >> 3, cnum); + dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Called"); } static void dump_calling_party_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix) @@ -1425,12 +1605,7 @@ static void dump_calling_party_number(int full_ie, struct pri *ctrl, q931_ie *ie static void dump_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix) { - unsigned char cnum[256]; - q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3); - pri_message(ctrl, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", - prefix, len, ie->data[0] >> 7, - subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, - (ie->data[0] & 0x08) >> 3, cnum); + dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Calling"); } static void dump_redirecting_number(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix) @@ -1547,6 +1722,26 @@ static void dump_connected_number(int full_ie, struct pri *ctrl, q931_ie *ie, in pri_message(ctrl, " '%s' ]\n", cnum); } +static int receive_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) +{ + if (len < 3) { + return -1; + } + + return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie, + 1, len - 3); +} + +static int transmit_connected_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order) +{ + return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie, + 1, len, order); +} + +static void dump_connected_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix) +{ + dump_subaddr_helper(full_ie, ctrl, ie, 1 , len, len - 3, prefix, "Connected"); +} static int receive_redirecting_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) { @@ -1603,12 +1798,7 @@ static int transmit_redirecting_number(int full_ie, struct pri *ctrl, q931_call static void dump_redirecting_subaddr(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix) { - unsigned char cnum[256]; - q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4); - pri_message(ctrl, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n", - prefix, len, ie->data[0] >> 7, - subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4, - (ie->data[0] & 0x08) >> 3, cnum); + dump_subaddr_helper(full_ie, ctrl, ie, 2, len, len - 4, prefix, "Redirecting"); } static int receive_redirection_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) @@ -1656,9 +1846,33 @@ static int transmit_redirection_number(int full_ie, struct pri *ctrl, q931_call static int receive_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) { - /* copy digits to call->callingsubaddr */ - q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3); - return 0; + if (len < 3) { + return -1; + } + + return receive_subaddr_helper(full_ie, ctrl, &call->remote_id.subaddress, msgtype, ie, + 1, len - 3); +} + +static int transmit_calling_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order) +{ + return transmit_subaddr_helper(full_ie, ctrl, &call->local_id.subaddress, msgtype, ie, + 1, len, order); +} + +static int receive_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) +{ + if (len < 3) { + return -1; + } + return receive_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie, 1, + len - 3); +} + +static int transmit_called_party_subaddr(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order) +{ + return transmit_subaddr_helper(full_ie, ctrl, &call->called.subaddress, msgtype, ie, + 1, len, order); } static int receive_called_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) @@ -2854,9 +3068,9 @@ static struct ie ies[] = { { 1, Q931_CLOSED_USER_GROUP, "Closed User Group" }, { 1, Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication", dump_reverse_charging_indication, receive_reverse_charging_indication, transmit_reverse_charging_indication }, { 1, Q931_CALLING_PARTY_NUMBER, "Calling Party Number", dump_calling_party_number, receive_calling_party_number, transmit_calling_party_number }, - { 1, Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr }, + { 1, Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr, transmit_calling_party_subaddr }, { 1, Q931_CALLED_PARTY_NUMBER, "Called Party Number", dump_called_party_number, receive_called_party_number, transmit_called_party_number }, - { 1, Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr }, + { 1, Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr, receive_called_party_subaddr, transmit_called_party_subaddr }, { 0, Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number }, { 1, Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr }, { 0, Q931_TRANSIT_NET_SELECT, "Transit Network Selection" }, @@ -2885,6 +3099,7 @@ static struct ie ies[] = { { 1, Q931_IE_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status }, { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number }, { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number, receive_connected_number, transmit_connected_number }, + { 1, Q931_IE_CONNECTED_SUBADDR, "Connected Subaddress", dump_connected_subaddr, receive_connected_subaddr, transmit_connected_subaddr }, { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number }, { 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" }, { 1, Q931_IE_UPDATE, "Update" }, @@ -3822,7 +4037,15 @@ static void pri_disconnect_timeout(void *data) q931_release(ctrl, c, PRI_CAUSE_NORMAL_CLEARING); } -static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_DISPLAY, Q931_IE_CONNECTED_NUM, -1 }; +static int connect_ies[] = { + Q931_CHANNEL_IDENT, + Q931_IE_FACILITY, + Q931_PROGRESS_INDICATOR, + Q931_DISPLAY, + Q931_IE_CONNECTED_NUM, + Q931_IE_CONNECTED_SUBADDR, + -1 +}; int q931_connect(struct pri *ctrl, q931_call *c, int channel, int nonisdn) { @@ -3951,7 +4174,9 @@ static int setup_ies[] = { Q931_DISPLAY, Q931_REVERSE_CHARGE_INDIC, Q931_CALLING_PARTY_NUMBER, + Q931_CALLING_PARTY_SUBADDR, Q931_CALLED_PARTY_NUMBER, + Q931_CALLED_PARTY_SUBADDR, Q931_REDIRECTING_NUMBER, Q931_IE_USER_USER, Q931_SENDING_COMPLETE, @@ -3972,7 +4197,9 @@ static int cis_setup_ies[] = { Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLING_PARTY_NUMBER, + Q931_CALLING_PARTY_SUBADDR, Q931_CALLED_PARTY_NUMBER, + Q931_CALLED_PARTY_SUBADDR, Q931_SENDING_COMPLETE, -1 }; @@ -4714,13 +4941,20 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct } libpri_copy_string(ctrl->ev.ring.callingnum, c->remote_id.number.str, sizeof(ctrl->ev.ring.callingnum)); libpri_copy_string(ctrl->ev.ring.callingname, c->remote_id.name.str, sizeof(ctrl->ev.ring.callingname)); - libpri_copy_string(ctrl->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(ctrl->ev.ring.callingsubaddr)); + q931_party_id_copy_to_pri(&ctrl->ev.ring.calling, &c->remote_id); + /* for backwards compatibility, still need ctrl->ev.ring.callingsubaddr */ + if (!c->remote_id.subaddress.type) { /* NSAP: Type = 0 */ + libpri_copy_string(ctrl->ev.ring.callingsubaddr, (char *) c->remote_id.subaddress.data, sizeof(ctrl->ev.ring.callingsubaddr)); + } else { + ctrl->ev.ring.callingsubaddr[0] = '\0'; + } ctrl->ev.ring.ani2 = c->ani2; /* Called party information */ ctrl->ev.ring.calledplan = c->called.number.plan; libpri_copy_string(ctrl->ev.ring.callednum, c->called.number.str, sizeof(ctrl->ev.ring.callednum)); + q931_party_subaddress_copy_to_pri(&ctrl->ev.ring.called_subaddress, &c->called.subaddress); /* Original called party information (For backward compatibility) */ libpri_copy_string(ctrl->ev.ring.origcalledname, c->redirecting.orig_called.name.str, sizeof(ctrl->ev.ring.origcalledname)); @@ -5078,8 +5312,16 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct ctrl->ev.ring.call = c; ctrl->ev.ring.channel = q931_encode_channel(c); libpri_copy_string(ctrl->ev.ring.callednum, c->overlap_digits, sizeof(ctrl->ev.ring.callednum)); - libpri_copy_string(ctrl->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(ctrl->ev.ring.callingsubaddr)); - ctrl->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */ + + q931_party_id_copy_to_pri(&ctrl->ev.ring.calling, &c->remote_id); + /* for backwards compatibility, still need ctrl->ev.ring.callingsubaddr */ + if (!c->remote_id.subaddress.type) { /* NSAP: Type = 0 */ + libpri_copy_string(ctrl->ev.ring.callingsubaddr, (char *) c->remote_id.subaddress.data, sizeof(ctrl->ev.ring.callingsubaddr)); + } else { + ctrl->ev.ring.callingsubaddr[0] = '\0'; + } + + ctrl->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */ return Q931_RES_HAVEEVENT; case Q931_STATUS_ENQUIRY: if (c->newcall) {