q931.c 130 KB
Newer Older
Mark Spencer's avatar
Mark Spencer committed
1 2 3
/*
 * libpri: An implementation of Primary Rate ISDN
 *
4
 * Written by Mark Spencer <markster@digium.com>
Mark Spencer's avatar
Mark Spencer committed
5
 *
6
 * Copyright (C) 2001-2005, Digium, Inc.
Mark Spencer's avatar
Mark Spencer committed
7
 * All Rights Reserved.
8 9 10 11 12 13 14 15
 */

/*
 * See http://www.asterisk.org for more information about
 * the Asterisk project. Please do not directly contact
 * any of the maintainers of this project for assistance;
 * the project provides a web site, mailing lists and IRC
 * channels for your use.
Mark Spencer's avatar
Mark Spencer committed
16
 *
17 18 19 20
 * This program is free software, distributed under the terms of
 * the GNU General Public License Version 2 as published by the
 * Free Software Foundation. See the LICENSE file included with
 * this program for more details.
Mark Spencer's avatar
Mark Spencer committed
21
 *
22 23 24 25 26 27
 * In addition, when this program is distributed with Asterisk in
 * any form that would qualify as a 'combined work' or as a
 * 'derivative work' (but not mere aggregation), you can redistribute
 * and/or modify the combination under the terms of the license
 * provided with that copy of Asterisk, instead of the license
 * terms granted here.
Mark Spencer's avatar
Mark Spencer committed
28
 */
29

30
#include "compat.h"
Mark Spencer's avatar
Mark Spencer committed
31 32 33 34
#include "libpri.h"
#include "pri_internal.h"
#include "pri_q921.h"
#include "pri_q931.h"
35
#include "pri_facility.h"
36
#include "rose.h"
Mark Spencer's avatar
Mark Spencer committed
37 38 39 40

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
41
#include <ctype.h>
Mark Spencer's avatar
Mark Spencer committed
42
#include <stdio.h>
43
#include <limits.h>
Mark Spencer's avatar
Mark Spencer committed
44

45 46
#define MAX_MAND_IES 10

Mark Spencer's avatar
Mark Spencer committed
47 48
struct msgtype {
	int msgnum;
49
	char *name;
50
	int mandies[MAX_MAND_IES];
Mark Spencer's avatar
Mark Spencer committed
51 52
};

53
static struct msgtype msgs[] = {
Mark Spencer's avatar
Mark Spencer committed
54 55 56 57 58
	/* Call establishment messages */
	{ Q931_ALERTING, "ALERTING" },
	{ Q931_CALL_PROCEEDING, "CALL PROCEEDING" },
	{ Q931_CONNECT, "CONNECT" },
	{ Q931_CONNECT_ACKNOWLEDGE, "CONNECT ACKNOWLEDGE" },
59 60
	{ Q931_PROGRESS, "PROGRESS", { Q931_PROGRESS_INDICATOR } },
	{ Q931_SETUP, "SETUP", { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT } },
Mark Spencer's avatar
Mark Spencer committed
61
	{ Q931_SETUP_ACKNOWLEDGE, "SETUP ACKNOWLEDGE" },
Mark Spencer's avatar
Mark Spencer committed
62 63
	
	/* Call disestablishment messages */
64
	{ Q931_DISCONNECT, "DISCONNECT", { Q931_CAUSE } },
Mark Spencer's avatar
Mark Spencer committed
65 66
	{ Q931_RELEASE, "RELEASE" },
	{ Q931_RELEASE_COMPLETE, "RELEASE COMPLETE" },
67 68
	{ Q931_RESTART, "RESTART", { Q931_RESTART_INDICATOR } },
	{ Q931_RESTART_ACKNOWLEDGE, "RESTART ACKNOWLEDGE", { Q931_RESTART_INDICATOR } },
Mark Spencer's avatar
Mark Spencer committed
69 70

	/* Miscellaneous */
71
	{ Q931_STATUS, "STATUS", { Q931_CAUSE, Q931_CALL_STATE } },
Mark Spencer's avatar
Mark Spencer committed
72
	{ Q931_STATUS_ENQUIRY, "STATUS ENQUIRY" },
Mark Spencer's avatar
Mark Spencer committed
73 74 75 76
	{ Q931_USER_INFORMATION, "USER_INFORMATION" },
	{ Q931_SEGMENT, "SEGMENT" },
	{ Q931_CONGESTION_CONTROL, "CONGESTION CONTROL" },
	{ Q931_INFORMATION, "INFORMATION" },
77
	{ Q931_FACILITY, "FACILITY" },
78
	{ Q931_NOTIFY, "NOTIFY", { Q931_IE_NOTIFY_IND } },
Mark Spencer's avatar
Mark Spencer committed
79 80 81 82 83 84 85 86 87

