46 #include <sys/socket.h>
47 #include <sys/ioctl.h>
52 #include <netinet/in.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/ip.h>
55 #include <arpa/inet.h>
99 #define DEFAULT_EXPIRY 120
100 #define MAX_EXPIRY 3600
101 #define DIRECTMEDIA 1
104 #define INADDR_NONE (in_addr_t)(-1)
113 .resync_threshold = 1000,
119 static const char tdesc[] =
"Media Gateway Control Protocol (MGCP)";
120 static const char config[] =
"mgcp.conf";
122 #define MGCP_DTMF_RFC2833 (1 << 0)
123 #define MGCP_DTMF_INBAND (1 << 1)
124 #define MGCP_DTMF_HYBRID (1 << 2)
126 #define DEFAULT_MGCP_GW_PORT 2427
127 #define DEFAULT_MGCP_CA_PORT 2727
128 #define MGCP_MAX_PACKET 1500
129 #define DEFAULT_RETRANS 1000
130 #define MAX_RETRANS 5
133 #define MGCP_CX_SENDONLY 0
134 #define MGCP_CX_RECVONLY 1
135 #define MGCP_CX_SENDRECV 2
136 #define MGCP_CX_CONF 3
137 #define MGCP_CX_CONFERENCE 3
138 #define MGCP_CX_MUTE 4
139 #define MGCP_CX_INACTIVE 4
251 #define MGCP_MAX_HEADERS 64
252 #define MGCP_MAX_LINES 64
282 #define RESPONSE_TIMEOUT 30
303 #define MGCP_SUBCHANNEL_MAGIC "!978!"
327 #define MGCP_ONHOOK 1
328 #define MGCP_OFFHOOK 2
404 struct sockaddr_in
addr;
406 struct in_addr
ourip;
475 .description =
tdesc,
520 sub->cxident[0] =
'\0';
521 sub->callid[0] =
'\0';
524 sub->alreadygone = 0;
525 memset(&
sub->tmpdest, 0,
sizeof(
sub->tmpdest));
538 if (gw->
addr.sin_addr.s_addr)
539 res=sendto(
mgcpsock, data,
len, 0, (
struct sockaddr *)&gw->
addr,
sizeof(
struct sockaddr_in));
541 res=sendto(
mgcpsock, data,
len, 0, (
struct sockaddr *)&gw->
defaddr,
sizeof(
struct sockaddr_in));
576 for (prev =
NULL, cur = gw->
msgs; cur; prev = cur, cur = cur->
next) {
579 prev->next = cur->
next;
654 for (prev =
NULL, cur = gw->
msgs; cur; prev = cur, cur = cur->
next) {
657 ast_debug(1,
"Retransmitting #%d transaction %u on [%s]\n",
662 prev->next = cur->
next;
701 char *data,
int len,
unsigned int seqno)
722 memcpy(msg->
buf, data, msg->
len);
725 for (cur = gw->
msgs; cur && cur->
next; cur = cur->
next);
759 queue = &
sub->cx_queue;
760 l = &
sub->cx_queue_lock;
765 if (!
sub->parent->ncs) {
777 queue = &
sub->cx_queue;
778 l = &
sub->cx_queue_lock;
801 memcpy(r, req,
sizeof(*r));
814 for (t = *queue; t && t->
next; t = t->
next);
843 snprintf(tone,
sizeof(tone),
"L/wt%s", distinctive_ring);
844 ast_debug(3,
"MGCP distinctive callwait %s\n", tone);
847 ast_debug(3,
"MGCP normal callwait %s\n", tone);
853 snprintf(tone,
sizeof(tone),
"L/r%s", distinctive_ring);
854 ast_debug(3,
"MGCP distinctive ring %s\n", tone);
910 ast_debug(1,
"Asked to hangup channel not connected\n");
914 ast_debug(1,
"Invalid magic. MGCP subchannel freed up already.\n");
922 if (!
sub->next->owner) {
943 sub->gate->deltimer = time(
NULL) + 5;
951 sub->cxident[0] =
'\0';
952 if ((
sub == p->
sub) &&
sub->next->owner) {
956 if (
sub->next->owner && bridged) {
967 if (
sub->next->owner && bridged) {
983 sub->alreadygone = 0;
986 sub->callid[0] =
'\0';
991 memset(&
sub->tmpdest, 0,
sizeof(
sub->tmpdest));
1006 ast_debug(3,
"MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
1010 ast_debug(3,
"MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
1023 int hasendpoints = 0;
1028 e->
command =
"mgcp show endpoints";
1030 "Usage: mgcp show endpoints\n"
1031 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
1053 if (!hasendpoints) {
1054 ast_cli(
a->fd,
" << No Endpoints Defined >> ");
1066 char *ename,*gname, *
c;
1070 e->
command =
"mgcp audit endpoint";
1072 "Usage: mgcp audit endpoint <endpointid>\n"
1073 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
1074 " Debug logging (core set debug on) MUST be on to see the results of this command.\n";
1087 for (gname = ename; *gname; gname++) {
1088 if (*gname ==
'@') {
1094 if (gname[0] ==
'[') {
1097 if ((
c = strrchr(gname,
']'))) {
1102 if (!strcasecmp(mg->
name, gname)) {
1104 if (!strcasecmp(me->
name, ename)) {
1116 ast_cli(
a->fd,
" << Could not find endpoint >> ");
1141 ast_verb(3,
"MGCP mgcp_answer(%s) on %s@%s-%d\n",
1228 ast_log(
LOG_WARNING,
"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1238 if (!
sub->sdpsent &&
sub->gate) {
1240 ast_debug(1,
"GATE ALLOCATED, sending sdp\n");
1244 if ((
sub->parent->sub ==
sub) || !
sub->parent->singlepath) {
1260 if (
sub->owner != oldchan) {
1278 ast_debug(1,
"Sending DTMF using inband/hybrid\n");
1281 ast_debug(1,
"Sending DTMF using RFC2833\n");
1300 ast_debug(1,
"Stopping DTMF using inband/hybrid\n");
1303 ast_debug(1,
"Stopping DTMF using RFC2833\n");
1304 if (
sub->parent->ncs) {
1336 char *
tmp, *endpt, *gw;
1340 if ((
tmp = strchr(endpt,
'@'))) {
1348 if (strcasecmp(g->
name, gw) == 0) {
1357 for (; e; e = e->
next) {
1358 if (strcasecmp(e->
name, endpt) == 0) {
1381 return "Other end has hungup";
1383 return "Local ring";
1385 return "Remote end is ringing";
1387 return "Remote end has answered";
1389 return "Remote end is busy";
1391 return "Make it go off hook";
1393 return "Line is off hook";
1395 return "Congestion (circuits busy)";
1397 return "Flash hook";
1401 return "Set a low-level option";
1405 return "Un-Key Radio";
1415 ast_debug(3,
"MGCP asked to indicate %d '%s' condition on channel %s\n",
1420 #ifdef DLINK_BUGGY_FIRMWARE
1423 if (!
sub->sdpsent) {
1479 tmp =
ast_channel_alloc(1,
state, i->
cid_num, i->
cid_name, i->
accountcode, i->
exten, i->
context, assignedids, requestor, i->
amaflags,
"MGCP/%s@%s-%d", i->
name, i->
parent->
name,
sub->id);
1544 char valuebuf[1024];
1562 ast_verb(3,
"MGCP mgcp_new(%s) created in state: %s\n",
1570 if (strncasecmp(line,
name, nameLen) == 0 && line[nameLen] ==
'=') {
1571 char *r = line + nameLen + 1;
1572 while (*r && (*r < 33)) ++r;
1584 for (x = 0; x < req->
lines; x++) {
1586 if (r[0] !=
'\0')
return r;
1600 while (*iterator < req->
lines) {
1602 if (r[0] !=
'\0')
return r;
1612 for (x = *start; x < req->
headers; x++) {
1616 while (*r && (*r < 33)) {
1639 if (!
c)
return NULL;
1641 while (*
c && (*
c < 33 || *
c ==
',')) {
1646 while (*
c && (*
c >= 33 && *
c !=
',')) {
1667 ast_debug(1,
"*** find Realtime MGCPGW\n");
1696 for (gwv = mgcpgwconfig; gwv; gwv = gwv->
next) {
1697 if (!strcasecmp(gwv->
name,
"lines")) {
1703 for (gwv = gwv && gwv->
next ? gwv : mgcpgwconfig; gwv->
next; gwv = gwv->
next);
1710 for (i = 0; i <
args.argc; i++) {
1715 if (!strcasecmp(gwv->
next->
name,
"line")) {
1729 for (gwv = mgcpgwconfig; gwv; gwv = gwv->
next) {
1755 char *at =
NULL, *
c;
1759 at = strchr(
tmp,
'@');
1767 if (at && (at[0] ==
'[')) {
1769 c = strrchr(at,
']');
1775 if ((!
name || !strcasecmp(g->
name, at)) &&
1776 (sin || g->
addr.sin_addr.s_addr || g->
defaddr.sin_addr.s_addr)) {
1779 if ((g->
addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1780 (g->
addr.sin_port != sin->sin_port)) {
1781 memcpy(&g->
addr, sin,
sizeof(g->
addr));
1784 struct sockaddr_in tmp3 = {0,};
1786 tmp3.sin_addr = g->
ourip;
1793 g->
ourip = tmp3.sin_addr;
1799 if (strcasecmp(g->
name, at)) {
1803 }
else if (!
name && sin) {
1804 if ((g->
addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1805 (g->
addr.sin_port != sin->sin_port)) {
1818 ast_debug(1,
"Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1869 }
else if (*
c ==
'\r') {
1892 req->
line[f] =
c + 1;
1893 }
else if (*
c ==
'\r') {
1905 while (*
c && *
c < 33)
c++;
1908 while (*
c && (*
c > 32))
c++;
1912 while (*
c && (*
c < 33))
c++;
1914 while (*
c && (*
c > 32))
c++;
1918 while (*
c && (*
c < 33))
c++;
1920 while (*
c && (*
c > 32))
c++;
1924 while (*
c && (*
c < 33))
c++;
1926 while (*
c && (*
c > 32))
c++;
1927 while (*
c && (*
c < 33))
c++;
1928 while (*
c && (*
c > 32))
c++;
1934 ast_debug(1,
"Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1951 int peerNonCodecCapability;
1954 int codec, codec_count=0;
1968 if (sscanf(
c,
"IN IP4 %256s", host) != 1) {
1977 if (sscanf(m,
"audio %30d RTP/AVP %n", &portno, &
len) != 1 || !
len) {
1987 if (sscanf(
codecs,
"%30d%n", &codec, &
len) != 1) {
2004 if (sscanf(
a,
"rtpmap: %30d %127[^/]/", &codec, mimeSubtype) != 2)
2016 ast_debug(1,
"Capabilities: us - %s, them - %s, combined - %s\n",
2022 ast_debug(1,
"Non-codec capabilities: us - %d, them - %d, combined - %d\n",
2033 if (req->
len >=
sizeof(req->
data) - 4) {
2055 if (req->
len >=
sizeof(req->
data) - 4) {
2120 memset(resp, 0,
sizeof(*resp));
2150 respprep(&resp, p, msg, req, msgrest);
2159 mgr->
buf[resp.
len] =
'\0';
2172 struct sockaddr_in sin;
2182 struct sockaddr_in dest = { 0, };
2198 if (
sub->tmpdest.sin_addr.s_addr) {
2199 dest.sin_addr =
sub->tmpdest.sin_addr;
2200 dest.sin_port =
sub->tmpdest.sin_port;
2202 memset(&
sub->tmpdest, 0,
sizeof(
sub->tmpdest));
2205 dest.sin_port = sin.sin_port;
2210 snprintf(o,
sizeof(o),
"o=root %d %d IN IP4 %s\r\n", (
int)getpid(), (
int)getpid(),
ast_inet_ntoa(dest.sin_addr));
2212 snprintf(
c,
sizeof(
c),
"c=IN IP4 %s\r\n",
ast_inet_ntoa(dest.sin_addr));
2214 snprintf(m,
sizeof(m),
"m=audio %d RTP/AVP", ntohs(dest.sin_port));
2227 snprintf(costr,
sizeof(costr),
" %d",
codec);
2228 strncat(m, costr,
sizeof(m) - strlen(m) - 1);
2230 strncat(
a, costr,
sizeof(
a) - strlen(
a) - 1);
2238 ast_debug(1,
"Answering with non-codec capability %d\n", (
int) x);
2241 snprintf(costr,
sizeof(costr),
" %d",
codec);
2242 strncat(m, costr,
sizeof(m) - strlen(m) - 1);
2244 strncat(
a, costr,
sizeof(
a) - strlen(
a) - 1);
2248 snprintf(costr,
sizeof costr,
"a=fmtp:%d 0-16\r\n",
codec);
2249 strncat(
a, costr,
sizeof(
a) - strlen(
a) - 1);
2254 strncat(m,
"\r\n",
sizeof(m) - strlen(m) - 1);
2255 len = strlen(v) + strlen(s) + strlen(o) + strlen(
c) + strlen(t) + strlen(m) + strlen(
a);
2256 snprintf(costr,
sizeof(costr),
"%d",
len);
2295 strncat(local,
tmp,
sizeof(local) - strlen(local) - 1);
2302 snprintf(
tmp,
sizeof(
tmp),
", dq-gi:%x",
sub->gate->gateid);
2303 strncat(local,
tmp,
sizeof(local) - strlen(local) - 1);
2307 ast_debug(1,
"Waiting for opened gate...\n");
2314 oseq =
reqprep(&resp, p,
"MDCX");
2338 ast_debug(3,
"Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2352 strncat(local,
tmp,
sizeof(local) - strlen(local) - 1);
2359 snprintf(
tmp,
sizeof(
tmp),
", dq-gi:%x",
sub->gate->gateid);
2360 strncat(local,
tmp,
sizeof(local) - strlen(local) - 1);
2364 oseq =
reqprep(&resp, p,
"CRCX");
2423 sub->gate->tech_pvt =
sub;
2444 strncat(local,
tmp,
sizeof(local) - strlen(local) - 1);
2449 ast_debug(3,
"Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2452 oseq =
reqprep(&resp, p,
"CRCX");
2471 ast_debug(3,
"MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2474 oseq =
reqprep(&resp, p,
"RQNT");
2514 snprintf(tone2,
sizeof(tone2),
"%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
2517 oseq =
reqprep(&resp, p,
"RQNT");
2530 ast_debug(3,
"MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2553 ast_debug(3,
"Modified %s@%s-%d with new mode: %s on callid: %s\n",
2560 if (p->
ncs && !fc) {
2569 strncat(local,
tmp,
sizeof(local) - strlen(local) - 1);
2574 if (!
sub->sdpsent) {
2577 snprintf(
tmp,
sizeof(
tmp),
", dq-gi:%x",
sub->gate->gateid);
2578 strncat(local,
tmp,
sizeof(local) - strlen(local) - 1);
2586 oseq =
reqprep(&resp, p,
"MDCX");
2588 if (!
sub->sdpsent) {
2595 switch (
sub->parent->hookstate) {
2603 if (!
sub->sdpsent) {
2617 char tone_indicate_end = 0;
2622 if (p && (!strcasecmp(tone, (p->
ncs ?
"L/ro" :
"G/cg")))) {
2623 tone_indicate_end = 1;
2631 }
else if (!tone_indicate_end){
2632 add_header(resp,
"R", (p->
ncs ?
"L/hu(N),L/hf(N),L/[0-9#*](N)" :
"L/hu(N),L/hf(N),D/[0-9#*](N)"));
2634 ast_debug(1,
"We don't want more digits if we will end the call\n");
2646 oseq =
reqprep(&resp, p,
"AUEP");
2662 ast_debug(3,
"Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
2664 oseq =
reqprep(&resp, p,
"DLCX");
2671 if (
sub->cxident[0])
2684 ast_debug(3,
"Delete connection %s %s@%s on callid: %s\n",
2685 cxident ? cxident :
"", p->
name, p->
parent->
name, callid ? callid :
"");
2686 oseq =
reqprep(&resp, p,
"DLCX");
2688 if (callid && *callid)
2691 if (cxident && *cxident)
2740 for (prev =
NULL, req = *queue; req; prev = req, req = req->
next) {
2741 if (req->
trid == ident) {
2750 ast_debug(1,
"Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2783 ast_verb(3,
"No command found on [%s] for transaction %u. Ignoring...\n",
2846 if (strcasecmp(
c,
sub->cxident)) {
2847 ast_log(
LOG_WARNING,
"Subchannel already has a cxident. sub->cxident: %s requested %s\n",
sub->cxident,
c);
2851 if (
sub->tmpdest.sin_addr.s_addr) {
2875 char cxident[80] =
"";
2877 if (
len > (
sizeof(cxident) - 1))
2878 len =
sizeof(cxident) - 1;
2880 ast_verb(3,
"Non existing connection id %s on %s@%s \n",
2892 if (strstr(
c,
"hu")) {
2905 }
else if (strstr(
c,
"hd")) {
2919 if (resp && resp->
lines) {
2946 if (
sub->rtp &&
sub->owner)
2953 snprintf(
sub->callid,
sizeof(
sub->callid),
"%08lx%s", (
unsigned long)
ast_random(),
sub->txident);
2955 if(!
sub->parent->pktcgatealloc) {
2976 int loop_pause = 100;
2978 const char *pickupexten;
2985 ast_log(
LOG_ERROR,
"Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
2988 pickupexten =
ast_strdupa(pickup_cfg->pickupexten);
2997 timeout -= loop_pause;
3021 ast_verb(3,
"Setting call forward to '%s' on channel %s\n",
3067 }
else if (res == 0) {
3068 ast_debug(1,
"not enough digits (and no ambiguous match)...\n");
3084 }
else if (!strcmp(p->
dtmf_buf, pickupexten)) {
3116 }
else if (!strcmp(p->
dtmf_buf,
"*78")) {
3125 }
else if (!strcmp(p->
dtmf_buf,
"*79")) {
3269 if (
sub->next->owner) {
3273 sub->next->alreadygone = 1;
3295 if (
sub->outgoing) {
3320 #ifdef DLINK_BUGGY_FIRMWARE
3352 ast_log(
LOG_WARNING,
"If we're onhook why are we here trying to handle a hd or hf?\n");
3378 if (!strcasecmp(req->
verb,
"RSIP")) {
3380 if (!strcasecmp(
get_header(req,
"RM"),
"X-keepalive")) {
3396 for (tmp_ep = g->
endpoints; tmp_ep; tmp_ep = tmp_ep->
next) {
3402 first_sub = tmp_ep->
sub;
3403 tmp_sub = tmp_ep->
sub;
3406 tmp_sub = tmp_sub->
next;
3407 if (tmp_sub == first_sub)
3412 }
else if (
sub->owner) {
3425 }
else if (!strcasecmp(req->
verb,
"NTFY")) {
3430 s = strchr(ev,
'/');
3434 if (strcasecmp(ev,
"hu") && strcasecmp(ev,
"hd") && strcasecmp(ev,
"ping")) {
3437 if (!strcasecmp(ev,
"hd")) {
3448 }
else if (!strcasecmp(ev,
"hf")) {
3466 if (!
sub->next->owner) {
3476 }
else if (
sub->owner &&
sub->next->owner) {
3478 if ((!
sub->outgoing) && (!
sub->next->outgoing)) {
3480 ast_verb(3,
"MGCP Conferencing %d and %d on %s@%s\n",
3491 ast_verb(3,
"We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
3506 }
else if (
sub->next->owner) {
3518 ast_log(
LOG_WARNING,
"Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
3521 }
else if (!strcasecmp(ev,
"hu")) {
3530 if (p->
transfer && (
sub->owner &&
sub->next->owner) && ((!
sub->outgoing) || (!
sub->next->outgoing))) {
3545 sub->alreadygone = 1;
3548 ast_verb(3,
"MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
3570 }
else if ((strlen(ev) == 1) &&
3571 (((ev[0] >=
'0') && (ev[0] <=
'9')) ||
3572 ((ev[0] >=
'A') && (ev[0] <=
'D')) ||
3573 (ev[0] ==
'*') || (ev[0] ==
'#'))) {
3581 if (
sub->next->owner)
3584 if (strstr(p->
curtone, (p->
ncs ?
"wt1" :
"wt")) && (ev[0] ==
'A')) {
3591 }
else if (!strcasecmp(ev,
"T")) {
3593 }
else if (!strcasecmp(ev,
"ping")) {
3620 sub->parent->parent->responses =
next;
3623 if (
seqno == cur->seqno)
3638 struct sockaddr_in sin;
3645 memset(&req, 0,
sizeof(req));
3646 res = recvfrom(
mgcpsock, req.
data,
sizeof(req.
data) - 1, 0, (
struct sockaddr *)&sin, &
len);
3648 if (
errno != ECONNREFUSED)
3652 req.
data[res] =
'\0';
3667 ast_debug(1,
"Ignoring provisional response on transaction %d\n", ident);
3678 for (prev =
NULL, cur = gw->
msgs; cur; prev = cur, cur = cur->
next) {
3679 if (cur->
seqno == ident) {
3680 ast_debug(1,
"Got response back on transaction %d\n", ident);
3701 ast_log(
LOG_NOTICE,
"Got response back on [%s] for transaction %d we aren't sending?\n",
3708 ast_log(
LOG_NOTICE,
"Message must have a verb, an idenitifier, version, and endpoint\n");
3745 for (i = 0; (i <
MAX_SUBS) && s; i++) {
3779 ast_debug(1,
"***** MGCP REALTIME PRUNE GW: %s\n", g->
name);
3827 lastpass = thispass;
3828 thispass = time(
NULL);
3831 if (thispass != lastpass) {
3836 if ((e->msgstate != res) && (e->hookstate ==
MGCP_ONHOOK) && (!e->rtp)){
3843 e->onhooktime = thispass;
3853 if(time(
NULL) > (lastrun + 60)) {
3878 lastrun = time(
NULL);
3884 pthread_testcancel();
3888 if ((res < 0) || (res > 1000)) {
3955 ast_verb(3,
"MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
3956 sub->parent->callwaiting,
sub->parent->dnd,
sub->owner ? 1 : 0,
sub->next->owner ? 1: 0);
3958 if (((
sub->parent->callwaiting) && ((
sub->owner) && (
sub->next->owner))) ||
3959 ((!
sub->parent->callwaiting) && (
sub->owner)) ||
3997 if (!strcasecmp(cat, gw->
name)) {
4005 if (!gw && !(gw =
ast_calloc(1,
sizeof(*gw)))) {
4019 for (; v; v = v->
next) {
4020 if (!strcasecmp(v->
name,
"host")) {
4021 if (!strcasecmp(v->
value,
"dynamic")) {
4024 memset(&gw->
addr.sin_addr, 0, 4);
4025 if (gw->
addr.sin_port) {
4028 gw->
addr.sin_port = 0;
4048 }
else if (!strcasecmp(v->
name,
"defaultip")) {
4060 }
else if (!strcasecmp(v->
name,
"permit") ||
4061 !strcasecmp(v->
name,
"deny")) {
4065 ast_log(
LOG_ERROR,
"Invalid ACL '%s' specified for MGCP gateway '%s' on line %d. Not creating.\n",
4075 }
else if (!strcasecmp(v->
name,
"port")) {
4076 gw->
addr.sin_port = htons(atoi(v->
value));
4077 }
else if (!strcasecmp(v->
name,
"context")) {
4079 }
else if (!strcasecmp(v->
name,
"dtmfmode")) {
4080 if (!strcasecmp(v->
value,
"inband"))
4082 else if (!strcasecmp(v->
value,
"rfc2833"))
4084 else if (!strcasecmp(v->
value,
"hybrid"))
4086 else if (!strcasecmp(v->
value,
"none"))
4090 }
else if (!strcasecmp(v->
name,
"nat")) {
4092 }
else if (!strcasecmp(v->
name,
"ncs")) {
4094 }
else if (!strcasecmp(v->
name,
"hangupongateremove")) {
4096 }
else if (!strcasecmp(v->
name,
"pktcgatealloc")) {
4098 }
else if (!strcasecmp(v->
name,
"callerid")) {
4099 if (!strcasecmp(v->
value,
"asreceived")) {
4105 }
else if (!strcasecmp(v->
name,
"language")) {
4107 }
else if (!strcasecmp(v->
name,
"accountcode")) {
4109 }
else if (!strcasecmp(v->
name,
"amaflags")) {
4116 }
else if (!strcasecmp(v->
name,
"setvar")) {