diff --git a/CHANGES b/CHANGES index 60ad216..dd4c2d5 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,8 @@ HEAD - play message to conference and music on hold to caller - add commands to remove users from chat - allow to specity the 'ETS 300 102-1' called party number octet 3 +- fixed possible buffer overflow in 'deflect' +- added 'h' option to chat to auto-hangup caller if alone in conference too long chan_capi-1.1.2 diff --git a/README b/README index 4e9c158..1178def 100644 --- a/README +++ b/README @@ -288,6 +288,7 @@ Deactivate CCBS: exten => s,1,capicommand(ccbsstop|${CCLINKAGEID}) Chat (MeetMe/Conference): + See also README.media for details! If the CAPI card/driver supports it, the caller can be put into a chat-room: (This uses the DSPs onboard a Dialogic(R) Diva(R) Rev.2 Media Board.) exten => s,1,capicommand(chat|||controller) @@ -295,6 +296,7 @@ Chat (MeetMe/Conference): exten => s,1,capicommand(chat|salesmeeting|m|1,3-6) Possible options: 'm' = The first caller will get music-on-hold until second caller arrives. + 'h' = Hangup after seconds if caller is alone in conference. 'o' = The caller is operator 'l' = The caller is listener diff --git a/README.Diva.fax b/README.Diva.fax index 4ddb26b..f6021c4 100644 --- a/README.Diva.fax +++ b/README.Diva.fax @@ -254,15 +254,15 @@ exten => i,1,Hangup() ; Received unexpected event [handle_fax] exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}[|||]) -exten => s,2,Hangup() +exten => s,n,Hangup() exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it Example with Clear Channel fax support: [handle_fax] -exten => s,1,capicommand(resource|1-4) ; Assign resource PLCI -exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}[|||]) -exten => s,2,Hangup() +exten => s,1,capicommand(resource|1-4) ; Assign resource PLCI (use controllers 1 to 4) +exten => s,n,capicommand(receivefax|/tmp/${UNIQUEID}[|||]) +exten => s,n,Hangup() exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it diff --git a/README.media b/README.media index b7c2204..f3eae5a 100644 --- a/README.media +++ b/README.media @@ -684,7 +684,7 @@ stoptonedetection Tone identifier: 0x82 - Dial tone detected - 0x83 - PABX internal dial tone detected + 0x83 - PABX internal dial tone detected 0x84 - Special dial tone (stutter dial tone) detected 0x85 - Second dial tone detected 0x86 - Ringing tone detected @@ -874,6 +874,7 @@ capicommand(chat|||controller) roomname - conference room name options m - The first caller will get music-on-hold until the second caller arrives + h - Hangup after seconds if caller is alone in conference. l - The caller is listener (passive) conference member and cannot be unmuted by 'chat_mute' command o - The caller is conference operator and cannot be muted by 'chat_mute' command controller - CAPI controller @@ -884,6 +885,7 @@ exten => s,n,capicommand(chat|test|m|1,3) exten => s,n,capicommand(chat|test|m|1-4) exten => s,n,capicommand(chat|test|m|1-4,7) exten => s,n,capicommand(chat|test|m|1-4,7-10) +exten => s,n,capicommand(chat|test|mh300|1-4) IVR example: ///////////////////////////////////////////////////////////////////// @@ -904,7 +906,7 @@ exten => 1,n,capicommand(vc|txdgain|3|0) ; Install voice command menu for volume exten => 1,n,capicommand(chat|test1|m|1-4) ; Create/enter conference room 'test1' exten => 2,1,capicommand(clamping|100) ; Activate suppression of DTMF tones -exten => 2,1,capicommand(txdgain|-128) ; Deactivate tx path +exten => 2,n,capicommand(txdgain|-128) ; Deactivate tx path exten => 2,n,capicommand(vc|incrxdgain|0|1.5) ; Install voice command menu for volume control, '0' to increase volume exten => 2,n,capicommand(vc|incrxdgain|1|-1.5) ; Install voice command menu for volume control, '1' to decrease volume exten => 2,n,capicommand(vc|txdgain|2|-128) ; Install voice command menu for volume control, '2' to mute tx path @@ -1144,6 +1146,7 @@ capicommand(chat_play||||controller) roomname - conference room name options m - The caller will get music-on-hold while message is played + s - The caller will hear the same message that is played filename - Voice message file name. Should be in aLaw (uLaw) format. controller - CAPI controller @@ -1184,9 +1187,9 @@ capicommand(chat_command||) Command does not apply to calling member and be used by operators only. l - Remove all listeners from conference. Command does not apply to calling member and be used by operators only. - o - Remove all operators from conference. + o - Remove all operators from conference. Command does not apply to calling member and be used by operators only. - a - Remove all users from conference. + a - Remove all users from conference. Command does not apply to calling member and be used by operators only. roomname - optional, room caller assigned to is used if not present diff --git a/README.qsig b/README.qsig index 481a305..2af5289 100644 --- a/README.qsig +++ b/README.qsig @@ -20,20 +20,20 @@ None yet - you will be welcome here :-) No support for Asterisk 1.0.x any more, you need at least Asterisk 1.2.x , 1.4.x or 1.6.x. -What is Q.SIG +What is QSIG ============= -Q.SIG is a protocol extension for ISDN. +QSIG is a protocol extension for ISDN. It is mainly used on connecting PBXs of different PBX vendors, which allows better interoperability. As example there can be a name of an extension transferred between different PBXs, which is not possibile with standard ISDN. These extensions will be transmitted as encoded facility information elements. -To use Q.SIG with Asterisk, you willll need a card such as a Dialogic(R) Diva(R) +To use QSIG with Asterisk, you willll need a card such as a Dialogic(R) Diva(R) Media Board (BRI like PRI) that supports QSIG. Maybe others do also work, if so, let me now. -The Q.SIG support includes: +The QSIG support includes: ========================== - Name presentation on Call SETUP incoming like outgoing @@ -50,7 +50,7 @@ The Q.SIG support includes: at the moment only incoming handling is supported -- Possibility to inform Q.SIG switch about a call from the public network +- Possibility to inform QSIG switch about a call from the public network If you set the variable QSIG_SETUP=X, then the QSIG switch on the other side will know, that this call source is the public network - you will get a different ring tone, etc. In dialplan use: Set(__QSIG_SETUP=X) command. @@ -110,11 +110,11 @@ Please visit: http://www.melware.org/ChanCapiConf -Simply enable Q.SIG with the following line in your capi.conf interface: +Simply enable QSIG with the following line in your capi.conf interface: Here we go with new configuration -Set Q.SIG to one of the following values, which corresponds to your configuration. +Set QSIG to one of the following values, which corresponds to your configuration. 0 QSIG turned off 1 Alcatel (4400 & Enterprise - Maybe OXO/4200) ECMA (wrongly named ECMA - it is ETSI) variant diff --git a/chan_capi.c b/chan_capi.c index 22c9ffe..eefe591 100644 --- a/chan_capi.c +++ b/chan_capi.c @@ -2112,7 +2112,7 @@ static CC_BRIDGE_RETURN pbx_capi_bridge( /* * a new channel is needed */ -static struct ast_channel *capi_new(struct capi_pvt *i, int state) +static struct ast_channel *capi_new(struct capi_pvt *i, int state, const char *linkedid) { struct ast_channel *tmp; int fmt; @@ -2120,7 +2120,11 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state) #ifdef CC_AST_HAS_EXT_CHAN_ALLOC tmp = ast_channel_alloc(0, state, i->cid, NULL, #ifdef CC_AST_HAS_EXT2_CHAN_ALLOC - i->accountcode, i->dnid, i->context, i->amaflags, + i->accountcode, i->dnid, i->context, +#ifdef CC_AST_HAS_LINKEDID_CHAN_ALLOC + linkedid, +#endif + i->amaflags, #endif CC_MESSAGE_BIGNAME "/%s/%s-%x", i->vname, i->dnid, capi_counter++); #else @@ -2146,7 +2150,7 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state) #endif if (!(capi_create_reader_writer_pipe(i))) { - ast_channel_free(tmp); + ast_channel_release(tmp); return NULL; } tmp->fds[0] = i->readerfd; @@ -2286,8 +2290,14 @@ static struct ast_channel *capi_new(struct capi_pvt *i, int state) /* * PBX wants us to dial ... */ +#ifdef CC_AST_HAS_REQUEST_REQUESTOR +static struct ast_channel * +pbx_capi_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause) +/* TODO: new field requestor to link to called channel */ +#else static struct ast_channel * pbx_capi_request(const char *type, int format, void *data, int *cause) +#endif { struct capi_pvt *i; struct ast_channel *tmp = NULL; @@ -2359,7 +2369,13 @@ pbx_capi_request(const char *type, int format, void *data, int *cause) } /* when we come here, we found a free controller match */ cc_copy_string(i->dnid, dest, sizeof(i->dnid)); - tmp = capi_new(i, AST_STATE_RESERVED); + tmp = capi_new(i, AST_STATE_RESERVED, +#ifdef CC_AST_HAS_REQUEST_REQUESTOR + requestor ? requestor->linkedid : NULL +#else + NULL +#endif + ); if (!tmp) { cc_log(LOG_ERROR, "cannot create new " CC_MESSAGE_NAME " channel\n"); interface_cleanup(i); @@ -4392,7 +4408,7 @@ static void capidev_handle_connect_indication(_cmsg *CMSG, unsigned int PLCI, un i->MessageNumber = HEADER_MSGNUM(CMSG); i->cid_ton = callernplan; - capi_new(i, AST_STATE_DOWN); + capi_new(i, AST_STATE_DOWN, NULL); if (i->isdnmode == CAPI_ISDNMODE_DID) { i->state = CAPI_STATE_DID; } else { @@ -4861,10 +4877,11 @@ static struct capi_pvt* get_active_plci (struct ast_channel *c) { */ static int pbx_capi_call_deflect(struct ast_channel *c, char *param) { +#define DEFLECT_NUMBER_MAX_LEN 35 struct capi_pvt *i = CC_CHANNEL_PVT(c); char *number; int numberlen; - char facnumber[32]; + char facnumber[DEFLECT_NUMBER_MAX_LEN + 4]; if (!param) { cc_log(LOG_WARNING, CC_MESSAGE_NAME @@ -4879,9 +4896,10 @@ static int pbx_capi_call_deflect(struct ast_channel *c, char *param) " deflection requires an argument (destination phone number)\n"); return -1; } - if (numberlen > 35) { + if (numberlen > DEFLECT_NUMBER_MAX_LEN) { cc_log(LOG_WARNING, CC_MESSAGE_NAME - " deflection does only support phone number up to 35 digits\n"); + " deflection does only support phone number up to %d digits\n", + DEFLECT_NUMBER_MAX_LEN); return -1; } if (!(capi_controllers[i->controller]->CD)) { @@ -6274,7 +6292,11 @@ pbx_capi_command_proc_t pbx_capi_lockup_command_by_name(const char* name) /* * capi command interface */ +#ifdef CC_AST_HAS_CONST_CHAR_IN_REGAPPL +static int pbx_capicommand_exec(struct ast_channel *chan, const char *data) +#else static int pbx_capicommand_exec(struct ast_channel *chan, void *data) +#endif { int res = 0; #ifdef CC_AST_HAS_VERSION_1_4 @@ -6533,7 +6555,7 @@ static int pbx_capi_devicestate(void *data) /* AST_DEVICE_UNAVAILABLE */ } cc_verbose(3, 1, VERBOSE_PREFIX_4 "chan_capi devicestate requested for %s is '%s'\n", - (char *)data, devstate2str(res)); + (char *)data, ast_devstate2str(res)); } return res; diff --git a/chan_capi.h b/chan_capi.h index ec348f8..e26ea93 100644 --- a/chan_capi.h +++ b/chan_capi.h @@ -126,6 +126,14 @@ static inline unsigned int read_capi_dword(void *m) #define FRAME_DATA_PTR data #endif +#ifndef CC_AST_HAS_CHANNEL_RELEASE +#define ast_channel_release(x) ast_channel_free(x) +#endif + +#ifndef CC_AST_HAS_AST_DEVSTATE2STR +#define ast_devstate2str(x) devstate2str(x) +#endif + /* */ #define return_on_no_interface(x) \ if (!i) { \ diff --git a/chan_capi_chat.c b/chan_capi_chat.c index 24f733c..9696b4d 100644 --- a/chan_capi_chat.c +++ b/chan_capi_chat.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "chan_capi_platform.h" #include "chan_capi20.h" @@ -24,6 +25,7 @@ #include "chan_capi_command.h" #define CHAT_FLAG_MOH 0x0001 +#define CHAT_FLAG_SAMEMSG 0x0002 typedef enum { RoomMemberDefault = 0, /* Rx/Tx by default, muted by operator */ @@ -321,7 +323,7 @@ static void update_all_capi_mixers(unsigned int roomnumber) } } - free (segments); + free(segments); } } @@ -403,7 +405,7 @@ static struct capichat_s *add_chat_member(char *roomname, struct capi_pvt *i, ro } } room->info |= PBX_CHAT_MEMBER_INFO_RECENT; - room->time = time(0); + room->time = time(NULL); room->next = chat_list; chat_list = room; @@ -422,7 +424,8 @@ static struct capichat_s *add_chat_member(char *roomname, struct capi_pvt *i, ro * loop during chat */ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, - struct capichat_s *room, unsigned int flags, struct capi_pvt* iline, FILE* voice_message) + struct capichat_s *room, unsigned int flags, struct capi_pvt* iline, + FILE* voice_message, unsigned int hangup_timeout) { struct ast_frame *f; int ms; @@ -434,6 +437,7 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, struct ast_channel *chan = c; int moh_active = 0, voice_message_moh_active = 0; int write_block_nr = 2; + time_t alone_since = time(NULL); if (voice_message == NULL) { ast_indicate(chan, -1); @@ -442,19 +446,17 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, waitfd = i->readerfd; if (i->channeltype == CAPI_CHANNELTYPE_NULL) { nfds = 1; - if (voice_message == NULL) { - ast_set_read_format(chan, capi_capability); - ast_set_write_format(chan, capi_capability); - } + ast_set_read_format(chan, capi_capability); + ast_set_write_format(chan, capi_capability); } - if ((flags & CHAT_FLAG_MOH) && ((room->active < 2) || (voice_message != 0))) { + if ((flags & CHAT_FLAG_MOH) && ((room->active < 2) || (voice_message != NULL))) { #if defined(CC_AST_HAS_VERSION_1_6) || defined(CC_AST_HAS_VERSION_1_4) ast_moh_start(chan, NULL, NULL); #else ast_moh_start(chan, NULL); #endif - if (voice_message == 0) { + if (voice_message == NULL) { moh_active = 1; } else { voice_message_moh_active = 1; @@ -476,6 +478,8 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, if (rchan) { f = ast_read(chan); if (!f) { + if (voice_message != NULL) + continue; cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: chat: no frame, hangup.\n", i->vname); break; @@ -488,16 +492,16 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, } else if (f->frametype == AST_FRAME_VOICE) { cc_verbose(5, 1, VERBOSE_PREFIX_3 "%s: chat: voice frame.\n", i->vname); - if ((voice_message == 0) && (i->channeltype == CAPI_CHANNELTYPE_NULL)) { + if ((voice_message == NULL) && (i->channeltype == CAPI_CHANNELTYPE_NULL)) { capi_write_frame(i, f); - } else if (iline != 0) { + } else if ((iline != NULL) && (!(flags & CHAT_FLAG_SAMEMSG))) { capi_write_frame(iline, f); } } else if (f->frametype == AST_FRAME_NULL) { /* ignore NULL frame */ cc_verbose(5, 1, VERBOSE_PREFIX_3 "%s: chat: NULL frame, ignoring.\n", i->vname); - } else if ((f->frametype == AST_FRAME_DTMF_END) && (voice_message == 0)) { + } else if ((f->frametype == AST_FRAME_DTMF_END) && (voice_message == NULL)) { pbx_capi_voicecommand_process_digit (i, c, f->subclass); } else { cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: chat: unhandled frame %d/%d.\n", @@ -512,9 +516,10 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, } f = capi_read_pipeframe(i); if (f->frametype == AST_FRAME_VOICE) { - if (voice_message == 0) { + if (voice_message == NULL) { ast_write(chan, f); } else { + struct ast_frame *fr2; char* p = f->FRAME_DATA_PTR; int len; @@ -524,6 +529,15 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, memset (&p[len], 0x00, f->datalen-len); len = 0; } + if (flags & CHAT_FLAG_SAMEMSG) { + fr2 = ast_frdup(f); + if (iline != NULL) { + capi_write_frame(iline, fr2); + } else { + ast_write(chan, fr2); + ast_frfree(fr2); + } + } capi_write_frame(i, f); } } while ((write_block_nr-- != 0) && (len > 0)); @@ -549,6 +563,17 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, ast_moh_stop(chan); moh_active = 0; } + if (hangup_timeout > 0) { + if (room->active > 1) { + alone_since = time(NULL); + } else { + if ((alone_since + hangup_timeout) < time(NULL)) { + cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: chat: reached (alone) hangup timeout.\n", + i->vname); + break; + } + } + } } if (voice_message_moh_active != 0) { ast_moh_stop(chan); @@ -567,6 +592,7 @@ int pbx_capi_chat(struct ast_channel *c, char *param) ast_group_t tmpcntr; unsigned long long contr = 0; unsigned int flags = 0; + unsigned int hangup_timeout = 0; room_member_type_t room_member_type = RoomMemberDefault; roomname = strsep(¶m, "|"); @@ -591,6 +617,14 @@ int pbx_capi_chat(struct ast_channel *c, char *param) case 'm': flags |= CHAT_FLAG_MOH; break; + case 'h': + hangup_timeout = 0; + while (isdigit(options[1])) { + hangup_timeout *= 10; + hangup_timeout += (options[1] - '0'); + options++; + } + break; case 'l': room_member_type = RoomMemberListener; break; @@ -607,8 +641,8 @@ int pbx_capi_chat(struct ast_channel *c, char *param) } cc_verbose(3, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME " chat: %s: roomname=%s " - "options=%s controller=%s (0x%llx)\n", - c->name, roomname, options, controller, contr); + "options=%s hangup_timeout=%d controller=%s (0x%llx)\n", + c->name, roomname, options, hangup_timeout, controller, contr); if (c->tech == &capi_tech) { i = CC_CHANNEL_PVT(c); @@ -641,7 +675,7 @@ int pbx_capi_chat(struct ast_channel *c, char *param) } /* main loop */ - chat_handle_events(c, i, room, flags, 0, 0); + chat_handle_events(c, i, room, flags, 0, 0, hangup_timeout); del_chat_member(room); @@ -701,7 +735,9 @@ int pbx_capi_chat_play(struct ast_channel *c, char *param) case 'm': flags |= CHAT_FLAG_MOH; break; - + case 's': + flags |= CHAT_FLAG_SAMEMSG; + break; default: cc_log(LOG_WARNING, "Unknown chat option '%c'.\n", *options); @@ -710,6 +746,11 @@ int pbx_capi_chat_play(struct ast_channel *c, char *param) options++; } + if ((flags & (CHAT_FLAG_MOH | CHAT_FLAG_SAMEMSG)) == (CHAT_FLAG_MOH | CHAT_FLAG_SAMEMSG)) { + cc_log(LOG_WARNING, "chat_play: option 's' overrides 'm'.\n"); + flags &= ~CHAT_FLAG_MOH; + } + f = fopen(file_name, "rb"); if (f == NULL) { cc_log(LOG_WARNING, "can't open voice file (%s)\n", strerror(errno)); @@ -765,7 +806,7 @@ int pbx_capi_chat_play(struct ast_channel *c, char *param) } /* main loop */ - chat_handle_events(c, i, room, flags, (c->tech == &capi_tech) ? (CC_CHANNEL_PVT(c)) : 0, f); + chat_handle_events(c, i, room, flags, (c->tech == &capi_tech) ? (CC_CHANNEL_PVT(c)) : 0, f, 0); del_chat_member(room); @@ -776,7 +817,7 @@ out: return 0; } -int pbx_capi_chat_command (struct ast_channel *c, char *param) +int pbx_capi_chat_command(struct ast_channel *c, char *param) { struct capichat_s *room, *tmproom; struct capi_pvt *i; diff --git a/chan_capi_supplementary.c b/chan_capi_supplementary.c index e2a5822..5d75819 100644 --- a/chan_capi_supplementary.c +++ b/chan_capi_supplementary.c @@ -369,7 +369,11 @@ static void ccbsnr_remote_user_free(_cmsg *CMSG, char type, unsigned int PLCI, _ #ifdef CC_AST_HAS_EXT_CHAN_ALLOC c = ast_channel_alloc(0, state, handlename, NULL, #ifdef CC_AST_HAS_EXT2_CHAN_ALLOC - 0, ccbsnr->exten, ccbsnr->context, 0, + 0, ccbsnr->exten, ccbsnr->context, +#ifdef CC_AST_HAS_LINKEDID_CHAN_ALLOC + NULL, +#endif + 0, #endif "CCBSNR/%x", ccbsnr->handle); #else diff --git a/create_config.sh b/create_config.sh index 82cdda6..9e5a191 100755 --- a/create_config.sh +++ b/create_config.sh @@ -60,6 +60,11 @@ case "$AVERSIONNUM" in echo " * assuming Asterisk version 1.4" VER=1_4 ;; + 999999) + echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE + echo " * assuming Asterisk version 1.6" + VER=1_6 + ;; *) if [ "$VER" = "1_6" ]; then echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE @@ -158,6 +163,41 @@ check_version_onesix() echo "#undef CC_AST_HAS_UNION_DATA_IN_FRAME" >>$CONFIGFILE echo " * no new union data in ast_frame structure" fi + if grep -q "ast_channel_release.*struct" $INCLUDEDIR/channel.h; then + echo "#define CC_AST_HAS_CHANNEL_RELEASE" >>$CONFIGFILE + echo " * found ast_channel_release function" + else + echo "#undef CC_AST_HAS_CHANNEL_RELEASE" >>$CONFIGFILE + echo " * no new ast_channel_release function" + fi + if grep -q "ast_devstate2str.*enum" $INCLUDEDIR/devicestate.h; then + echo "#define CC_AST_HAS_AST_DEVSTATE2STR" >>$CONFIGFILE + echo " * found new ast_devstate2str function" + else + echo "#undef CC_AST_HAS_AST_DEVSTATE2STR" >>$CONFIGFILE + echo " * obsolete devstate2str function" + fi + if grep -q "ast_request.*requestor" $INCLUDEDIR/channel.h; then + echo "#define CC_AST_HAS_REQUEST_REQUESTOR" >>$CONFIGFILE + echo " * found requestor in ast_request" + else + echo "#undef CC_AST_HAS_REQUEST_REQUESTOR" >>$CONFIGFILE + echo " * no requestor in ast_request" + fi + if grep -q "ast_register_application2.*void " $INCLUDEDIR/module.h; then + echo "#undef CC_AST_HAS_CONST_CHAR_IN_REGAPPL" >>$CONFIGFILE + echo " * no const char in ast_register_application" + else + echo "#define CC_AST_HAS_CONST_CHAR_IN_REGAPPL" >>$CONFIGFILE + echo " * found const char in ast_register_application" + fi + if grep -q "ast_channel_alloc.*linkedid" $INCLUDEDIR/channel.h; then + echo "#define CC_AST_HAS_LINKEDID_CHAN_ALLOC" >>$CONFIGFILE + echo " * found linkedid in ast_channel_alloc" + else + echo "#undef CC_AST_HAS_LINKEDID_CHAN_ALLOC" >>$CONFIGFILE + echo " * no linkedid in ast_channel_alloc" + fi } case $VER in