	/* Call Management */
	{ Q931_HOLD, "HOLD" },
	{ Q931_HOLD_ACKNOWLEDGE, "HOLD ACKNOWLEDGE" },
	{ Q931_HOLD_REJECT, "HOLD REJECT" },
	{ Q931_RETRIEVE, "RETRIEVE" },
	{ Q931_RETRIEVE_ACKNOWLEDGE, "RETRIEVE ACKNOWLEDGE" },
	{ Q931_RETRIEVE_REJECT, "RETRIEVE REJECT" },
	{ Q931_RESUME, "RESUME" },
88 89
	{ Q931_RESUME_ACKNOWLEDGE, "RESUME ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
	{ Q931_RESUME_REJECT, "RESUME REJECT", { Q931_CAUSE } },
Mark Spencer's avatar
Mark Spencer committed
90 91 92
	{ Q931_SUSPEND, "SUSPEND" },
	{ Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" },
	{ Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
93 94
};
static int post_handle_q931_message(struct pri *pri, struct q931_mh *mh, struct q931_call *c, int missingmand);
Mark Spencer's avatar
Mark Spencer committed
95

96 97 98
struct msgtype maintenance_msgs[] = {
	{ NATIONAL_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
	{ NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
Mark Spencer's avatar
Mark Spencer committed
99
};
100
static int post_handle_maintenance_message(struct pri *pri, struct q931_mh *mh, struct q931_call *c);
Mark Spencer's avatar
Mark Spencer committed
101

102
static struct msgtype causes[] = {
Mark Spencer's avatar
Mark Spencer committed
103 104 105 106 107 108 109 110 111 112
	{ PRI_CAUSE_UNALLOCATED, "Unallocated (unassigned) number" },
	{ PRI_CAUSE_NO_ROUTE_TRANSIT_NET, "No route to specified transmit network" },
	{ PRI_CAUSE_NO_ROUTE_DESTINATION, "No route to destination" },
	{ PRI_CAUSE_CHANNEL_UNACCEPTABLE, "Channel unacceptable" },
	{ PRI_CAUSE_CALL_AWARDED_DELIVERED, "Call awarded and being delivered in an established channel" },
	{ PRI_CAUSE_NORMAL_CLEARING, "Normal Clearing" },
	{ PRI_CAUSE_USER_BUSY, "User busy" },
	{ PRI_CAUSE_NO_USER_RESPONSE, "No user responding" },
	{ PRI_CAUSE_NO_ANSWER, "User alerting, no answer" },
	{ PRI_CAUSE_CALL_REJECTED, "Call Rejected" },
Mark Spencer's avatar
Mark Spencer committed
113
	{ PRI_CAUSE_NUMBER_CHANGED, "Number changed" },
Mark Spencer's avatar
Mark Spencer committed
114 115
	{ PRI_CAUSE_DESTINATION_OUT_OF_ORDER, "Destination out of order" },
	{ PRI_CAUSE_INVALID_NUMBER_FORMAT, "Invalid number format" },
Mark Spencer's avatar
Mark Spencer committed
116
	{ PRI_CAUSE_FACILITY_REJECTED, "Facility rejected" },
Mark Spencer's avatar
Mark Spencer committed
117 118 119
	{ PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY, "Response to STATus ENQuiry" },
	{ PRI_CAUSE_NORMAL_UNSPECIFIED, "Normal, unspecified" },
	{ PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION, "Circuit/channel congestion" },
Mark Spencer's avatar
Mark Spencer committed
120
	{ PRI_CAUSE_NETWORK_OUT_OF_ORDER, "Network out of order" },
Mark Spencer's avatar
Mark Spencer committed
121 122 123 124
	{ PRI_CAUSE_NORMAL_TEMPORARY_FAILURE, "Temporary failure" },
	{ PRI_CAUSE_SWITCH_CONGESTION, "Switching equipment congestion" },
	{ PRI_CAUSE_ACCESS_INFO_DISCARDED, "Access information discarded" },
	{ PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, "Requested channel not available" },
Mark Spencer's avatar
Mark Spencer committed
125 126 127 128
	{ PRI_CAUSE_PRE_EMPTED, "Pre-empted" },
	{ PRI_CAUSE_FACILITY_NOT_SUBSCRIBED, "Facility not subscribed" },
	{ PRI_CAUSE_OUTGOING_CALL_BARRED, "Outgoing call barred" },
	{ PRI_CAUSE_INCOMING_CALL_BARRED, "Incoming call barred" },
Mark Spencer's avatar
Mark Spencer committed
129
	{ PRI_CAUSE_BEARERCAPABILITY_NOTAUTH, "Bearer capability not authorized" },
Mark Spencer's avatar
Mark Spencer committed
130
	{ PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL, "Bearer capability not available" },
Mark Spencer's avatar
Mark Spencer committed
131
	{ PRI_CAUSE_BEARERCAPABILITY_NOTIMPL, "Bearer capability not implemented" },
132
	{ PRI_CAUSE_SERVICEOROPTION_NOTAVAIL, "Service or option not available, unspecified" },
Mark Spencer's avatar
Mark Spencer committed
133 134
	{ PRI_CAUSE_CHAN_NOT_IMPLEMENTED, "Channel not implemented" },
	{ PRI_CAUSE_FACILITY_NOT_IMPLEMENTED, "Facility not implemented" },
Mark Spencer's avatar
Mark Spencer committed
135
	{ PRI_CAUSE_INVALID_CALL_REFERENCE, "Invalid call reference value" },
136
	{ PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST, "Identified channel does not exist" },
Mark Spencer's avatar
Mark Spencer committed
137
	{ PRI_CAUSE_INCOMPATIBLE_DESTINATION, "Incompatible destination" },
Mark Spencer's avatar
Mark Spencer committed
138
	{ PRI_CAUSE_INVALID_MSG_UNSPECIFIED, "Invalid message unspecified" },
Mark Spencer's avatar
Mark Spencer committed
139 140
	{ PRI_CAUSE_MANDATORY_IE_MISSING, "Mandatory information element is missing" },
	{ PRI_CAUSE_MESSAGE_TYPE_NONEXIST, "Message type nonexist." },
Mark Spencer's avatar
Mark Spencer committed
141
	{ PRI_CAUSE_WRONG_MESSAGE, "Wrong message" },
Mark Spencer's avatar
Mark Spencer committed
142 143 144 145
	{ PRI_CAUSE_IE_NONEXIST, "Info. element nonexist or not implemented" },
	{ PRI_CAUSE_INVALID_IE_CONTENTS, "Invalid information element contents" },
	{ PRI_CAUSE_WRONG_CALL_STATE, "Message not compatible with call state" },
	{ PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE, "Recover on timer expiry" },
Mark Spencer's avatar
Mark Spencer committed
146
	{ PRI_CAUSE_MANDATORY_IE_LENGTH_ERROR, "Mandatory IE length error" },
Mark Spencer's avatar
Mark Spencer committed
147 148 149 150
	{ PRI_CAUSE_PROTOCOL_ERROR, "Protocol error, unspecified" },
	{ PRI_CAUSE_INTERWORKING, "Interworking, unspecified" },
};

151
static struct msgtype facilities[] = {
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
       { 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" }
};

Mark Spencer's avatar
Mark Spencer committed
170 171 172 173 174 175 176 177
#define FLAG_PREFERRED 2
#define FLAG_EXCLUSIVE 4

#define RESET_INDICATOR_CHANNEL	0
#define RESET_INDICATOR_DS1		6
#define RESET_INDICATOR_PRI		7

#define TRANS_MODE_64_CIRCUIT	0x10
Mark Spencer's avatar
Mark Spencer committed
178
#define TRANS_MODE_2x64_CIRCUIT	0x11
Mark Spencer's avatar
Mark Spencer committed
179 180
#define TRANS_MODE_384_CIRCUIT	0x13
#define TRANS_MODE_1536_CIRCUIT	0x15
Mark Spencer's avatar
Mark Spencer committed
181
#define TRANS_MODE_1920_CIRCUIT	0x17
Mark Spencer's avatar
Mark Spencer committed
182
#define TRANS_MODE_MULTIRATE	0x18
183
#define TRANS_MODE_PACKET		0x40
Mark Spencer's avatar
Mark Spencer committed
184 185 186 187 188 189 190 191 192 193

#define RATE_ADAPT_56K			0x0f

#define LAYER_2_LAPB			0x46

#define LAYER_3_X25				0x66

/* The 4ESS uses a different audio field */
#define PRI_TRANS_CAP_AUDIO_4ESS	0x08

194
/* Don't forget to update PRI_PROG_xxx at libpri.h */
195
#define Q931_PROG_CALL_NOT_E2E_ISDN						0x01
Mark Spencer's avatar
Mark Spencer committed
196 197
#define Q931_PROG_CALLED_NOT_ISDN						0x02
#define Q931_PROG_CALLER_NOT_ISDN						0x03
198
#define Q931_PROG_CALLER_RETURNED_TO_ISDN					0x04
Mark Spencer's avatar
Mark Spencer committed
199 200 201 202 203 204
#define Q931_PROG_INBAND_AVAILABLE						0x08
#define Q931_PROG_DELAY_AT_INTERF						0x0a
#define Q931_PROG_INTERWORKING_WITH_PUBLIC				0x10
#define Q931_PROG_INTERWORKING_NO_RELEASE				0x11
#define Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER	0x12
#define Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER	0x13
Mark Spencer's avatar
Mark Spencer committed
205

Mark Spencer's avatar
Mark Spencer committed
206 207 208 209
#define CODE_CCITT					0x0
#define CODE_INTERNATIONAL 			0x1
#define CODE_NATIONAL 				0x2
#define CODE_NETWORK_SPECIFIC		0x3
Mark Spencer's avatar
Mark Spencer committed
210 211 212 213 214 215

#define LOC_USER					0x0
#define LOC_PRIV_NET_LOCAL_USER		0x1
#define LOC_PUB_NET_LOCAL_USER		0x2
#define LOC_TRANSIT_NET				0x3
#define LOC_PUB_NET_REMOTE_USER		0x4
216
#define LOC_PRIV_NET_REMOTE_USER	0x5
Mark Spencer's avatar
Mark Spencer committed
217 218 219
#define LOC_INTERNATIONAL_NETWORK	0x7
#define LOC_NETWORK_BEYOND_INTERWORKING	0xa

220
static char *ie2str(int ie);
221
static char *msg2str(int msg);
222

Mark Spencer's avatar
Mark Spencer committed
223

224
#define FUNC_DUMP(name) void ((name))(int full_ie, struct pri *pri, q931_ie *ie, int len, char prefix)
225
#define FUNC_RECV(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
226
#define FUNC_SEND(name) int ((name))(int full_ie, struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
227

228 229 230 231 232 233 234 235 236 237 238 239
#if 1
/* Update call state with transition trace. */
#define UPDATE_OURCALLSTATE(pri,c,newstate) do {\
	if (pri->debug & (PRI_DEBUG_Q931_STATE) && c->ourcallstate != newstate) \
		pri_message(pri, DBGHEAD "call %d on channel %d enters state %d (%s)\n", DBGINFO, \
		            c->cr, c->channelno, newstate, callstate2str(newstate)); \
	c->ourcallstate = newstate; \
	} while (0)
#else
/* Update call state with no trace. */
#define UPDATE_OURCALLSTATE(pri,c,newstate) c->ourcallstate = newstate
#endif
240

Mark Spencer's avatar
Mark Spencer committed
241
struct ie {
242 243 244
	/* Maximal count of same IEs at the message (0 - any, 1..n - limited) */
	int max_count;
	/* IE code */
Mark Spencer's avatar
Mark Spencer committed
245
	int ie;
246
	/* IE friendly name */
Mark Spencer's avatar
Mark Spencer committed
247 248
	char *name;
	/* Dump an IE for debugging (preceed all lines by prefix) */
249
	FUNC_DUMP(*dump);
Mark Spencer's avatar
Mark Spencer committed
250
	/* Handle IE  returns 0 on success, -1 on failure */
251
	FUNC_RECV(*receive);
Mark Spencer's avatar
Mark Spencer committed
252
	/* Add IE to a message, return the # of bytes added or -1 on failure */
253
	FUNC_SEND(*transmit);
Mark Spencer's avatar
Mark Spencer committed
254 255
};

Mark Spencer's avatar
Mark Spencer committed
256 257 258 259 260 261 262 263 264
static char *code2str(int code, struct msgtype *codes, int max)
{
	int x;
	for (x=0;x<max; x++) 
		if (codes[x].msgnum == code)
			return codes[x].name;
	return "Unknown";
}

265 266 267 268 269 270 271 272 273 274 275 276 277 278
static char *pritype(int type)
{
	switch (type) {
	case PRI_CPE:
		return "CPE";
		break;
	case PRI_NETWORK:
		return "NET";
		break;
	default:
		return "UNKNOWN";
	}
}

Mark Spencer's avatar
Mark Spencer committed
279 280
static void call_init(struct q931_call *c)
{
Mark Spencer's avatar
Mark Spencer committed
281
	c->forceinvert = -1;	
Mark Spencer's avatar
Mark Spencer committed
282 283 284
	c->cr = -1;
	c->slotmap = -1;
	c->channelno = -1;
285
	c->newcall = 1;
286
	c->ourcallstate = Q931_CALL_STATE_NULL;
287
	c->peercallstate = Q931_CALL_STATE_NULL;
Mark Spencer's avatar
Mark Spencer committed
288 289 290 291 292 293 294 295 296 297 298 299 300
}

static char *binary(int b, int len) {
	static char res[33];
	int x;
	memset(res, 0, sizeof(res));
	if (len > 32)
		len = 32;
	for (x=1;x<=len;x++)
		res[x-1] = b & (1 << (len - x)) ? '1' : '0';
	return res;
}

301
static FUNC_RECV(receive_channel_id)
Mark Spencer's avatar
Mark Spencer committed
302 303 304
{	
	int x;
	int pos=0;
305 306
#ifdef NO_BRI_SUPPORT
 	if (!ie->data[0] & 0x20) {
307
		pri_error(pri, "!! Not PRI type!?\n");
308 309 310 311
 		return -1;
 	}
#endif
#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
312 313
	if (pri->bri) {
		if (!(ie->data[0] & 3))
314
			call->justsignalling = 1;
315 316 317 318 319 320 321 322 323 324 325 326 327
		else
			call->channelno = ie->data[0] & 3;
	} else {
		switch (ie->data[0] & 3) {
			case 0:
				call->justsignalling = 1;
				break;
			case 1:
				break;
			default:
				pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
				return -1;
		}
Mark Spencer's avatar
Mark Spencer committed
328
	}
329
#endif
Mark Spencer's avatar
Mark Spencer committed
330 331 332 333 334 335 336 337
	if (ie->data[0] & 0x08)
		call->chanflags = FLAG_EXCLUSIVE;
	else
		call->chanflags = FLAG_PREFERRED;
	pos++;
	if (ie->data[0] & 0x40) {
		/* DS1 specified -- stop here */
		call->ds1no = ie->data[1] & 0x7f;
338
		call->ds1explicit = 1;
Mark Spencer's avatar
Mark Spencer committed
339
		pos++;
340 341 342
	} else
		call->ds1explicit = 0;

343
	if (pos+2 < len) {
Mark Spencer's avatar
Mark Spencer committed
344 345
		/* More coming */
		if ((ie->data[pos] & 0x0f) != 3) {
346
			pri_error(pri, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
Mark Spencer's avatar
Mark Spencer committed
347 348 349
			return -1;
		}
		if ((ie->data[pos] & 0x60) != 0) {
350
			pri_error(pri, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
Mark Spencer's avatar
Mark Spencer committed
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
			return -1;
		}
		if (ie->data[pos] & 0x10) {
			/* Expect Slot Map */
			call->slotmap = 0;
			pos++;
			for (x=0;x<3;x++) {
				call->slotmap <<= 8;
				call->slotmap |= ie->data[x + pos];
			}
			return 0;
		} else {
			pos++;
			/* Only expect a particular channel */
			call->channelno = ie->data[pos] & 0x7f;
366 367
			if (pri->chan_mapping_logical && call->channelno > 15)
				call->channelno++;
Mark Spencer's avatar
Mark Spencer committed
368 369 370 371 372 373 374
			return 0;
		}
	} else
		return 0;
	return -1;
}

375
static FUNC_SEND(transmit_channel_id)
Mark Spencer's avatar
Mark Spencer committed
376 377
{
	int pos=0;
378

379
	
380 381 382
	/* We are ready to transmit single IE only */
	if (order > 1)
		return 0;
383 384 385 386 387 388 389
	
	if (call->justsignalling) {
		ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
					   ECMA-165 section 7.3 */
		return pos + 2;
	}
		
Mark Spencer's avatar
Mark Spencer committed
390
	/* Start with standard stuff */
391
	if (pri->switchtype == PRI_SWITCH_GR303_TMC)
Mark Spencer's avatar
Mark Spencer committed
392
		ie->data[pos] = 0x69;
393 394 395 396 397
	else if (pri->bri) {
		ie->data[pos] = 0x80;
		if (call->channelno > -1)
			ie->data[pos] |= (call->channelno & 0x3);
	} else
398
		ie->data[pos] = 0xa1;
Mark Spencer's avatar
Mark Spencer committed
399 400 401 402 403 404 405 406
	/* Add exclusive flag if necessary */
	if (call->chanflags & FLAG_EXCLUSIVE)
		ie->data[pos] |= 0x08;
	else if (!(call->chanflags & FLAG_PREFERRED)) {
		/* Don't need this IE */
		return 0;
	}

407
	if (((pri->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit) {
Mark Spencer's avatar
Mark Spencer committed
408
		/* Note that we are specifying the identifier */
Mark Spencer's avatar
Mark Spencer committed
409
		ie->data[pos++] |= 0x40;
Mark Spencer's avatar
Mark Spencer committed
410
		/* We need to use the Channel Identifier Present thingy.  Just specify it and we're done */
Mark Spencer's avatar
Mark Spencer committed
411
		ie->data[pos++] = 0x80 | call->ds1no;
Mark Spencer's avatar
Mark Spencer committed
412 413
	} else
		pos++;
414 415 416 417

	if (pri->bri)
		return pos + 2;

Mark Spencer's avatar
Mark Spencer committed
418 419 420 421 422
	if ((call->channelno > -1) || (call->slotmap != -1)) {
		/* We'll have the octet 8.2 and 8.3's present */
		ie->data[pos++] = 0x83;
		if (call->channelno > -1) {
			/* Channel number specified */
423 424 425 426
			if (pri->chan_mapping_logical && call->channelno > 16)
				ie->data[pos++] = 0x80 | (call->channelno - 1);
			else
				ie->data[pos++] = 0x80 | call->channelno;
Mark Spencer's avatar
Mark Spencer committed
427 428 429 430 431 432 433 434 435 436 437
			return pos + 2;
		}
		/* We have to send a channel map */
		if (call->slotmap != -1) {
			ie->data[pos-1] |= 0x10;
			ie->data[pos++] = (call->slotmap & 0xff0000) >> 16;
			ie->data[pos++] = (call->slotmap & 0xff00) >> 8;
			ie->data[pos++] = (call->slotmap & 0xff);
			return pos + 2;
		}
	}
438
	if (call->ds1no > 0) {
Mark Spencer's avatar
Mark Spencer committed
439 440 441
		/* We're done */
		return pos + 2;
	}
442
	pri_error(pri, "!! No channel map, no channel, and no ds1?  What am I supposed to identify?\n");
Mark Spencer's avatar
Mark Spencer committed
443 444 445
	return -1;
}

446
static FUNC_DUMP(dump_channel_id)
Mark Spencer's avatar
Mark Spencer committed
447 448 449 450
{
	int pos=0;
	int x;
	int res = 0;
451
	static const char*	msg_chan_sel[] = {
452
		"No channel selected", "B1 channel", "B2 channel","Any channel selected",  
453 454 455
		"No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
	};

456
	pri_message(pri, "%c Channel ID (len=%2d) [ Ext: %d  IntID: %s  %s  Spare: %d  %s  Dchan: %d\n",
Mark Spencer's avatar
Mark Spencer committed
457 458
		prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
		(ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
459
		(ie->data[0] & 0x08) ? "Exclusive" : "Preferred",  (ie->data[0] & 0x04) ? 1 : 0);
460
	pri_message(pri, "%c                        ChanSel: %s\n",
461
		prefix, msg_chan_sel[(ie->data[0] & 0x3) + ((ie->data[0]>>3) & 0x4)]);
Mark Spencer's avatar
Mark Spencer committed
462 463 464 465
	pos++;
	len--;
	if (ie->data[0] &  0x40) {
		/* Explicitly defined DS1 */
466
		pri_message(pri, "%c                       Ext: %d  DS1 Identifier: %d  \n", prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
Mark Spencer's avatar
Mark Spencer committed
467 468 469 470
		pos++;
	} else {
		/* Implicitly defined DS1 */
	}
471
	if (pos+2 < len) {
Mark Spencer's avatar
Mark Spencer committed
472
		/* Still more information here */
473
		pri_message(pri, "%c                       Ext: %d  Coding: %d  %s Specified  Channel Type: %d\n",
Mark Spencer's avatar
Mark Spencer committed
474 475 476 477 478
				prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5, 
				(ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
		if (!(ie->data[pos] & 0x10)) {
			/* Number specified */
			pos++;
479 480
			pri_message(pri, "%c                       Ext: %d  Channel: %d Type: %s]\n", prefix, (ie->data[pos] & 0x80) >> 7, 
				(ie->data[pos]) & 0x7f, pritype(pri->localtype));
Mark Spencer's avatar
Mark Spencer committed
481 482 483 484 485 486 487
		} else {
			pos++;
			/* Map specified */
			for (x=0;x<3;x++) {
				res <<= 8;
				res |= ie->data[pos++];
			}
488
			pri_message(pri, "%c                       Map: %s ]\n", prefix, binary(res, 24));
Mark Spencer's avatar
Mark Spencer committed
489
		}
490
	} else pri_message(pri, "                         ]\n");				
Mark Spencer's avatar
Mark Spencer committed
491 492 493 494
}

static char *ri2str(int ri)
{
Mark Spencer's avatar
Mark Spencer committed
495 496 497 498 499 500
	static struct msgtype ris[] = {
		{ 0, "Indicated Channel" },
		{ 6, "Single DS1 Facility" },
		{ 7, "All DS1 Facilities" },
	};
	return code2str(ri, ris, sizeof(ris) / sizeof(ris[0]));
Mark Spencer's avatar
Mark Spencer committed
501 502
}

503
static FUNC_DUMP(dump_restart_indicator)
Mark Spencer's avatar
Mark Spencer committed
504
{
505
	pri_message(pri, "%c Restart Indentifier (len=%2d) [ Ext: %d  Spare: %d  Resetting %s (%d) ]\n", 
506
		prefix, len, (ie->data[0] & 0x80) >> 7, (ie->data[0] & 0x78) >> 3, ri2str(ie->data[0] & 0x7), ie->data[0] & 0x7);
Mark Spencer's avatar
Mark Spencer committed
507 508
}

509
static FUNC_RECV(receive_restart_indicator)
Mark Spencer's avatar
Mark Spencer committed
510 511 512 513 514 515
{
	/* Pretty simple */
	call->ri = ie->data[0] & 0x7;
	return 0;
}

516
static FUNC_SEND(transmit_restart_indicator)
Mark Spencer's avatar
Mark Spencer committed
517 518 519 520 521 522 523 524 525 526 527 528 529
{
	/* Pretty simple */
	switch(call->ri) {
	case 0:
	case 6:
	case 7:
		ie->data[0] = 0x80 | (call->ri & 0x7);
		break;
	case 5:
		/* Switch compatibility */
		ie->data[0] = 0xA0 | (call->ri & 0x7);
		break;
	default:
530
		pri_error(pri, "!! Invalid restart indicator value %d\n", call->ri);
Mark Spencer's avatar
Mark Spencer committed
531 532 533 534 535
		return-1;
	}
	return 3;
}

Mark Spencer's avatar
Mark Spencer committed
536 537 538 539 540 541 542 543 544 545 546 547 548 549
static char *redirection_reason2str(int mode)
{
	static struct msgtype modes[] = {
		{ PRI_REDIR_UNKNOWN, "Unknown" },
		{ PRI_REDIR_FORWARD_ON_BUSY, "Forwarded on busy" },
		{ PRI_REDIR_FORWARD_ON_NO_REPLY, "Forwarded on no reply" },
		{ PRI_REDIR_DEFLECTION, "Call deflected" },
		{ PRI_REDIR_DTE_OUT_OF_ORDER, "Called DTE out of order" },
		{ PRI_REDIR_FORWARDED_BY_DTE, "Forwarded by called DTE" },
		{ PRI_REDIR_UNCONDITIONAL, "Forwarded unconditionally" },
	};
	return code2str(mode, modes, sizeof(modes) / sizeof(modes[0]));
}

Mark Spencer's avatar
Mark Spencer committed
550 551
static char *cap2str(int mode)
{
Mark Spencer's avatar
Mark Spencer committed
552 553 554 555 556
	static struct msgtype modes[] = {
		{ PRI_TRANS_CAP_SPEECH, "Speech" },
		{ PRI_TRANS_CAP_DIGITAL, "Unrestricted digital information" },
		{ PRI_TRANS_CAP_RESTRICTED_DIGITAL, "Restricted digital information" },
		{ PRI_TRANS_CAP_3_1K_AUDIO, "3.1kHz audio" },
557
		{ PRI_TRANS_CAP_DIGITAL_W_TONES, "Unrestricted digital information with tones/announcements" },
Mark Spencer's avatar
Mark Spencer committed
558 559 560 561
		{ PRI_TRANS_CAP_VIDEO, "Video" },
		{ PRI_TRANS_CAP_AUDIO_4ESS, "3.1khz audio (4ESS)" },
	};
	return code2str(mode, modes, sizeof(modes) / sizeof(modes[0]));
Mark Spencer's avatar
Mark Spencer committed
562 563 564 565
}

static char *mode2str(int mode)
{
Mark Spencer's avatar
Mark Spencer committed
566 567 568 569 570 571 572 573 574 575
	static struct msgtype modes[] = {
		{ TRANS_MODE_64_CIRCUIT, "64kbps, circuit-mode" },
		{ TRANS_MODE_2x64_CIRCUIT, "2x64kbps, circuit-mode" },
		{ TRANS_MODE_384_CIRCUIT, "384kbps, circuit-mode" },
		{ TRANS_MODE_1536_CIRCUIT, "1536kbps, circuit-mode" },
		{ TRANS_MODE_1920_CIRCUIT, "1920kbps, circuit-mode" },
		{ TRANS_MODE_MULTIRATE, "Multirate (Nx64kbps)" },
		{ TRANS_MODE_PACKET, "Packet Mode" },
	};
	return code2str(mode, modes, sizeof(modes) / sizeof(modes[0]));
Mark Spencer's avatar
Mark Spencer committed
576 577 578 579
}

static char *l12str(int proto)
{
Mark Spencer's avatar
Mark Spencer committed
580
	static struct msgtype protos[] = {
581
 		{ PRI_LAYER_1_ITU_RATE_ADAPT, "V.110 Rate Adaption" },
Mark Spencer's avatar
Mark Spencer committed
582 583 584 585
		{ PRI_LAYER_1_ULAW, "u-Law" },
		{ PRI_LAYER_1_ALAW, "A-Law" },
		{ PRI_LAYER_1_G721, "G.721 ADPCM" },
		{ PRI_LAYER_1_G722_G725, "G.722/G.725 7kHz Audio" },
586
 		{ PRI_LAYER_1_H223_H245, "H.223/H.245 Multimedia" },
Mark Spencer's avatar
Mark Spencer committed
587 588 589
		{ PRI_LAYER_1_NON_ITU_ADAPT, "Non-ITU Rate Adaption" },
		{ PRI_LAYER_1_V120_RATE_ADAPT, "V.120 Rate Adaption" },
		{ PRI_LAYER_1_X31_RATE_ADAPT, "X.31 Rate Adaption" },
Mark Spencer's avatar
Mark Spencer committed
590 591
	};
	return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
Mark Spencer's avatar
Mark Spencer committed
592 593 594 595
}

static char *ra2str(int proto)
{
Mark Spencer's avatar
Mark Spencer committed
596
	static struct msgtype protos[] = {
597
		{ PRI_RATE_ADAPT_9K6, "9.6 kbit/s" },
Mark Spencer's avatar
Mark Spencer committed
598 599
	};
	return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
Mark Spencer's avatar
Mark Spencer committed
600 601 602 603
}

static char *l22str(int proto)
{
Mark Spencer's avatar
Mark Spencer committed
604 605 606 607
	static struct msgtype protos[] = {
		{ LAYER_2_LAPB, "LAPB" },
	};
	return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
Mark Spencer's avatar
Mark Spencer committed
608 609 610 611
}

static char *l32str(int proto)
{
Mark Spencer's avatar
Mark Spencer committed
612 613 614 615
	static struct msgtype protos[] = {
		{ LAYER_3_X25, "X.25" },
	};
	return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
Mark Spencer's avatar
Mark Spencer committed
616 617
}

618 619 620 621 622 623 624 625 626 627
static char *int_rate2str(int proto)
{
    static struct msgtype protos[] = {
		{ PRI_INT_RATE_8K, "8 kbit/s" },
		{ PRI_INT_RATE_16K, "16 kbit/s" },
		{ PRI_INT_RATE_32K, "32 kbit/s" },
    };
    return code2str(proto, protos, sizeof(protos) / sizeof(protos[0]));
}

628
static FUNC_DUMP(dump_bearer_capability)
Mark Spencer's avatar
Mark Spencer committed
629 630
{
	int pos=2;
631
	pri_message(pri, "%c Bearer Capability (len=%2d) [ Ext: %d  Q.931 Std: %d  Info transfer capability: %s (%d)\n",
632
		prefix, len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
633
	pri_message(pri, "%c                              Ext: %d  Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
634 635

	/* octet 4.1 exists iff mode/rate is multirate */
Mark Spencer's avatar
Mark Spencer committed
636
	if ((ie->data[1] & 0x7f) == 0x18) {
637
	    pri_message(pri, "%c                              Ext: %d  Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
Mark Spencer's avatar
Mark Spencer committed
638 639
		pos++;
	}
640

641 642 643 644 645 646 647 648 649 650 651 652 653 654
	/* don't count the IE num and length as part of the data */
	len -= 2;
	
	/* Look for octet 5; this is identified by bits 5,6 == 01 */
     	if (pos < len &&
		(ie->data[pos] & 0x60) == 0x20) {

		/* although the layer1 is only the bottom 5 bits of the byte,
		   previous versions of this library passed bits 5&6 through
		   too, so we have to do the same for binary compatability */
		u_int8_t layer1 = ie->data[pos] & 0x7f;

		pri_message(pri, "%c                                User information layer 1: %s (%d)\n",
		            prefix, l12str(layer1), layer1);
Mark Spencer's avatar
Mark Spencer committed
655
		pos++;
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
		
		/* octet 5a? */
		if (pos < len && !(ie->data[pos-1] & 0x80)) {
			int ra = ie->data[pos] & 0x7f;

			pri_message(pri, "%c                                Async: %d, Negotiation: %d, "
				"User rate: %s (%#x)\n", 
				prefix,
				ra & PRI_RATE_ADAPT_ASYNC ? 1 : 0,
				ra & PRI_RATE_ADAPT_NEGOTIATION_POSS ? 1 : 0,
				ra2str(ra & PRI_RATE_USER_RATE_MASK),
				ra & PRI_RATE_USER_RATE_MASK);
			pos++;
		}
		
		/* octet 5b? */
		if (pos < len && !(ie->data[pos-1] & 0x80)) {
			u_int8_t data = ie->data[pos];
			if (layer1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
				pri_message(pri, "%c                                Intermediate rate: %s (%d), "
					"NIC on Tx: %d, NIC on Rx: %d, "
					"Flow control on Tx: %d, "
					"Flow control on Rx: %d\n",
					prefix, int_rate2str((data & 0x60)>>5),
					(data & 0x60)>>5,
					(data & 0x10)?1:0,
					(data & 0x08)?1:0,
					(data & 0x04)?1:0,
					(data & 0x02)?1:0);
			} else if (layer1 == PRI_LAYER_1_V120_RATE_ADAPT) {
				pri_message(pri, "%c                                Hdr: %d, Multiframe: %d, Mode: %d, "
					"LLI negot: %d, Assignor: %d, "
					"In-band neg: %d\n", prefix,
					(data & 0x40)?1:0,
					(data & 0x20)?1:0,
					(data & 0x10)?1:0,
					(data & 0x08)?1:0,
					(data & 0x04)?1:0,
					(data & 0x02)?1:0);
			} else {
				pri_message(pri, "%c                                Unknown octet 5b: 0x%x\n", data );
			}
			pos++;
		}

		/* octet 5c? */
		if (pos < len && !(ie->data[pos-1] & 0x80)) {
			u_int8_t data = ie->data[pos];
			const char *stop_bits[] = {"?","1","1.5","2"};
			const char *data_bits[] = {"?","5","7","8"};
			const char *parity[] = {"Odd","?","Even","None",
				       "zero","one","?","?"};
	
			pri_message(pri, "%c                                Stop bits: %s, data bits: %s, "
			    "parity: %s\n", prefix,
			    stop_bits[(data & 0x60) >> 5],
			    data_bits[(data & 0x18) >> 3],
			    parity[(data & 0x7)]);
	
			pos++;
		}
	
			/* octet 5d? */
		if (pos < len && !(ie->data[pos-1] & 0x80)) {
			u_int8_t data = ie->data[pos];
			pri_message(pri, "%c                                Duplex mode: %d, modem type: %d\n",
				prefix, (data & 0x40) ? 1 : 0,data & 0x3F);
 			pos++;
		}
 	}


	/* Look for octet 6; this is identified by bits 5,6 == 10 */
	if (pos < len && 
		(ie->data[pos] & 0x60) == 0x40) {
		pri_message(pri, "%c                                User information layer 2: %s (%d)\n",
			prefix, l22str(ie->data[pos] & 0x1f),
			ie->data[pos] & 0x1f);
Mark Spencer's avatar
Mark Spencer committed
734
		pos++;
735 736 737 738 739 740 741
	}

	/* Look for octet 7; this is identified by bits 5,6 == 11 */
	if (pos < len && (ie->data[pos] & 0x60) == 0x60) {
		pri_message(pri, "%c                                User information layer 3: %s (%d)\n",
			prefix, l32str(ie->data[pos] & 0x1f),
			ie->data[pos] & 0x1f);
Mark Spencer's avatar
Mark Spencer committed
742
		pos++;
743 744 745 746 747 748 749 750 751 752 753 754

		/* octets 7a and 7b? */
		if (pos + 1 < len && !(ie->data[pos-1] & 0x80) &&
			!(ie->data[pos] & 0x80)) {
			unsigned int proto;
			proto = ((ie->data[pos] & 0xF) << 4 ) | 
			         (ie->data[pos+1] & 0xF);

			pri_message(pri, "%c                                Network layer: 0x%x\n", prefix,
			            proto );
			pos += 2;
		}
Mark Spencer's avatar
Mark Spencer committed
755 756 757
	}
}

758
static FUNC_RECV(receive_bearer_capability)
Mark Spencer's avatar
Mark Spencer committed
759 760 761
{
	int pos=2;
	if (ie->data[0] & 0x60) {
762
		pri_error(pri, "!! non-standard Q.931 standard field\n");
Mark Spencer's avatar
Mark Spencer committed
763 764 765 766
		return -1;
	}
	call->transcapability = ie->data[0] & 0x1f;
	call->transmoderate = ie->data[1] & 0x7f;
767 768 769 770 771 772 773 774 775 776 777 778
   
	/* octet 4.1 exists iff mode/rate is multirate */
	if (call->transmoderate == TRANS_MODE_MULTIRATE) {
		call->transmultiple = ie->data[pos++] & 0x7f;
	}

	/* Look for octet 5; this is identified by bits 5,6 == 01 */
	if (pos < len && 
	     (ie->data[pos] & 0x60) == 0x20 ) {
		/* although the layer1 is only the bottom 5 bits of the byte,
		   previous versions of this library passed bits 5&6 through
		   too, so we have to do the same for binary compatability */
Mark Spencer's avatar
Mark Spencer committed
779 780
		call->userl1 = ie->data[pos] & 0x7f;
		pos++;
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
		
		/* octet 5a? */
		if (pos < len && !(ie->data[pos-1] & 0x80)) {
			call->rateadaption = ie->data[pos] & 0x7f;
			pos++;
 		}
		
		/* octets 5b through 5d? */
		while (pos < len && !(ie->data[pos-1] & 0x80)) {
			pos++;
		}
		
	}

	/* Look for octet 6; this is identified by bits 5,6 == 10 */
     	if (pos < len && 
             (ie->data[pos] & 0x60) == 0x40) {
		call->userl2 = ie->data[pos++] & 0x1f;
	}

	/* Look for octet 7; this is identified by bits 5,6 == 11 */
     	if (pos < len && 
             (ie->data[pos] & 0x60) == 0x60) {
		call->userl3 = ie->data[pos++] & 0x1f;
Mark Spencer's avatar
Mark Spencer committed
805 806 807 808
	}
	return 0;
}

809
static FUNC_SEND(transmit_bearer_capability)
Mark Spencer's avatar
Mark Spencer committed
810 811
{
	int tc;
812
	int pos;
813 814 815 816 817

	/* We are ready to transmit single IE only */	
	if(order > 1)
		return 0;

Mark Spencer's avatar
Mark Spencer committed
818
	tc = call->transcapability;
819
	if (pri->subchannel && !pri->bri) {
Mark Spencer's avatar
Mark Spencer committed
820 821 822 823 824
		/* Bearer capability is *hard coded* in GR-303 */
		ie->data[0] = 0x88;
		ie->data[1] = 0x90;
		return 4;
	}
825 826 827 828 829 830 831
	
	if (call->justsignalling) {
		ie->data[0] = 0xa8;
		ie->data[1] = 0x80;
		return 4;
	}
	
Mark Spencer's avatar
Mark Spencer committed
832 833
	ie->data[0] = 0x80 | tc;
	ie->data[1] = call->transmoderate | 0x80;
834 835 836 837 838 839 840 841 842

 	pos = 2;
 	/* octet 4.1 exists iff mode/rate is multirate */
 	if (call->transmoderate == TRANS_MODE_MULTIRATE ) {
 		ie->data[pos++] = call->transmultiple | 0x80;
	}

	if ((tc & PRI_TRANS_CAP_DIGITAL) && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&
		(call->transmoderate == TRANS_MODE_PACKET)) {
843 844 845
		/* Apparently EuroISDN switches don't seem to like user layer 2/3 */
		return 4;
	}
846 847 848 849 850 851

	if ((tc & PRI_TRANS_CAP_DIGITAL) && (call->transmoderate == TRANS_MODE_64_CIRCUIT)) {
		/* Unrestricted digital 64k data calls don't use user layer 2/3 */
		return 4;
	}

Mark Spencer's avatar
Mark Spencer committed
852 853
	if (call->transmoderate != TRANS_MODE_PACKET) {
		/* If you have an AT&T 4ESS, you don't send any more info */
854
		if ((pri->switchtype != PRI_SWITCH_ATT4ESS) && (call->userl1 > -1)) {
855
			ie->data[pos++] = call->userl1 | 0x80; /* XXX Ext bit? XXX */
856
			if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
857
				ie->data[pos++] = call->rateadaption | 0x80;
858
			}
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
			return pos + 2;
 		}
 
 		ie->data[pos++] = 0xa0 | (call->userl1 & 0x1f);
 
 		if (call->userl1 == PRI_LAYER_1_ITU_RATE_ADAPT) {
 		    ie->data[pos-1] &= ~0x80; /* clear EXT bit in octet 5 */
 		    ie->data[pos++] = call->rateadaption | 0x80;
 		}
 	}
 	
 	
 	if (call->userl2 != -1)
 		ie->data[pos++] = 0xc0 | (call->userl2 & 0x1f);
 
 	if (call->userl3 != -1)
 		ie->data[pos++] = 0xe0 | (call->userl3 & 0x1f);
 
 	return pos + 2;
Mark Spencer's avatar
Mark Spencer committed
878 879 880 881
}

char *pri_plan2str(int plan)
{
Mark Spencer's avatar
Mark Spencer committed
882 883 884 885 886 887 888 889
	static struct msgtype plans[] = {
		{ PRI_INTERNATIONAL_ISDN, "International number in ISDN" },
		{ PRI_NATIONAL_ISDN, "National number in ISDN" },
		{ PRI_LOCAL_ISDN, "Local number in ISDN" },
		{ PRI_PRIVATE, "Private numbering plan" },
		{ PRI_UNKNOWN, "Unknown numbering plan" },
	};
	return code2str(plan, plans, sizeof(plans) / sizeof(plans[0]));
Mark Spencer's avatar
Mark Spencer committed
890 891
}

Mark Spencer's avatar
Mark Spencer committed
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
static char *npi2str(int plan)
{
	static struct msgtype plans[] = {
		{ PRI_NPI_UNKNOWN, "Unknown Number Plan" },
		{ PRI_NPI_E163_E164, "ISDN/Telephony Numbering Plan (E.164/E.163)" },
		{ PRI_NPI_X121, "Data Numbering Plan (X.121)" },
		{ PRI_NPI_F69, "Telex Numbering Plan (F.69)" },
		{ PRI_NPI_NATIONAL, "National Standard Numbering Plan" },
		{ PRI_NPI_PRIVATE, "Private Numbering Plan" },
		{ PRI_NPI_RESERVED, "Reserved Number Plan" },
	};
	return code2str(plan, plans, sizeof(plans) / sizeof(plans[0]));
}

static char *ton2str(int plan)
{
	static struct msgtype plans[] = {
		{ PRI_TON_UNKNOWN, "Unknown Number Type" },
		{ PRI_TON_INTERNATIONAL, "International Number" },
		{ PRI_TON_NATIONAL, "National Number" },
		{ PRI_TON_NET_SPECIFIC, "Network Specific Number" },
		{ PRI_TON_SUBSCRIBER, "Subscriber Number" },
		{ PRI_TON_ABBREVIATED, "Abbreviated number" },
		{ PRI_TON_RESERVED, "Reserved Number" },
	};
	return code2str(plan, plans, sizeof(plans) / sizeof(plans[0]));
}

static char *subaddrtype2str(int plan)
{
	static struct msgtype plans[] = {
		{ 0, "NSAP (X.213/ISO 8348 AD2)" },
		{ 2, "User Specified" },
	};
	return code2str(plan, plans, sizeof(plans) / sizeof(plans[0]));
}

Mark Spencer's avatar
Mark Spencer committed
929 930
char *pri_pres2str(int pres)
{
Mark Spencer's avatar
Mark Spencer committed
931 932 933 934 935 936 937 938
	static struct msgtype press[] = {
		{ PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "Presentation permitted, user number not screened" },
		{ PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "Presentation permitted, user number passed network screening" },
		{ PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "Presentation permitted, user number failed network screening" },
		{ PRES_ALLOWED_NETWORK_NUMBER, "Presentation allowed of network provided number" },
		{ PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "Presentation prohibited, user number not screened" },
		{ PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "Presentation prohibited, user number passed network screening" },
		{ PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "Presentation prohibited, user number failed network screening" },
939
		{ PRES_PROHIB_NETWORK_NUMBER, "Presentation prohibited of network provided number" },
940
		{ PRES_NUMBER_NOT_AVAILABLE, "Number not available" },
Mark Spencer's avatar
Mark Spencer committed
941 942
	};
	return code2str(pres, press, sizeof(press) / sizeof(press[0]));
Mark Spencer's avatar
Mark Spencer committed
943 944 945 946
}

static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len)
{
947
	if ((len < 0) || (len > maxlen - 1)) {
Mark Spencer's avatar
Mark Spencer committed
948 949 950 951 952 953 954
		num[0] = 0;
		return;
	}
	memcpy(num, src, len);
	num[len] = 0;
}

955
static FUNC_DUMP(dump_called_party_number)
Mark Spencer's avatar
Mark Spencer committed
956
{
957
	unsigned char cnum[256];
Mark Spencer's avatar
Mark Spencer committed
958 959

	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
960
	pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)  '%s' ]\n",
Mark Spencer's avatar
Mark Spencer committed
961 962 963
		prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
}

964
static FUNC_DUMP(dump_called_party_subaddr)
Mark Spencer's avatar
Mark Spencer committed
965
{
966
	unsigned char cnum[256];
Mark Spencer's avatar
Mark Spencer committed
967
	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
968
	pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d)  O: %d  '%s' ]\n",
Mark Spencer's avatar
Mark Spencer committed
969 970 971
		prefix, len, ie->data[0] >> 7,
		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
		(ie->data[0] & 0x08) >> 3, cnum);
Mark Spencer's avatar
Mark Spencer committed
972 973
}

974
static FUNC_DUMP(dump_calling_party_number)
Mark Spencer's avatar
Mark Spencer committed
975
{
976
	unsigned char cnum[256];
977
	if (ie->data[0] & 0x80)
978
		q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
979 980
	else
		q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
981
	pri_message(pri, "%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
982
	if (ie->data[0] & 0x80)
983
		pri_message(pri, "%c                           Presentation: %s (%d)  '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
984
	else
985
		pri_message(pri, "%c                           Presentation: %s (%d)  '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
Mark Spencer's avatar
Mark Spencer committed
986
}
Mark Spencer's avatar
Mark Spencer committed
987

988
static FUNC_DUMP(dump_calling_party_subaddr)
Mark Spencer's avatar
Mark Spencer committed
989
{
990
	unsigned char cnum[256];
991
	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
992
	pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d)  O: %d  '%s' ]\n",
Mark Spencer's avatar
Mark Spencer committed
993 994 995
		prefix, len, ie->data[0] >> 7,
		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
		(ie->data[0] & 0x08) >> 3, cnum);
Mark Spencer's avatar
Mark Spencer committed
996 997
}

998
static FUNC_DUMP(dump_redirecting_number)
Mark Spencer's avatar
Mark Spencer committed
999
{
1000
	unsigned char cnum[256];
1001 1002 1003 1004 1005 1006
	int i = 0;
	/* 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:	/* Octet 3 */
1007
			pri_message(pri, "%c Redirecting Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)",
1008 1009 1010
				prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
			break;
		case 1: /* Octet 3a */
1011
			pri_message(pri, "\n%c                               Ext: %d  Presentation: %s (%d)",
1012 1013 1014
				prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
			break;
		case 2: /* Octet 3b */
1015
			pri_message(pri, "\n%c                               Ext: %d  Reason: %s (%d)",
1016 1017 1018
				prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f);
			break;
		}
1019
	} while(!(ie->data[i++]& 0x80));
1020
	q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
1021
	pri_message(pri, "  '%s' ]\n", cnum);
1022 1023
}

1024
static FUNC_DUMP(dump_connected_number)
1025
{
1026
	unsigned char cnum[256];
1027 1028 1029 1030 1031 1032
	int i = 0;
	/* 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:	/* Octet 3 */
1033
			pri_message(pri, "%c Connected Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)",
1034 1035 1036
				prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
			break;
		case 1: /* Octet 3a */
1037
			pri_message(pri, "\n%c                             Ext: %d  Presentation: %s (%d)",
1038 1039 1040
				prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
			break;
		}
1041
	} while(!(ie->data[i++]& 0x80));
1042
	q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
1043
	pri_message(pri, "  '%s' ]\n", cnum);
1044 1045 1046
}


1047
static FUNC_RECV(receive_redirecting_number)
1048 1049
{
	int i = 0;
1050

1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
	/* 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->redirectingplan = ie->data[i] & 0x7f;
			break;
		case 1:
			call->redirectingpres = ie->data[i] & 0x7f;
			break;
		case 2:
			call->redirectingreason = ie->data[i] & 0x0f;
			break;
		}
1065
	} while(!(ie->data[i++] & 0x80));
1066
	q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
1067
	return 0;
Mark Spencer's avatar
Mark Spencer committed
1068 1069
}

1070 1071
static FUNC_SEND(transmit_redirecting_number)
{
1072 1073
	if (order > 1)
		return 0;
1074
	if (call->redirectingnum && *call->redirectingnum) {
1075 1076 1077 1078 1079 1080 1081 1082
		ie->data[0] = call->redirectingplan;
		ie->data[1] = call->redirectingpres;
		ie->data[2] = (call->redirectingreason & 0x0f) | 0x80;
		memcpy(ie->data + 3, call->redirectingnum, strlen(call->redirectingnum));
		return strlen(call->redirectingnum) + 3 + 2;
	}
	return 0;
}
1083

1084
static FUNC_DUMP(dump_redirecting_subaddr)
Mark Spencer's avatar
Mark Spencer committed
1085
{
1086
	unsigned char cnum[256];
Mark Spencer's avatar
Mark Spencer committed
1087
	q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
1088
	pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d)  O: %d  '%s' ]\n",
Mark Spencer's avatar
Mark Spencer committed
1089 1090 1091 1092
		prefix, len, ie->data[0] >> 7,
		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
		(ie->data[0] & 0x08) >> 3, cnum);
}
Mark Spencer's avatar
Mark Spencer committed
1093

Mark Spencer's avatar
Mark Spencer committed
1094 1095 1096
static FUNC_RECV(receive_calling_party_subaddr)
{
	/* copy digits to call->callingsubaddr */
1097
 	q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3);
Mark Spencer's avatar
Mark Spencer committed
1098 1099 1100
	return 0;
}

1101
static FUNC_RECV(receive_called_party_number)
Mark Spencer's avatar
Mark Spencer committed
1102
{
1103
	/* copy digits to call->callednum */
1104
 	q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
Mark Spencer's avatar
Mark Spencer committed
1105 1106 1107 1108
	call->calledplan = ie->data[0] & 0x7f;
	return 0;
}

1109
static FUNC_SEND(transmit_called_party_number)
Mark Spencer's avatar
Mark Spencer committed
1110 1111
{
	ie->data[0] = 0x80 | call->calledplan;
1112
	if (*call->callednum)
Mark Spencer's avatar
Mark Spencer committed
1113 1114 1115 1116
		memcpy(ie->data + 1, call->callednum, strlen(call->callednum));
	return strlen(call->callednum) + 3;
}

1117
static FUNC_RECV(receive_calling_party_number)
Mark Spencer's avatar
Mark Spencer committed
1118
{
1119 1120
	u_int8_t *data;
	size_t length;
1121
        
1122
	if (ie->data[0] & 0x80) {
1123 1124
		data = ie->data + 1;
		length = len - 3;
1125 1126
		call->callerpres = 0; /* PI presentation allowed SI user-provided, not screened */        
	} else {
1127 1128 1129 1130 1131 1132 1133 1134
		data = ie->data + 2;
		length = len - 4;
		call->callerpres = ie->data[1] & 0x7f;
	}

	if (call->callerpres == PRES_ALLOWED_NETWORK_NUMBER ||
		call->callerpres == PRES_PROHIB_NETWORK_NUMBER) {
		q931_get_number((u_int8_t *)call->callerani, sizeof(call->callerani), data, length);
1135
		call->callerplanani = ie->data[0] & 0x7f;
1136

1137
		if (!*call->callernum) { /*Copy ANI to CallerID if CallerID is not already set */
1138
			libpri_copy_string(call->callernum, call->callerani, sizeof(call->callernum));
1139 1140 1141 1142
			call->callerplan = call->callerplanani;
		}
		
	} else {
1143
		q931_get_number((u_int8_t *)call->callernum, sizeof(call->callernum), data, length);
1144 1145
		call->callerplan = ie->data[0] & 0x7f;
	}
1146

Mark Spencer's avatar
Mark Spencer committed
1147 1148 1149
	return 0;
}

1150
static FUNC_SEND(transmit_calling_party_number)
Mark Spencer's avatar
Mark Spencer committed
1151 1152 1153
{
	ie->data[0] = call->callerplan;
	ie->data[1] = 0x80 | call->callerpres;
1154
	if (*call->callernum) 
Mark Spencer's avatar
Mark Spencer committed
1155 1156 1157 1158
		memcpy(ie->data + 2, call->callernum, strlen(call->callernum));
	return strlen(call->callernum) + 4;
}

1159
static FUNC_DUMP(dump_user_user)
1160
{
1161
	int x;
1162
	pri_message(pri, "%c User-User Information (len=%2d) [", prefix, len);
1163
	for (x=0;x<ie->len;x++)
1164 1165
		pri_message(pri, " %02x", ie->data[x] & 0x7f);
	pri_message(pri, " ]\n");
1166 1167 1168
}


1169
static FUNC_RECV(receive_user_user)
1170 1171 1172
{        
        call->useruserprotocoldisc = ie->data[0] & 0xff;
        if (call->useruserprotocoldisc == 4) /* IA5 */
1173
          q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
1174 1175 1176
	return 0;
}

1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
static FUNC_SEND(transmit_user_user)
{        
	int datalen = strlen(call->useruserinfo);
	if (datalen > 0) {
		/* Restricted to 35 characters */
		if (msgtype == Q931_USER_INFORMATION) {
			if (datalen > 260)
				datalen = 260;
		} else {
			if (datalen > 35)
				datalen = 35;
		}
		ie->data[0] = 4; /* IA5 characters */
		memcpy(&ie->data[1], call->useruserinfo, datalen);
		call->useruserinfo[0] = '\0';
		return datalen + 3;
	}

	return 0;
}

1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
static FUNC_DUMP(dump_change_status)
{
	int x;
	
	pri_message(pri, "%c Change Status Information (len=%2d) [", prefix, len);
	for (x=0; x<ie->len; x++) {
		pri_message(pri, " %02x", ie->data[x] & 0x7f);
	}
	pri_message(pri, " ]\n");
}

static FUNC_RECV(receive_change_status)
{
	call->changestatus = ie->data[0] & 0x0f;
	return 0;
}

static FUNC_SEND(transmit_change_status)
{
	ie->data[0] = 0xc0 | call->changestatus;
	return 3;
}

Mark Spencer's avatar
Mark Spencer committed
1221 1222
static char *prog2str(int prog)
{
Mark Spencer's avatar
Mark Spencer committed
1223
	static struct msgtype progs[] = {
Mark Spencer's avatar
Mark Spencer committed
1224 1225 1226 1227 1228 1229 1230 1231 1232
		{ Q931_PROG_CALL_NOT_E2E_ISDN, "Call is not end-to-end ISDN; further call progress information may be available inband." },
		{ Q931_PROG_CALLED_NOT_ISDN, "Called equipment is non-ISDN." },
		{ Q931_PROG_CALLER_NOT_ISDN, "Calling equipment is non-ISDN." },
		{ Q931_PROG_INBAND_AVAILABLE, "Inband information or appropriate pattern now available." },
		{ Q931_PROG_DELAY_AT_INTERF, "Delay in response at called Interface." },
		{ Q931_PROG_INTERWORKING_WITH_PUBLIC, "Interworking with a public network." },
		{ Q931_PROG_INTERWORKING_NO_RELEASE, "Interworking with a network unable to supply a release signal." },
		{ Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER, "Interworking with a network unable to supply a release signal before answer." },
		{ Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER, "Interworking with a network unable to supply a release signal after answer." },
Mark Spencer's avatar
Mark Spencer committed
1233 1234
	};
	return code2str(prog, progs, sizeof(progs) / sizeof(progs[0]));
Mark Spencer's avatar
Mark Spencer committed
1235 1236 1237 1238
}

static char *coding2str(int cod)
{
Mark Spencer's avatar
Mark Spencer committed
1239 1240 1241 1242 1243 1244 1245
	static struct msgtype cods[] = {
		{ CODE_CCITT, "CCITT (ITU) standard" },
		{ CODE_INTERNATIONAL, "Non-ITU international standard" }, 
		{ CODE_NATIONAL, "National standard" }, 
		{ CODE_NETWORK_SPECIFIC, "Network specific standard" },
	};
	return code2str(cod, cods, sizeof(cods) / sizeof(cods[0]));
Mark Spencer's avatar
Mark Spencer committed
1246 1247 1248 1249
}

static char *loc2str(int loc)
{
Mark Spencer's avatar
Mark Spencer committed
1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
	static struct msgtype locs[] = {
		{ LOC_USER, "User" },
		{ LOC_PRIV_NET_LOCAL_USER, "Private network serving the local user" },
		{ LOC_PUB_NET_LOCAL_USER, "Public network serving the local user" },
		{ LOC_TRANSIT_NET, "Transit network" },
		{ LOC_PUB_NET_REMOTE_USER, "Public network serving the remote user" },
		{ LOC_PRIV_NET_REMOTE_USER, "Private network serving the remote user" },
		{ LOC_INTERNATIONAL_NETWORK, "International network" },
		{ LOC_NETWORK_BEYOND_INTERWORKING, "Network beyond the interworking point" },
	};
	return code2str(loc, locs, sizeof(locs) / sizeof(locs[0]));
Mark Spencer's avatar
Mark Spencer committed
1261 1262
}

1263
static FUNC_DUMP(dump_progress_indicator)
Mark Spencer's avatar
Mark Spencer committed
1264
{
1265
	pri_message(pri, "%c Progress Indicator (len=%2d) [ Ext: %d  Coding: %s (%d)  0: %d  Location: %s (%d)\n",
1266
		prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
Mark Spencer's avatar
Mark Spencer committed
1267
		(ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
1268
	pri_message(pri, "%c                               Ext: %d  Progress Description: %s (%d) ]\n",
Mark Spencer's avatar
Mark Spencer committed
1269 1270 1271
		prefix, ie->data[1] >> 7, prog2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
}

1272
static FUNC_RECV(receive_display)
1273 1274 1275 1276 1277 1278 1279 1280
{
	unsigned char *data;
	data = ie->data;
	if (data[0] & 0x80) {
		/* Skip over character set */
		data++;
		len--;
	}
1281
	q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
1282 1283 1284
	return 0;
}

1285
static FUNC_SEND(transmit_display)
1286
{
1287
	int i;
1288
	
1289 1290 1291
	if ((pri->switchtype == PRI_SWITCH_QSIG) ||
	    ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) && (pri->localtype == PRI_CPE)) ||
	    !call->callername[0])
1292 1293 1294 1295 1296 1297
		return 0;

	i = 0;
	if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
		ie->data[0] = 0xb1;
		++i;
1298
	}
1299 1300
	memcpy(ie->data + i, call->callername, strlen(call->callername));
	return 2 + i + strlen(call->callername);
1301 1302
}

1303
static FUNC_RECV(receive_progress_indicator)
Mark Spencer's avatar
Mark Spencer committed
1304 1305
{
	call->progloc = ie->data[0] & 0xf;
Mark Spencer's avatar
Mark Spencer committed
1306
	call->progcode = (ie->data[0] & 0x60) >> 5;
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
	switch (call->progress = (ie->data[1] & 0x7f)) {
	case Q931_PROG_CALL_NOT_E2E_ISDN:
		call->progressmask |= PRI_PROG_CALL_NOT_E2E_ISDN;
		break;
	case Q931_PROG_CALLED_NOT_ISDN:
		call->progressmask |= PRI_PROG_CALLED_NOT_ISDN;
		break;
	case Q931_PROG_CALLER_NOT_ISDN:
		call->progressmask |= PRI_PROG_CALLER_NOT_ISDN;
		break;
1317 1318 1319
	case Q931_PROG_CALLER_RETURNED_TO_ISDN:
		call->progressmask |= PRI_PROG_CALLER_RETURNED_TO_ISDN;
		break;
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
	case Q931_PROG_INBAND_AVAILABLE:
		call->progressmask |= PRI_PROG_INBAND_AVAILABLE;
		break;
	case Q931_PROG_DELAY_AT_INTERF:
		call->progressmask |= PRI_PROG_DELAY_AT_INTERF;
		break;
	case Q931_PROG_INTERWORKING_WITH_PUBLIC:
		call->progressmask |= PRI_PROG_INTERWORKING_WITH_PUBLIC;
		break;
	case Q931_PROG_INTERWORKING_NO_RELEASE:
		call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE;
		break;
	case Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER:
		call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER;
		break;
	case Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER:
		call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
		break;
	default:
1339
		pri_error(pri, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
1340 1341
		break;
	}
Mark Spencer's avatar
Mark Spencer committed
1342 1343 1344
	return 0;
}

1345 1346 1347 1348 1349 1350
static FUNC_SEND(transmit_facility)
{
	struct apdu_event *tmp;
	int i = 0;

	for (tmp = call->apdus; tmp; tmp = tmp->next) {
1351
		if ((tmp->message == msgtype) && !tmp->sent)
1352 1353 1354 1355 1356
			break;
	}
	if (!tmp)	/* No APDU found */
		return 0;

1357 1358 1359 1360 1361
	if (pri->debug & PRI_DEBUG_APDU) {
		pri_message(pri, "Adding facility ie contents to send message:\n");
		facility_decode_dump(pri, tmp->apdu, tmp->apdu_len);
	}

1362 1363
	if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */
		pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len);
1364 1365
		return 0;
	}
1366

1367
	memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
1368
	i += tmp->apdu_len;
1369
	tmp->sent = 1;
1370 1371 1372 1373

	return i + 2;
}

1374
static i