Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dca4921d2 | ||
|
|
b14525f475 | ||
|
|
5feca71b83 | ||
|
|
8d5be5281a | ||
|
|
ef3a4f1b5a | ||
|
|
969b121c9b | ||
|
|
b32ccb3fdd | ||
|
|
9b04f86bf6 | ||
|
|
2d986a8567 | ||
|
|
399513b13b | ||
|
|
ea17cdae4f | ||
|
|
d878403e92 | ||
|
|
12c20f0f91 | ||
|
|
fb53af3a71 | ||
|
|
585c016da8 | ||
|
|
f86ab05045 |
1
pri.c
1
pri.c
@@ -300,6 +300,7 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
||||
pri_default_timers(p, switchtype);
|
||||
if (master) {
|
||||
pri_set_debug(p, master->debug);
|
||||
pri_set_inbanddisconnect(p, master->acceptinbanddisconnect);
|
||||
if (master->sendfacility)
|
||||
pri_facility_enable(p);
|
||||
}
|
||||
|
||||
@@ -3745,25 +3745,65 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
|
||||
/* CallingName is put in remote_id.name */
|
||||
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
||||
&invoke->args.qsig.CallingName.name);
|
||||
|
||||
switch (msgtype) {
|
||||
case Q931_SETUP:
|
||||
case Q931_CONNECT:
|
||||
/* The caller name will automatically be reported. */
|
||||
break;
|
||||
default:
|
||||
/* Setup connected line subcommand */
|
||||
subcmd = q931_alloc_subcommand(ctrl);
|
||||
if (!subcmd) {
|
||||
break;
|
||||
}
|
||||
subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
|
||||
q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &call->remote_id);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ROSE_QSIG_CalledName:
|
||||
/* CalledName is put in remote_id.name */
|
||||
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
||||
&invoke->args.qsig.CalledName.name);
|
||||
|
||||
/* Setup connected line subcommand */
|
||||
subcmd = q931_alloc_subcommand(ctrl);
|
||||
if (!subcmd) {
|
||||
switch (msgtype) {
|
||||
case Q931_SETUP:
|
||||
case Q931_CONNECT:
|
||||
/* The called name will automatically be reported. */
|
||||
pri_error(ctrl, "ERROR: Too many facility subcommands\n");
|
||||
break;
|
||||
default:
|
||||
/* Setup connected line subcommand */
|
||||
subcmd = q931_alloc_subcommand(ctrl);
|
||||
if (!subcmd) {
|
||||
break;
|
||||
}
|
||||
subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
|
||||
q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &call->remote_id);
|
||||
break;
|
||||
}
|
||||
subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
|
||||
q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &call->remote_id);
|
||||
break;
|
||||
case ROSE_QSIG_ConnectedName:
|
||||
/* ConnectedName is put in remote_id.name */
|
||||
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
||||
&invoke->args.qsig.ConnectedName.name);
|
||||
|
||||
switch (msgtype) {
|
||||
case Q931_SETUP:
|
||||
case Q931_CONNECT:
|
||||
/* The connected line name will automatically be reported. */
|
||||
break;
|
||||
default:
|
||||
/* Setup connected line subcommand */
|
||||
subcmd = q931_alloc_subcommand(ctrl);
|
||||
if (!subcmd) {
|
||||
break;
|
||||
}
|
||||
subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
|
||||
q931_party_id_copy_to_pri(&subcmd->u.connected_line.id, &call->remote_id);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#if 0 /* Not handled yet */
|
||||
case ROSE_QSIG_BusyName:
|
||||
|
||||
@@ -458,6 +458,8 @@ struct q931_call {
|
||||
* (Caller-ID for answered or connected-line for originated calls.)
|
||||
*/
|
||||
struct q931_party_id remote_id;
|
||||
/*! \brief Automatic Number Identification (ANI) */
|
||||
struct q931_party_number ani;
|
||||
|
||||
/*!
|
||||
* \brief Staging place for the Q.931 redirection number ie.
|
||||
|
||||
80
q931.c
80
q931.c
@@ -1994,26 +1994,41 @@ static int transmit_called_party_number(int full_ie, struct pri *ctrl, q931_call
|
||||
static int receive_calling_party_number(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||
{
|
||||
int i = 0;
|
||||
struct q931_party_number number;
|
||||
|
||||
q931_party_number_init(&number);
|
||||
number.valid = 1;
|
||||
number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
|
||||
|
||||
call->remote_id.number.valid = 1;
|
||||
call->remote_id.number.presentation =
|
||||
PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
|
||||
/* To follow Q.931 (4.5.1), we must search for start of octet 4 by
|
||||
walking through all bytes until one with ext bit (8) set to 1 */
|
||||
do {
|
||||
switch (i) {
|
||||
case 0:
|
||||
call->remote_id.number.plan = ie->data[i] & 0x7f;
|
||||
number.plan = ie->data[i] & 0x7f;
|
||||
break;
|
||||
case 1:
|
||||
/* Keep only the presentation and screening fields */
|
||||
call->remote_id.number.presentation =
|
||||
number.presentation =
|
||||
ie->data[i] & (PRI_PRES_RESTRICTION | PRI_PRES_NUMBER_TYPE);
|
||||
break;
|
||||
}
|
||||
} while (!(ie->data[i++] & 0x80));
|
||||
q931_get_number((unsigned char *) call->remote_id.number.str,
|
||||
sizeof(call->remote_id.number.str), ie->data + i, ie->len - i);
|
||||
q931_get_number((unsigned char *) number.str, sizeof(number.str), ie->data + i,
|
||||
ie->len - i);
|
||||
|
||||
/* There can be more than one calling party number ie in the SETUP message. */
|
||||
if (number.presentation == (PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER)
|
||||
|| number.presentation == (PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER)) {
|
||||
/* The number is network provided so it is an ANI number. */
|
||||
call->ani = number;
|
||||
if (!call->remote_id.number.valid) {
|
||||
/* Copy ANI to CallerID if CallerID is not already set. */
|
||||
call->remote_id.number = number;
|
||||
}
|
||||
} else {
|
||||
call->remote_id.number = number;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2401,25 +2416,28 @@ static int process_facility(struct pri *ctrl, q931_call *call, int msgtype, q931
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = rose_decode(ctrl, pos, end, &rose);
|
||||
if (!pos) {
|
||||
return -1;
|
||||
}
|
||||
switch (rose.type) {
|
||||
case ROSE_COMP_TYPE_INVOKE:
|
||||
rose_handle_invoke(ctrl, call, msgtype, ie, &header, &rose.component.invoke);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_RESULT:
|
||||
rose_handle_result(ctrl, call, msgtype, ie, &header, &rose.component.result);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_ERROR:
|
||||
rose_handle_error(ctrl, call, msgtype, ie, &header, &rose.component.error);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_REJECT:
|
||||
rose_handle_reject(ctrl, call, msgtype, ie, &header, &rose.component.reject);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
/* Process all components in the facility. */
|
||||
while (pos < end) {
|
||||
pos = rose_decode(ctrl, pos, end, &rose);
|
||||
if (!pos) {
|
||||
return -1;
|
||||
}
|
||||
switch (rose.type) {
|
||||
case ROSE_COMP_TYPE_INVOKE:
|
||||
rose_handle_invoke(ctrl, call, msgtype, ie, &header, &rose.component.invoke);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_RESULT:
|
||||
rose_handle_result(ctrl, call, msgtype, ie, &header, &rose.component.result);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_ERROR:
|
||||
rose_handle_error(ctrl, call, msgtype, ie, &header, &rose.component.error);
|
||||
break;
|
||||
case ROSE_COMP_TYPE_REJECT:
|
||||
rose_handle_reject(ctrl, call, msgtype, ie, &header, &rose.component.reject);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3511,6 +3529,7 @@ void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr)
|
||||
q931_party_address_init(&call->called);
|
||||
q931_party_id_init(&call->local_id);
|
||||
q931_party_id_init(&call->remote_id);
|
||||
q931_party_number_init(&call->ani);
|
||||
q931_party_redirecting_init(&call->redirecting);
|
||||
|
||||
/* PRI is set to whoever called us */
|
||||
@@ -5670,6 +5689,7 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca
|
||||
q931_party_address_init(&c->called);
|
||||
q931_party_id_init(&c->local_id);
|
||||
q931_party_id_init(&c->remote_id);
|
||||
q931_party_number_init(&c->ani);
|
||||
q931_party_redirecting_init(&c->redirecting);
|
||||
|
||||
/*
|
||||
@@ -6474,11 +6494,9 @@ static void q931_fill_ring_event(struct pri *ctrl, struct q931_call *call)
|
||||
/* Calling party information */
|
||||
ctrl->ev.ring.callingpres = q931_party_id_presentation(&call->remote_id);
|
||||
ctrl->ev.ring.callingplan = call->remote_id.number.plan;
|
||||
if (call->remote_id.number.valid
|
||||
&& (call->remote_id.number.presentation == PRES_ALLOWED_NETWORK_NUMBER
|
||||
|| call->remote_id.number.presentation == PRES_PROHIB_NETWORK_NUMBER)) {
|
||||
ctrl->ev.ring.callingplanani = call->remote_id.number.plan;
|
||||
libpri_copy_string(ctrl->ev.ring.callingani, call->remote_id.number.str,
|
||||
if (call->ani.valid) {
|
||||
ctrl->ev.ring.callingplanani = call->ani.plan;
|
||||
libpri_copy_string(ctrl->ev.ring.callingani, call->ani.str,
|
||||
sizeof(ctrl->ev.ring.callingani));
|
||||
} else {
|
||||
ctrl->ev.ring.callingplanani = -1;
|
||||
|
||||
7
rose.c
7
rose.c
@@ -2241,13 +2241,6 @@ const unsigned char *rose_decode(struct pri *ctrl, const unsigned char *pos,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos < end) {
|
||||
if (ctrl->debug & PRI_DEBUG_APDU) {
|
||||
pri_message(ctrl, " %u byte(s) of trailing data not consumed.\n",
|
||||
(unsigned) (end - pos));
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
148
rosetest.c
148
rosetest.c
@@ -994,7 +994,6 @@ static unsigned char rose_etsi_indefinite_len[] = {
|
||||
0x00, 0x00,
|
||||
0x05, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
@@ -1039,7 +1038,6 @@ static unsigned char rose_etsi_unused_indefinite_len[] = {
|
||||
0x00, 0x00,
|
||||
0x05, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
@@ -1076,45 +1074,7 @@ static unsigned char rose_etsi_unused[] = {
|
||||
0x30, 0x06,
|
||||
0x84, 0x04,
|
||||
0x31, 0x38, 0x30, 0x33,
|
||||
0x05, 0x00,
|
||||
0x00, 0x00
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
static unsigned char rose_etsi_extra[] = {
|
||||
/* *INDENT-OFF* */
|
||||
/*
|
||||
* Context Specific/C [1 0x01] <A1> Len:24 <18>
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <44>
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <07>
|
||||
* Sequence/C(48 0x30) <30> Len:16 <10>
|
||||
* Enumerated(10 0x0A) <0A> Len:1 <01>
|
||||
* <01>
|
||||
* Enumerated(10 0x0A) <0A> Len:1 <01>
|
||||
* <05>
|
||||
* Sequence/C(48 0x30) <30> Len:6 <06>
|
||||
* Context Specific [4 0x04] <84> Len:4 <04>
|
||||
* <31 38 30 33>
|
||||
* NULL(5 0x05) <05> Len:0 <00>
|
||||
*/
|
||||
0x91,
|
||||
0xA1, 0x18,
|
||||
0x02, 0x01,
|
||||
0x44,
|
||||
0x02, 0x01,
|
||||
0x07,
|
||||
0x30, 0x10,
|
||||
0x0A, 0x01,
|
||||
0x01,
|
||||
0x0A, 0x01,
|
||||
0x05,
|
||||
0x30, 0x06,
|
||||
0x84, 0x04,
|
||||
0x31, 0x38, 0x30, 0x33,
|
||||
0x05, 0x00,
|
||||
0x00, 0x00
|
||||
0x05, 0x00
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
@@ -2116,6 +2076,62 @@ static const struct rose_message rose_qsig_msgs[] = {
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
static unsigned char rose_qsig_multiple_msg[] = {
|
||||
/* *INDENT-OFF* */
|
||||
/*
|
||||
* Context Specific/C [10 0x0A] <AA> Len:6 <06>
|
||||
* Context Specific [0 0x00] <80> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific [2 0x02] <82> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific [11 0x0B] <8B> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific/C [1 0x01] <A1> Len:16 <10>
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <01> - "~"
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <55> - "U"
|
||||
* Sequence/C(48 0x30) <30> Len:8 <08>
|
||||
* Context Specific [2 0x02] <82> Len:3 <03>
|
||||
* <01 30 40> - "~0@"
|
||||
* Context Specific [6 0x06] <86> Len:1 <01>
|
||||
* <01> - "~"
|
||||
* Context Specific/C [1 0x01] <A1> Len:19 <13>
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <02> - "~"
|
||||
* Integer(2 0x02) <02> Len:1 <01>
|
||||
* <00> - "~"
|
||||
* Context Specific [0 0x00] <80> Len:11 <0B>
|
||||
* <4D 6F 64 65 6D 20 44 69-73 63 6F> - "Modem Disco"
|
||||
*/
|
||||
0x9f,
|
||||
0xaa, 0x06,
|
||||
0x80, 0x01,
|
||||
0x00,
|
||||
0x82, 0x01,
|
||||
0x00,
|
||||
0x8b, 0x01,
|
||||
0x00,
|
||||
0xa1, 0x10,
|
||||
0x02, 0x01,
|
||||
0x01,
|
||||
0x02, 0x01,
|
||||
0x55,
|
||||
0x30, 0x08,
|
||||
0x82, 0x03,
|
||||
0x01, 0x30, 0x40,
|
||||
0x86, 0x01,
|
||||
0x01,
|
||||
0xa1, 0x13,
|
||||
0x02, 0x01,
|
||||
0x02,
|
||||
0x02, 0x01,
|
||||
0x00,
|
||||
0x80, 0x0b,
|
||||
0x4d, 0x6f, 0x64, 0x65, 0x6d, 0x20, 0x44, 0x69, 0x73, 0x63, 0x6f
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
|
||||
static const struct rose_message rose_dms100_msgs[] = {
|
||||
/* *INDENT-OFF* */
|
||||
@@ -2223,17 +2239,22 @@ static void rose_test_msg(struct pri *ctrl, unsigned index,
|
||||
if (!dec_pos) {
|
||||
pri_error(ctrl, "Error: Message:%u failed to decode header\n", index);
|
||||
} else {
|
||||
dec_pos = rose_decode(ctrl, dec_pos, dec_end, &decoded_msg);
|
||||
if (!dec_pos) {
|
||||
pri_error(ctrl, "Error: Message:%u failed to decode ROSE\n", index);
|
||||
} else {
|
||||
if (header
|
||||
&& memcmp(header, &decoded_header, sizeof(decoded_header))) {
|
||||
pri_error(ctrl, "Error: Message:%u Header did not match\n",
|
||||
while (dec_pos < dec_end) {
|
||||
dec_pos = rose_decode(ctrl, dec_pos, dec_end, &decoded_msg);
|
||||
if (!dec_pos) {
|
||||
pri_error(ctrl, "Error: Message:%u failed to decode ROSE\n",
|
||||
index);
|
||||
}
|
||||
if (memcmp(encode_msg, &decoded_msg, sizeof(decoded_msg))) {
|
||||
pri_error(ctrl, "Error: Message:%u ROSE did not match\n", index);
|
||||
break;
|
||||
} else {
|
||||
if (header
|
||||
&& memcmp(header, &decoded_header, sizeof(decoded_header))) {
|
||||
pri_error(ctrl, "Error: Message:%u Header did not match\n",
|
||||
index);
|
||||
}
|
||||
if (memcmp(encode_msg, &decoded_msg, sizeof(decoded_msg))) {
|
||||
pri_error(ctrl, "Error: Message:%u ROSE did not match\n",
|
||||
index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2271,9 +2292,12 @@ static void rose_test_exception(struct pri *ctrl, const char *name,
|
||||
if (!pos) {
|
||||
pri_error(ctrl, "Error: %s test: Message failed to decode header\n", name);
|
||||
} else {
|
||||
pos = rose_decode(ctrl, pos, end, &decoded_msg);
|
||||
if (!pos) {
|
||||
pri_error(ctrl, "Error: %s test: Message failed to decode ROSE\n", name);
|
||||
while (pos < end) {
|
||||
pos = rose_decode(ctrl, pos, end, &decoded_msg);
|
||||
if (!pos) {
|
||||
pri_error(ctrl, "Error: %s test: Message failed to decode ROSE\n", name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2382,24 +2406,20 @@ int main(int argc, char *argv[])
|
||||
|
||||
dummy_ctrl.switchtype = PRI_SWITCH_EUROISDN_E1;
|
||||
|
||||
rose_test_exception(&dummy_ctrl, "Extra bytes on end", rose_etsi_extra,
|
||||
sizeof(rose_etsi_extra));
|
||||
|
||||
rose_test_exception(&dummy_ctrl, "Indefinite length", rose_etsi_indefinite_len,
|
||||
sizeof(rose_etsi_indefinite_len) - 2);
|
||||
rose_test_exception(&dummy_ctrl, "Indefinite length (extra)",
|
||||
rose_etsi_indefinite_len, sizeof(rose_etsi_indefinite_len));
|
||||
sizeof(rose_etsi_indefinite_len));
|
||||
|
||||
rose_test_exception(&dummy_ctrl, "Unused components (indefinite length)",
|
||||
rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len) - 2);
|
||||
rose_test_exception(&dummy_ctrl, "Unused components (indefinite length, extra)",
|
||||
rose_etsi_unused_indefinite_len, sizeof(rose_etsi_unused_indefinite_len));
|
||||
|
||||
rose_test_exception(&dummy_ctrl, "Unused components", rose_etsi_unused,
|
||||
sizeof(rose_etsi_unused) - 2);
|
||||
rose_test_exception(&dummy_ctrl, "Unused components (extra)", rose_etsi_unused,
|
||||
sizeof(rose_etsi_unused));
|
||||
|
||||
dummy_ctrl.switchtype = PRI_SWITCH_QSIG;
|
||||
|
||||
rose_test_exception(&dummy_ctrl, "Multiple component messages",
|
||||
rose_qsig_multiple_msg, sizeof(rose_qsig_multiple_msg));
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
pri_message(&dummy_ctrl, "\n\n"
|
||||
|
||||
Reference in New Issue
Block a user