aboutsummaryrefslogtreecommitdiffstats
path: root/1.2-netsec/pbx
diff options
context:
space:
mode:
Diffstat (limited to '1.2-netsec/pbx')
-rw-r--r--1.2-netsec/pbx/Makefile80
-rw-r--r--1.2-netsec/pbx/dundi-parser.c832
-rw-r--r--1.2-netsec/pbx/dundi-parser.h88
-rw-r--r--1.2-netsec/pbx/pbx_ael.c1284
-rw-r--r--1.2-netsec/pbx/pbx_config.c1831
-rw-r--r--1.2-netsec/pbx/pbx_dundi.c4831
-rw-r--r--1.2-netsec/pbx/pbx_gtkconsole.c518
-rw-r--r--1.2-netsec/pbx/pbx_kdeconsole.cc61
-rw-r--r--1.2-netsec/pbx/pbx_kdeconsole.h37
-rw-r--r--1.2-netsec/pbx/pbx_kdeconsole_main.cc81
-rw-r--r--1.2-netsec/pbx/pbx_loopback.c207
-rw-r--r--1.2-netsec/pbx/pbx_realtime.c274
-rw-r--r--1.2-netsec/pbx/pbx_spool.c445
13 files changed, 0 insertions, 10569 deletions
diff --git a/1.2-netsec/pbx/Makefile b/1.2-netsec/pbx/Makefile
deleted file mode 100644
index f86ae4859..000000000
--- a/1.2-netsec/pbx/Makefile
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Asterisk -- A telephony toolkit for Linux.
-#
-# Makefile for PBX modules
-#
-# Copyright (C) 1999-2005, Mark Spencer
-#
-# Mark Spencer <markster@digium.com>
-#
-# This program is free software, distributed under the terms of
-# the GNU General Public License
-#
-
-PBX_LIBS=pbx_config.so pbx_spool.so pbx_dundi.so pbx_loopback.so pbx_realtime.so \
- pbx_ael.so
-
-ifeq ($(findstring BSD,${OSARCH}),BSD)
- CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
-endif
-
-# Add GTK console if appropriate
-#PBX_LIBS+=$(shell $(CROSS_COMPILE_BIN)gtk-config --cflags >/dev/null 2>/dev/null && echo "pbx_gtkconsole.so")
-# Add KDE Console if appropriate
-#PBX_LIBS+=$(shell [ "$$QTDIR" != "" ] && echo "pbx_kdeconsole.so")
-
-GTK_FLAGS=`${CROSS_COMPILE_BIN}gtk-config --cflags gthread`
-GTK_LIBS=`${CROSS_COMPILE_BIN}gtk-config --libs gthread`
-MOC=$(QTDIR)/bin/moc
-KDE_FLAGS=-I$(KDEDIR)/include -I$(KDEDIR)/include/kde -I$(QTDIR)/include
-KDE_LIBS=-L$(KDEDIR)/lib -L$(QTDIR)/lib -lqt -lkdecore -lkdeui
-
-ifeq (${OSARCH},CYGWIN)
-CYGSOLINK=-Wl,--out-implib=lib$@.a -Wl,--export-all-symbols
-CYGSOLIB=-L.. -L. -L../res -lasterisk.dll
-else
-CFLAGS+=-fPIC
-endif
-
-KDE_CONSOLE_OBJS=pbx_kdeconsole_main.o pbx_kdeconsole.o
-
-all: depend $(PBX_LIBS)
-
-clean:
- rm -f *.so *.o .depend
-
-pbx_gtkconsole.o: pbx_gtkconsole.c
- $(CC) $(CFLAGS) $(GTK_FLAGS) -c -o $@ $<
-
-pbx_gtkconsole.so: pbx_gtkconsole.o
- $(CC) $(SOLINK) -o $@ $< $(GTK_LIBS)
-
-pbx_kdeconsole.o: pbx_kdeconsole.cc pbx_kdeconsole.moc
- $(CXX) $(CFLAGS) $(KDE_FLAGS) -c -o $@ $<
-
-pbx_kdeconsole_main.o: pbx_kdeconsole_main.cc pbx_kdeconsole.h
- $(CXX) $(CFLAGS) $(KDE_FLAGS) -c -o $@ $<
-
-pbx_kdeconsole.so: $(KDE_CONSOLE_OBJS)
- $(CC) $(SOLINK) -o $@ $(KDE_CONSOLE_OBJS) $(KDE_LIBS)
-
-pbx_dundi.so: dundi-parser.o pbx_dundi.o
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} pbx_dundi.o dundi-parser.o -lz ${CYGSOLIB}
-
-%.moc : %.h
- $(MOC) $< -o $@
-
-%.so : %.o
- $(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB}
-
-ifneq ($(wildcard .depend),)
- include .depend
-endif
-
-install: all
- for x in $(PBX_LIBS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
-
-depend: .depend
-
-.depend:
- ../build_tools/mkdep $(CFLAGS) `ls *.c`
diff --git a/1.2-netsec/pbx/dundi-parser.c b/1.2-netsec/pbx/dundi-parser.c
deleted file mode 100644
index 9b9d9d205..000000000
--- a/1.2-netsec/pbx/dundi-parser.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Distributed Universal Number Discovery (DUNDi)
- *
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/frame.h"
-#include "asterisk/utils.h"
-#include "asterisk/dundi.h"
-#include "dundi-parser.h"
-#include "asterisk/dundi.h"
-
-static void internaloutput(const char *str)
-{
- fputs(str, stdout);
-}
-
-static void internalerror(const char *str)
-{
- fprintf(stderr, "WARNING: %s", str);
-}
-
-static void (*outputf)(const char *str) = internaloutput;
-static void (*errorf)(const char *str) = internalerror;
-
-char *dundi_eid_to_str(char *s, int maxlen, dundi_eid *eid)
-{
- int x;
- char *os = s;
- if (maxlen < 18) {
- if (s && (maxlen > 0))
- *s = '\0';
- } else {
- for (x=0;x<5;x++) {
- sprintf(s, "%02x:", eid->eid[x]);
- s += 3;
- }
- sprintf(s, "%02x", eid->eid[5]);
- }
- return os;
-}
-
-char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
-{
- int x;
- char *os = s;
- if (maxlen < 13) {
- if (s && (maxlen > 0))
- *s = '\0';
- } else {
- for (x=0;x<6;x++) {
- sprintf(s, "%02X", eid->eid[x]);
- s += 2;
- }
- }
- return os;
-}
-
-int dundi_str_to_eid(dundi_eid *eid, char *s)
-{
- unsigned int eid_int[6];
- int x;
- if (sscanf(s, "%x:%x:%x:%x:%x:%x", &eid_int[0], &eid_int[1], &eid_int[2],
- &eid_int[3], &eid_int[4], &eid_int[5]) != 6)
- return -1;
- for (x=0;x<6;x++)
- eid->eid[x] = eid_int[x];
- return 0;
-}
-
-int dundi_str_short_to_eid(dundi_eid *eid, char *s)
-{
- unsigned int eid_int[6];
- int x;
- if (sscanf(s, "%2x%2x%2x%2x%2x%2x", &eid_int[0], &eid_int[1], &eid_int[2],
- &eid_int[3], &eid_int[4], &eid_int[5]) != 6)
- return -1;
- for (x=0;x<6;x++)
- eid->eid[x] = eid_int[x];
- return 0;
-}
-
-int dundi_eid_zero(dundi_eid *eid)
-{
- int x;
- for (x=0;x<sizeof(eid->eid) / sizeof(eid->eid[0]);x++)
- if (eid->eid[x]) return 0;
- return 1;
-}
-
-int dundi_eid_cmp(dundi_eid *eid1, dundi_eid *eid2)
-{
- return memcmp(eid1, eid2, sizeof(dundi_eid));
-}
-
-static void dump_string(char *output, int maxlen, void *value, int len)
-{
- maxlen--;
- if (maxlen > len)
- maxlen = len;
- strncpy(output,value, maxlen);
- output[maxlen] = '\0';
-}
-
-static void dump_cbypass(char *output, int maxlen, void *value, int len)
-{
- maxlen--;
- strncpy(output, "Bypass Caches", maxlen);
- output[maxlen] = '\0';
-}
-
-static void dump_eid(char *output, int maxlen, void *value, int len)
-{
- if (len == 6)
- dundi_eid_to_str(output, maxlen, (dundi_eid *)value);
- else
- snprintf(output, maxlen, "Invalid EID len %d", len);
-}
-
-char *dundi_hint2str(char *buf, int bufsiz, int flags)
-{
- strcpy(buf, "");
- buf[bufsiz-1] = '\0';
- if (flags & DUNDI_HINT_TTL_EXPIRED) {
- strncat(buf, "TTLEXPIRED|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_HINT_DONT_ASK) {
- strncat(buf, "DONTASK|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_HINT_UNAFFECTED) {
- strncat(buf, "UNAFFECTED|", bufsiz - strlen(buf) - 1);
- }
- /* Get rid of trailing | */
- if (ast_strlen_zero(buf))
- strcpy(buf, "NONE|");
- buf[strlen(buf)-1] = '\0';
- return buf;
-}
-
-static void dump_hint(char *output, int maxlen, void *value, int len)
-{
- unsigned short flags;
- char tmp[512];
- char tmp2[256];
- if (len < 2) {
- strncpy(output, "<invalid contents>", maxlen);
- return;
- }
- memcpy(&flags, value, sizeof(flags));
- flags = ntohs(flags);
- memset(tmp, 0, sizeof(tmp));
- dundi_hint2str(tmp2, sizeof(tmp2), flags);
- snprintf(tmp, sizeof(tmp), "[%s] ", tmp2);
- memcpy(tmp + strlen(tmp), value + 2, len - 2);
- strncpy(output, tmp, maxlen - 1);
-}
-
-static void dump_cause(char *output, int maxlen, void *value, int len)
-{
- static char *causes[] = {
- "SUCCESS",
- "GENERAL",
- "DYNAMIC",
- "NOAUTH" ,
- };
- char tmp[256];
- char tmp2[256];
- int mlen;
- unsigned char cause;
- if (len < 1) {
- strncpy(output, "<invalid contents>", maxlen);
- return;
- }
- cause = *((unsigned char *)value);
- memset(tmp2, 0, sizeof(tmp2));
- mlen = len - 1;
- if (mlen > 255)
- mlen = 255;
- memcpy(tmp2, value + 1, mlen);
- if (cause < sizeof(causes) / sizeof(causes[0])) {
- if (len > 1)
- snprintf(tmp, sizeof(tmp), "%s: %s", causes[cause], tmp2);
- else
- snprintf(tmp, sizeof(tmp), "%s", causes[cause]);
- } else {
- if (len > 1)
- snprintf(tmp, sizeof(tmp), "%d: %s", cause, tmp2);
- else
- snprintf(tmp, sizeof(tmp), "%d", cause);
- }
-
- strncpy(output,tmp, maxlen);
- output[maxlen] = '\0';
-}
-
-static void dump_int(char *output, int maxlen, void *value, int len)
-{
- if (len == (int)sizeof(unsigned int))
- snprintf(output, maxlen, "%lu", (unsigned long)ntohl(*((unsigned int *)value)));
- else
- snprintf(output, maxlen, "Invalid INT");
-}
-
-static void dump_short(char *output, int maxlen, void *value, int len)
-{
- if (len == (int)sizeof(unsigned short))
- snprintf(output, maxlen, "%d", ntohs(*((unsigned short *)value)));
- else
- snprintf(output, maxlen, "Invalid SHORT");
-}
-
-static void dump_byte(char *output, int maxlen, void *value, int len)
-{
- if (len == (int)sizeof(unsigned char))
- snprintf(output, maxlen, "%d", *((unsigned char *)value));
- else
- snprintf(output, maxlen, "Invalid BYTE");
-}
-
-static char *proto2str(int proto, char *buf, int bufsiz)
-{
- switch(proto) {
- case DUNDI_PROTO_NONE:
- strncpy(buf, "None", bufsiz - 1);
- break;
- case DUNDI_PROTO_IAX:
- strncpy(buf, "IAX", bufsiz - 1);
- break;
- case DUNDI_PROTO_SIP:
- strncpy(buf, "SIP", bufsiz - 1);
- break;
- case DUNDI_PROTO_H323:
- strncpy(buf, "H.323", bufsiz - 1);
- break;
- default:
- snprintf(buf, bufsiz, "Unknown Proto(%d)", proto);
- }
- buf[bufsiz-1] = '\0';
- return buf;
-}
-
-char *dundi_flags2str(char *buf, int bufsiz, int flags)
-{
- strcpy(buf, "");
- buf[bufsiz-1] = '\0';
- if (flags & DUNDI_FLAG_EXISTS) {
- strncat(buf, "EXISTS|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_MATCHMORE) {
- strncat(buf, "MATCHMORE|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_CANMATCH) {
- strncat(buf, "CANMATCH|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_IGNOREPAT) {
- strncat(buf, "IGNOREPAT|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_RESIDENTIAL) {
- strncat(buf, "RESIDENCE|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_COMMERCIAL) {
- strncat(buf, "COMMERCIAL|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_MOBILE) {
- strncat(buf, "MOBILE", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_NOUNSOLICITED) {
- strncat(buf, "NOUNSLCTD|", bufsiz - strlen(buf) - 1);
- }
- if (flags & DUNDI_FLAG_NOCOMUNSOLICIT) {
- strncat(buf, "NOCOMUNSLTD|", bufsiz - strlen(buf) - 1);
- }
- /* Get rid of trailing | */
- if (ast_strlen_zero(buf))
- strcpy(buf, "NONE|");
- buf[strlen(buf)-1] = '\0';
- return buf;
-}
-
-static void dump_answer(char *output, int maxlen, void *value, int len)
-{
- struct dundi_answer *answer;
- char proto[40];
- char flags[40];
- char eid_str[40];
- char tmp[512]="";
- if (len >= 10) {
- answer = (struct dundi_answer *)(value);
- memcpy(tmp, answer->data, (len >= 500) ? 500 : len - 10);
- dundi_eid_to_str(eid_str, sizeof(eid_str), &answer->eid);
- snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]",
- dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)),
- ntohs(answer->weight),
- proto2str(answer->protocol, proto, sizeof(proto)),
- tmp, eid_str);
- } else
- strncpy(output, "Invalid Answer", maxlen - 1);
-}
-
-static void dump_encrypted(char *output, int maxlen, void *value, int len)
-{
- char iv[33];
- int x;
- if ((len > 16) && !(len % 16)) {
- /* Build up IV */
- for (x=0;x<16;x++) {
- snprintf(iv + (x << 1), 3, "%02x", ((unsigned char *)value)[x]);
- }
- snprintf(output, maxlen, "[IV %s] %d encrypted blocks\n", iv, len / 16);
- } else
- snprintf(output, maxlen, "Invalid Encrypted Datalen %d", len);
-}
-
-static void dump_raw(char *output, int maxlen, void *value, int len)
-{
- int x;
- unsigned char *u = value;
- output[maxlen - 1] = '\0';
- strcpy(output, "[ ");
- for (x=0;x<len;x++) {
- snprintf(output + strlen(output), maxlen - strlen(output) - 1, "%02x ", u[x]);
- }
- strncat(output + strlen(output), "]", maxlen - strlen(output) - 1);
-}
-
-static struct dundi_ie {
- int ie;
- char *name;
- void (*dump)(char *output, int maxlen, void *value, int len);
-} ies[] = {
- { DUNDI_IE_EID, "ENTITY IDENT", dump_eid },
- { DUNDI_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
- { DUNDI_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
- { DUNDI_IE_EID_DIRECT, "DIRECT EID", dump_eid },
- { DUNDI_IE_ANSWER, "ANSWER", dump_answer },
- { DUNDI_IE_TTL, "TTL", dump_short },
- { DUNDI_IE_VERSION, "VERSION", dump_short },
- { DUNDI_IE_EXPIRATION, "EXPIRATION", dump_short },
- { DUNDI_IE_UNKNOWN, "UKWN DUNDI CMD", dump_byte },
- { DUNDI_IE_CAUSE, "CAUSE", dump_cause },
- { DUNDI_IE_REQEID, "REQUEST EID", dump_eid },
- { DUNDI_IE_ENCDATA, "ENCDATA", dump_encrypted },
- { DUNDI_IE_SHAREDKEY, "SHAREDKEY", dump_raw },
- { DUNDI_IE_SIGNATURE, "SIGNATURE", dump_raw },
- { DUNDI_IE_KEYCRC32, "KEYCRC32", dump_int },
- { DUNDI_IE_HINT, "HINT", dump_hint },
- { DUNDI_IE_DEPARTMENT, "DEPARTMENT", dump_string },
- { DUNDI_IE_ORGANIZATION, "ORGANIZTN", dump_string },
- { DUNDI_IE_LOCALITY, "LOCALITY", dump_string },
- { DUNDI_IE_STATE_PROV, "STATEPROV", dump_string },
- { DUNDI_IE_COUNTRY, "COUNTRY", dump_string },
- { DUNDI_IE_EMAIL, "EMAIL", dump_string },
- { DUNDI_IE_PHONE, "PHONE", dump_string },
- { DUNDI_IE_IPADDR, "ADDRESS", dump_string },
- { DUNDI_IE_CACHEBYPASS, "CBYPASS", dump_cbypass },
-};
-
-const char *dundi_ie2str(int ie)
-{
- int x;
- for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
- if (ies[x].ie == ie)
- return ies[x].name;
- }
- return "Unknown IE";
-}
-
-static void dump_ies(unsigned char *iedata, int spaces, int len)
-{
- int ielen;
- int ie;
- int x;
- int found;
- char interp[1024];
- char tmp[1024];
- if (len < 2)
- return;
- while(len >= 2) {
- ie = iedata[0];
- ielen = iedata[1];
- /* Encrypted data is the remainder */
- if (ie == DUNDI_IE_ENCDATA)
- ielen = len - 2;
- if (ielen + 2> len) {
- snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
- outputf(tmp);
- return;
- }
- found = 0;
- for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
- if (ies[x].ie == ie) {
- if (ies[x].dump) {
- ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
- snprintf(tmp, (int)sizeof(tmp), " %s%-15.15s : %s\n", (spaces ? " " : "" ), ies[x].name, interp);
- outputf(tmp);
- } else {
- if (ielen)
- snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
- else
- strcpy(interp, "Present");
- snprintf(tmp, (int)sizeof(tmp), " %s%-15.15s : %s\n", (spaces ? " " : "" ), ies[x].name, interp);
- outputf(tmp);
- }
- found++;
- }
- }
- if (!found) {
- snprintf(tmp, (int)sizeof(tmp), " %sUnknown IE %03d : Present\n", (spaces ? " " : "" ), ie);
- outputf(tmp);
- }
- iedata += (2 + ielen);
- len -= (2 + ielen);
- }
- outputf("\n");
-}
-
-void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
-{
- char *pref[] = {
- "Tx",
- "Rx",
- " ETx",
- " Erx" };
- char *commands[] = {
- "ACK ",
- "DPDISCOVER ",
- "DPRESPONSE ",
- "EIDQUERY ",
- "EIDRESPONSE ",
- "PRECACHERQ ",
- "PRECACHERP ",
- "INVALID ",
- "UNKNOWN CMD ",
- "NULL ",
- "REQREQ ",
- "REGRESPONSE ",
- "CANCEL ",
- "ENCRYPT ",
- "ENCREJ " };
- char class2[20];
- char *class;
- char subclass2[20];
- char *subclass;
- char tmp[256];
- char retries[20];
- char iabuf[INET_ADDRSTRLEN];
- if (ntohs(fhi->dtrans) & DUNDI_FLAG_RETRANS)
- strcpy(retries, "Yes");
- else
- strcpy(retries, "No");
- if ((ntohs(fhi->strans) & DUNDI_FLAG_RESERVED)) {
- /* Ignore frames with high bit set to 1 */
- return;
- }
- if ((fhi->cmdresp & 0x3f) > (int)sizeof(commands)/(int)sizeof(char *)) {
- snprintf(class2, (int)sizeof(class2), "(%d?)", fhi->cmdresp);
- class = class2;
- } else {
- class = commands[(int)(fhi->cmdresp & 0x3f)];
- }
- snprintf(subclass2, (int)sizeof(subclass2), "%02x", fhi->cmdflags);
- subclass = subclass2;
- snprintf(tmp, (int)sizeof(tmp),
- "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s (%s)\n",
- pref[rx],
- retries, fhi->oseqno, fhi->iseqno, class, fhi->cmdresp & 0x40 ? "Response" : "Command");
- outputf(tmp);
- snprintf(tmp, (int)sizeof(tmp),
- "%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s:%d]%s\n", (rx > 1) ? " " : "",
- subclass, ntohs(fhi->strans) & ~DUNDI_FLAG_RESERVED, ntohs(fhi->dtrans) & ~DUNDI_FLAG_RETRANS,
- ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port),
- fhi->cmdresp & 0x80 ? " (Final)" : "");
- outputf(tmp);
- dump_ies(fhi->ies, rx > 1, datalen);
-}
-
-int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
-{
- char tmp[256];
- if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
- snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
- errorf(tmp);
- return -1;
- }
- ied->buf[ied->pos++] = ie;
- ied->buf[ied->pos++] = datalen;
- memcpy(ied->buf + ied->pos, data, datalen);
- ied->pos += datalen;
- return 0;
-}
-
-int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *data)
-{
- char tmp[256];
- int datalen = data ? strlen(data) + 1 : 1;
- if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
- snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
- errorf(tmp);
- return -1;
- }
- ied->buf[ied->pos++] = ie;
- ied->buf[ied->pos++] = datalen;
- ied->buf[ied->pos++] = cause;
- memcpy(ied->buf + ied->pos, data, datalen-1);
- ied->pos += datalen-1;
- return 0;
-}
-
-int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data)
-{
- char tmp[256];
- int datalen = data ? strlen(data) + 2 : 2;
- if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
- snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
- errorf(tmp);
- return -1;
- }
- ied->buf[ied->pos++] = ie;
- ied->buf[ied->pos++] = datalen;
- flags = htons(flags);
- memcpy(ied->buf + ied->pos, &flags, sizeof(flags));
- ied->pos += 2;
- memcpy(ied->buf + ied->pos, data, datalen-1);
- ied->pos += datalen-2;
- return 0;
-}
-
-int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
-{
- char tmp[256];
- datalen += 16;
- if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
- snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
- errorf(tmp);
- return -1;
- }
- ied->buf[ied->pos++] = ie;
- ied->buf[ied->pos++] = datalen;
- memcpy(ied->buf + ied->pos, iv, 16);
- ied->pos += 16;
- if (data) {
- memcpy(ied->buf + ied->pos, data, datalen-16);
- ied->pos += datalen-16;
- }
- return 0;
-}
-
-int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *data)
-{
- char tmp[256];
- int datalen = data ? strlen(data) + 11 : 11;
- int x;
- unsigned short myw;
- if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
- snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
- errorf(tmp);
- return -1;
- }
- ied->buf[ied->pos++] = ie;
- ied->buf[ied->pos++] = datalen;
- for (x=0;x<6;x++)
- ied->buf[ied->pos++] = eid->eid[x];
- ied->buf[ied->pos++] = protocol;
- myw = htons(flags);
- memcpy(ied->buf + ied->pos, &myw, 2);
- ied->pos += 2;
- myw = htons(weight);
- memcpy(ied->buf + ied->pos, &myw, 2);
- ied->pos += 2;
- memcpy(ied->buf + ied->pos, data, datalen-11);
- ied->pos += datalen-11;
- return 0;
-}
-
-int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
-{
- return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
-}
-
-int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value)
-{
- unsigned int newval;
- newval = htonl(value);
- return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
-}
-
-int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
-{
- unsigned short newval;
- newval = htons(value);
- return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
-}
-
-int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str)
-{
- return dundi_ie_append_raw(ied, ie, str, strlen(str));
-}
-
-int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
-{
- return dundi_ie_append_raw(ied, ie, (unsigned char *)eid, sizeof(dundi_eid));
-}
-
-int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
-{
- return dundi_ie_append_raw(ied, ie, &dat, 1);
-}
-
-int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
-{
- return dundi_ie_append_raw(ied, ie, NULL, 0);
-}
-
-void dundi_set_output(void (*func)(const char *))
-{
- outputf = func;
-}
-
-void dundi_set_error(void (*func)(const char *))
-{
- errorf = func;
-}
-
-int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
-{
- /* Parse data into information elements */
- int len;
- int ie;
- char tmp[256];
- memset(ies, 0, (int)sizeof(struct dundi_ies));
- ies->ttl = -1;
- ies->expiration = -1;
- ies->unknowncmd = -1;
- ies->cause = -1;
- while(datalen >= 2) {
- ie = data[0];
- len = data[1];
- if (len > datalen - 2) {
- errorf("Information element length exceeds message size\n");
- return -1;
- }
- switch(ie) {
- case DUNDI_IE_EID:
- case DUNDI_IE_EID_DIRECT:
- if (len != (int)sizeof(dundi_eid)) {
- errorf("Improper entity identifer, expecting 6 bytes!\n");
- } else if (ies->eidcount < DUNDI_MAX_STACK) {
- ies->eids[ies->eidcount] = (dundi_eid *)(data + 2);
- ies->eid_direct[ies->eidcount] = (ie == DUNDI_IE_EID_DIRECT);
- ies->eidcount++;
- } else
- errorf("Too many entities in stack!\n");
- break;
- case DUNDI_IE_REQEID:
- if (len != (int)sizeof(dundi_eid)) {
- errorf("Improper requested entity identifer, expecting 6 bytes!\n");
- } else
- ies->reqeid = (dundi_eid *)(data + 2);
- break;
- case DUNDI_IE_CALLED_CONTEXT:
- ies->called_context = (char *)data + 2;
- break;
- case DUNDI_IE_CALLED_NUMBER:
- ies->called_number = (char *)data + 2;
- break;
- case DUNDI_IE_ANSWER:
- if (len < sizeof(struct dundi_answer)) {
- snprintf(tmp, (int)sizeof(tmp), "Answer expected to be >=%d bytes long but was %d\n", (int)sizeof(struct dundi_answer), len);
- errorf(tmp);
- } else {
- if (ies->anscount < DUNDI_MAX_ANSWERS)
- ies->answers[ies->anscount++]= (struct dundi_answer *)(data + 2);
- else
- errorf("Ignoring extra answers!\n");
- }
- break;
- case DUNDI_IE_TTL:
- if (len != (int)sizeof(unsigned short)) {
- snprintf(tmp, (int)sizeof(tmp), "Expecting ttl to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
- errorf(tmp);
- } else
- ies->ttl = ntohs(*((unsigned short *)(data + 2)));
- break;
- case DUNDI_IE_VERSION:
- if (len != (int)sizeof(unsigned short)) {
- snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
- errorf(tmp);
- } else
- ies->version = ntohs(*((unsigned short *)(data + 2)));
- break;
- case DUNDI_IE_EXPIRATION:
- if (len != (int)sizeof(unsigned short)) {
- snprintf(tmp, (int)sizeof(tmp), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
- errorf(tmp);
- } else
- ies->expiration = ntohs(*((unsigned short *)(data + 2)));
- break;
- case DUNDI_IE_KEYCRC32:
- if (len != (int)sizeof(unsigned int)) {
- snprintf(tmp, (int)sizeof(tmp), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
- errorf(tmp);
- } else
- ies->keycrc32 = ntohl(*((unsigned int *)(data + 2)));
- break;
- case DUNDI_IE_UNKNOWN:
- if (len == 1)
- ies->unknowncmd = data[2];
- else {
- snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
- errorf(tmp);
- }
- break;
- case DUNDI_IE_CAUSE:
- if (len >= 1) {
- ies->cause = data[2];
- ies->causestr = (char *)data + 3;
- } else {
- snprintf(tmp, (int)sizeof(tmp), "Expected at least one byte cause, but was %d long\n", len);
- errorf(tmp);
- }
- break;
- case DUNDI_IE_HINT:
- if (len >= 2) {
- ies->hint = (struct dundi_hint *)(data + 2);
- } else {
- snprintf(tmp, (int)sizeof(tmp), "Expected at least two byte hint, but was %d long\n", len);
- errorf(tmp);
- }
- break;
- case DUNDI_IE_DEPARTMENT:
- ies->q_dept = (char *)data + 2;
- break;
- case DUNDI_IE_ORGANIZATION:
- ies->q_org = (char *)data + 2;
- break;
- case DUNDI_IE_LOCALITY:
- ies->q_locality = (char *)data + 2;
- break;
- case DUNDI_IE_STATE_PROV:
- ies->q_stateprov = (char *)data + 2;
- break;
- case DUNDI_IE_COUNTRY:
- ies->q_country = (char *)data + 2;
- break;
- case DUNDI_IE_EMAIL:
- ies->q_email = (char *)data + 2;
- break;
- case DUNDI_IE_PHONE:
- ies->q_phone = (char *)data + 2;
- break;
- case DUNDI_IE_IPADDR:
- ies->q_ipaddr = (char *)data + 2;
- break;
- case DUNDI_IE_ENCDATA:
- /* Recalculate len as the remainder of the message, regardless of
- theoretical length */
- len = datalen - 2;
- if ((len > 16) && !(len % 16)) {
- ies->encblock = (struct dundi_encblock *)(data + 2);
- ies->enclen = len - 16;
- } else {
- snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted data length %d\n", len);
- errorf(tmp);
- }
- break;
- case DUNDI_IE_SHAREDKEY:
- if (len == 128) {
- ies->encsharedkey = (unsigned char *)(data + 2);
- } else {
- snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted shared key length %d\n", len);
- errorf(tmp);
- }
- break;
- case DUNDI_IE_SIGNATURE:
- if (len == 128) {
- ies->encsig = (unsigned char *)(data + 2);
- } else {
- snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted signature length %d\n", len);
- errorf(tmp);
- }
- break;
- case DUNDI_IE_CACHEBYPASS:
- ies->cbypass = 1;
- break;
- default:
- snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie), ie, len);
- outputf(tmp);
- }
- /* Overwrite information element with 0, to null terminate previous portion */
- data[0] = 0;
- datalen -= (len + 2);
- data += (len + 2);
- }
- /* Null-terminate last field */
- *data = '\0';
- if (datalen) {
- errorf("Invalid information element contents, strange boundary\n");
- return -1;
- }
- return 0;
-}
diff --git a/1.2-netsec/pbx/dundi-parser.h b/1.2-netsec/pbx/dundi-parser.h
deleted file mode 100644
index 62bbf4384..000000000
--- a/1.2-netsec/pbx/dundi-parser.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Distributed Universal Number Discovery (DUNDi)
- *
- * Copyright (C) 2004 - 2005, Digium Inc.
- *
- * Written by Mark Spencer <markster@digium.com>
- *
- * This program is Free Software distributed under the terms of
- * of the GNU General Public License.
- */
-
-#ifndef _DUNDI_PARSER_H
-#define _DUNDI_PARSER_H
-
-#include "asterisk/dundi.h"
-#include "asterisk/aes.h"
-
-#define DUNDI_MAX_STACK 512
-#define DUNDI_MAX_ANSWERS 100
-
-struct dundi_ies {
- dundi_eid *eids[DUNDI_MAX_STACK + 1];
- int eid_direct[DUNDI_MAX_STACK + 1];
- dundi_eid *reqeid;
- int eidcount;
- char *called_context;
- char *called_number;
- struct dundi_answer *answers[DUNDI_MAX_ANSWERS + 1];
- struct dundi_hint *hint;
- int anscount;
- int ttl;
- int version;
- int expiration;
- int unknowncmd;
- unsigned char *pubkey;
- int cause;
- char *q_dept;
- char *q_org;
- char *q_locality;
- char *q_stateprov;
- char *q_country;
- char *q_email;
- char *q_phone;
- char *q_ipaddr;
- char *causestr;
- unsigned char *encsharedkey;
- unsigned char *encsig;
- unsigned long keycrc32;
- struct dundi_encblock *encblock;
- int enclen;
- int cbypass;
-};
-
-struct dundi_ie_data {
- int pos;
- unsigned char buf[8192];
-};
-
-/* Choose a different function for output */
-extern void dundi_set_output(void (*output)(const char *data));
-/* Choose a different function for errors */
-extern void dundi_set_error(void (*output)(const char *data));
-extern void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);
-
-extern const char *dundi_ie2str(int ie);
-
-extern int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen);
-extern int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin);
-extern int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value);
-extern int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value);
-extern int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, char *str);
-extern int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid);
-extern int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, char *desc);
-extern int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, char *data);
-extern int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, char *desc);
-extern int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen);
-extern int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat);
-extern int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie);
-extern int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen);
-extern char *dundi_eid_to_str(char *s, int maxlen, dundi_eid *eid);
-extern char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid);
-extern int dundi_str_to_eid(dundi_eid *eid, char *s);
-extern int dundi_str_short_to_eid(dundi_eid *eid, char *s);
-extern int dundi_eid_zero(dundi_eid *eid);
-extern int dundi_eid_cmp(dundi_eid *eid1, dundi_eid *eid2);
-extern char *dundi_flags2str(char *s, int maxlen, int flags);
-extern char *dundi_hint2str(char *s, int maxlen, int flags);
-#endif
diff --git a/1.2-netsec/pbx/pbx_ael.c b/1.2-netsec/pbx/pbx_ael.c
deleted file mode 100644
index 4b758a61b..000000000
--- a/1.2-netsec/pbx/pbx_ael.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Compile symbolic Asterisk Extension Logic into Asterisk extensions
- *
- */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/pbx.h"
-#include "asterisk/config.h"
-#include "asterisk/module.h"
-#include "asterisk/logger.h"
-#include "asterisk/cli.h"
-#include "asterisk/callerid.h"
-
-struct stringlink {
- struct stringlink *next;
- char data[0];
-};
-
-#define FILLIN_BREAK 1
-#define FILLIN_CONTINUE 2
-
-struct fillin {
- struct fillin *next;
- char exten[AST_MAX_EXTENSION];
- int priority;
- int type;
-};
-
-#ifdef __AST_DEBUG_MALLOC
-static void FREE(void *ptr)
-{
- free(ptr);
-}
-#else
-#define FREE free
-#endif
-
-#define DEBUG_READ (1 << 0)
-#define DEBUG_TOKENS (1 << 1)
-#define DEBUG_MACROS (1 << 2)
-#define DEBUG_CONTEXTS (1 << 3)
-
-static int aeldebug = 0;
-
-static char *dtext = "Asterisk Extension Language Compiler";
-static char *config = "extensions.ael";
-static char *registrar = "pbx_ael";
-
-static char *__grab_token(char *src, const char *filename, int lineno, int link)
-{
- char *c;
- char *b;
- char *a;
- int level = 0;
- char *ret;
-#if 0
- if (aeldebug || DEBUG_TOKENS)
- ast_verbose("Searching for token in '%s'!\n", src);
-#endif
- c = src;
- while(*c) {
- if ((*c == '\\')) {
- c++;
- if (!*c)
- c--;
- } else {
- if ((*c == '{') || (*c == '(')) {
- level++;
- } else if ((*c == '}') || (*c == ')')) {
- if (level)
- level--;
- else
- ast_log(LOG_WARNING, "Syntax error at line %d of '%s', too many closing braces!\n", lineno, filename);
- } else if ((*c == ';') && !level) {
- /* Got a token! */
- *c = '\0';
- b = c;
- b--;
- c++;
- while((b > src) && (*b < 33)) {
- *b = '\0';
- b--;
- }
- a = ast_skip_blanks(src);
- if (link) {
- ret = malloc(strlen(a) + sizeof(struct stringlink) + 1);
- if (ret)
- strcpy(ret + sizeof(struct stringlink), a);
- } else
- ret = strdup(a);
- /* Save remainder */
- memmove(src, c, strlen(c) + 1);
- return ret;
- }
- }
- c++;
- }
- return NULL;
-}
-
-static char *grab_token(char *src, const char *filename, int lineno)
-{
- return __grab_token(src, filename, lineno, 0);
-}
-
-static struct stringlink *arg_parse(char *args, const char *filename, int lineno)
-{
- struct stringlink *cur, *prev=NULL, *root=NULL;
- if (args) {
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("Parsing args '%s'!\n", args);
- if (args[0] == '{') {
- /* Strip mandatory '}' from end */
- args[strlen(args) - 1] = '\0';
- while ((cur = (struct stringlink *)__grab_token(args + 1, filename, lineno, 1))) {
- cur->next = NULL;
- if (prev)
- prev->next = cur;
- else
- root = cur;
- prev = cur;
- }
- } else if (*args) {
- root = malloc(sizeof(struct stringlink) + strlen(args) + 1);
- if (root) {
- strcpy(root->data, args);
- root->next = NULL;
- }
- }
- }
- return root;
-}
-
-static char *grab_else(char *args, const char *filename, int lineno)
-{
- char *ret = NULL;
- int level=0;
- char *c;
- if (args) {
- if (args[0] == '{') {
- c = args;
- while(*c) {
- if (*c == '{')
- level++;
- else if (*c == '}') {
- level--;
- if (!level) {
- c++;
- while(*c && (*c < 33)) { *c = '\0'; c++; };
- if (!strncasecmp(c, "else", 4) &&
- ((c[4] == '{') || (c[4] < 33))) {
- /* Ladies and gentlemen, we have an else clause */
- *c = '\0';
- c += 4;
- c = ast_skip_blanks(c);
- ret = c;
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("Returning else clause '%s'\n", c);
- }
- break;
- }
- }
- c++;
- }
- }
- }
- return ret;
-}
-
-static struct stringlink *param_parse(char *parms, const char *macro, const char *filename, int lineno)
-{
- char *s, *e;
- struct stringlink *root = NULL, *prev=NULL, *cur;
- if (!parms || !*parms)
- return NULL;
- if (*parms != '(') {
- ast_log(LOG_NOTICE, "Syntax error in parameter list for macro '%s' at about line %d of %s: Expecting '(' but got '%c'\n", macro, lineno, filename, *parms);
- return NULL;
- }
- s = parms + 1;
- while(*s) {
- s = ast_skip_blanks(s);
- e = s;
- while(*e && (*e != ')') && (*e != ',')) {
- if (*e < 33)
- *e = '\0';
- e++;
- }
- if (*e) {
- /* Strip token */
- *e = '\0';
- e++;
- /* Skip over whitespace */
- e = ast_skip_blanks(e);
- /* Link */
- cur = malloc(strlen(s) + sizeof(struct stringlink) + 1);
- if (cur) {
- cur->next = NULL;
- strcpy(cur->data, s);
- if (prev)
- prev->next = cur;
- else
- root = cur;
- prev = cur;
- }
- s = e;
- }
- }
- return root;
-}
-
-static void arg_free(struct stringlink *cur)
-{
- struct stringlink *last;
- while(cur) {
- last = cur;
- cur = cur->next;
- free(last);
- }
-}
-
-static void handle_globals(struct stringlink *vars)
-{
- while(vars) {
- pbx_builtin_setvar(NULL, vars->data);
- vars = vars->next;
- }
-}
-
-static struct stringlink *split_token(char *token, const char *filename, int lineno)
-{
- char *args, *p;
- struct stringlink *argv;
- args = token;
- while (*args && (*args > 32) && (*args != '{') && (*args != '(')) args++;
- if (*args) {
- p = args;
- args = ast_skip_blanks(args);
- if (*args != '(') {
- *p = '\0';
- } else {
- while (*args && (*args != ')')) args++;
- if (*args == ')') {
- args++;
- args = ast_skip_blanks(args);
- }
- }
- if (!*args)
- args = NULL;
- } else args = NULL;
- argv = arg_parse(args, filename, lineno);
- if (args)
- *args = '\0';
- return argv;
-}
-
-static int matches_keyword(const char *data, const char *keyword)
-{
- char c;
- if (!strncasecmp(data, keyword, strlen(keyword))) {
- c = data[strlen(keyword)];
- if ((c < 33) || (c == '(') || (c == '{'))
- return 1;
- }
- return 0;
-}
-
-static struct stringlink *split_params(char *token, const char *filename, int lineno)
-{
- char *params;
- struct stringlink *paramv;
- params = token;
- while(*params && (*params > 32) && (*params != '(')) params++;
- if (*params) {
- if (*params != '(') {
- *params = '\0';
- params++;
- params = ast_skip_blanks(params);
- }
- if (!*params)
- params = NULL;
- } else params = NULL;
- paramv = param_parse(params, token, filename, lineno);
- if (params)
- *params = '\0';
- return paramv;
-}
-
-static const char *get_case(char *s, char **restout, int *pattern)
-{
- char *newcase=NULL;
- char *rest=NULL;
- if (!strncasecmp(s, "case", 4) && s[4] && ((s[4] < 33) || (s[4] == ':'))) {
- newcase = s + 4;
- newcase = ast_skip_blanks(newcase);
- rest = newcase;
- *pattern = 0;
- } else if (!strncasecmp(s, "pattern", 7) && s[7] && ((s[7] < 33) || (s[7] == ':'))) {
- newcase = s + 8;
- newcase = ast_skip_blanks(newcase);
- rest = newcase;
- *pattern = 1;
- } else if (!strncasecmp(s, "default", 7) && ((s[7] < 33) || (s[7] == ':'))) {
- newcase = ".";
- rest = s + 7;
- rest = ast_skip_blanks(rest);
- *pattern = 1;
- }
-
- if (rest) {
- while (*rest && (*rest > 32) && (*rest != ':')) rest++;
- if (*rest) {
- *rest = 0;
- rest++;
- while (*rest && ((*rest == ':') || (*rest < 33))) rest++;
- *restout = rest;
- } else {
- *restout = "";
- }
- } else
- *restout = s;
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("GETCASE: newcase is '%s', rest = '%s'\n", newcase, *restout);
- return newcase;
-}
-
-static void fillin_free(struct fillin *fillin)
-{
- struct fillin *cur, *next;
- cur = fillin;
- while(cur) {
- next = cur->next;
- free(cur);
- cur = next;
- }
-}
-
-static void fillin_process(struct ast_context *con, struct fillin *fillin, const char *filename, int lineno, const char *breakexten, int breakprio, const char *contexten, int contprio)
-{
- struct fillin *cur;
- char *app;
- char mdata[AST_MAX_EXTENSION + 20];
- cur = fillin;
- while(cur) {
- if (cur->type == FILLIN_BREAK) {
- if (breakexten && breakprio) {
- app = "Goto";
- snprintf(mdata, sizeof(mdata), "%s|%d", breakexten, breakprio);
- } else {
- app = "NoOp";
- snprintf(mdata, sizeof(mdata), "Invalid break");
- ast_log(LOG_NOTICE, "Ignoring inappropriate break around line %d of %s\n", lineno, filename);
- }
- if (ast_add_extension2(con, 0, cur->exten, cur->priority, NULL, NULL, app, strdup(mdata), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of break '%s'\n", cur->priority, cur->exten);
- } else if (cur->type == FILLIN_CONTINUE) {
- if (contexten && contprio) {
- app = "Goto";
- snprintf(mdata, sizeof(mdata), "%s|%d", contexten, contprio);
- } else {
- app = "NoOp";
- snprintf(mdata, sizeof(mdata), "Invalid continue");
- ast_log(LOG_NOTICE, "Ignoring inappropriate continue around line %d of %s\n", lineno, filename);
- }
- if (ast_add_extension2(con, 0, cur->exten, cur->priority, NULL, NULL, app, strdup(mdata), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of continue '%s'\n", cur->priority, cur->exten);
- } else {
- ast_log(LOG_WARNING, "Whoa, unknown fillin type '%d'\n", cur->type);
- }
- cur = cur->next;
- }
-}
-
-static int match_assignment(char *variable, char **value)
-{
- char *c;
- char *ws;
- int inpar = 0;
- c = variable;
-
- while (*c) {
- if(*c == ')' && (inpar > 0)) {
- inpar--;
- } else if(*c == '(' && (inpar >= 0)) {
- inpar++;
- } else if(*c == '=' && (inpar == 0)) {
- break;
- }
- c++;
- }
- ws = c;
- c = ast_skip_blanks(c);
- if (*c == '=') {
- *ws = '\0';
- *c = '\0';
- c++;
- c = ast_skip_blanks(c);
- *value = c;
- return 1;
- }
- return 0;
-}
-
-static int matches_label(char *data, char **rest)
-{
- char last = 0;
- char *start = data;
- while (*data > 32) {
- last = *data;
- data++;
- }
- if (last != ':') {
- data = ast_skip_blanks(data);
- last = *data;
- data++;
- }
- if (last == ':') {
- *rest = data;
- /* Go back and trim up the label */
- while(*start && ((*start > 32) && (*start != ':'))) start++;
- *start = '\0';
- return 1;
- }
- return 0;
-}
-
-static char *argument_end(char *str)
-{
- int level=0;
- while(*++str) {
- switch(*str) {
- case '(':
- level++;
- break;
- case ')':
- if(level)
- level--;
- else
- return str;
- break;
- default:
- break;
- }
- }
- return NULL;
-}
-
-static int build_step(const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label);
-static int __build_step(const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label)
-{
- char *app;
- char *args;
- char *c;
- char *margs=NULL;
- char *oargs;
- char *rest;
- const char *curcase, *newcase;
- struct stringlink *swargs, *cur;
- int cpos;
- int mlen;
- int pattern = 0;
- struct fillin *fillin;
-
- data = ast_skip_blanks(data);
- if (matches_label(data, &c)) {
- *label = data;
- data = c;
- data = ast_skip_blanks(data);
- }
- if (ast_strlen_zero(data))
- return 0;
- if (matches_keyword(data, "switch")) {
- fillin = NULL;
- /* Switch */
- args = data + strlen("switch");
- while ((*args < 33) && (*args != '(')) args++;
- if ((*args == '(') && (c = argument_end(args))) {
- args++;
- *c = '\0';
- c++;
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--SWITCH on : %s\n", args);
- mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
- margs = alloca(mlen);
- app = "Goto";
- sprintf(margs, "sw-%d-%s|1", *pos, args);
- ast_process_quotes_and_slashes(margs, ',', '|');
- oargs = args;
- args = margs;
- if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- else {
- *label = NULL;
- (*pos)++;
- }
- app = "NoOp";
- sprintf(margs, "Finish switch-%d", *pos - 1);
- if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- else {
- *label = NULL;
- (*pos)++;
- }
- c = ast_skip_blanks(c);
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("ARG Parsing '%s'\n", c);
- swargs = arg_parse(c, filename, lineno);
- cur = swargs;
- curcase = NULL;
- while(cur) {
- if ((newcase = get_case(cur->data, &rest, &pattern))) {
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--NEWCASE: '%s'!\n", newcase);
- if (curcase) {
- /* Handle fall through */
- char tmp[strlen(newcase) + strlen(name) + 40];
- sprintf(tmp, "sw-%d-%s|%d", *pos - 2, newcase, 1);
- ast_add_extension2(con, 0, margs, cpos, NULL, NULL, "Goto", strdup(tmp), FREE, registrar);
- }
- curcase = newcase;
- cpos = 1;
- if (pattern)
- snprintf(margs, mlen, "_sw-%d-%s", *pos - 2, curcase);
- else
- snprintf(margs, mlen, "sw-%d-%s", *pos - 2, curcase);
- if (!strcasecmp(rest, "break")) {
- char tmp[strlen(exten) + 10];
- sprintf(tmp, "%s|%d", exten, *pos - 1);
- ast_add_extension2(con, 0, exten, cpos, *label, NULL, "Goto", strdup(tmp), FREE, registrar);
- curcase = NULL;
- *label = NULL;
- } else
- build_step("switch", margs, filename, lineno, con, margs, &cpos, rest, &fillin, label);
- } else if (curcase) {
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("Building statement from '%s'\n", rest);
- if (!strcasecmp(rest, "break")) {
- char tmp[strlen(exten) + 10];
- sprintf(tmp, "%s|%d", exten, *pos - 1);
- ast_add_extension2(con, 0, margs, cpos, *label, NULL, "Goto", strdup(tmp), FREE, registrar);
- curcase = NULL;
- *label = NULL;
- } else
- build_step("switch", margs, filename, lineno, con, margs, &cpos, rest, &fillin, label);
- } else
- ast_log(LOG_WARNING, "Unreachable code in switch at about line %d of %s\n", lineno, filename);
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--SWARG: %s\n", cur->data);
- cur = cur->next;
- }
- /* Can't do anything with these */
- fillin_process(con, fillin, filename, lineno, NULL, 0, NULL, 0);
- fillin_free(fillin);
- arg_free(swargs);
- } else
- ast_log(LOG_WARNING, "Syntax error in switch declaration in %s around line %d!\n", filename, lineno);
-
- } else if (matches_keyword(data, "if")) {
- /* If... */
- args = data + strlen("if");
- while ((*args < 33) && (*args != '(')) args++;
- if ((*args == '(') && (c = argument_end(args))) {
- int ifblock;
- int ifstart;
- int elsestart;
- int ifend;
- int ifskip;
- char *elses;
- char *iflabel;
- args++;
- *c = '\0';
- c++;
- c = ast_skip_blanks(c);
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--IF on : '%s' : '%s'\n", args, c);
- mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
- margs = alloca(mlen);
- /* Remember where the ifblock starts, and skip over */
- ifblock = (*pos)++;
- iflabel = *label;
- *label = NULL;
- /* Remember where the start of the ifblock is */
- ifstart = *pos;
- snprintf(margs, mlen, "if-%s-%d", name, ifblock);
- /* Now process the block of the if */
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("Searching for elses in '%s'\n", c);
- elses = grab_else(c, filename, lineno);
- build_step("if", margs, filename, lineno, con, exten, pos, c, fillout, label);
- if (elses) {
- /* Reserve a goto to exit the if */
- ifskip = *pos;
- (*pos)++;
- elsestart = *pos;
- build_step("else", margs, filename, lineno, con, exten, pos, elses, fillout, label);
- } else {
- elsestart = *pos;
- ifskip = 0;
- }
- ifend = *pos;
- (*pos)++;
- app = "NoOp";
- snprintf(margs, mlen, "Finish if-%s-%d", name, ifblock);
- if (ast_add_extension2(con, 0, exten, ifend, *label, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- *label = NULL;
- app = "GotoIf";
- snprintf(margs, mlen, "$[ %s ]?%d:%d", args, ifstart, elsestart);
- if (ast_add_extension2(con, 0, exten, ifblock, iflabel, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- if (ifskip) {
- /* Skip as appropriate around else clause */
- snprintf(margs, mlen, "%d", ifend);
- if (ast_add_extension2(con, 0, exten, ifskip, NULL, NULL, "Goto", strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- }
- } else
- ast_log(LOG_WARNING, "Syntax error in if declaration in %s around line %d!\n", filename, lineno);
- } else if (matches_keyword(data, "while")) {
- /* While... */
- fillin = NULL;
- args = data + strlen("while");
- while ((*args < 33) && (*args != '(')) args++;
- if ((*args == '(') && (c = argument_end(args))) {
- int whileblock;
- int whilestart;
- int whileend;
- char *whilelabel;
- args++;
- *c = '\0';
- c++;
- c = ast_skip_blanks(c);
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--WHILE on : '%s' : '%s'\n", args, c);
- mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
- margs = alloca(mlen);
- /* Remember where to put the conditional, and keep its position */
- whilestart = (*pos);
- whilelabel = *label;
- *label = NULL;
- (*pos)++;
- /* Remember where the whileblock starts */
- whileblock = (*pos);
- snprintf(margs, mlen, "while-%s-%d", name, whilestart);
- build_step("while", margs, filename, lineno, con, exten, pos, c, &fillin, label);
- /* Close the loop */
- app = "Goto";
- snprintf(margs, mlen, "%d", whilestart);
- if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- *label = NULL;
- whileend = (*pos);
- /* Place trailer */
- app = "NoOp";
- snprintf(margs, mlen, "Finish while-%s-%d", name, whilestart);
- if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- *label = NULL;
- app = "GotoIf";
- snprintf(margs, mlen, "$[ %s ]?%d:%d", args, whileblock, whileend);
- if (ast_add_extension2(con, 0, exten, whilestart, whilelabel, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- fillin_process(con, fillin, filename, lineno, exten, whileend, exten, whilestart);
- fillin_free(fillin);
- } else
- ast_log(LOG_WARNING, "Syntax error in while declaration in %s around line %d!\n", filename, lineno);
- } else if (matches_keyword(data, "jump")) {
- char *p;
- /* Jump... */
- fillin = NULL;
- args = data + strlen("jump");
- args = ast_skip_blanks(args);
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--JUMP to : '%s'\n", args);
- p = strchr(args, ',');
- if (p) {
- *p = '\0';
- p++;
- } else
- p = "1";
- c = strchr(args, '@');
- if (c) {
- *c = '\0';
- c++;
- }
- mlen = strlen(exten) + 128 + strlen(args) + strlen(name) + (c ? strlen(c) : 0);
- margs = alloca(mlen);
- if (c)
- snprintf(margs, mlen, "%s|%s|%s", c,args, p);
- else
- snprintf(margs, mlen, "%s|%s", args, p);
- app = "Goto";
- if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- *label = NULL;
- } else if (matches_keyword(data, "goto")) {
- /* Jump... */
- fillin = NULL;
- args = data + strlen("goto");
- args = ast_skip_blanks(args);
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--GOTO to : '%s'\n", args);
- app = "Goto";
- if (args[0] == '(' && args[strlen(args) - 1] == ')') {
- args[0] = '\0';
- args++;
- args[strlen(args) - 1] = '\0';
- }
- if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(args), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- *label = NULL;
- } else if (matches_keyword(data, "for")) {
- /* While... */
- fillin = NULL;
- args = data + strlen("for");
- while ((*args < 33) && (*args != '(')) args++;
- if ((*args == '(') && (c = argument_end(args))) {
- int forblock;
- int forprep;
- int forstart;
- int forend;
- struct stringlink *fields;
- char *tmp;
- char *forlabel = NULL;
- args++;
- *c = '\0';
- c++;
- c = ast_skip_blanks(c);
- /* Parse arguments first */
- tmp = alloca(strlen(args) + 10);
- if (tmp) {
- snprintf(tmp, strlen(args) + 10, "{%s;}", args);
- fields = arg_parse(tmp, filename, lineno);
- } else
- fields = NULL;
- if (fields && fields->next && fields->next->next) {
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("--FOR ('%s' ; '%s' ; '%s') : '%s'\n", fields->data, fields->next->data, fields->next->next->data, c);
- mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
- margs = alloca(mlen);
- forprep = *pos;
- snprintf(margs, mlen, "for-%s-%d", name, forprep);
- fillin = NULL;
- build_step("while", margs, filename, lineno, con, exten, pos, fields->data, &fillin, label);
- /* Remember where to put the conditional, and keep its position */
- forstart = (*pos);
- forlabel = *label;
- (*pos)++;
- *label = NULL;
- /* Remember where the whileblock starts */
- forblock = (*pos);
- build_step("for", margs, filename, lineno, con, exten, pos, fields->next->next->data, &fillin, label);
- build_step("for", margs, filename, lineno, con, exten, pos, c, &fillin, label);
- /* Close the loop */
- app = "Goto";
- snprintf(margs, mlen, "%d", forstart);
- if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- *label = NULL;
- forend = (*pos);
- /* Place trailer */
- app = "NoOp";
- snprintf(margs, mlen, "Finish for-%s-%d", name, forprep);
- if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- *label = NULL;
- app = "GotoIf";
- snprintf(margs, mlen, "$[ %s ]?%d:%d", fields->next->data, forblock, forend);
- if (ast_add_extension2(con, 0, exten, forstart, forlabel, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", forstart, what, name);
- fillin_process(con, fillin, filename, lineno, exten, forend, exten, forstart);
- fillin_free(fillin);
- } else
- ast_log(LOG_NOTICE, "Improper for declaration in %s around line %d!\n", filename, lineno);
- arg_free(fields);
- } else
- ast_log(LOG_WARNING, "Syntax error in for declaration in %s around line %d!\n", filename, lineno);
-
- } else if (!strcasecmp(data, "break") || !strcasecmp(data, "continue")) {
- struct fillin *fi;
- fi = malloc(sizeof(struct fillin));
- if (fi) {
- memset(fi, 0, sizeof(struct fillin));
- if (!strcasecmp(data, "break"))
- fi->type = FILLIN_BREAK;
- else
- fi->type = FILLIN_CONTINUE;
- ast_copy_string(fi->exten, exten, sizeof(fi->exten));
- fi->priority = (*pos)++;
- fi->next = *fillout;
- *fillout = fi;
- }
- } else if (match_assignment(data, &rest)) {
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("ASSIGN '%s' = '%s'\n", data, rest);
- mlen = strlen(rest) + strlen(data) + 20;
- margs = alloca(mlen);
- snprintf(margs, mlen, "%s=$[ %s ]", data, rest);
- app = "Set";
- if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(margs), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add assignment at priority '%d' of %s '%s'\n", *pos, what, name);
- else {
- *label = NULL;
- (*pos)++;
- }
- } else {
- app = data;
- args = app;
- while (*args && (*args > 32) && (*args != '(')) args++;
- if (*args != '(') {
- while(*args && (*args != '(')) { *args = '\0'; args++; };
- }
- if (*args == '(') {
- *args = '\0';
- args++;
- /* Got arguments, trim trailing ')' */
- c = args + strlen(args) - 1;
- while((c >= args) && (*c < 33) && (*c != ')')) { *c = '\0'; c--; };
- if ((c >= args) && (*c == ')')) *c = '\0';
- } else
- args = "";
- ast_process_quotes_and_slashes(args, ',', '|');
- if (app[0] == '&') {
- app++;
- margs = alloca(strlen(args) + strlen(app) + 10);
- sprintf(margs, "%s|%s", app, args);
- args = margs;
- app = "Macro";
- }
- if (aeldebug & DEBUG_TOKENS)
- ast_verbose("-- APP: '%s', ARGS: '%s'\n", app, args);
- if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
- else {
- (*pos)++;
- *label = NULL;
- }
- }
- return 0;
-}
-
-static int build_step(const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label)
-{
- struct stringlink *args, *cur;
- int res=0;
- struct fillin *fillin=NULL;
- int dropfill = 0;
- char *labelin = NULL;
- if (!fillout) {
- fillout = &fillin;
- dropfill = 1;
- }
- if (!label) {
- label = &labelin;
- };
- args = arg_parse(data, filename, lineno);
- cur = args;
- while(cur) {
- res |= __build_step(what, name, filename, lineno, con, exten, pos, cur->data, fillout, label);
- cur = cur->next;
- }
- arg_free(args);
- if (dropfill) {
- fillin_process(con, fillin, filename, lineno, NULL, 0, NULL, 0);
- fillin_free(fillin);
- }
- return res;
-}
-
-static int parse_catch(char *data, char **catch, char **rest)
-{
- /* Skip the word 'catch' */
- data += 5;
- data = ast_skip_blanks(data);
- /* Here's the extension */
- *catch = data;
- if (!*data)
- return 0;
- while (*data && (*data > 32)) data++;
- if (!*data)
- return 0;
- /* Trim any trailing spaces */
- *data = '\0';
- data++;
- data = ast_skip_blanks(data);
- if (!*data)
- return 0;
- *rest = data;
- return 1;
-}
-
-static void handle_macro(struct ast_context **local_contexts, struct stringlink *vars, const char *filename, int lineno)
-{
- struct stringlink *argv;
- struct stringlink *paramv;
- struct stringlink *cur;
- struct ast_context *con;
- struct fillin *fillin;
- char *catch, *rest;
- char name[256];
- int pos;
- int cpos;
-
- if (aeldebug & DEBUG_MACROS)
- ast_verbose("Root macro def is '%s'\n", vars->data);
- argv = split_token(vars->data, filename, lineno);
- paramv = split_params(vars->data, filename, lineno);
- if (aeldebug & DEBUG_MACROS)
- ast_verbose("Found macro '%s'\n", vars->data);
- snprintf(name, sizeof(name), "macro-%s", vars->data);
- con = ast_context_create(local_contexts, name, registrar);
- if (con) {
- pos = 1;
- cur = paramv;
- while(cur) {
- if (aeldebug & DEBUG_MACROS)
- ast_verbose(" PARAM => '%s'\n", cur->data);
- snprintf(name, sizeof(name), "%s=${ARG%d}", cur->data, pos);
- if (ast_add_extension2(con, 0, "s", pos, NULL, NULL, "Set", strdup(name), FREE, registrar))
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of macro '%s'\n", pos, vars->data);
- else
- pos++;
- cur = cur->next;
- }
- cur = argv;
- while(cur) {
- if (aeldebug & DEBUG_MACROS)
- ast_verbose(" STEP => '%s'\n", cur->data);
- if (matches_keyword(cur->data, "catch")) {
- if (aeldebug & DEBUG_MACROS)
- ast_verbose("--CATCH: '%s'\n", cur->data);
- if (parse_catch(cur->data, &catch, &rest)) {
- cpos = 1;
- build_step("catch", catch, filename, lineno, con, catch, &cpos, rest, NULL, NULL);
- } else
- ast_log(LOG_NOTICE, "Parse error for catch at about line %d of %s\n", lineno, filename);
- } else {
- fillin = NULL;
- build_step("macro", vars->data, filename, lineno, con, "s", &pos, cur->data, NULL, NULL);
- }
- cur = cur->next;
- }
- } else
- ast_log(LOG_WARNING, "Unable to create context '%s'\n", name);
- arg_free(paramv);
- arg_free(argv);
- if (vars->next)
- ast_log(LOG_NOTICE, "Ignoring excess tokens in macro definition around line %d of %s!\n", lineno, filename);
-}
-
-static int matches_extension(char *exten, char **extout)
-{
- char *c;
- *extout = NULL;
- c = exten;
- while(*c && (*c > 32)) c++;
- if (*c) {
- *c = '\0';
- c++;
- c = ast_skip_blanks(c);
- if (*c) {
- if (*c == '=') {
- *c = '\0';
- c++;
- if (*c == '>')
- c++;
- c = ast_skip_blanks(c);
- *extout = c;
- return 1;
- }
- }
- }
- return 0;
-}
-
-static void parse_keyword(char *s, char **o)
-{
- char *c;
- c = s;
- while((*c) && (*c > 32)) c++;
- if (*c) {
- *c = '\0';
- c++;
- c = ast_skip_blanks(c);
- *o = c;
- } else
- *o = NULL;
-}
-
-static void handle_context(struct ast_context **local_contexts, struct stringlink *vars, const char *filename, int lineno)
-{
- struct stringlink *argv;
- struct stringlink *cur2;
- struct stringlink *argv2;
- struct stringlink *cur;
- struct ast_context *con;
- char *rest;
- char *c;
- char name[256];
- int pos;
-
- if (aeldebug & DEBUG_CONTEXTS)
- ast_verbose("Root context def is '%s'\n", vars->data);
- argv = split_token(vars->data, filename, lineno);
- if (aeldebug & DEBUG_CONTEXTS)
- ast_verbose("Found context '%s'\n", vars->data);
- snprintf(name, sizeof(name), "%s", vars->data);
- con = ast_context_create(local_contexts, name, registrar);
- if (con) {
- cur = argv;
- while(cur) {
- if (matches_keyword(cur->data, "includes")) {
- if (aeldebug & DEBUG_CONTEXTS)
- ast_verbose("--INCLUDES: '%s'\n", cur->data);
- parse_keyword(cur->data, &rest);
- if (rest) {
- argv2 = arg_parse(rest, filename, lineno);
- cur2 = argv2;
- while(cur2) {
- ast_context_add_include2(con, cur2->data, registrar);
- cur2 = cur2->next;
- }
- arg_free(argv2);
- }
- } else if (matches_keyword(cur->data, "ignorepat")) {
- if (aeldebug & DEBUG_CONTEXTS)
- ast_verbose("--IGNOREPAT: '%s'\n", cur->data);
- parse_keyword(cur->data, &rest);
- if (rest) {
- argv2 = arg_parse(rest, filename, lineno);
- cur2 = argv2;
- while(cur2) {
- ast_context_add_ignorepat2(con, cur2->data, registrar);
- cur2 = cur2->next;
- }
- arg_free(argv2);
- }
- } else if (matches_keyword(cur->data, "switches") || matches_keyword(cur->data, "eswitches")) {
- if (aeldebug & DEBUG_CONTEXTS)
- ast_verbose("--[E]SWITCH: '%s'\n", cur->data);
- parse_keyword(cur->data, &rest);
- if (rest) {
- argv2 = arg_parse(rest, filename, lineno);
- cur2 = argv2;
- while(cur2) {
- c = strchr(cur2->data, '/');
- if (c) {
- *c = '\0';
- c++;
- } else
- c = "";
- ast_context_add_switch2(con, cur2->data, c, (cur->data[0] == 'e'), registrar);
- cur2 = cur2->next;
- }
- arg_free(argv2);
- }
- } else if (matches_extension(cur->data, &rest)) {
- if (aeldebug & DEBUG_CONTEXTS)
- ast_verbose("Extension: '%s' => '%s'\n", cur->data, rest);
- pos = 1;
- build_step("extension", cur->data, filename, lineno, con, cur->data, &pos, rest, NULL, NULL);
- }
- cur = cur->next;
- }
- } else
- ast_log(LOG_WARNING, "Unable to create context '%s'\n", name);
- arg_free(argv);
- if (vars->next)
- ast_log(LOG_NOTICE, "Ignoring excess tokens in macro definition around line %d of %s!\n", lineno, filename);
-}
-
-static int handle_root_token(struct ast_context **local_contexts, char *token, int level, const char *filename, int lineno)
-{
- struct stringlink *argv, *cur;
- argv = split_token(token, filename, lineno);
- if (aeldebug & DEBUG_TOKENS) {
- ast_verbose("Found root token '%s' at level %d (%s:%d)!\n", token, level, filename, lineno);
- cur = argv;
- while(cur) {
- ast_verbose(" ARG => '%s'\n", cur->data);
- cur = cur->next;
- }
- }
- if (!strcasecmp(token, "globals")) {
- handle_globals(argv);
- } else if (!strcasecmp(token, "macro")) {
- handle_macro(local_contexts, argv, filename, lineno);
- } else if (!strcasecmp(token, "context")) {
- handle_context(local_contexts, argv, filename, lineno);
- } else {
- ast_log(LOG_NOTICE, "Unknown root token '%s'\n", token);
- }
- arg_free(argv);
- return 0;
-}
-
-
-static int ast_ael_compile(struct ast_context **local_contexts, const char *filename)
-{
- char *rfilename;
- char *buf, *tbuf;
- int bufsiz;
- FILE *f;
- char *c;
- char *token;
- int lineno=0;
-
- if (filename[0] == '/')
- rfilename = (char *)filename;
- else {
- rfilename = alloca(strlen(filename) + strlen(ast_config_AST_CONFIG_DIR) + 2);
- sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, filename);
- }
-
- f = fopen(rfilename, "r");
- if (!f) {
- ast_log(LOG_WARNING, "Unable to open '%s': %s\n", rfilename, strerror(errno));
- return -1;
- }
- buf = malloc(4096);
- if (!buf) {
- ast_log(LOG_WARNING, "Out of memory!\n");
- fclose(f);
- return -1;
- }
- buf[0] = 0;
- bufsiz = 4096;
- while(!feof(f)) {
- if (bufsiz - strlen(buf) < 2048) {
- bufsiz += 4096;
- tbuf = realloc(buf, bufsiz);
- if (tbuf) {
- buf = tbuf;
- } else {
- free(buf);
- ast_log(LOG_WARNING, "Out of memory!\n");
- fclose(f);
- }
- }
- if (fgets(buf + strlen(buf), bufsiz - strlen(buf), f)) {
- lineno++;
- while(*buf && buf[strlen(buf) - 1] < 33)
- buf[strlen(buf) - 1] = '\0';
- c = strstr(buf, "//");
- if (c)
- *c = '\0';
- if (*buf) {
- if (aeldebug & DEBUG_READ)
- ast_verbose("Newly composed line '%s'\n", buf);
- while((token = grab_token(buf, filename, lineno))) {
- handle_root_token(local_contexts, token, 0, filename, lineno);
- free(token);
- }
- }
- }
- };
- free(buf);
- fclose(f);
- return 0;
-}
-
-static int pbx_load_module(void)
-{
- struct ast_context *local_contexts=NULL, *con;
- ast_ael_compile(&local_contexts, config);
- ast_merge_contexts_and_delete(&local_contexts, registrar);
- for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
- ast_context_verify_includes(con);
-
- return 0;
-}
-
-/* CLI interface */
-static int ael_debug_read(int fd, int argc, char *argv[])
-{
- aeldebug |= DEBUG_READ;
- return 0;
-}
-
-static int ael_debug_tokens(int fd, int argc, char *argv[])
-{
- aeldebug |= DEBUG_TOKENS;
- return 0;
-}
-
-static int ael_debug_macros(int fd, int argc, char *argv[])
-{
- aeldebug |= DEBUG_MACROS;
- return 0;
-}
-
-static int ael_debug_contexts(int fd, int argc, char *argv[])
-{
- aeldebug |= DEBUG_CONTEXTS;
- return 0;
-}
-
-static int ael_no_debug(int fd, int argc, char *argv[])
-{
- aeldebug = 0;
- return 0;
-}
-
-static int ael_reload(int fd, int argc, char *argv[])
-{
- ast_context_destroy(NULL, registrar);
- return (pbx_load_module());
-}
-
-static struct ast_cli_entry ael_cli[] = {
- { { "ael", "reload", NULL }, ael_reload, "Reload AEL configuration"},
- { { "ael", "debug", "read", NULL }, ael_debug_read, "Enable AEL read debug"},
- { { "ael", "debug", "tokens", NULL }, ael_debug_tokens, "Enable AEL tokens debug"},
- { { "ael", "debug", "macros", NULL }, ael_debug_macros, "Enable AEL macros debug"},
- { { "ael", "debug", "contexts", NULL }, ael_debug_contexts, "Enable AEL contexts debug"},
- { { "ael", "no", "debug", NULL }, ael_no_debug, "Disable AEL debug messages"},
-};
-
-/*
- * Standard module functions ...
- */
-int unload_module(void)
-{
- ast_context_destroy(NULL, registrar);
- ast_cli_unregister_multiple(ael_cli, sizeof(ael_cli)/ sizeof(ael_cli[0]));
- return 0;
-}
-
-
-int load_module(void)
-{
- ast_cli_register_multiple(ael_cli, sizeof(ael_cli)/ sizeof(ael_cli[0]));
- return (pbx_load_module());
-}
-
-int reload(void)
-{
- ast_context_destroy(NULL, registrar);
- return pbx_load_module();
-}
-
-int usecount(void)
-{
- return 0;
-}
-
-char *description(void)
-{
- return dtext;
-}
-
-char *key(void)
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/pbx/pbx_config.c b/1.2-netsec/pbx/pbx_config.c
deleted file mode 100644
index 42e43470a..000000000
--- a/1.2-netsec/pbx/pbx_config.c
+++ /dev/null
@@ -1,1831 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Populate and remember extensions from static config file
- *
- *
- */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/pbx.h"
-#include "asterisk/config.h"
-#include "asterisk/options.h"
-#include "asterisk/module.h"
-#include "asterisk/logger.h"
-#include "asterisk/cli.h"
-#include "asterisk/callerid.h"
-
-#ifdef __AST_DEBUG_MALLOC
-static void FREE(void *ptr)
-{
- free(ptr);
-}
-#else
-#define FREE free
-#endif
-
-static char *dtext = "Text Extension Configuration";
-static char *config = "extensions.conf";
-static char *registrar = "pbx_config";
-
-static int static_config = 0;
-static int write_protect_config = 1;
-static int autofallthrough_config = 0;
-static int clearglobalvars_config = 0;
-
-AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
-
-static struct ast_context *local_contexts = NULL;
-
-/*
- * Help for commands provided by this module ...
- */
-static char context_dont_include_help[] =
-"Usage: dont include <context> in <context>\n"
-" Remove an included context from another context.\n";
-
-static char context_remove_extension_help[] =
-"Usage: remove extension exten@context [priority]\n"
-" Remove an extension from a given context. If a priority\n"
-" is given, only that specific priority from the given extension\n"
-" will be removed.\n";
-
-static char context_add_include_help[] =
-"Usage: include <context> in <context>\n"
-" Include a context in another context.\n";
-
-static char save_dialplan_help[] =
-"Usage: save dialplan [/path/to/extension/file]\n"
-" Save dialplan created by pbx_config module.\n"
-"\n"
-"Example: save dialplan (/etc/asterisk/extensions.conf)\n"
-" save dialplan /home/markster (/home/markster/extensions.conf)\n";
-
-static char context_add_extension_help[] =
-"Usage: add extension <exten>,<priority>,<app>,<app-data> into <context>\n"
-" [replace]\n\n"
-" This command will add new extension into <context>. If there is an\n"
-" existence of extension with the same priority and last 'replace'\n"
-" arguments is given here we simply replace this extension.\n"
-"\n"
-"Example: add extension 6123,1,Dial,IAX/216.207.245.56/6123 into local\n"
-" Now, you can dial 6123 and talk to Markster :)\n";
-
-static char context_add_ignorepat_help[] =
-"Usage: add ignorepat <pattern> into <context>\n"
-" This command adds a new ignore pattern into context <context>\n"
-"\n"
-"Example: add ignorepat _3XX into local\n";
-
-static char context_remove_ignorepat_help[] =
-"Usage: remove ignorepat <pattern> from <context>\n"
-" This command removes an ignore pattern from context <context>\n"
-"\n"
-"Example: remove ignorepat _3XX from local\n";
-
-static char reload_extensions_help[] =
-"Usage: reload extensions.conf without reloading any other modules\n"
-" This command does not delete global variables unless\n"
-" clearglobalvars is set to yes in extensions.conf\n"
-"\n"
-"Example: extensions reload\n";
-
-/*
- * Implementation of functions provided by this module
- */
-
-/*!
- * REMOVE INCLUDE command stuff
- */
-static int handle_context_dont_include(int fd, int argc, char *argv[])
-{
- if (argc != 5)
- return RESULT_SHOWUSAGE;
-
- if (strcmp(argv[3], "in"))
- return RESULT_SHOWUSAGE;
-
- if (!ast_context_remove_include(argv[4], argv[2], registrar)) {
- ast_cli(fd, "We are not including '%s' in '%s' now\n",
- argv[2], argv[4]);
- return RESULT_SUCCESS;
- }
-
- ast_cli(fd, "Failed to remove '%s' include from '%s' context\n",
- argv[2], argv[4]);
- return RESULT_FAILURE;
-}
-
-static char *complete_context_dont_include(char *line, char *word,
- int pos, int state)
-{
- int which = 0;
-
- /*
- * Context completion ...
- */
- if (pos == 2) {
- struct ast_context *c;
-
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock context list\n");
- return NULL;
- }
-
- /* walk pbx_get_contexts ... */
- c = ast_walk_contexts(NULL);
- while (c) {
- struct ast_include *i;
-
- if (ast_lock_context(c)) {
- c = ast_walk_contexts(c);
- continue;
- }
-
- i = ast_walk_context_includes(c, NULL);
- while (i) {
- if (!strlen(word) ||
- !strncmp(ast_get_include_name(i), word, strlen(word))) {
- struct ast_context *nc;
- int already_served = 0;
-
- /* check if this include is already served or not */
-
- /* go through all contexts again till we reach actuall
- * context or already_served = 1
- */
- nc = ast_walk_contexts(NULL);
- while (nc && nc != c && !already_served) {
- if (!ast_lock_context(nc)) {
- struct ast_include *ni;
-
- ni = ast_walk_context_includes(nc, NULL);
- while (ni && !already_served) {
- if (!strcmp(ast_get_include_name(i),
- ast_get_include_name(ni)))
- already_served = 1;
- ni = ast_walk_context_includes(nc, ni);
- }
-
- ast_unlock_context(nc);
- }
- nc = ast_walk_contexts(nc);
- }
-
- if (!already_served) {
- if (++which > state) {
- char *res =
- strdup(ast_get_include_name(i));
- ast_unlock_context(c);
- ast_unlock_contexts();
- return res;
- }
- }
- }
- i = ast_walk_context_includes(c, i);
- }
-
- ast_unlock_context(c);
- c = ast_walk_contexts(c);
- }
-
- ast_unlock_contexts();
- return NULL;
- }
-
- /*
- * 'in' completion ... (complete only if previous context is really
- * included somewhere)
- */
- if (pos == 3) {
- struct ast_context *c;
- char *context, *dupline, *duplinet;
-
- if (state > 0) return NULL;
-
- /* take 'context' from line ... */
- if (!(dupline = strdup(line))) {
- ast_log(LOG_ERROR, "Out of free memory\n");
- return NULL;
- }
-
- duplinet = dupline;
- strsep(&duplinet, " "); /* skip 'dont' */
- strsep(&duplinet, " "); /* skip 'include' */
- context = strsep(&duplinet, " ");
-
- if (!context) {
- free(dupline);
- return NULL;
- }
-
- if (ast_lock_contexts()) {
- ast_log(LOG_WARNING, "Failed to lock contexts list\n");
- free(dupline);
- return NULL;
- }
-
- /* go through all contexts and check if is included ... */
- c = ast_walk_contexts(NULL);
- while (c) {
- struct ast_include *i;
- if (ast_lock_context(c)) {
- free(dupline);
- ast_unlock_contexts();
- return NULL;
- }
-
- i = ast_walk_context_includes(c, NULL);
- while (i) {
- /* is it our context? */
- if (!strcmp(ast_get_include_name(i), context)) {
- /* yes, it is, context is really included, so
- * complete "in" command
- */
- free(dupline);
- ast_unlock_context(c);
- ast_unlock_contexts();
- return strdup("in");
- }
- i = ast_walk_context_includes(c, i);
- }
- ast_unlock_context(c);
- c = ast_walk_contexts(c);
- }
- free(dupline);
- ast_unlock_contexts();
- return NULL;
- }
-
- /*
- * Context from which we removing include ...
- */
- if (pos == 4) {
- struct ast_context *c;
- char *context, *dupline, *duplinet, *in;
-
- if (!(dupline = strdup(line))) {
- ast_log(LOG_ERROR, "Out of free memory\n");
- return NULL;
- }
-
- duplinet = dupline;
-
- strsep(&duplinet, " "); /* skip 'dont' */
- strsep(&duplinet, " "); /* skip 'include' */
-
- if (!(context = strsep(&duplinet, " "))) {
- free(dupline);
- return NULL;
- }
-
- /* third word must be in */
- in = strsep(&duplinet, " ");
- if (!in ||
- strcmp(in, "in")) {
- free(dupline);
- return NULL;
- }
-
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock context list\n");
- free(dupline);
- return NULL;
- }
-
- /* walk through all contexts ... */
- c = ast_walk_contexts(NULL);
- while (c) {
- struct ast_include *i;
- if (ast_lock_context(c)) {
- free(dupline);
- return NULL;
- }
-
- /* walk through all includes and check if it is our context */
- i = ast_walk_context_includes(c, NULL);
- while (i) {
- /* is in this context included another on which we want to
- * remove?
- */
- if (!strcmp(context, ast_get_include_name(i))) {
- /* yes, it's included, is matching our word too? */
- if (!strncmp(ast_get_context_name(c),
- word, strlen(word))) {
- /* check state for completion */
- if (++which > state) {
- char *res = strdup(ast_get_context_name(c));
- free(dupline);
- ast_unlock_context(c);
- ast_unlock_contexts();
- return res;
- }
- }
- break;
- }
- i = ast_walk_context_includes(c, i);
- }
- ast_unlock_context(c);
- c = ast_walk_contexts(c);
- }
-
- free(dupline);
- ast_unlock_contexts();
- return NULL;
- }
-
- return NULL;
-}
-
-/*!
- * REMOVE EXTENSION command stuff
- */
-static int handle_context_remove_extension(int fd, int argc, char *argv[])
-{
- int removing_priority = 0;
- char *exten, *context;
-
- if (argc != 4 && argc != 3) return RESULT_SHOWUSAGE;
-
- /*
- * Priority input checking ...
- */
- if (argc == 4) {
- char *c = argv[3];
-
- /* check for digits in whole parameter for right priority ...
- * why? because atoi (strtol) returns 0 if any characters in
- * string and whole extension will be removed, it's not good
- */
- if (strcmp("hint", c)) {
- while (*c != '\0') {
- if (!isdigit(*c++)) {
- ast_cli(fd, "Invalid priority '%s'\n", argv[3]);
- return RESULT_FAILURE;
- }
- }
- removing_priority = atoi(argv[3]);
- } else
- removing_priority = PRIORITY_HINT;
-
- if (removing_priority == 0) {
- ast_cli(fd, "If you want to remove whole extension, please " \
- "omit priority argument\n");
- return RESULT_FAILURE;
- }
- }
-
- /*
- * Format exten@context checking ...
- */
- if (!(context = strchr(argv[2], (int)'@'))) {
- ast_cli(fd, "First argument must be in exten@context format\n");
- return RESULT_FAILURE;
- }
-
- *context++ = '\0';
- exten = argv[2];
- if ((!strlen(exten)) || (!(strlen(context)))) {
- ast_cli(fd, "Missing extension or context name in second argument '%s@%s'\n",
- exten == NULL ? "?" : exten, context == NULL ? "?" : context);
- return RESULT_FAILURE;
- }
-
- if (!ast_context_remove_extension(context, exten, removing_priority, registrar)) {
- if (!removing_priority)
- ast_cli(fd, "Whole extension %s@%s removed\n",
- exten, context);
- else
- ast_cli(fd, "Extension %s@%s with priority %d removed\n",
- exten, context, removing_priority);
-
- return RESULT_SUCCESS;
- }
-
- ast_cli(fd, "Failed to remove extension %s@%s\n", exten, context);
-
- return RESULT_FAILURE;
-}
-
-#define BROKEN_READLINE 1
-
-#ifdef BROKEN_READLINE
-/*
- * There is one funny thing, when you have word like 300@ and you hit
- * <tab>, you arguments will like as your word is '300 ', so it '@'
- * characters acts sometimes as word delimiter and sometimes as a part
- * of word
- *
- * This fix function, allocates new word variable and store here every
- * time xxx@yyy always as one word and correct pos is set too
- *
- * It's ugly, I know, but I'm waiting for Mark suggestion if upper is
- * bug or feature ...
- */
-static int fix_complete_args(char *line, char **word, int *pos)
-{
- char *_line, *_strsep_line, *_previous_word = NULL, *_word = NULL;
- int words = 0;
-
- _line = strdup(line);
-
- _strsep_line = _line;
- while (_strsep_line) {
- _previous_word = _word;
- _word = strsep(&_strsep_line, " ");
-
- if (_word && strlen(_word)) words++;
- }
-
-
- if (_word || _previous_word) {
- if (_word) {
- if (!strlen(_word)) words++;
- *word = strdup(_word);
- } else
- *word = strdup(_previous_word);
- *pos = words - 1;
- free(_line);
- return 0;
- }
-
- free(_line);
- return -1;
-}
-#endif /* BROKEN_READLINE */
-
-static char *complete_context_remove_extension(char *line, char *word, int pos,
- int state)
-{
- char *ret = NULL;
- int which = 0;
-
-#ifdef BROKEN_READLINE
- /*
- * Fix arguments, *word is a new allocated structure, REMEMBER to
- * free *word when you want to return from this function ...
- */
- if (fix_complete_args(line, &word, &pos)) {
- ast_log(LOG_ERROR, "Out of free memory\n");
- return NULL;
- }
-#endif
-
- /*
- * exten@context completion ...
- */
- if (pos == 2) {
- struct ast_context *c;
- struct ast_exten *e;
- char *context = NULL, *exten = NULL, *delim = NULL;
-
- /* now, parse values from word = exten@context */
- if ((delim = strchr(word, (int)'@'))) {
- /* check for duplicity ... */
- if (delim != strrchr(word, (int)'@')) {
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- return NULL;
- }
-
- *delim = '\0';
- exten = strdup(word);
- context = strdup(delim + 1);
- *delim = '@';
- } else {
- exten = strdup(word);
- }
-#ifdef BROKEN_READLINE
- free(word);
-#endif
-
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock context list\n");
- free(context); free(exten);
- return NULL;
- }
-
- /* find our context ... */
- c = ast_walk_contexts(NULL);
- while (c) {
- /* our context? */
- if ( (!context || !strlen(context)) || /* if no input, all contexts ... */
- (context && !strncmp(ast_get_context_name(c),
- context, strlen(context))) ) { /* if input, compare ... */
- /* try to complete extensions ... */
- e = ast_walk_context_extensions(c, NULL);
- while (e) {
- /* our extension? */
- if ( (!exten || !strlen(exten)) || /* if not input, all extensions ... */
- (exten && !strncmp(ast_get_extension_name(e), exten,
- strlen(exten))) ) { /* if input, compare ... */
- if (++which > state) {
- /* If there is an extension then return
- * exten@context.
- */
- if (exten) {
- ret = malloc(strlen(ast_get_extension_name(e)) +
- strlen(ast_get_context_name(c)) + 2);
- if (ret)
- sprintf(ret, "%s@%s", ast_get_extension_name(e),
- ast_get_context_name(c));
- }
- free(exten); free(context);
-
- ast_unlock_contexts();
-
- return ret;
- }
- }
- e = ast_walk_context_extensions(c, e);
- }
- }
- c = ast_walk_contexts(c);
- }
-
- ast_unlock_contexts();
-
- free(exten); free(context);
-
- return NULL;
- }
-
- /*
- * Complete priority ...
- */
- if (pos == 3) {
- char *delim, *exten, *context, *dupline, *duplinet, *ec;
- struct ast_context *c;
-
- dupline = strdup(line);
- if (!dupline) {
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- return NULL;
- }
- duplinet = dupline;
-
- strsep(&duplinet, " "); /* skip 'remove' */
- strsep(&duplinet, " "); /* skip 'extension */
-
- if (!(ec = strsep(&duplinet, " "))) {
- free(dupline);
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- return NULL;
- }
-
- /* wrong exten@context format? */
- if (!(delim = strchr(ec, (int)'@')) ||
- (strchr(ec, (int)'@') != strrchr(ec, (int)'@'))) {
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- free(dupline);
- return NULL;
- }
-
- /* check if there is exten and context too ... */
- *delim = '\0';
- if ((!strlen(ec)) || (!strlen(delim + 1))) {
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- free(dupline);
- return NULL;
- }
-
- exten = strdup(ec);
- context = strdup(delim + 1);
- free(dupline);
-
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock context list\n");
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- free(exten); free(context);
- return NULL;
- }
-
- /* walk contexts */
- c = ast_walk_contexts(NULL);
- while (c) {
- if (!strcmp(ast_get_context_name(c), context)) {
- struct ast_exten *e;
-
- /* walk extensions */
- free(context);
- e = ast_walk_context_extensions(c, NULL);
- while (e) {
- if (!strcmp(ast_get_extension_name(e), exten)) {
- struct ast_exten *priority;
- char buffer[10];
-
- free(exten);
- priority = ast_walk_extension_priorities(e, NULL);
- /* serve priorities */
- do {
- snprintf(buffer, 10, "%u",
- ast_get_extension_priority(priority));
- if (!strncmp(word, buffer, strlen(word))) {
- if (++which > state) {
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- ast_unlock_contexts();
- return strdup(buffer);
- }
- }
- priority = ast_walk_extension_priorities(e,
- priority);
- } while (priority);
-
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- ast_unlock_contexts();
- return NULL;
- }
- e = ast_walk_context_extensions(c, e);
- }
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- free(exten);
- ast_unlock_contexts();
- return NULL;
- }
- c = ast_walk_contexts(c);
- }
-
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- free(exten); free(context);
-
- ast_unlock_contexts();
- return NULL;
- }
-
-#ifdef BROKEN_READLINE
- free(word);
-#endif
- return NULL;
-}
-
-/*!
- * Include context ...
- */
-static int handle_context_add_include(int fd, int argc, char *argv[])
-{
- if (argc != 5) return RESULT_SHOWUSAGE;
-
- /* third arg must be 'in' ... */
- if (strcmp(argv[3], "in") && strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
-
- if (ast_context_add_include(argv[4], argv[2], registrar)) {
- switch (errno) {
- case ENOMEM:
- ast_cli(fd, "Out of memory for context addition\n"); break;
-
- case EBUSY:
- ast_cli(fd, "Failed to lock context(s) list, please try again later\n"); break;
-
- case EEXIST:
- ast_cli(fd, "Context '%s' already included in '%s' context\n",
- argv[2], argv[4]); break;
-
- case ENOENT:
- case EINVAL:
- ast_cli(fd, "There is no existence of context '%s'\n",
- errno == ENOENT ? argv[4] : argv[2]); break;
-
- default:
- ast_cli(fd, "Failed to include '%s' in '%s' context\n",
- argv[2], argv[4]); break;
- }
- return RESULT_FAILURE;
- }
-
- /* show some info ... */
- ast_cli(fd, "Context '%s' included in '%s' context\n",
- argv[2], argv[4]);
-
- return RESULT_SUCCESS;
-}
-
-static char *complete_context_add_include(char *line, char *word, int pos,
- int state)
-{
- struct ast_context *c;
- int which = 0;
-
- /* server context for inclusion ... */
- if (pos == 1)
- {
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock context list\n");
- return NULL;
- }
-
- /* server all contexts */
- c = ast_walk_contexts(NULL);
- while (c) {
- if ((!strlen(word) ||
- !strncmp(ast_get_context_name(c), word, strlen(word))) &&
- ++which > state)
- {
- char *context = strdup(ast_get_context_name(c));
- ast_unlock_contexts();
- return context;
- }
- c = ast_walk_contexts(c);
- }
-
- ast_unlock_contexts();
- }
-
- /* complete 'in' only if context exist ... */
- if (pos == 2)
- {
- char *context, *dupline, *duplinet;
-
- if (state != 0) return NULL;
-
- /* parse context from line ... */
- if (!(dupline = strdup(line))) {
- ast_log(LOG_ERROR, "Out of free memory\n");
- if (state == 0) return strdup("in");
- return NULL;
- }
-
- duplinet = dupline;
-
- strsep(&duplinet, " ");
- context = strsep(&duplinet, " ");
- if (context) {
- struct ast_context *c;
- int context_existence = 0;
-
- /* check for context existence ... */
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock context list\n");
- free(dupline);
- /* our fault, we can't check, so complete 'in' ... */
- return strdup("in");
- }
-
- c = ast_walk_contexts(NULL);
- while (c && !context_existence) {
- if (!strcmp(context, ast_get_context_name(c))) {
- context_existence = 1;
- continue;
- }
- c = ast_walk_contexts(c);
- }
-
- /* if context exists, return 'into' ... */
- if (context_existence) {
- free(dupline);
- ast_unlock_contexts();
- return strdup("into");
- }
-
- ast_unlock_contexts();
- }
-
- free(dupline);
- return NULL;
- }
-
- /* serve context into which we include another context */
- if (pos == 3)
- {
- char *context, *dupline, *duplinet, *in;
- int context_existence = 0;
-
- if (!(dupline = strdup(line))) {
- ast_log(LOG_ERROR, "Out of free memory\n");
- return NULL;
- }
-
- duplinet = dupline;
-
- strsep(&duplinet, " "); /* skip 'include' */
- context = strsep(&duplinet, " ");
- in = strsep(&duplinet, " ");
-
- /* given some context and third word is in? */
- if (!strlen(context) || strcmp(in, "in")) {
- free(dupline);
- return NULL;
- }
-
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock context list\n");
- free(dupline);
- return NULL;
- }
-
- /* check for context existence ... */
- c = ast_walk_contexts(NULL);
- while (c && !context_existence) {
- if (!strcmp(context, ast_get_context_name(c))) {
- context_existence = 1;
- continue;
- }
- c = ast_walk_contexts(c);
- }
-
- if (!context_existence) {
- free(dupline);
- ast_unlock_contexts();
- return NULL;
- }
-
- /* go through all contexts ... */
- c = ast_walk_contexts(NULL);
- while (c) {
- /* must be different contexts ... */
- if (strcmp(context, ast_get_context_name(c))) {
- if (!ast_lock_context(c)) {
- struct ast_include *i;
- int included = 0;
-
- /* check for duplicity inclusion ... */
- i = ast_walk_context_includes(c, NULL);
- while (i && !included) {
- if (!strcmp(ast_get_include_name(i), context))
- included = 1;
- i = ast_walk_context_includes(c, i);
- }
- ast_unlock_context(c);
-
- /* not included yet, so show possibility ... */
- if (!included &&
- !strncmp(ast_get_context_name(c), word, strlen(word))){
-
- if (++which > state) {
- char *res = strdup(ast_get_context_name(c));
- free(dupline);
- ast_unlock_contexts();
- return res;
- }
- }
- }
- }
- c = ast_walk_contexts(c);
- }
-
- ast_unlock_contexts();
- free(dupline);
- return NULL;
- }
-
- return NULL;
-}
-
-/*!
- * \brief 'save dialplan' CLI command implementation functions ...
- */
-static int handle_save_dialplan(int fd, int argc, char *argv[])
-{
- char filename[256];
- struct ast_context *c;
- struct ast_config *cfg;
- struct ast_variable *v;
- int context_header_written;
- int incomplete = 0; /* incomplete config write? */
- FILE *output;
-
- if (! (static_config && !write_protect_config)) {
- ast_cli(fd,
- "I can't save dialplan now, see '%s' example file.\n",
- config);
- return RESULT_FAILURE;
- }
-
- if (argc != 2 && argc != 3) return RESULT_SHOWUSAGE;
-
- if (ast_mutex_lock(&save_dialplan_lock)) {
- ast_cli(fd,
- "Failed to lock dialplan saving (another proccess saving?)\n");
- return RESULT_FAILURE;
- }
-
- /* have config path? */
- if (argc == 3) {
- /* is there extension.conf too? */
- if (!strstr(argv[2], ".conf")) {
- /* no, only directory path, check for last '/' occurence */
- if (*(argv[2] + strlen(argv[2]) -1) == '/')
- snprintf(filename, sizeof(filename), "%s%s",
- argv[2], config);
- else
- /* without config extensions.conf, add it */
- snprintf(filename, sizeof(filename), "%s/%s",
- argv[2], config);
- } else
- /* there is an .conf */
- snprintf(filename, sizeof(filename), argv[2]);
- } else
- /* no config file, default one */
- snprintf(filename, sizeof(filename), "%s/%s",
- (char *)ast_config_AST_CONFIG_DIR, config);
-
- cfg = ast_config_load("extensions.conf");
-
- /* try to lock contexts list */
- if (ast_lock_contexts()) {
- ast_cli(fd, "Failed to lock contexts list\n");
- ast_mutex_unlock(&save_dialplan_lock);
- ast_config_destroy(cfg);
- return RESULT_FAILURE;
- }
-
- /* create new file ... */
- if (!(output = fopen(filename, "wt"))) {
- ast_cli(fd, "Failed to create file '%s'\n",
- filename);
- ast_unlock_contexts();
- ast_mutex_unlock(&save_dialplan_lock);
- ast_config_destroy(cfg);
- return RESULT_FAILURE;
- }
-
- /* fireout general info */
- fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\n\n",
- static_config ? "yes" : "no",
- write_protect_config ? "yes" : "no");
-
- if ((v = ast_variable_browse(cfg, "globals"))) {
- fprintf(output, "[globals]\n");
- while(v) {
- fprintf(output, "%s => %s\n", v->name, v->value);
- v = v->next;
- }
- fprintf(output, "\n");
- }
-
- ast_config_destroy(cfg);
-
- /* walk all contexts */
- c = ast_walk_contexts(NULL);
- while (c) {
- context_header_written = 0;
-
- /* try to lock context and fireout all info */
- if (!ast_lock_context(c)) {
- struct ast_exten *e, *last_written_e = NULL;
- struct ast_include *i;
- struct ast_ignorepat *ip;
- struct ast_sw *sw;
-
- /* registered by this module? */
- if (!strcmp(ast_get_context_registrar(c), registrar)) {
- fprintf(output, "[%s]\n", ast_get_context_name(c));
- context_header_written = 1;
- }
-
- /* walk extensions ... */
- e = ast_walk_context_extensions(c, NULL);
- while (e) {
- struct ast_exten *p;
-
- /* fireout priorities */
- p = ast_walk_extension_priorities(e, NULL);
- while (p) {
- if (!strcmp(ast_get_extension_registrar(p),
- registrar)) {
-
- /* make empty line between different extensions */
- if (last_written_e != NULL &&
- strcmp(ast_get_extension_name(last_written_e),
- ast_get_extension_name(p)))
- fprintf(output, "\n");
- last_written_e = p;
-
- if (!context_header_written) {
- fprintf(output, "[%s]\n", ast_get_context_name(c));
- context_header_written = 1;
- }
-
- if (ast_get_extension_priority(p)!=PRIORITY_HINT) {
- char *tempdata = NULL, *startdata;
- tempdata = strdup((char *)ast_get_extension_app_data(p));
- if (tempdata) {
- startdata = tempdata;
- while (*tempdata) {
- if (*tempdata == '|')
- *tempdata = ',';
- tempdata++;
- }
- tempdata = startdata;
- }
- if (ast_get_extension_matchcid(p))
- fprintf(output, "exten => %s/%s,%d,%s(%s)\n",
- ast_get_extension_name(p),
- ast_get_extension_cidmatch(p),
- ast_get_extension_priority(p),
- ast_get_extension_app(p),
- tempdata);
- else
- fprintf(output, "exten => %s,%d,%s(%s)\n",
- ast_get_extension_name(p),
- ast_get_extension_priority(p),
- ast_get_extension_app(p),
- tempdata);
- if (tempdata)
- free(tempdata);
- } else
- fprintf(output, "exten => %s,hint,%s\n",
- ast_get_extension_name(p),
- ast_get_extension_app(p));
-
- }
- p = ast_walk_extension_priorities(e, p);
- }
-
- e = ast_walk_context_extensions(c, e);
- }
-
- /* written any extensions? ok, write space between exten & inc */
- if (last_written_e) fprintf(output, "\n");
-
- /* walk through includes */
- i = ast_walk_context_includes(c, NULL);
- while (i) {
- if (!strcmp(ast_get_include_registrar(i), registrar)) {
- if (!context_header_written) {
- fprintf(output, "[%s]\n", ast_get_context_name(c));
- context_header_written = 1;
- }
- fprintf(output, "include => %s\n",
- ast_get_include_name(i));
- }
- i = ast_walk_context_includes(c, i);
- }
-
- if (ast_walk_context_includes(c, NULL))
- fprintf(output, "\n");
-
- /* walk through switches */
- sw = ast_walk_context_switches(c, NULL);
- while (sw) {
- if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
- if (!context_header_written) {
- fprintf(output, "[%s]\n", ast_get_context_name(c));
- context_header_written = 1;
- }
- fprintf(output, "switch => %s/%s\n",
- ast_get_switch_name(sw),
- ast_get_switch_data(sw));
- }
- sw = ast_walk_context_switches(c, sw);
- }
-
- if (ast_walk_context_switches(c, NULL))
- fprintf(output, "\n");
-
- /* fireout ignorepats ... */
- ip = ast_walk_context_ignorepats(c, NULL);
- while (ip) {
- if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
- if (!context_header_written) {
- fprintf(output, "[%s]\n", ast_get_context_name(c));
- context_header_written = 1;
- }
-
- fprintf(output, "ignorepat => %s\n",
- ast_get_ignorepat_name(ip));
- }
- ip = ast_walk_context_ignorepats(c, ip);
- }
-
- ast_unlock_context(c);
- } else
- incomplete = 1;
-
- c = ast_walk_contexts(c);
- }
-
- ast_unlock_contexts();
- ast_mutex_unlock(&save_dialplan_lock);
- fclose(output);
-
- if (incomplete) {
- ast_cli(fd, "Saved dialplan is incomplete\n");
- return RESULT_FAILURE;
- }
-
- ast_cli(fd, "Dialplan successfully saved into '%s'\n",
- filename);
- return RESULT_SUCCESS;
-}
-
-/*!
- * \brief ADD EXTENSION command stuff
- */
-static int handle_context_add_extension(int fd, int argc, char *argv[])
-{
- char *whole_exten;
- char *exten, *prior;
- int iprior = -2;
- char *cidmatch, *app, *app_data;
- char *start, *end;
-
- /* check for arguments at first */
- if (argc != 5 && argc != 6) return RESULT_SHOWUSAGE;
- if (strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
- if (argc == 6) if (strcmp(argv[5], "replace")) return RESULT_SHOWUSAGE;
-
- whole_exten = argv[2];
- exten = strsep(&whole_exten,",");
- if (strchr(exten, '/')) {
- cidmatch = exten;
- strsep(&cidmatch,"/");
- } else {
- cidmatch = NULL;
- }
- prior = strsep(&whole_exten,",");
- if (prior) {
- if (!strcmp(prior, "hint")) {
- iprior = PRIORITY_HINT;
- } else {
- if (sscanf(prior, "%d", &iprior) != 1) {
- ast_cli(fd, "'%s' is not a valid priority\n", prior);
- prior = NULL;
- }
- }
- }
- app = whole_exten;
- if (app && (start = strchr(app, '(')) && (end = strrchr(app, ')'))) {
- *start = *end = '\0';
- app_data = start + 1;
- ast_process_quotes_and_slashes(app_data, ',', '|');
- } else {
- if (app) {
- app_data = strchr(app, ',');
- if (app_data) {
- *app_data = '\0';
- app_data++;
- }
- } else
- app_data = NULL;
- }
-
- if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT)) return RESULT_SHOWUSAGE;
-
- if (!app_data)
- app_data="";
- if (ast_add_extension(argv[4], argc == 6 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
- (void *)strdup(app_data), free, registrar)) {
- switch (errno) {
- case ENOMEM:
- ast_cli(fd, "Out of free memory\n"); break;
-
- case EBUSY:
- ast_cli(fd, "Failed to lock context(s) list, please try again later\n"); break;
-
- case ENOENT:
- ast_cli(fd, "No existence of '%s' context\n", argv[4]); break;
-
- case EEXIST:
- ast_cli(fd, "Extension %s@%s with priority %s already exists\n",
- exten, argv[4], prior); break;
-
- default:
- ast_cli(fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
- exten, prior, app, app_data, argv[4]); break;
- }
- return RESULT_FAILURE;
- }
-
- if (argc == 6)
- ast_cli(fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
- exten, argv[4], prior, exten, prior, app, app_data);
- else
- ast_cli(fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
- exten, prior, app, app_data, argv[4]);
-
- return RESULT_SUCCESS;
-}
-
-/*! add extension 6123,1,Dial,IAX/212.71.138.13/6123 into local */
-static char *complete_context_add_extension(char *line, char *word,
- int pos, int state)
-{
- int which = 0;
-
- /* complete 'into' word ... */
- if (pos == 3) {
- if (state == 0) return strdup("into");
- return NULL;
- }
-
- /* complete context */
- if (pos == 4) {
- struct ast_context *c;
-
- /* try to lock contexts list ... */
- if (ast_lock_contexts()) {
- ast_log(LOG_WARNING, "Failed to lock contexts list\n");
- return NULL;
- }
-
- /* walk through all contexts */
- c = ast_walk_contexts(NULL);
- while (c) {
- /* matching context? */
- if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
- if (++which > state) {
- char *res = strdup(ast_get_context_name(c));
- ast_unlock_contexts();
- return res;
- }
- }
- c = ast_walk_contexts(c);
- }
-
- ast_unlock_contexts();
- return NULL;
- }
-
- if (pos == 5) return state == 0 ? strdup("replace") : NULL;
-
- return NULL;
-}
-
-/*!
- * IGNOREPAT CLI stuff
- */
-static int handle_context_add_ignorepat(int fd, int argc, char *argv[])
-{
- if (argc != 5) return RESULT_SHOWUSAGE;
- if (strcmp(argv[3], "into")) return RESULT_SHOWUSAGE;
-
- if (ast_context_add_ignorepat(argv[4], argv[2], registrar)) {
- switch (errno) {
- case ENOMEM:
- ast_cli(fd, "Out of free memory\n"); break;
-
- case ENOENT:
- ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
- break;
-
- case EEXIST:
- ast_cli(fd, "Ignore pattern '%s' already included in '%s' context\n",
- argv[2], argv[4]);
- break;
-
- case EBUSY:
- ast_cli(fd, "Failed to lock context(s) list, please, try again later\n");
- break;
-
- default:
- ast_cli(fd, "Failed to add ingore pattern '%s' into '%s' context\n",
- argv[2], argv[4]);
- break;
- }
- return RESULT_FAILURE;
- }
-
- ast_cli(fd, "Ignore pattern '%s' added into '%s' context\n",
- argv[2], argv[4]);
- return RESULT_SUCCESS;
-}
-
-static char *complete_context_add_ignorepat(char *line, char *word,
- int pos, int state)
-{
- if (pos == 3) return state == 0 ? strdup("into") : NULL;
-
- if (pos == 4) {
- struct ast_context *c;
- int which = 0;
- char *dupline, *duplinet, *ignorepat = NULL;
-
- dupline = strdup(line);
- duplinet = dupline;
-
- if (duplinet) {
- strsep(&duplinet, " "); /* skip 'add' */
- strsep(&duplinet, " "); /* skip 'ignorepat' */
- ignorepat = strsep(&duplinet, " ");
- }
-
- if (ast_lock_contexts()) {
- ast_log(LOG_ERROR, "Failed to lock contexts list\n");
- return NULL;
- }
-
- c = ast_walk_contexts(NULL);
- while (c) {
- if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
- int serve_context = 1;
- if (ignorepat) {
- if (!ast_lock_context(c)) {
- struct ast_ignorepat *ip;
- ip = ast_walk_context_ignorepats(c, NULL);
- while (ip && serve_context) {
- if (!strcmp(ast_get_ignorepat_name(ip), ignorepat))
- serve_context = 0;
- ip = ast_walk_context_ignorepats(c, ip);
- }
- ast_unlock_context(c);
- }
- }
- if (serve_context) {
- if (++which > state) {
- char *context = strdup(ast_get_context_name(c));
- if (dupline) free(dupline);
- ast_unlock_contexts();
- return context;
- }
- }
- }
- c = ast_walk_contexts(c);
- }
-
- if (dupline) free(dupline);
- ast_unlock_contexts();
- return NULL;
- }
-
- return NULL;
-}
-
-static int handle_context_remove_ignorepat(int fd, int argc, char *argv[])
-{
- if (argc != 5) return RESULT_SHOWUSAGE;
- if (strcmp(argv[3], "from")) return RESULT_SHOWUSAGE;
-
- if (ast_context_remove_ignorepat(argv[4], argv[2], registrar)) {
- switch (errno) {
- case EBUSY:
- ast_cli(fd, "Failed to lock context(s) list, please try again later\n");
- break;
-
- case ENOENT:
- ast_cli(fd, "There is no existence of '%s' context\n", argv[4]);
- break;
-
- case EINVAL:
- ast_cli(fd, "There is no existence of '%s' ignore pattern in '%s' context\n",
- argv[2], argv[4]);
- break;
-
- default:
- ast_cli(fd, "Failed to remove ignore pattern '%s' from '%s' context\n", argv[2], argv[4]);
- break;
- }
- return RESULT_FAILURE;
- }
-
- ast_cli(fd, "Ignore pattern '%s' removed from '%s' context\n",
- argv[2], argv[4]);
- return RESULT_SUCCESS;
-}
-
-static int pbx_load_module(void);
-
-static int handle_reload_extensions(int fd, int argc, char *argv[])
-{
- if (argc!=2) return RESULT_SHOWUSAGE;
- pbx_load_module();
- return RESULT_SUCCESS;
-}
-
-static char *complete_context_remove_ignorepat(char *line, char *word,
- int pos, int state)
-{
- struct ast_context *c;
- int which = 0;
-
- if (pos == 2) {
- if (ast_lock_contexts()) {
- ast_log(LOG_WARNING, "Failed to lock contexts list\n");
- return NULL;
- }
-
- c = ast_walk_contexts(NULL);
- while (c) {
- if (!ast_lock_context(c)) {
- struct ast_ignorepat *ip;
-
- ip = ast_walk_context_ignorepats(c, NULL);
- while (ip) {
- if (!strncmp(ast_get_ignorepat_name(ip), word, strlen(word))) {
- if (which + 1 > state) {
- struct ast_context *cw;
- int already_served = 0;
- cw = ast_walk_contexts(NULL);
- while (cw && cw != c && !already_served) {
- if (!ast_lock_context(cw)) {
- struct ast_ignorepat *ipw;
- ipw = ast_walk_context_ignorepats(cw, NULL);
- while (ipw) {
- if (!strcmp(ast_get_ignorepat_name(ipw),
- ast_get_ignorepat_name(ip))) already_served = 1;
- ipw = ast_walk_context_ignorepats(cw, ipw);
- }
- ast_unlock_context(cw);
- }
- cw = ast_walk_contexts(cw);
- }
- if (!already_served) {
- char *ret = strdup(ast_get_ignorepat_name(ip));
- ast_unlock_context(c);
- ast_unlock_contexts();
- return ret;
- }
- } else
- which++;
- }
- ip = ast_walk_context_ignorepats(c, ip);
- }
-
- ast_unlock_context(c);
- }
- c = ast_walk_contexts(c);
- }
-
- ast_unlock_contexts();
- return NULL;
- }
-
- if (pos == 3) return state == 0 ? strdup("from") : NULL;
-
- if (pos == 4) {
- char *dupline, *duplinet, *ignorepat;
-
- dupline = strdup(line);
- if (!dupline) {
- ast_log(LOG_WARNING, "Out of free memory\n");
- return NULL;
- }
-
- duplinet = dupline;
- strsep(&duplinet, " ");
- strsep(&duplinet, " ");
- ignorepat = strsep(&duplinet, " ");
-
- if (!ignorepat) {
- free(dupline);
- return NULL;
- }
-
- if (ast_lock_contexts()) {
- ast_log(LOG_WARNING, "Failed to lock contexts list\n");
- free(dupline);
- return NULL;
- }
-
- c = ast_walk_contexts(NULL);
- while (c) {
- if (!ast_lock_context(c)) {
- struct ast_ignorepat *ip;
- ip = ast_walk_context_ignorepats(c, NULL);
- while (ip) {
- if (!strcmp(ast_get_ignorepat_name(ip), ignorepat)) {
- if (!strncmp(ast_get_context_name(c), word, strlen(word))) {
- if (++which > state) {
- char *ret = strdup(ast_get_context_name(c));
- free(dupline);
- ast_unlock_context(c);
- ast_unlock_contexts();
- return ret;
- }
- }
- }
- ip = ast_walk_context_ignorepats(c, ip);
- }
-
- ast_unlock_context(c);
- }
- c = ast_walk_contexts(c);
- }
-
- free(dupline);
- ast_unlock_contexts();
- return NULL;
- }
-
- return NULL;
-}
-
-/*!
- * CLI entries for commands provided by this module
- */
-static struct ast_cli_entry context_dont_include_cli =
- { { "dont", "include", NULL }, handle_context_dont_include,
- "Remove a specified include from context", context_dont_include_help,
- complete_context_dont_include };
-
-static struct ast_cli_entry context_remove_extension_cli =
- { { "remove", "extension", NULL }, handle_context_remove_extension,
- "Remove a specified extension", context_remove_extension_help,
- complete_context_remove_extension };
-
-static struct ast_cli_entry context_add_include_cli =
- { { "include", "context", NULL }, handle_context_add_include,
- "Include context in other context", context_add_include_help,
- complete_context_add_include };
-
-static struct ast_cli_entry save_dialplan_cli =
- { { "save", "dialplan", NULL }, handle_save_dialplan,
- "Save dialplan", save_dialplan_help };
-
-static struct ast_cli_entry context_add_extension_cli =
- { { "add", "extension", NULL }, handle_context_add_extension,
- "Add new extension into context", context_add_extension_help,
- complete_context_add_extension };
-
-static struct ast_cli_entry context_add_ignorepat_cli =
- { { "add", "ignorepat", NULL }, handle_context_add_ignorepat,
- "Add new ignore pattern", context_add_ignorepat_help,
- complete_context_add_ignorepat };
-
-static struct ast_cli_entry context_remove_ignorepat_cli =
- { { "remove", "ignorepat", NULL }, handle_context_remove_ignorepat,
- "Remove ignore pattern from context", context_remove_ignorepat_help,
- complete_context_remove_ignorepat };
-
-static struct ast_cli_entry reload_extensions_cli =
- { { "extensions", "reload", NULL}, handle_reload_extensions,
- "Reload extensions and *only* extensions", reload_extensions_help };
-
-/*!
- * Standard module functions ...
- */
-int unload_module(void)
-{
- ast_cli_unregister(&context_add_extension_cli);
- if (static_config && !write_protect_config)
- ast_cli_unregister(&save_dialplan_cli);
- ast_cli_unregister(&context_add_include_cli);
- ast_cli_unregister(&context_dont_include_cli);
- ast_cli_unregister(&context_remove_extension_cli);
- ast_cli_unregister(&context_remove_ignorepat_cli);
- ast_cli_unregister(&context_add_ignorepat_cli);
- ast_cli_unregister(&reload_extensions_cli);
- ast_context_destroy(NULL, registrar);
- return 0;
-}
-
-static int pbx_load_module(void)
-{
- struct ast_config *cfg;
- struct ast_variable *v;
- char *cxt, *ext, *pri, *appl, *data, *tc, *cidmatch;
- struct ast_context *con;
- char *end;
- char *label;
- char realvalue[256];
- int lastpri = -2;
-
- cfg = ast_config_load(config);
- if (cfg) {
- /* Use existing config to populate the PBX table */
- static_config = ast_true(ast_variable_retrieve(cfg, "general",
- "static"));
- write_protect_config = ast_true(ast_variable_retrieve(cfg, "general",
- "writeprotect"));
- autofallthrough_config = ast_true(ast_variable_retrieve(cfg, "general",
- "autofallthrough"));
- clearglobalvars_config = ast_true(ast_variable_retrieve(cfg, "general",
- "clearglobalvars"));
- option_priority_jumping = !ast_false(ast_variable_retrieve(cfg, "general",
- "priorityjumping"));
-
- v = ast_variable_browse(cfg, "globals");
- while(v) {
- memset(realvalue, 0, sizeof(realvalue));
- pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
- pbx_builtin_setvar_helper(NULL, v->name, realvalue);
- v = v->next;
- }
- cxt = ast_category_browse(cfg, NULL);
- while(cxt) {
- /* All categories but "general" or "globals" are considered contexts */
- if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals")) {
- cxt = ast_category_browse(cfg, cxt);
- continue;
- }
- if ((con=ast_context_create(&local_contexts,cxt, registrar))) {
- v = ast_variable_browse(cfg, cxt);
- while(v) {
- if (!strcasecmp(v->name, "exten")) {
- char *stringp=NULL;
- int ipri = -2;
- char realext[256]="";
- char *plus, *firstp, *firstc;
- tc = strdup(v->value);
- if(tc!=NULL){
- stringp=tc;
- ext = strsep(&stringp, ",");
- if (!ext)
- ext="";
- pbx_substitute_variables_helper(NULL, ext, realext, sizeof(realext) - 1);
- cidmatch = strchr(realext, '/');
- if (cidmatch) {
- *cidmatch = '\0';
- cidmatch++;
- ast_shrink_phone_number(cidmatch);
- }
- pri = strsep(&stringp, ",");
- if (!pri)
- pri="";
- label = strchr(pri, '(');
- if (label) {
- *label = '\0';
- label++;
- end = strchr(label, ')');
- if (end)
- *end = '\0';
- else
- ast_log(LOG_WARNING, "Label missing trailing ')' at line %d\n", v->lineno);
- }
- plus = strchr(pri, '+');
- if (plus) {
- *plus = '\0';
- plus++;
- }
- if (!strcmp(pri,"hint"))
- ipri=PRIORITY_HINT;
- else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
- if (lastpri > -2)
- ipri = lastpri + 1;
- else
- ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
- } else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
- if (lastpri > -2)
- ipri = lastpri;
- else
- ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
- } else {
- if (sscanf(pri, "%d", &ipri) != 1) {
- if ((ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
- ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
- ipri = 0;
- }
- }
- }
- appl = stringp;
- if (!appl)
- appl="";
- /* Find the first occurrence of either '(' or ',' */
- firstc = strchr(appl, ',');
- firstp = strchr(appl, '(');
- if (firstc && ((!firstp) || (firstc < firstp))) {
- /* comma found, no parenthesis */
- /* or both found, but comma found first */
- appl = strsep(&stringp, ",");
- data = stringp;
- } else if ((!firstc) && (!firstp)) {
- /* Neither found */
- data = "";
- } else {
- /* Final remaining case is parenthesis found first */
- appl = strsep(&stringp, "(");
- data = stringp;
- end = strrchr(data, ')');
- if ((end = strrchr(data, ')'))) {
- *end = '\0';
- } else {
- ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
- }
- ast_process_quotes_and_slashes(data, ',', '|');
- }
-
- if (!data)
- data="";
- while(*appl && (*appl < 33)) appl++;
- if (ipri) {
- if (plus)
- ipri += atoi(plus);
- lastpri = ipri;
- if(!option_dontwarn) {
- if (!strcmp(realext, "_."))
- ast_log(LOG_WARNING, "The use of '_.' for an extension is strongly discouraged and can have unexpected behavior. Please use '_X.' instead at line %d\n", v->lineno);
- }
- if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), FREE, registrar)) {
- ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
- }
- }
- free(tc);
- } else fprintf(stderr,"Error strdup returned NULL in %s\n",__PRETTY_FUNCTION__);
- } else if(!strcasecmp(v->name, "include")) {
- memset(realvalue, 0, sizeof(realvalue));
- pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
- if (ast_context_add_include2(con, realvalue, registrar))
- ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
- } else if(!strcasecmp(v->name, "ignorepat")) {
- memset(realvalue, 0, sizeof(realvalue));
- pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
- if (ast_context_add_ignorepat2(con, realvalue, registrar))
- ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
- } else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
- char *stringp=NULL;
- memset(realvalue, 0, sizeof(realvalue));
- if (!strcasecmp(v->name, "switch"))
- pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
- else
- strncpy(realvalue, v->value, sizeof(realvalue) - 1);
- tc = realvalue;
- stringp=tc;
- appl = strsep(&stringp, "/");
- data = strsep(&stringp, "");
- if (!data)
- data = "";
- if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), registrar))
- ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
- }
- v = v->next;
- }
- }
- cxt = ast_category_browse(cfg, cxt);
- }
- ast_config_destroy(cfg);
- }
- ast_merge_contexts_and_delete(&local_contexts,registrar);
-
- for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
- ast_context_verify_includes(con);
-
- pbx_set_autofallthrough(autofallthrough_config);
-
- return 0;
-}
-
-int load_module(void)
-{
- if (pbx_load_module()) return -1;
-
- ast_cli_register(&context_remove_extension_cli);
- ast_cli_register(&context_dont_include_cli);
- ast_cli_register(&context_add_include_cli);
- if (static_config && !write_protect_config)
- ast_cli_register(&save_dialplan_cli);
- ast_cli_register(&context_add_extension_cli);
- ast_cli_register(&context_add_ignorepat_cli);
- ast_cli_register(&context_remove_ignorepat_cli);
- ast_cli_register(&reload_extensions_cli);
-
- return 0;
-}
-
-int reload(void)
-{
- ast_context_destroy(NULL, registrar);
- if (clearglobalvars_config)
- pbx_builtin_clear_globals();
- pbx_load_module();
- return 0;
-}
-
-int usecount(void)
-{
- return 0;
-}
-
-char *description(void)
-{
- return dtext;
-}
-
-char *key(void)
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/pbx/pbx_dundi.c b/1.2-netsec/pbx/pbx_dundi.c
deleted file mode 100644
index 8f0457296..000000000
--- a/1.2-netsec/pbx/pbx_dundi.c
+++ /dev/null
@@ -1,4831 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Distributed Universal Number Discovery (DUNDi)
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <errno.h>
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(SOLARIS) || defined(__Darwin__)
-#include <sys/types.h>
-#include <netinet/in_systm.h>
-#endif
-#include <netinet/ip.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__Darwin__)
-#include <net/if_dl.h>
-#include <ifaddrs.h>
-#endif
-#include <zlib.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/options.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/frame.h"
-#include "asterisk/file.h"
-#include "asterisk/cli.h"
-#include "asterisk/lock.h"
-#include "asterisk/md5.h"
-#include "asterisk/dundi.h"
-#include "asterisk/sched.h"
-#include "asterisk/io.h"
-#include "asterisk/utils.h"
-#include "asterisk/crypto.h"
-#include "asterisk/astdb.h"
-#include "asterisk/acl.h"
-#include "asterisk/aes.h"
-
-#include "dundi-parser.h"
-
-#define MAX_RESULTS 64
-
-#define MAX_PACKET_SIZE 8192
-
-extern char ast_config_AST_KEY_DIR[];
-
-static char *tdesc = "Distributed Universal Number Discovery (DUNDi)";
-
-static char *app = "DUNDiLookup";
-static char *synopsis = "Look up a number with DUNDi";
-static char *descrip =
-"DUNDiLookup(number[|context[|options]])\n"
-" Looks up a given number in the global context specified or in\n"
-"the reserved 'e164' context if not specified. Returns -1 if the channel\n"
-"is hungup during the lookup or 0 otherwise. On completion, the variable\n"
-"${DUNDTECH} and ${DUNDDEST} will contain the technology and destination\n"
-"of the appropriate technology and destination to access the number. If no\n"
-"answer was found, and the priority n + 101 exists, execution will continue\n"
-"at that location. Note that this will only occur if the global priority\n"
-"jumping option is enabled in extensions.conf. If the 'b' option is specified,\n"
-"the internal DUNDi cache will by bypassed.\n";
-
-#define DUNDI_MODEL_INBOUND (1 << 0)
-#define DUNDI_MODEL_OUTBOUND (1 << 1)
-#define DUNDI_MODEL_SYMMETRIC (DUNDI_MODEL_INBOUND | DUNDI_MODEL_OUTBOUND)
-
-/* Keep times of last 10 lookups */
-#define DUNDI_TIMING_HISTORY 10
-
-#define FLAG_ISREG (1 << 0) /* Transaction is register request */
-#define FLAG_DEAD (1 << 1) /* Transaction is dead */
-#define FLAG_FINAL (1 << 2) /* Transaction has final message sent */
-#define FLAG_ISQUAL (1 << 3) /* Transaction is a qualification */
-#define FLAG_ENCRYPT (1 << 4) /* Transaction is encrypted wiht ECX/DCX */
-#define FLAG_SENDFULLKEY (1 << 5) /* Send full key on transaction */
-#define FLAG_STOREHIST (1 << 6) /* Record historic performance */
-
-#define DUNDI_FLAG_INTERNAL_NOPARTIAL (1 << 17)
-
-#if 0
-#define DUNDI_SECRET_TIME 15 /* Testing only */
-#else
-#define DUNDI_SECRET_TIME DUNDI_DEFAULT_CACHE_TIME
-#endif
-
-#define KEY_OUT 0
-#define KEY_IN 1
-
-static struct io_context *io;
-static struct sched_context *sched;
-static int netsocket = -1;
-static pthread_t netthreadid = AST_PTHREADT_NULL;
-static pthread_t precachethreadid = AST_PTHREADT_NULL;
-static int tos = 0;
-static int dundidebug = 0;
-static int authdebug = 0;
-static int dundi_ttl = DUNDI_DEFAULT_TTL;
-static int dundi_key_ttl = DUNDI_DEFAULT_KEY_EXPIRE;
-static int dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;
-static int global_autokilltimeout = 0;
-static dundi_eid global_eid;
-static int default_expiration = 60;
-static int global_storehistory = 0;
-static char dept[80];
-static char org[80];
-static char locality[80];
-static char stateprov[80];
-static char country[80];
-static char email[80];
-static char phone[80];
-static char secretpath[80];
-static char cursecret[80];
-static char ipaddr[80];
-static time_t rotatetime;
-static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } };
-struct permission {
- struct permission *next;
- int allow;
- char name[0];
-};
-
-struct dundi_packet {
- struct dundi_hdr *h;
- struct dundi_packet *next;
- int datalen;
- struct dundi_transaction *parent;
- int retransid;
- int retrans;
- unsigned char data[0];
-};
-
-struct dundi_hint_metadata {
- unsigned short flags;
- char exten[AST_MAX_EXTENSION];
-};
-
-struct dundi_precache_queue {
- struct dundi_precache_queue *next;
- char *context;
- time_t expiration;
- char number[0];
-};
-
-struct dundi_request;
-
-struct dundi_transaction {
- struct sockaddr_in addr; /* Other end of transaction */
- struct timeval start; /* When this transaction was created */
- dundi_eid eids[DUNDI_MAX_STACK + 1];
- int eidcount; /* Number of eids in eids */
- dundi_eid us_eid; /* Our EID, to them */
- dundi_eid them_eid; /* Their EID, to us */
- aes_encrypt_ctx ecx; /* AES 128 Encryption context */
- aes_decrypt_ctx dcx; /* AES 128 Decryption context */
- unsigned int flags; /* Has final packet been sent */
- int ttl; /* Remaining TTL for queries on this one */
- int thread; /* We have a calling thread */
- int retranstimer; /* How long to wait before retransmissions */
- int autokillid; /* ID to kill connection if answer doesn't come back fast enough */
- int autokilltimeout; /* Recommended timeout for autokill */
- unsigned short strans; /* Our transaction identifier */
- unsigned short dtrans; /* Their transaction identifer */
- unsigned char iseqno; /* Next expected received seqno */
- unsigned char oiseqno; /* Last received incoming seqno */
- unsigned char oseqno; /* Next transmitted seqno */
- unsigned char aseqno; /* Last acknowledge seqno */
- struct dundi_packet *packets; /* Packets to be retransmitted */
- struct dundi_packet *lasttrans; /* Last transmitted / ACK'd packet */
- struct dundi_transaction *next; /* Next with respect to the parent */
- struct dundi_request *parent; /* Parent request (if there is one) */
- struct dundi_transaction *allnext; /* Next with respect to all DUNDi transactions */
-} *alltrans;
-
-struct dundi_request {
- char dcontext[AST_MAX_EXTENSION];
- char number[AST_MAX_EXTENSION];
- dundi_eid query_eid;
- dundi_eid root_eid;
- struct dundi_result *dr;
- struct dundi_entity_info *dei;
- struct dundi_hint_metadata *hmd;
- int maxcount;
- int respcount;
- int expiration;
- int cbypass;
- int pfds[2];
- unsigned long crc32; /* CRC-32 of all but root EID's in avoid list */
- struct dundi_transaction *trans; /* Transactions */
- struct dundi_request *next;
-} *requests;
-
-static struct dundi_mapping {
- char dcontext[AST_MAX_EXTENSION];
- char lcontext[AST_MAX_EXTENSION];
- int weight;
- int options;
- int tech;
- int dead;
- char dest[AST_MAX_EXTENSION];
- struct dundi_mapping *next;
-} *mappings = NULL;
-
-static struct dundi_peer {
- dundi_eid eid;
- struct sockaddr_in addr; /* Address of DUNDi peer */
- struct permission *permit;
- struct permission *include;
- struct permission *precachesend;
- struct permission *precachereceive;
- dundi_eid us_eid;
- char inkey[80];
- char outkey[80];
- int dead;
- int registerid;
- int qualifyid;
- int sentfullkey;
- int order;
- unsigned char txenckey[256]; /* Transmitted encrypted key + sig */
- unsigned char rxenckey[256]; /* Cache received encrypted key + sig */
- unsigned long us_keycrc32; /* CRC-32 of our key */
- aes_encrypt_ctx us_ecx; /* Cached AES 128 Encryption context */
- aes_decrypt_ctx us_dcx; /* Cached AES 128 Decryption context */
- unsigned long them_keycrc32;/* CRC-32 of our key */
- aes_encrypt_ctx them_ecx; /* Cached AES 128 Encryption context */
- aes_decrypt_ctx them_dcx; /* Cached AES 128 Decryption context */
- time_t keyexpire; /* When to expire/recreate key */
- int registerexpire;
- int lookuptimes[DUNDI_TIMING_HISTORY];
- char *lookups[DUNDI_TIMING_HISTORY];
- int avgms;
- struct dundi_transaction *regtrans; /* Registration transaction */
- struct dundi_transaction *qualtrans; /* Qualify transaction */
- struct dundi_transaction *keypending;
- int model; /* Pull model */
- int pcmodel; /* Push/precache model */
- int dynamic; /* Are we dynamic? */
- int lastms; /* Last measured latency */
- int maxms; /* Max permissible latency */
- struct timeval qualtx; /* Time of transmit */
- struct dundi_peer *next;
-} *peers;
-
-static struct dundi_precache_queue *pcq;
-
-AST_MUTEX_DEFINE_STATIC(peerlock);
-AST_MUTEX_DEFINE_STATIC(pclock);
-
-static int dundi_xmit(struct dundi_packet *pack);
-
-static void dundi_debug_output(const char *data)
-{
- if (dundidebug)
- ast_verbose("%s", data);
-}
-
-static void dundi_error_output(const char *data)
-{
- ast_log(LOG_WARNING, "%s", data);
-}
-
-static int has_permission(struct permission *ps, char *cont)
-{
- int res=0;
- while(ps) {
- if (!strcasecmp(ps->name, "all") || !strcasecmp(ps->name, cont))
- res = ps->allow;
- ps = ps->next;
- }
- return res;
-}
-
-static char *tech2str(int tech)
-{
- switch(tech) {
- case DUNDI_PROTO_NONE:
- return "None";
- case DUNDI_PROTO_IAX:
- return "IAX2";
- case DUNDI_PROTO_SIP:
- return "SIP";
- case DUNDI_PROTO_H323:
- return "H323";
- default:
- return "Unknown";
- }
-}
-
-static int str2tech(char *str)
-{
- if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2"))
- return DUNDI_PROTO_IAX;
- else if (!strcasecmp(str, "SIP"))
- return DUNDI_PROTO_SIP;
- else if (!strcasecmp(str, "H323"))
- return DUNDI_PROTO_H323;
- else
- return -1;
-}
-
-static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *md, int *expiration, int cybpass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[]);
-static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[]);
-static struct dundi_transaction *create_transaction(struct dundi_peer *p);
-static struct dundi_transaction *find_transaction(struct dundi_hdr *hdr, struct sockaddr_in *sin)
-{
- /* Look for an exact match first */
- struct dundi_transaction *trans;
- trans = alltrans;
- while(trans) {
- if (!inaddrcmp(&trans->addr, sin) &&
- ((trans->strans == (ntohs(hdr->dtrans) & 32767)) /* Matches our destination */ ||
- ((trans->dtrans == (ntohs(hdr->strans) & 32767)) && (!hdr->dtrans))) /* We match their destination */) {
- if (hdr->strans)
- trans->dtrans = ntohs(hdr->strans) & 32767;
- break;
- }
- trans = trans->allnext;
- }
- if (!trans) {
- switch(hdr->cmdresp & 0x7f) {
- case DUNDI_COMMAND_DPDISCOVER:
- case DUNDI_COMMAND_EIDQUERY:
- case DUNDI_COMMAND_PRECACHERQ:
- case DUNDI_COMMAND_REGREQ:
- case DUNDI_COMMAND_NULL:
- case DUNDI_COMMAND_ENCRYPT:
- if (hdr->strans) {
- /* Create new transaction */
- trans = create_transaction(NULL);
- if (trans) {
- memcpy(&trans->addr, sin, sizeof(trans->addr));
- trans->dtrans = ntohs(hdr->strans) & 32767;
- } else
- ast_log(LOG_WARNING, "Out of memory!\n");
- }
- break;
- default:
- break;
- }
- }
- return trans;
-}
-
-static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied);
-
-static int dundi_ack(struct dundi_transaction *trans, int final)
-{
- return dundi_send(trans, DUNDI_COMMAND_ACK, 0, final, NULL);
-}
-static void dundi_reject(struct dundi_hdr *h, struct sockaddr_in *sin)
-{
- struct {
- struct dundi_packet pack;
- struct dundi_hdr hdr;
- } tmp;
- struct dundi_transaction trans;
- /* Never respond to an INVALID with another INVALID */
- if (h->cmdresp == DUNDI_COMMAND_INVALID)
- return;
- memset(&tmp, 0, sizeof(tmp));
- memset(&trans, 0, sizeof(trans));
- memcpy(&trans.addr, sin, sizeof(trans.addr));
- tmp.hdr.strans = h->dtrans;
- tmp.hdr.dtrans = h->strans;
- tmp.hdr.iseqno = h->oseqno;
- tmp.hdr.oseqno = h->iseqno;
- tmp.hdr.cmdresp = DUNDI_COMMAND_INVALID;
- tmp.hdr.cmdflags = 0;
- tmp.pack.h = (struct dundi_hdr *)tmp.pack.data;
- tmp.pack.datalen = sizeof(struct dundi_hdr);
- tmp.pack.parent = &trans;
- dundi_xmit(&tmp.pack);
-}
-
-static void reset_global_eid(void)
-{
-#if defined(SIOCGIFHWADDR)
- int x,s;
- char eid_str[20];
- struct ifreq ifr;
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s > 0) {
- x = 0;
- for(x=0;x<10;x++) {
- memset(&ifr, 0, sizeof(ifr));
- snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth%d", x);
- if (!ioctl(s, SIOCGIFHWADDR, &ifr)) {
- memcpy(&global_eid, ((unsigned char *)&ifr.ifr_hwaddr) + 2, sizeof(global_eid));
- ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifr.ifr_name);
- close(s);
- return;
- }
- }
- close(s);
- }
-#else
-#if defined(ifa_broadaddr) && !defined(SOLARIS)
- char eid_str[20];
- struct ifaddrs *ifap;
-
- if (getifaddrs(&ifap) == 0) {
- struct ifaddrs *p;
- for (p = ifap; p; p = p->ifa_next) {
- if (p->ifa_addr->sa_family == AF_LINK) {
- struct sockaddr_dl* sdp = (struct sockaddr_dl*) p->ifa_addr;
- memcpy(
- &(global_eid.eid),
- sdp->sdl_data + sdp->sdl_nlen, 6);
- ast_log(LOG_DEBUG, "Seeding global EID '%s' from '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid), ifap->ifa_name);
- freeifaddrs(ifap);
- return;
- }
- }
- freeifaddrs(ifap);
- }
-#endif
-#endif
- ast_log(LOG_NOTICE, "No ethernet interface found for seeding global EID You will have to set it manually.\n");
-}
-
-static int get_trans_id(void)
-{
- struct dundi_transaction *t;
- int stid = (rand() % 32766) + 1;
- int tid = stid;
- do {
- t = alltrans;
- while(t) {
- if (t->strans == tid)
- break;
- t = t->allnext;
- }
- if (!t)
- return tid;
- tid = (tid % 32766) + 1;
- } while (tid != stid);
- return 0;
-}
-
-static int reset_transaction(struct dundi_transaction *trans)
-{
- int tid;
- tid = get_trans_id();
- if (tid < 1)
- return -1;
- trans->strans = tid;
- trans->dtrans = 0;
- trans->iseqno = 0;
- trans->oiseqno = 0;
- trans->oseqno = 0;
- trans->aseqno = 0;
- ast_clear_flag(trans, FLAG_FINAL);
- return 0;
-}
-
-static struct dundi_peer *find_peer(dundi_eid *eid)
-{
- struct dundi_peer *cur;
- if (!eid)
- eid = &empty_eid;
- cur = peers;
- while(cur) {
- if (!dundi_eid_cmp(&cur->eid,eid))
- return cur;
- cur = cur->next;
- }
- return NULL;
-}
-
-static void build_iv(unsigned char *iv)
-{
- /* XXX Would be nice to be more random XXX */
- unsigned int *fluffy;
- int x;
- fluffy = (unsigned int *)(iv);
- for (x=0;x<4;x++)
- fluffy[x] = rand();
-}
-
-struct dundi_query_state {
- dundi_eid *eids[DUNDI_MAX_STACK + 1];
- int directs[DUNDI_MAX_STACK + 1];
- dundi_eid reqeid;
- char called_context[AST_MAX_EXTENSION];
- char called_number[AST_MAX_EXTENSION];
- struct dundi_mapping *maps;
- int nummaps;
- int nocache;
- struct dundi_transaction *trans;
- void *chal;
- int challen;
- int ttl;
- char fluffy[0];
-};
-
-static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map, char *called_number, dundi_eid *us_eid, int anscnt, struct dundi_hint_metadata *hmd)
-{
- struct ast_flags flags = {0};
- int x;
- if (!ast_strlen_zero(map->lcontext)) {
- if (ast_exists_extension(NULL, map->lcontext, called_number, 1, NULL))
- ast_set_flag(&flags, DUNDI_FLAG_EXISTS);
- if (ast_canmatch_extension(NULL, map->lcontext, called_number, 1, NULL))
- ast_set_flag(&flags, DUNDI_FLAG_CANMATCH);
- if (ast_matchmore_extension(NULL, map->lcontext, called_number, 1, NULL))
- ast_set_flag(&flags, DUNDI_FLAG_MATCHMORE);
- if (ast_ignore_pattern(map->lcontext, called_number))
- ast_set_flag(&flags, DUNDI_FLAG_IGNOREPAT);
-
- /* Clearly we can't say 'don't ask' anymore if we found anything... */
- if (ast_test_flag(&flags, AST_FLAGS_ALL))
- ast_clear_flag_nonstd(hmd, DUNDI_HINT_DONT_ASK);
-
- if (map->options & DUNDI_FLAG_INTERNAL_NOPARTIAL) {
- /* Skip partial answers */
- ast_clear_flag(&flags, DUNDI_FLAG_MATCHMORE|DUNDI_FLAG_CANMATCH);
- }
- if (ast_test_flag(&flags, AST_FLAGS_ALL)) {
- struct varshead headp;
- struct ast_var_t *newvariable;
- ast_set_flag(&flags, map->options & 0xffff);
- ast_copy_flags(dr + anscnt, &flags, AST_FLAGS_ALL);
- dr[anscnt].techint = map->tech;
- dr[anscnt].weight = map->weight;
- dr[anscnt].expiration = dundi_cache_time;
- ast_copy_string(dr[anscnt].tech, tech2str(map->tech), sizeof(dr[anscnt].tech));
- dr[anscnt].eid = *us_eid;
- dundi_eid_to_str(dr[anscnt].eid_str, sizeof(dr[anscnt].eid_str), &dr[anscnt].eid);
- if (ast_test_flag(&flags, DUNDI_FLAG_EXISTS)) {
- AST_LIST_HEAD_INIT_NOLOCK(&headp);
- newvariable = ast_var_assign("NUMBER", called_number);
- AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
- newvariable = ast_var_assign("EID", dr[anscnt].eid_str);
- AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
- newvariable = ast_var_assign("SECRET", cursecret);
- AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
- newvariable = ast_var_assign("IPADDR", ipaddr);
- AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
- pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest));
- while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */
- newvariable = AST_LIST_REMOVE_HEAD(&headp, entries);
- ast_var_delete(newvariable);
- }
- } else
- dr[anscnt].dest[0] = '\0';
- anscnt++;
- } else {
- /* No answers... Find the fewest number of digits from the
- number for which we have no answer. */
- char tmp[AST_MAX_EXTENSION];
- for (x=0;x<AST_MAX_EXTENSION;x++) {
- tmp[x] = called_number[x];
- if (!tmp[x])
- break;
- if (!ast_canmatch_extension(NULL, map->lcontext, tmp, 1, NULL)) {
- /* Oops found something we can't match. If this is longer
- than the running hint, we have to consider it */
- if (strlen(tmp) > strlen(hmd->exten)) {
- ast_copy_string(hmd->exten, tmp, sizeof(hmd->exten));
- }
- break;
- }
- }
- }
- }
- return anscnt;
-}
-
-static void destroy_trans(struct dundi_transaction *trans, int fromtimeout);
-
-static void *dundi_lookup_thread(void *data)
-{
- struct dundi_query_state *st = data;
- struct dundi_result dr[MAX_RESULTS];
- struct dundi_ie_data ied;
- struct dundi_hint_metadata hmd;
- char eid_str[20];
- int res, x;
- int ouranswers=0;
- int max = 999999;
- int expiration = dundi_cache_time;
-
- ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
- st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
- memset(&ied, 0, sizeof(ied));
- memset(&dr, 0, sizeof(dr));
- memset(&hmd, 0, sizeof(hmd));
- /* Assume 'don't ask for anything' and 'unaffected', no TTL expired */
- hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
- for (x=0;x<st->nummaps;x++)
- ouranswers = dundi_lookup_local(dr, st->maps + x, st->called_number, &st->trans->us_eid, ouranswers, &hmd);
- if (ouranswers < 0)
- ouranswers = 0;
- for (x=0;x<ouranswers;x++) {
- if (dr[x].weight < max)
- max = dr[x].weight;
- }
-
- if (max) {
- /* If we do not have a canonical result, keep looking */
- res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, st->called_context, st->called_number, st->ttl, 1, &hmd, &expiration, st->nocache, 0, NULL, st->eids, st->directs);
- if (res > 0) {
- /* Append answer in result */
- ouranswers += res;
- } else {
- if ((res < -1) && (!ouranswers))
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_DUPLICATE, "Duplicate Request Pending");
- }
- }
- ast_mutex_lock(&peerlock);
- /* Truncate if "don't ask" isn't present */
- if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK))
- hmd.exten[0] = '\0';
- if (ast_test_flag(st->trans, FLAG_DEAD)) {
- ast_log(LOG_DEBUG, "Our transaction went away!\n");
- st->trans->thread = 0;
- destroy_trans(st->trans, 0);
- } else {
- for (x=0;x<ouranswers;x++) {
- /* Add answers */
- if (dr[x].expiration && (expiration > dr[x].expiration))
- expiration = dr[x].expiration;
- dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
- }
- dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
- dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
- dundi_send(st->trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
- st->trans->thread = 0;
- }
- ast_mutex_unlock(&peerlock);
- free(st);
- return NULL;
-}
-
-static void *dundi_precache_thread(void *data)
-{
- struct dundi_query_state *st = data;
- struct dundi_ie_data ied;
- struct dundi_hint_metadata hmd;
- char eid_str[20];
-
- ast_log(LOG_DEBUG, "Whee, precaching '%s@%s' for '%s'\n", st->called_number, st->called_context,
- st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
- memset(&ied, 0, sizeof(ied));
-
- /* Now produce precache */
- dundi_precache_internal(st->called_context, st->called_number, st->ttl, st->eids);
-
- ast_mutex_lock(&peerlock);
- /* Truncate if "don't ask" isn't present */
- if (!ast_test_flag_nonstd(&hmd, DUNDI_HINT_DONT_ASK))
- hmd.exten[0] = '\0';
- if (ast_test_flag(st->trans, FLAG_DEAD)) {
- ast_log(LOG_DEBUG, "Our transaction went away!\n");
- st->trans->thread = 0;
- destroy_trans(st->trans, 0);
- } else {
- dundi_send(st->trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
- st->trans->thread = 0;
- }
- ast_mutex_unlock(&peerlock);
- free(st);
- return NULL;
-}
-
-static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[]);
-
-static void *dundi_query_thread(void *data)
-{
- struct dundi_query_state *st = data;
- struct dundi_entity_info dei;
- struct dundi_ie_data ied;
- struct dundi_hint_metadata hmd;
- char eid_str[20];
- int res;
- ast_log(LOG_DEBUG, "Whee, looking up '%s@%s' for '%s'\n", st->called_number, st->called_context,
- st->eids[0] ? dundi_eid_to_str(eid_str, sizeof(eid_str), st->eids[0]) : "ourselves");
- memset(&ied, 0, sizeof(ied));
- memset(&dei, 0, sizeof(dei));
- memset(&hmd, 0, sizeof(hmd));
- if (!dundi_eid_cmp(&st->trans->us_eid, &st->reqeid)) {
- /* Ooh, it's us! */
- ast_log(LOG_DEBUG, "Neat, someone look for us!\n");
- ast_copy_string(dei.orgunit, dept, sizeof(dei.orgunit));
- ast_copy_string(dei.org, org, sizeof(dei.org));
- ast_copy_string(dei.locality, locality, sizeof(dei.locality));
- ast_copy_string(dei.stateprov, stateprov, sizeof(dei.stateprov));
- ast_copy_string(dei.country, country, sizeof(dei.country));
- ast_copy_string(dei.email, email, sizeof(dei.email));
- ast_copy_string(dei.phone, phone, sizeof(dei.phone));
- res = 1;
- } else {
- /* If we do not have a canonical result, keep looking */
- res = dundi_query_eid_internal(&dei, st->called_context, &st->reqeid, &hmd, st->ttl, 1, st->eids);
- }
- ast_mutex_lock(&peerlock);
- if (ast_test_flag(st->trans, FLAG_DEAD)) {
- ast_log(LOG_DEBUG, "Our transaction went away!\n");
- st->trans->thread = 0;
- destroy_trans(st->trans, 0);
- } else {
- if (res) {
- dundi_ie_append_str(&ied, DUNDI_IE_DEPARTMENT, dei.orgunit);
- dundi_ie_append_str(&ied, DUNDI_IE_ORGANIZATION, dei.org);
- dundi_ie_append_str(&ied, DUNDI_IE_LOCALITY, dei.locality);
- dundi_ie_append_str(&ied, DUNDI_IE_STATE_PROV, dei.stateprov);
- dundi_ie_append_str(&ied, DUNDI_IE_COUNTRY, dei.country);
- dundi_ie_append_str(&ied, DUNDI_IE_EMAIL, dei.email);
- dundi_ie_append_str(&ied, DUNDI_IE_PHONE, dei.phone);
- if (!ast_strlen_zero(dei.ipaddr))
- dundi_ie_append_str(&ied, DUNDI_IE_IPADDR, dei.ipaddr);
- }
- dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
- dundi_send(st->trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
- st->trans->thread = 0;
- }
- ast_mutex_unlock(&peerlock);
- free(st);
- return NULL;
-}
-
-static int dundi_answer_entity(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
-{
- struct dundi_query_state *st;
- int totallen;
- int x;
- int skipfirst=0;
- struct dundi_ie_data ied;
- char eid_str[20];
- char *s;
- pthread_t lookupthread;
- pthread_attr_t attr;
- if (ies->eidcount > 1) {
- /* Since it is a requirement that the first EID is the authenticating host
- and the last EID is the root, it is permissible that the first and last EID
- could be the same. In that case, we should go ahead copy only the "root" section
- since we will not need it for authentication. */
- if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
- skipfirst = 1;
- }
- totallen = sizeof(struct dundi_query_state);
- totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
- st = malloc(totallen);
- if (st) {
- memset(st, 0, totallen);
- ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
- memcpy(&st->reqeid, ies->reqeid, sizeof(st->reqeid));
- st->trans = trans;
- st->ttl = ies->ttl - 1;
- if (st->ttl < 0)
- st->ttl = 0;
- s = st->fluffy;
- for (x=skipfirst;ies->eids[x];x++) {
- st->eids[x-skipfirst] = (dundi_eid *)s;
- *st->eids[x-skipfirst] = *ies->eids[x];
- s += sizeof(dundi_eid);
- }
- ast_log(LOG_DEBUG, "Answering EID query for '%s@%s'!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), ies->reqeid), ies->called_context);
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- trans->thread = 1;
- if (ast_pthread_create(&lookupthread, &attr, dundi_query_thread, st)) {
- trans->thread = 0;
- ast_log(LOG_WARNING, "Unable to create thread!\n");
- free(st);
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
- dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
- return -1;
- }
- } else {
- ast_log(LOG_WARNING, "Out of memory!\n");
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
- dundi_send(trans, DUNDI_COMMAND_EIDRESPONSE, 0, 1, &ied);
- return -1;
- }
- return 0;
-}
-
-static int cache_save_hint(dundi_eid *eidpeer, struct dundi_request *req, struct dundi_hint *hint, int expiration)
-{
- int unaffected;
- char key1[256];
- char key2[256];
- char eidpeer_str[20];
- char eidroot_str[20];
- char data[80];
- time_t timeout;
-
- if (expiration < 0)
- expiration = dundi_cache_time;
-
- /* Only cache hint if "don't ask" is there... */
- if (!ast_test_flag_nonstd(hint, htons(DUNDI_HINT_DONT_ASK)))
- return 0;
-
- unaffected = ast_test_flag_nonstd(hint, htons(DUNDI_HINT_UNAFFECTED));
-
- dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
- dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
- snprintf(key1, sizeof(key1), "hint/%s/%s/%s/e%08lx", eidpeer_str, hint->data, req->dcontext, unaffected ? 0 : req->crc32);
- snprintf(key2, sizeof(key2), "hint/%s/%s/%s/r%s", eidpeer_str, hint->data, req->dcontext, eidroot_str);
-
- time(&timeout);
- timeout += expiration;
- snprintf(data, sizeof(data), "%ld|", (long)(timeout));
-
- ast_db_put("dundi/cache", key1, data);
- ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key1);
- ast_db_put("dundi/cache", key2, data);
- ast_log(LOG_DEBUG, "Caching hint at '%s'\n", key2);
- return 0;
-}
-
-static int cache_save(dundi_eid *eidpeer, struct dundi_request *req, int start, int unaffected, int expiration, int push)
-{
- int x;
- char key1[256];
- char key2[256];
- char data[1024];
- char eidpeer_str[20];
- char eidroot_str[20];
- time_t timeout;
-
- if (expiration < 1)
- expiration = dundi_cache_time;
-
- /* Keep pushes a little longer, cut pulls a little short */
- if (push)
- expiration += 10;
- else
- expiration -= 10;
- if (expiration < 1)
- expiration = 1;
- dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), eidpeer);
- dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
- snprintf(key1, sizeof(key1), "%s/%s/%s/e%08lx", eidpeer_str, req->number, req->dcontext, unaffected ? 0 : req->crc32);
- snprintf(key2, sizeof(key2), "%s/%s/%s/r%s", eidpeer_str, req->number, req->dcontext, eidroot_str);
- /* Build request string */
- time(&timeout);
- timeout += expiration;
- snprintf(data, sizeof(data), "%ld|", (long)(timeout));
- for (x=start;x<req->respcount;x++) {
- /* Skip anything with an illegal pipe in it */
- if (strchr(req->dr[x].dest, '|'))
- continue;
- snprintf(data + strlen(data), sizeof(data) - strlen(data), "%d/%d/%d/%s/%s|",
- req->dr[x].flags, req->dr[x].weight, req->dr[x].techint, req->dr[x].dest,
- dundi_eid_to_str_short(eidpeer_str, sizeof(eidpeer_str), &req->dr[x].eid));
- }
- ast_db_put("dundi/cache", key1, data);
- ast_db_put("dundi/cache", key2, data);
- return 0;
-}
-
-static int dundi_prop_precache(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
-{
- struct dundi_query_state *st;
- int totallen;
- int x,z;
- struct dundi_ie_data ied;
- char *s;
- struct dundi_result dr2[MAX_RESULTS];
- struct dundi_request dr;
- struct dundi_hint_metadata hmd;
-
- struct dundi_mapping *cur;
- int mapcount;
- int skipfirst = 0;
-
- pthread_t lookupthread;
- pthread_attr_t attr;
-
- memset(&dr2, 0, sizeof(dr2));
- memset(&dr, 0, sizeof(dr));
- memset(&hmd, 0, sizeof(hmd));
-
- /* Forge request structure to hold answers for cache */
- hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
- dr.dr = dr2;
- dr.maxcount = MAX_RESULTS;
- dr.expiration = dundi_cache_time;
- dr.hmd = &hmd;
- dr.pfds[0] = dr.pfds[1] = -1;
- trans->parent = &dr;
- ast_copy_string(dr.dcontext, ies->called_context ? ies->called_context : "e164", sizeof(dr.dcontext));
- ast_copy_string(dr.number, ies->called_number, sizeof(dr.number));
-
- for (x=0;x<ies->anscount;x++) {
- if (trans->parent->respcount < trans->parent->maxcount) {
- /* Make sure it's not already there */
- for (z=0;z<trans->parent->respcount;z++) {
- if ((trans->parent->dr[z].techint == ies->answers[x]->protocol) &&
- !strcmp(trans->parent->dr[z].dest, (char *)ies->answers[x]->data))
- break;
- }
- if (z == trans->parent->respcount) {
- /* Copy into parent responses */
- trans->parent->dr[trans->parent->respcount].flags = ntohs(ies->answers[x]->flags);
- trans->parent->dr[trans->parent->respcount].techint = ies->answers[x]->protocol;
- trans->parent->dr[trans->parent->respcount].weight = ntohs(ies->answers[x]->weight);
- trans->parent->dr[trans->parent->respcount].eid = ies->answers[x]->eid;
- if (ies->expiration > 0)
- trans->parent->dr[trans->parent->respcount].expiration = ies->expiration;
- else
- trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
- dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str,
- sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
- &ies->answers[x]->eid);
- ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies->answers[x]->data,
- sizeof(trans->parent->dr[trans->parent->respcount].dest));
- ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies->answers[x]->protocol),
- sizeof(trans->parent->dr[trans->parent->respcount].tech));
- trans->parent->respcount++;
- ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);
- } else if (trans->parent->dr[z].weight > ies->answers[x]->weight) {
- /* Update weight if appropriate */
- trans->parent->dr[z].weight = ies->answers[x]->weight;
- }
- } else
- ast_log(LOG_NOTICE, "Dropping excessive answers in precache for %s@%s\n",
- trans->parent->number, trans->parent->dcontext);
-
- }
- /* Save all the results (if any) we had. Even if no results, still cache lookup. */
- cache_save(&trans->them_eid, trans->parent, 0, 0, ies->expiration, 1);
- if (ies->hint)
- cache_save_hint(&trans->them_eid, trans->parent, ies->hint, ies->expiration);
-
- totallen = sizeof(struct dundi_query_state);
- /* Count matching map entries */
- mapcount = 0;
- cur = mappings;
- while(cur) {
- if (!strcasecmp(cur->dcontext, ccontext))
- mapcount++;
- cur = cur->next;
- }
-
- /* If no maps, return -1 immediately */
- if (!mapcount)
- return -1;
-
- if (ies->eidcount > 1) {
- /* Since it is a requirement that the first EID is the authenticating host
- and the last EID is the root, it is permissible that the first and last EID
- could be the same. In that case, we should go ahead copy only the "root" section
- since we will not need it for authentication. */
- if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
- skipfirst = 1;
- }
-
- /* Prepare to run a query and then propagate that as necessary */
- totallen += mapcount * sizeof(struct dundi_mapping);
- totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
- st = malloc(totallen);
- if (st) {
- memset(st, 0, totallen);
- ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
- ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
- st->trans = trans;
- st->ttl = ies->ttl - 1;
- st->nocache = ies->cbypass;
- if (st->ttl < 0)
- st->ttl = 0;
- s = st->fluffy;
- for (x=skipfirst;ies->eids[x];x++) {
- st->eids[x-skipfirst] = (dundi_eid *)s;
- *st->eids[x-skipfirst] = *ies->eids[x];
- st->directs[x-skipfirst] = ies->eid_direct[x];
- s += sizeof(dundi_eid);
- }
- /* Append mappings */
- x = 0;
- st->maps = (struct dundi_mapping *)s;
- cur = mappings;
- while(cur) {
- if (!strcasecmp(cur->dcontext, ccontext)) {
- if (x < mapcount) {
- st->maps[x] = *cur;
- st->maps[x].next = NULL;
- x++;
- }
- }
- cur = cur->next;
- }
- st->nummaps = mapcount;
- ast_log(LOG_DEBUG, "Forwarding precache for '%s@%s'!\n", ies->called_number, ies->called_context);
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- trans->thread = 1;
- if (ast_pthread_create(&lookupthread, &attr, dundi_precache_thread, st)) {
- trans->thread = 0;
- ast_log(LOG_WARNING, "Unable to create thread!\n");
- free(st);
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
- dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
- return -1;
- }
- } else {
- ast_log(LOG_WARNING, "Out of memory!\n");
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
- dundi_send(trans, DUNDI_COMMAND_PRECACHERP, 0, 1, &ied);
- return -1;
- }
- return 0;
-}
-
-static int dundi_answer_query(struct dundi_transaction *trans, struct dundi_ies *ies, char *ccontext)
-{
- struct dundi_query_state *st;
- int totallen;
- int x;
- struct dundi_ie_data ied;
- char *s;
- struct dundi_mapping *cur;
- int mapcount;
- int skipfirst = 0;
-
- pthread_t lookupthread;
- pthread_attr_t attr;
- totallen = sizeof(struct dundi_query_state);
- /* Count matching map entries */
- mapcount = 0;
- cur = mappings;
- while(cur) {
- if (!strcasecmp(cur->dcontext, ccontext))
- mapcount++;
- cur = cur->next;
- }
- /* If no maps, return -1 immediately */
- if (!mapcount)
- return -1;
-
- if (ies->eidcount > 1) {
- /* Since it is a requirement that the first EID is the authenticating host
- and the last EID is the root, it is permissible that the first and last EID
- could be the same. In that case, we should go ahead copy only the "root" section
- since we will not need it for authentication. */
- if (!dundi_eid_cmp(ies->eids[0], ies->eids[ies->eidcount - 1]))
- skipfirst = 1;
- }
-
- totallen += mapcount * sizeof(struct dundi_mapping);
- totallen += (ies->eidcount - skipfirst) * sizeof(dundi_eid);
- st = malloc(totallen);
- if (st) {
- memset(st, 0, totallen);
- ast_copy_string(st->called_context, ies->called_context, sizeof(st->called_context));
- ast_copy_string(st->called_number, ies->called_number, sizeof(st->called_number));
- st->trans = trans;
- st->ttl = ies->ttl - 1;
- st->nocache = ies->cbypass;
- if (st->ttl < 0)
- st->ttl = 0;
- s = st->fluffy;
- for (x=skipfirst;ies->eids[x];x++) {
- st->eids[x-skipfirst] = (dundi_eid *)s;
- *st->eids[x-skipfirst] = *ies->eids[x];
- st->directs[x-skipfirst] = ies->eid_direct[x];
- s += sizeof(dundi_eid);
- }
- /* Append mappings */
- x = 0;
- st->maps = (struct dundi_mapping *)s;
- cur = mappings;
- while(cur) {
- if (!strcasecmp(cur->dcontext, ccontext)) {
- if (x < mapcount) {
- st->maps[x] = *cur;
- st->maps[x].next = NULL;
- x++;
- }
- }
- cur = cur->next;
- }
- st->nummaps = mapcount;
- ast_log(LOG_DEBUG, "Answering query for '%s@%s'!\n", ies->called_number, ies->called_context);
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- trans->thread = 1;
- if (ast_pthread_create(&lookupthread, &attr, dundi_lookup_thread, st)) {
- trans->thread = 0;
- ast_log(LOG_WARNING, "Unable to create thread!\n");
- free(st);
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of threads");
- dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
- return -1;
- }
- } else {
- ast_log(LOG_WARNING, "Out of memory!\n");
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Out of memory");
- dundi_send(trans, DUNDI_COMMAND_DPRESPONSE, 0, 1, &ied);
- return -1;
- }
- return 0;
-}
-
-static int cache_lookup_internal(time_t now, struct dundi_request *req, char *key, char *eid_str_full, int *lowexpiration)
-{
- char data[1024];
- char *ptr, *term, *src;
- int tech;
- struct ast_flags flags;
- int weight;
- int length;
- int z;
- int expiration;
- char fs[256];
- time_t timeout;
- /* Build request string */
- if (!ast_db_get("dundi/cache", key, data, sizeof(data))) {
- ptr = data;
- if (sscanf(ptr, "%d|%n", (int *)&timeout, &length) == 1) {
- expiration = timeout - now;
- if (expiration > 0) {
- ast_log(LOG_DEBUG, "Found cache expiring in %d seconds!\n", (int)(timeout - now));
- ptr += length;
- while((sscanf(ptr, "%d/%d/%d/%n", &(flags.flags), &weight, &tech, &length) == 3)) {
- ptr += length;
- term = strchr(ptr, '|');
- if (term) {
- *term = '\0';
- src = strrchr(ptr, '/');
- if (src) {
- *src = '\0';
- src++;
- } else
- src = "";
- ast_log(LOG_DEBUG, "Found cached answer '%s/%s' originally from '%s' with flags '%s' on behalf of '%s'\n",
- tech2str(tech), ptr, src, dundi_flags2str(fs, sizeof(fs), flags.flags), eid_str_full);
- /* Make sure it's not already there */
- for (z=0;z<req->respcount;z++) {
- if ((req->dr[z].techint == tech) &&
- !strcmp(req->dr[z].dest, ptr))
- break;
- }
- if (z == req->respcount) {
- /* Copy into parent responses */
- ast_copy_flags(&(req->dr[req->respcount]), &flags, AST_FLAGS_ALL);
- req->dr[req->respcount].weight = weight;
- req->dr[req->respcount].techint = tech;
- req->dr[req->respcount].expiration = expiration;
- dundi_str_short_to_eid(&req->dr[req->respcount].eid, src);
- dundi_eid_to_str(req->dr[req->respcount].eid_str,
- sizeof(req->dr[req->respcount].eid_str), &req->dr[req->respcount].eid);
- ast_copy_string(req->dr[req->respcount].dest, ptr,
- sizeof(req->dr[req->respcount].dest));
- ast_copy_string(req->dr[req->respcount].tech, tech2str(tech),
- sizeof(req->dr[req->respcount].tech));
- req->respcount++;
- ast_clear_flag_nonstd(req->hmd, DUNDI_HINT_DONT_ASK);
- } else if (req->dr[z].weight > weight)
- req->dr[z].weight = weight;
- ptr = term + 1;
- }
- }
- /* We found *something* cached */
- if (expiration < *lowexpiration)
- *lowexpiration = expiration;
- return 1;
- } else
- ast_db_del("dundi/cache", key);
- } else
- ast_db_del("dundi/cache", key);
- }
-
- return 0;
-}
-
-static int cache_lookup(struct dundi_request *req, dundi_eid *peer_eid, unsigned long crc32, int *lowexpiration)
-{
- char key[256];
- char eid_str[20];
- char eidroot_str[20];
- time_t now;
- int res=0;
- int res2=0;
- char eid_str_full[20];
- char tmp[256]="";
- int x;
-
- time(&now);
- dundi_eid_to_str_short(eid_str, sizeof(eid_str), peer_eid);
- dundi_eid_to_str_short(eidroot_str, sizeof(eidroot_str), &req->root_eid);
- dundi_eid_to_str(eid_str_full, sizeof(eid_str_full), peer_eid);
- snprintf(key, sizeof(key), "%s/%s/%s/e%08lx", eid_str, req->number, req->dcontext, crc32);
- res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
- snprintf(key, sizeof(key), "%s/%s/%s/e%08lx", eid_str, req->number, req->dcontext, 0L);
- res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
- snprintf(key, sizeof(key), "%s/%s/%s/r%s", eid_str, req->number, req->dcontext, eidroot_str);
- res |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
- x = 0;
- if (!req->respcount) {
- while(!res2) {
- /* Look and see if we have a hint that would preclude us from looking at this
- peer for this number. */
- if (!(tmp[x] = req->number[x]))
- break;
- x++;
- /* Check for hints */
- snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08lx", eid_str, tmp, req->dcontext, crc32);
- res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
- snprintf(key, sizeof(key), "hint/%s/%s/%s/e%08lx", eid_str, tmp, req->dcontext, 0L);
- res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
- snprintf(key, sizeof(key), "hint/%s/%s/%s/r%s", eid_str, tmp, req->dcontext, eidroot_str);
- res2 |= cache_lookup_internal(now, req, key, eid_str_full, lowexpiration);
- if (res2) {
- if (strlen(tmp) > strlen(req->hmd->exten)) {
- /* Update meta data if appropriate */
- ast_copy_string(req->hmd->exten, tmp, sizeof(req->hmd->exten));
- }
- }
- }
- res |= res2;
- }
-
- return res;
-}
-
-static void qualify_peer(struct dundi_peer *peer, int schedonly);
-
-static void apply_peer(struct dundi_transaction *trans, struct dundi_peer *p)
-{
- if (!trans->addr.sin_addr.s_addr)
- memcpy(&trans->addr, &p->addr, sizeof(trans->addr));
- trans->us_eid = p->us_eid;
- trans->them_eid = p->eid;
- /* Enable encryption if appropriate */
- if (!ast_strlen_zero(p->inkey))
- ast_set_flag(trans, FLAG_ENCRYPT);
- if (p->maxms) {
- trans->autokilltimeout = p->maxms;
- trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
- if (p->lastms > 1) {
- trans->retranstimer = p->lastms * 2;
- /* Keep it from being silly */
- if (trans->retranstimer < 150)
- trans->retranstimer = 150;
- }
- if (trans->retranstimer > DUNDI_DEFAULT_RETRANS_TIMER)
- trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
- } else
- trans->autokilltimeout = global_autokilltimeout;
-}
-
-static int do_register_expire(void *data)
-{
- struct dundi_peer *peer = data;
- char eid_str[20];
- /* Called with peerlock already held */
- ast_log(LOG_DEBUG, "Register expired for '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- peer->registerexpire = -1;
- peer->lastms = 0;
- memset(&peer->addr, 0, sizeof(peer->addr));
- return 0;
-}
-
-static int update_key(struct dundi_peer *peer)
-{
- unsigned char key[16];
- struct ast_key *ekey, *skey;
- char eid_str[20];
- int res;
- if (!peer->keyexpire || (peer->keyexpire < time(NULL))) {
- build_iv(key);
- aes_encrypt_key128(key, &peer->us_ecx);
- aes_decrypt_key128(key, &peer->us_dcx);
- ekey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
- if (!ekey) {
- ast_log(LOG_NOTICE, "No such key '%s' for creating RSA encrypted shared key for '%s'!\n",
- peer->inkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- return -1;
- }
- skey = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
- if (!skey) {
- ast_log(LOG_NOTICE, "No such key '%s' for signing RSA encrypted shared key for '%s'!\n",
- peer->outkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- return -1;
- }
- if ((res = ast_encrypt_bin(peer->txenckey, key, sizeof(key), ekey)) != 128) {
- ast_log(LOG_NOTICE, "Whoa, got a weird encrypt size (%d != %d)!\n", res, 128);
- return -1;
- }
- if ((res = ast_sign_bin(skey, (char *)peer->txenckey, 128, peer->txenckey + 128))) {
- ast_log(LOG_NOTICE, "Failed to sign key (%d)!\n", res);
- return -1;
- }
- peer->us_keycrc32 = crc32(0L, peer->txenckey, 128);
- peer->sentfullkey = 0;
- /* Looks good */
- time(&peer->keyexpire);
- peer->keyexpire += dundi_key_ttl;
- }
- return 0;
-}
-
-static int encrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, aes_encrypt_ctx *ecx)
-{
- unsigned char curblock[16];
- int x;
- memcpy(curblock, iv, sizeof(curblock));
- while(len > 0) {
- for (x=0;x<16;x++)
- curblock[x] ^= src[x];
- aes_encrypt(curblock, dst, ecx);
- memcpy(curblock, dst, sizeof(curblock));
- dst += 16;
- src += 16;
- len -= 16;
- }
- return 0;
-}
-static int decrypt_memcpy(unsigned char *dst, unsigned char *src, int len, unsigned char *iv, aes_decrypt_ctx *dcx)
-{
- unsigned char lastblock[16];
- int x;
- memcpy(lastblock, iv, sizeof(lastblock));
- while(len > 0) {
- aes_decrypt(src, dst, dcx);
- for (x=0;x<16;x++)
- dst[x] ^= lastblock[x];
- memcpy(lastblock, src, sizeof(lastblock));
- dst += 16;
- src += 16;
- len -= 16;
- }
- return 0;
-}
-
-static struct dundi_hdr *dundi_decrypt(struct dundi_transaction *trans, unsigned char *dst, int *dstlen, struct dundi_hdr *ohdr, struct dundi_encblock *src, int srclen)
-{
- int space = *dstlen;
- unsigned long bytes;
- struct dundi_hdr *h;
- unsigned char *decrypt_space;
- decrypt_space = alloca(srclen);
- if (!decrypt_space)
- return NULL;
- decrypt_memcpy(decrypt_space, src->encdata, srclen, src->iv, &trans->dcx);
- /* Setup header */
- h = (struct dundi_hdr *)dst;
- *h = *ohdr;
- bytes = space - 6;
- if (uncompress(dst + 6, &bytes, decrypt_space, srclen) != Z_OK) {
- ast_log(LOG_DEBUG, "Ouch, uncompress failed :(\n");
- return NULL;
- }
- /* Update length */
- *dstlen = bytes + 6;
- /* Return new header */
- return h;
-}
-
-static int dundi_encrypt(struct dundi_transaction *trans, struct dundi_packet *pack)
-{
- unsigned char *compress_space;
- int len;
- int res;
- unsigned long bytes;
- struct dundi_ie_data ied;
- struct dundi_peer *peer;
- unsigned char iv[16];
- len = pack->datalen + pack->datalen / 100 + 42;
- compress_space = alloca(len);
- if (compress_space) {
- memset(compress_space, 0, len);
- /* We care about everthing save the first 6 bytes of header */
- bytes = len;
- res = compress(compress_space, &bytes, pack->data + 6, pack->datalen - 6);
- if (res != Z_OK) {
- ast_log(LOG_DEBUG, "Ouch, compression failed!\n");
- return -1;
- }
- memset(&ied, 0, sizeof(ied));
- /* Say who we are */
- if (!pack->h->iseqno && !pack->h->oseqno) {
- /* Need the key in the first copy */
- if (!(peer = find_peer(&trans->them_eid)))
- return -1;
- if (update_key(peer))
- return -1;
- if (!peer->sentfullkey)
- ast_set_flag(trans, FLAG_SENDFULLKEY);
- /* Append key data */
- dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
- if (ast_test_flag(trans, FLAG_SENDFULLKEY)) {
- dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128);
- dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
- } else {
- dundi_ie_append_int(&ied, DUNDI_IE_KEYCRC32, peer->us_keycrc32);
- }
- /* Setup contexts */
- trans->ecx = peer->us_ecx;
- trans->dcx = peer->us_dcx;
-
- /* We've sent the full key */
- peer->sentfullkey = 1;
- }
- /* Build initialization vector */
- build_iv(iv);
- /* Add the field, rounded up to 16 bytes */
- dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, iv, NULL, ((bytes + 15) / 16) * 16);
- /* Copy the data */
- if ((ied.pos + bytes) >= sizeof(ied.buf)) {
- ast_log(LOG_NOTICE, "Final packet too large!\n");
- return -1;
- }
- encrypt_memcpy(ied.buf + ied.pos, compress_space, bytes, iv, &trans->ecx);
- ied.pos += ((bytes + 15) / 16) * 16;
- /* Reconstruct header */
- pack->datalen = sizeof(struct dundi_hdr);
- pack->h->cmdresp = DUNDI_COMMAND_ENCRYPT;
- pack->h->cmdflags = 0;
- memcpy(pack->h->ies, ied.buf, ied.pos);
- pack->datalen += ied.pos;
- return 0;
- }
- return -1;
-}
-
-static int check_key(struct dundi_peer *peer, unsigned char *newkey, unsigned char *newsig, unsigned long keycrc32)
-{
- unsigned char dst[128];
- int res;
- struct ast_key *key, *skey;
- char eid_str[20];
- if (option_debug)
- ast_log(LOG_DEBUG, "Expected '%08lx' got '%08lx'\n", peer->them_keycrc32, keycrc32);
- if (peer->them_keycrc32 && (peer->them_keycrc32 == keycrc32)) {
- /* A match */
- return 1;
- } else if (!newkey || !newsig)
- return 0;
- if (!memcmp(peer->rxenckey, newkey, 128) &&
- !memcmp(peer->rxenckey + 128, newsig, 128)) {
- /* By definition, a match */
- return 1;
- }
- /* Decrypt key */
- key = ast_key_get(peer->outkey, AST_KEY_PRIVATE);
- if (!key) {
- ast_log(LOG_NOTICE, "Unable to find key '%s' to decode shared key from '%s'\n",
- peer->outkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- return -1;
- }
-
- skey = ast_key_get(peer->inkey, AST_KEY_PUBLIC);
- if (!skey) {
- ast_log(LOG_NOTICE, "Unable to find key '%s' to verify shared key from '%s'\n",
- peer->inkey, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- return -1;
- }
-
- /* First check signature */
- res = ast_check_signature_bin(skey, (char *)newkey, 128, newsig);
- if (res)
- return 0;
-
- res = ast_decrypt_bin(dst, newkey, sizeof(dst), key);
- if (res != 16) {
- if (res >= 0)
- ast_log(LOG_NOTICE, "Weird, key decoded to the wrong size (%d)\n", res);
- return 0;
- }
- /* Decrypted, passes signature */
- ast_log(LOG_DEBUG, "Wow, new key combo passed signature and decrypt!\n");
- memcpy(peer->rxenckey, newkey, 128);
- memcpy(peer->rxenckey + 128, newsig, 128);
- peer->them_keycrc32 = crc32(0L, peer->rxenckey, 128);
- aes_decrypt_key128(dst, &peer->them_dcx);
- aes_encrypt_key128(dst, &peer->them_ecx);
- return 1;
-}
-
-static int handle_command_response(struct dundi_transaction *trans, struct dundi_hdr *hdr, int datalen, int encrypted)
-{
- /* Handle canonical command / response */
- int final = hdr->cmdresp & 0x80;
- int cmd = hdr->cmdresp & 0x7f;
- int x,y,z;
- int resp;
- int res;
- int authpass=0;
- unsigned char *bufcpy;
- struct dundi_ie_data ied;
- struct dundi_ies ies;
- struct dundi_peer *peer;
- char eid_str[20];
- char eid_str2[20];
- memset(&ied, 0, sizeof(ied));
- memset(&ies, 0, sizeof(ies));
- if (datalen) {
- bufcpy = alloca(datalen);
- if (!bufcpy)
- return -1;
- /* Make a copy for parsing */
- memcpy(bufcpy, hdr->ies, datalen);
- ast_log(LOG_DEBUG, "Got canonical message %d (%d), %d bytes data%s\n", cmd, hdr->oseqno, datalen, final ? " (Final)" : "");
- if (dundi_parse_ies(&ies, bufcpy, datalen) < 0) {
- ast_log(LOG_WARNING, "Failed to parse DUNDI information elements!\n");
- return -1;
- }
- }
- switch(cmd) {
- case DUNDI_COMMAND_DPDISCOVER:
- case DUNDI_COMMAND_EIDQUERY:
- case DUNDI_COMMAND_PRECACHERQ:
- if (cmd == DUNDI_COMMAND_EIDQUERY)
- resp = DUNDI_COMMAND_EIDRESPONSE;
- else if (cmd == DUNDI_COMMAND_PRECACHERQ)
- resp = DUNDI_COMMAND_PRECACHERP;
- else
- resp = DUNDI_COMMAND_DPRESPONSE;
- /* A dialplan or entity discover -- qualify by highest level entity */
- peer = find_peer(ies.eids[0]);
- if (!peer) {
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL);
- dundi_send(trans, resp, 0, 1, &ied);
- } else {
- int hasauth = 0;
- trans->us_eid = peer->us_eid;
- if (strlen(peer->inkey)) {
- hasauth = encrypted;
- } else
- hasauth = 1;
- if (hasauth) {
- /* Okay we're authentiated and all, now we check if they're authorized */
- if (!ies.called_context)
- ies.called_context = "e164";
- if (cmd == DUNDI_COMMAND_EIDQUERY) {
- res = dundi_answer_entity(trans, &ies, ies.called_context);
- } else {
- if (ast_strlen_zero(ies.called_number)) {
- /* They're not permitted to access that context */
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_GENERAL, "Invalid or missing number/entity");
- dundi_send(trans, resp, 0, 1, &ied);
- } else if ((cmd == DUNDI_COMMAND_DPDISCOVER) &&
- (peer->model & DUNDI_MODEL_INBOUND) &&
- has_permission(peer->permit, ies.called_context)) {
- res = dundi_answer_query(trans, &ies, ies.called_context);
- if (res < 0) {
- /* There is no such dundi context */
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
- dundi_send(trans, resp, 0, 1, &ied);
- }
- } else if ((cmd = DUNDI_COMMAND_PRECACHERQ) &&
- (peer->pcmodel & DUNDI_MODEL_INBOUND) &&
- has_permission(peer->include, ies.called_context)) {
- res = dundi_prop_precache(trans, &ies, ies.called_context);
- if (res < 0) {
- /* There is no such dundi context */
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unsupported DUNDI Context");
- dundi_send(trans, resp, 0, 1, &ied);
- }
- } else {
- /* They're not permitted to access that context */
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Permission to context denied");
- dundi_send(trans, resp, 0, 1, &ied);
- }
- }
- } else {
- /* They're not permitted to access that context */
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Unencrypted responses not permitted");
- dundi_send(trans, resp, 0, 1, &ied);
- }
- }
- break;
- case DUNDI_COMMAND_REGREQ:
- /* A register request -- should only have one entity */
- peer = find_peer(ies.eids[0]);
- if (!peer || !peer->dynamic) {
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, NULL);
- dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, &ied);
- } else {
- int hasauth = 0;
- trans->us_eid = peer->us_eid;
- if (!ast_strlen_zero(peer->inkey)) {
- hasauth = encrypted;
- } else
- hasauth = 1;
- if (hasauth) {
- int expire = default_expiration;
- char iabuf[INET_ADDRSTRLEN];
- char data[256];
- int needqual = 0;
- if (peer->registerexpire > -1)
- ast_sched_del(sched, peer->registerexpire);
- peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
- ast_inet_ntoa(iabuf, sizeof(iabuf), trans->addr.sin_addr);
- snprintf(data, sizeof(data), "%s:%d:%d", iabuf, ntohs(trans->addr.sin_port), expire);
- ast_db_put("dundi/dpeers", dundi_eid_to_str_short(eid_str, sizeof(eid_str), &peer->eid), data);
- if (inaddrcmp(&peer->addr, &trans->addr)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Registered DUNDi peer '%s' at '%s:%d'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), iabuf, ntohs(trans->addr.sin_port));
- needqual = 1;
- }
-
- memcpy(&peer->addr, &trans->addr, sizeof(peer->addr));
- dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration);
- dundi_send(trans, DUNDI_COMMAND_REGRESPONSE, 0, 1, &ied);
- if (needqual)
- qualify_peer(peer, 1);
- }
- }
- break;
- case DUNDI_COMMAND_DPRESPONSE:
- /* A dialplan response, lets see what we got... */
- if (ies.cause < 1) {
- /* Success of some sort */
- ast_log(LOG_DEBUG, "Looks like success of some sort (%d), %d answers\n", ies.cause, ies.anscount);
- if (ast_test_flag(trans, FLAG_ENCRYPT)) {
- authpass = encrypted;
- } else
- authpass = 1;
- if (authpass) {
- /* Pass back up answers */
- if (trans->parent && trans->parent->dr) {
- y = trans->parent->respcount;
- for (x=0;x<ies.anscount;x++) {
- if (trans->parent->respcount < trans->parent->maxcount) {
- /* Make sure it's not already there */
- for (z=0;z<trans->parent->respcount;z++) {
- if ((trans->parent->dr[z].techint == ies.answers[x]->protocol) &&
- !strcmp(trans->parent->dr[z].dest, (char *)ies.answers[x]->data))
- break;
- }
- if (z == trans->parent->respcount) {
- /* Copy into parent responses */
- trans->parent->dr[trans->parent->respcount].flags = ntohs(ies.answers[x]->flags);
- trans->parent->dr[trans->parent->respcount].techint = ies.answers[x]->protocol;
- trans->parent->dr[trans->parent->respcount].weight = ntohs(ies.answers[x]->weight);
- trans->parent->dr[trans->parent->respcount].eid = ies.answers[x]->eid;
- if (ies.expiration > 0)
- trans->parent->dr[trans->parent->respcount].expiration = ies.expiration;
- else
- trans->parent->dr[trans->parent->respcount].expiration = dundi_cache_time;
- dundi_eid_to_str(trans->parent->dr[trans->parent->respcount].eid_str,
- sizeof(trans->parent->dr[trans->parent->respcount].eid_str),
- &ies.answers[x]->eid);
- ast_copy_string(trans->parent->dr[trans->parent->respcount].dest, (char *)ies.answers[x]->data,
- sizeof(trans->parent->dr[trans->parent->respcount].dest));
- ast_copy_string(trans->parent->dr[trans->parent->respcount].tech, tech2str(ies.answers[x]->protocol),
- sizeof(trans->parent->dr[trans->parent->respcount].tech));
- trans->parent->respcount++;
- ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);
- } else if (trans->parent->dr[z].weight > ies.answers[x]->weight) {
- /* Update weight if appropriate */
- trans->parent->dr[z].weight = ies.answers[x]->weight;
- }
- } else
- ast_log(LOG_NOTICE, "Dropping excessive answers to request for %s@%s\n",
- trans->parent->number, trans->parent->dcontext);
- }
- /* Save all the results (if any) we had. Even if no results, still cache lookup. Let
- the cache know if this request was unaffected by our entity list. */
- cache_save(&trans->them_eid, trans->parent, y,
- ies.hint ? ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_UNAFFECTED)) : 0, ies.expiration, 0);
- if (ies.hint) {
- cache_save_hint(&trans->them_eid, trans->parent, ies.hint, ies.expiration);
- if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED)))
- ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED);
- if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_DONT_ASK))) {
- if (strlen((char *)ies.hint->data) > strlen(trans->parent->hmd->exten)) {
- ast_copy_string(trans->parent->hmd->exten, (char *)ies.hint->data,
- sizeof(trans->parent->hmd->exten));
- }
- } else {
- ast_clear_flag_nonstd(trans->parent->hmd, DUNDI_HINT_DONT_ASK);
- }
- }
- if (ies.expiration > 0) {
- if (trans->parent->expiration > ies.expiration) {
- trans->parent->expiration = ies.expiration;
- }
- }
- }
- /* Close connection if not final */
- if (!final)
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- }
-
- } else {
- /* Auth failure, check for data */
- if (!final) {
- /* Cancel if they didn't already */
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- }
- }
- break;
- case DUNDI_COMMAND_EIDRESPONSE:
- /* A dialplan response, lets see what we got... */
- if (ies.cause < 1) {
- /* Success of some sort */
- ast_log(LOG_DEBUG, "Looks like success of some sort (%d)\n", ies.cause);
- if (ast_test_flag(trans, FLAG_ENCRYPT)) {
- authpass = encrypted;
- } else
- authpass = 1;
- if (authpass) {
- /* Pass back up answers */
- if (trans->parent && trans->parent->dei && ies.q_org) {
- if (!trans->parent->respcount) {
- trans->parent->respcount++;
- if (ies.q_dept)
- ast_copy_string(trans->parent->dei->orgunit, ies.q_dept, sizeof(trans->parent->dei->orgunit));
- if (ies.q_org)
- ast_copy_string(trans->parent->dei->org, ies.q_org, sizeof(trans->parent->dei->org));
- if (ies.q_locality)
- ast_copy_string(trans->parent->dei->locality, ies.q_locality, sizeof(trans->parent->dei->locality));
- if (ies.q_stateprov)
- ast_copy_string(trans->parent->dei->stateprov, ies.q_stateprov, sizeof(trans->parent->dei->stateprov));
- if (ies.q_country)
- ast_copy_string(trans->parent->dei->country, ies.q_country, sizeof(trans->parent->dei->country));
- if (ies.q_email)
- ast_copy_string(trans->parent->dei->email, ies.q_email, sizeof(trans->parent->dei->email));
- if (ies.q_phone)
- ast_copy_string(trans->parent->dei->phone, ies.q_phone, sizeof(trans->parent->dei->phone));
- if (ies.q_ipaddr)
- ast_copy_string(trans->parent->dei->ipaddr, ies.q_ipaddr, sizeof(trans->parent->dei->ipaddr));
- if (!dundi_eid_cmp(&trans->them_eid, &trans->parent->query_eid)) {
- /* If it's them, update our address */
- ast_inet_ntoa(trans->parent->dei->ipaddr, sizeof(trans->parent->dei->ipaddr),
- trans->addr.sin_addr);
- }
- }
- if (ies.hint) {
- if (ast_test_flag_nonstd(ies.hint, htons(DUNDI_HINT_TTL_EXPIRED)))
- ast_set_flag_nonstd(trans->parent->hmd, DUNDI_HINT_TTL_EXPIRED);
- }
- }
- /* Close connection if not final */
- if (!final)
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- }
-
- } else {
- /* Auth failure, check for data */
- if (!final) {
- /* Cancel if they didn't already */
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- }
- }
- break;
- case DUNDI_COMMAND_REGRESPONSE:
- /* A dialplan response, lets see what we got... */
- if (ies.cause < 1) {
- int hasauth;
- /* Success of some sort */
- if (ast_test_flag(trans, FLAG_ENCRYPT)) {
- hasauth = encrypted;
- } else
- hasauth = 1;
-
- if (!hasauth) {
- ast_log(LOG_NOTICE, "Reponse to register not authorized!\n");
- if (!final) {
- dundi_ie_append_cause(&ied, DUNDI_IE_CAUSE, DUNDI_CAUSE_NOAUTH, "Improper signature in answer");
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, &ied);
- }
- } else {
- ast_log(LOG_DEBUG, "Yay, we've registered as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->us_eid),
- dundi_eid_to_str(eid_str2, sizeof(eid_str2), &trans->them_eid));
- /* Close connection if not final */
- if (!final)
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- }
- } else {
- /* Auth failure, cancel if they didn't for some reason */
- if (!final) {
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- }
- }
- break;
- case DUNDI_COMMAND_INVALID:
- case DUNDI_COMMAND_NULL:
- case DUNDI_COMMAND_PRECACHERP:
- /* Do nothing special */
- if (!final)
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- break;
- case DUNDI_COMMAND_ENCREJ:
- if ((ast_test_flag(trans, FLAG_SENDFULLKEY)) || !trans->lasttrans || !(peer = find_peer(&trans->them_eid))) {
- /* No really, it's over at this point */
- if (!final)
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- } else {
- /* Send with full key */
- ast_set_flag(trans, FLAG_SENDFULLKEY);
- if (final) {
- /* Ooops, we got a final message, start by sending ACK... */
- dundi_ack(trans, hdr->cmdresp & 0x80);
- trans->aseqno = trans->iseqno;
- /* Now, we gotta create a new transaction */
- if (!reset_transaction(trans)) {
- /* Make sure handle_frame doesn't destroy us */
- hdr->cmdresp &= 0x7f;
- /* Parse the message we transmitted */
- memset(&ies, 0, sizeof(ies));
- dundi_parse_ies(&ies, trans->lasttrans->h->ies, trans->lasttrans->datalen - sizeof(struct dundi_hdr));
- /* Reconstruct outgoing encrypted packet */
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
- dundi_ie_append_raw(&ied, DUNDI_IE_SHAREDKEY, peer->txenckey, 128);
- dundi_ie_append_raw(&ied, DUNDI_IE_SIGNATURE, peer->txenckey + 128, 128);
- if (ies.encblock)
- dundi_ie_append_encdata(&ied, DUNDI_IE_ENCDATA, ies.encblock->iv, ies.encblock->encdata, ies.enclen);
- dundi_send(trans, DUNDI_COMMAND_ENCRYPT, 0, trans->lasttrans->h->cmdresp & 0x80, &ied);
- peer->sentfullkey = 1;
- }
- }
- }
- break;
- case DUNDI_COMMAND_ENCRYPT:
- if (!encrypted) {
- /* No nested encryption! */
- if ((trans->iseqno == 1) && !trans->oseqno) {
- if (!ies.eids[0] || !(peer = find_peer(ies.eids[0])) ||
- ((!ies.encsharedkey || !ies.encsig) && !ies.keycrc32) ||
- (check_key(peer, ies.encsharedkey, ies.encsig, ies.keycrc32) < 1)) {
- if (!final) {
- dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
- }
- break;
- }
- apply_peer(trans, peer);
- /* Key passed, use new contexts for this session */
- trans->ecx = peer->them_ecx;
- trans->dcx = peer->them_dcx;
- }
- if (ast_test_flag(trans, FLAG_ENCRYPT) && ies.encblock && ies.enclen) {
- struct dundi_hdr *dhdr;
- unsigned char decoded[MAX_PACKET_SIZE];
- int ddatalen;
- ddatalen = sizeof(decoded);
- dhdr = dundi_decrypt(trans, decoded, &ddatalen, hdr, ies.encblock, ies.enclen);
- if (dhdr) {
- /* Handle decrypted response */
- if (dundidebug)
- dundi_showframe(dhdr, 3, &trans->addr, ddatalen - sizeof(struct dundi_hdr));
- handle_command_response(trans, dhdr, ddatalen - sizeof(struct dundi_hdr), 1);
- /* Carry back final flag */
- hdr->cmdresp |= dhdr->cmdresp & 0x80;
- break;
- } else
- ast_log(LOG_DEBUG, "Ouch, decrypt failed :(\n");
- }
- }
- if (!final) {
- /* Turn off encryption */
- ast_clear_flag(trans, FLAG_ENCRYPT);
- dundi_send(trans, DUNDI_COMMAND_ENCREJ, 0, 1, NULL);
- }
- break;
- default:
- /* Send unknown command if we don't know it, with final flag IFF it's the
- first command in the dialog and only if we haven't recieved final notification */
- if (!final) {
- dundi_ie_append_byte(&ied, DUNDI_IE_UNKNOWN, cmd);
- dundi_send(trans, DUNDI_COMMAND_UNKNOWN, 0, !hdr->oseqno, &ied);
- }
- }
- return 0;
-}
-
-static void destroy_packet(struct dundi_packet *pack, int needfree);
-static void destroy_packets(struct dundi_packet *p)
-{
- struct dundi_packet *prev;
- while(p) {
- prev = p;
- p = p->next;
- if (prev->retransid > -1)
- ast_sched_del(sched, prev->retransid);
- free(prev);
- }
-}
-
-
-static int ack_trans(struct dundi_transaction *trans, int iseqno)
-{
- /* Ack transmitted packet corresponding to iseqno */
- struct dundi_packet *pack;
- pack = trans->packets;
- while(pack) {
- if ((pack->h->oseqno + 1) % 255 == iseqno) {
- destroy_packet(pack, 0);
- if (trans->lasttrans) {
- ast_log(LOG_WARNING, "Whoa, there was still a last trans?\n");
- destroy_packets(trans->lasttrans);
- }
- trans->lasttrans = pack;
- if (trans->autokillid > -1)
- ast_sched_del(sched, trans->autokillid);
- trans->autokillid = -1;
- return 1;
- }
- pack = pack->next;
- }
- return 0;
-}
-
-static int handle_frame(struct dundi_hdr *h, struct sockaddr_in *sin, int datalen)
-{
- struct dundi_transaction *trans;
- trans = find_transaction(h, sin);
- if (!trans) {
- dundi_reject(h, sin);
- return 0;
- }
- /* Got a transaction, see where this header fits in */
- if (h->oseqno == trans->iseqno) {
- /* Just what we were looking for... Anything but ack increments iseqno */
- if (ack_trans(trans, h->iseqno) && ast_test_flag(trans, FLAG_FINAL)) {
- /* If final, we're done */
- destroy_trans(trans, 0);
- return 0;
- }
- if (h->cmdresp != DUNDI_COMMAND_ACK) {
- trans->oiseqno = trans->iseqno;
- trans->iseqno++;
- handle_command_response(trans, h, datalen, 0);
- }
- if (trans->aseqno != trans->iseqno) {
- dundi_ack(trans, h->cmdresp & 0x80);
- trans->aseqno = trans->iseqno;
- }
- /* Delete any saved last transmissions */
- destroy_packets(trans->lasttrans);
- trans->lasttrans = NULL;
- if (h->cmdresp & 0x80) {
- /* Final -- destroy now */
- destroy_trans(trans, 0);
- }
- } else if (h->oseqno == trans->oiseqno) {
- /* Last incoming sequence number -- send ACK without processing */
- dundi_ack(trans, 0);
- } else {
- /* Out of window -- simply drop */
- ast_log(LOG_DEBUG, "Dropping packet out of window!\n");
- }
- return 0;
-}
-
-static int socket_read(int *id, int fd, short events, void *cbdata)
-{
- struct sockaddr_in sin;
- int res;
- struct dundi_hdr *h;
- char buf[MAX_PACKET_SIZE];
- socklen_t len;
- len = sizeof(sin);
- res = recvfrom(netsocket, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &sin, &len);
- if (res < 0) {
- if (errno != ECONNREFUSED)
- ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
- return 1;
- }
- if (res < sizeof(struct dundi_hdr)) {
- ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct dundi_hdr));
- return 1;
- }
- buf[res] = '\0';
- h = (struct dundi_hdr *)buf;
- if (dundidebug)
- dundi_showframe(h, 1, &sin, res - sizeof(struct dundi_hdr));
- ast_mutex_lock(&peerlock);
- handle_frame(h, &sin, res - sizeof(struct dundi_hdr));
- ast_mutex_unlock(&peerlock);
- return 1;
-}
-
-static void build_secret(char *secret, int seclen)
-{
- unsigned char tmp[16];
- char *s;
- build_iv(tmp);
- secret[0] = '\0';
- ast_base64encode(secret, tmp, sizeof(tmp), seclen);
- /* Eliminate potential bad characters */
- while((s = strchr(secret, ';'))) *s = '+';
- while((s = strchr(secret, '/'))) *s = '+';
- while((s = strchr(secret, ':'))) *s = '+';
- while((s = strchr(secret, '@'))) *s = '+';
-}
-
-
-static void save_secret(const char *newkey, const char *oldkey)
-{
- char tmp[256];
- if (oldkey)
- snprintf(tmp, sizeof(tmp), "%s;%s", oldkey, newkey);
- else
- snprintf(tmp, sizeof(tmp), "%s", newkey);
- rotatetime = time(NULL) + DUNDI_SECRET_TIME;
- ast_db_put(secretpath, "secret", tmp);
- snprintf(tmp, sizeof(tmp), "%d", (int)rotatetime);
- ast_db_put(secretpath, "secretexpiry", tmp);
-}
-
-static void load_password(void)
-{
- char *current=NULL;
- char *last=NULL;
- char tmp[256];
- time_t expired;
-
- ast_db_get(secretpath, "secretexpiry", tmp, sizeof(tmp));
- if (sscanf(tmp, "%d", (int *)&expired) == 1) {
- ast_db_get(secretpath, "secret", tmp, sizeof(tmp));
- current = strchr(tmp, ';');
- if (!current)
- current = tmp;
- else {
- *current = '\0';
- current++;
- };
- if ((time(NULL) - expired) < 0) {
- if ((expired - time(NULL)) > DUNDI_SECRET_TIME)
- expired = time(NULL) + DUNDI_SECRET_TIME;
- } else if ((time(NULL) - (expired + DUNDI_SECRET_TIME)) < 0) {
- last = current;
- current = NULL;
- } else {
- last = NULL;
- current = NULL;
- }
- }
- if (current) {
- /* Current key is still valid, just setup rotatation properly */
- ast_copy_string(cursecret, current, sizeof(cursecret));
- rotatetime = expired;
- } else {
- /* Current key is out of date, rotate or eliminate all together */
- build_secret(cursecret, sizeof(cursecret));
- save_secret(cursecret, last);
- }
-}
-
-static void check_password(void)
-{
- char oldsecret[80];
- time_t now;
-
- time(&now);
-#if 0
- printf("%ld/%ld\n", now, rotatetime);
-#endif
- if ((now - rotatetime) >= 0) {
- /* Time to rotate keys */
- ast_copy_string(oldsecret, cursecret, sizeof(oldsecret));
- build_secret(cursecret, sizeof(cursecret));
- save_secret(cursecret, oldsecret);
- }
-}
-
-static void *network_thread(void *ignore)
-{
- /* Our job is simple: Send queued messages, retrying if necessary. Read frames
- from the network, and queue them for delivery to the channels */
- int res;
- /* Establish I/O callback for socket read */
- ast_io_add(io, netsocket, socket_read, AST_IO_IN, NULL);
- for(;;) {
- res = ast_sched_wait(sched);
- if ((res > 1000) || (res < 0))
- res = 1000;
- res = ast_io_wait(io, res);
- if (res >= 0) {
- ast_mutex_lock(&peerlock);
- ast_sched_runq(sched);
- ast_mutex_unlock(&peerlock);
- }
- check_password();
- }
- return NULL;
-}
-
-static void *process_precache(void *ign)
-{
- struct dundi_precache_queue *qe;
- time_t now;
- char context[256];
- char number[256];
- int run;
- for (;;) {
- time(&now);
- run = 0;
- ast_mutex_lock(&pclock);
- if (pcq) {
- if (!pcq->expiration) {
- /* Gone... Remove... */
- qe = pcq;
- pcq = pcq->next;
- free(qe);
- } else if (pcq->expiration < now) {
- /* Process this entry */
- pcq->expiration = 0;
- ast_copy_string(context, pcq->context, sizeof(context));
- ast_copy_string(number, pcq->number, sizeof(number));
- run = 1;
- }
- }
- ast_mutex_unlock(&pclock);
- if (run) {
- dundi_precache(context, number);
- } else
- sleep(1);
- }
- return NULL;
-}
-
-static int start_network_thread(void)
-{
- ast_pthread_create(&netthreadid, NULL, network_thread, NULL);
- ast_pthread_create(&precachethreadid, NULL, process_precache, NULL);
- return 0;
-}
-
-static int dundi_do_debug(int fd, int argc, char *argv[])
-{
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- dundidebug = 1;
- ast_cli(fd, "DUNDi Debugging Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int dundi_do_store_history(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- global_storehistory = 1;
- ast_cli(fd, "DUNDi History Storage Enabled\n");
- return RESULT_SUCCESS;
-}
-
-static int dundi_flush(int fd, int argc, char *argv[])
-{
- int stats=0;
- if ((argc < 2) || (argc > 3))
- return RESULT_SHOWUSAGE;
- if (argc > 2) {
- if (!strcasecmp(argv[2], "stats"))
- stats = 1;
- else
- return RESULT_SHOWUSAGE;
- }
- if (stats) {
- /* Flush statistics */
- struct dundi_peer *p;
- int x;
- ast_mutex_lock(&peerlock);
- p = peers;
- while(p) {
- for (x=0;x<DUNDI_TIMING_HISTORY;x++) {
- if (p->lookups[x])
- free(p->lookups[x]);
- p->lookups[x] = NULL;
- p->lookuptimes[x] = 0;
- }
- p->avgms = 0;
- p = p->next;
- }
- ast_mutex_unlock(&peerlock);
- } else {
- ast_db_deltree("dundi/cache", NULL);
- ast_cli(fd, "DUNDi Cache Flushed\n");
- }
- return RESULT_SUCCESS;
-}
-
-static int dundi_no_debug(int fd, int argc, char *argv[])
-{
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- dundidebug = 0;
- ast_cli(fd, "DUNDi Debugging Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static int dundi_no_store_history(int fd, int argc, char *argv[])
-{
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- global_storehistory = 0;
- ast_cli(fd, "DUNDi History Storage Disabled\n");
- return RESULT_SUCCESS;
-}
-
-static char *model2str(int model)
-{
- switch(model) {
- case DUNDI_MODEL_INBOUND:
- return "Inbound";
- case DUNDI_MODEL_OUTBOUND:
- return "Outbound";
- case DUNDI_MODEL_SYMMETRIC:
- return "Symmetric";
- default:
- return "Unknown";
- }
-}
-
-static char *complete_peer_helper(char *line, char *word, int pos, int state, int rpos)
-{
- int which=0;
- char *ret;
- struct dundi_peer *p;
- char eid_str[20];
- if (pos != rpos)
- return NULL;
- ast_mutex_lock(&peerlock);
- p = peers;
- while(p) {
- if (!strncasecmp(word, dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), strlen(word))) {
- if (++which > state)
- break;
- }
- p = p->next;
- }
- if (p) {
- ret = strdup(dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid));
- } else
- ret = NULL;
- ast_mutex_unlock(&peerlock);
- return ret;
-}
-
-static char *complete_peer_4(char *line, char *word, int pos, int state)
-{
- return complete_peer_helper(line, word, pos, state, 3);
-}
-
-static int rescomp(const void *a, const void *b)
-{
- const struct dundi_result *resa, *resb;
- resa = a;
- resb = b;
- if (resa->weight < resb->weight)
- return -1;
- if (resa->weight > resb->weight)
- return 1;
- return 0;
-}
-
-static void sort_results(struct dundi_result *results, int count)
-{
- qsort(results, count, sizeof(results[0]), rescomp);
-}
-
-static int dundi_do_lookup(int fd, int argc, char *argv[])
-{
- int res;
- char tmp[256];
- char fs[80] = "";
- char *context;
- int x;
- int bypass = 0;
- struct dundi_result dr[MAX_RESULTS];
- struct timeval start;
- if ((argc < 3) || (argc > 4))
- return RESULT_SHOWUSAGE;
- if (argc > 3) {
- if (!strcasecmp(argv[3], "bypass"))
- bypass=1;
- else
- return RESULT_SHOWUSAGE;
- }
- ast_copy_string(tmp, argv[2], sizeof(tmp));
- context = strchr(tmp, '@');
- if (context) {
- *context = '\0';
- context++;
- }
- start = ast_tvnow();
- res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
-
- if (res < 0)
- ast_cli(fd, "DUNDi lookup returned error.\n");
- else if (!res)
- ast_cli(fd, "DUNDi lookup returned no results.\n");
- else
- sort_results(dr, res);
- for (x=0;x<res;x++) {
- ast_cli(fd, "%3d. %5d %s/%s (%s)\n", x + 1, dr[x].weight, dr[x].tech, dr[x].dest, dundi_flags2str(fs, sizeof(fs), dr[x].flags));
- ast_cli(fd, " from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
- }
- ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
- return RESULT_SUCCESS;
-}
-
-static int dundi_do_precache(int fd, int argc, char *argv[])
-{
- int res;
- char tmp[256];
- char *context;
- struct timeval start;
- if ((argc < 3) || (argc > 3))
- return RESULT_SHOWUSAGE;
- ast_copy_string(tmp, argv[2], sizeof(tmp));
- context = strchr(tmp, '@');
- if (context) {
- *context = '\0';
- context++;
- }
- start = ast_tvnow();
- res = dundi_precache(context, tmp);
-
- if (res < 0)
- ast_cli(fd, "DUNDi precache returned error.\n");
- else if (!res)
- ast_cli(fd, "DUNDi precache returned no error.\n");
- ast_cli(fd, "DUNDi lookup completed in %d ms\n", ast_tvdiff_ms(ast_tvnow(), start));
- return RESULT_SUCCESS;
-}
-
-static int dundi_do_query(int fd, int argc, char *argv[])
-{
- int res;
- char tmp[256];
- char *context;
- dundi_eid eid;
- struct dundi_entity_info dei;
- if ((argc < 3) || (argc > 3))
- return RESULT_SHOWUSAGE;
- if (dundi_str_to_eid(&eid, argv[2])) {
- ast_cli(fd, "'%s' is not a valid EID!\n", argv[2]);
- return RESULT_SHOWUSAGE;
- }
- ast_copy_string(tmp, argv[2], sizeof(tmp));
- context = strchr(tmp, '@');
- if (context) {
- *context = '\0';
- context++;
- }
- res = dundi_query_eid(&dei, context, eid);
- if (res < 0)
- ast_cli(fd, "DUNDi Query EID returned error.\n");
- else if (!res)
- ast_cli(fd, "DUNDi Query EID returned no results.\n");
- else {
- ast_cli(fd, "DUNDi Query EID succeeded:\n");
- ast_cli(fd, "Department: %s\n", dei.orgunit);
- ast_cli(fd, "Organization: %s\n", dei.org);
- ast_cli(fd, "City/Locality: %s\n", dei.locality);
- ast_cli(fd, "State/Province: %s\n", dei.stateprov);
- ast_cli(fd, "Country: %s\n", dei.country);
- ast_cli(fd, "E-mail: %s\n", dei.email);
- ast_cli(fd, "Phone: %s\n", dei.phone);
- ast_cli(fd, "IP Address: %s\n", dei.ipaddr);
- }
- return RESULT_SUCCESS;
-}
-
-static int dundi_show_peer(int fd, int argc, char *argv[])
-{
- struct dundi_peer *peer;
- struct permission *p;
- char *order;
- char iabuf[INET_ADDRSTRLEN];
- char eid_str[20];
- int x, cnt;
-
- if (argc != 4)
- return RESULT_SHOWUSAGE;
- ast_mutex_lock(&peerlock);
- peer = peers;
- while(peer) {
- if (!strcasecmp(dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), argv[3]))
- break;
- peer = peer->next;
- }
- if (peer) {
- switch(peer->order) {
- case 0:
- order = "Primary";
- break;
- case 1:
- order = "Secondary";
- break;
- case 2:
- order = "Tertiary";
- break;
- case 3:
- order = "Quartiary";
- break;
- default:
- order = "Unknown";
- }
- ast_cli(fd, "Peer: %s\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- ast_cli(fd, "Model: %s\n", model2str(peer->model));
- ast_cli(fd, "Host: %s\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "<Unspecified>");
- ast_cli(fd, "Dynamic: %s\n", peer->dynamic ? "yes" : "no");
- ast_cli(fd, "KeyPend: %s\n", peer->keypending ? "yes" : "no");
- ast_cli(fd, "Reg: %s\n", peer->registerid < 0 ? "No" : "Yes");
- ast_cli(fd, "In Key: %s\n", ast_strlen_zero(peer->inkey) ? "<None>" : peer->inkey);
- ast_cli(fd, "Out Key: %s\n", ast_strlen_zero(peer->outkey) ? "<None>" : peer->outkey);
- if (peer->include) {
- ast_cli(fd, "Include logic%s:\n", peer->model & DUNDI_MODEL_OUTBOUND ? "" : " (IGNORED)");
- }
- p = peer->include;
- while(p) {
- ast_cli(fd, "-- %s %s\n", p->allow ? "include" : "do not include", p->name);
- p = p->next;
- }
- if (peer->permit) {
- ast_cli(fd, "Query logic%s:\n", peer->model & DUNDI_MODEL_INBOUND ? "" : " (IGNORED)");
- }
- p = peer->permit;
- while(p) {
- ast_cli(fd, "-- %s %s\n", p->allow ? "permit" : "deny", p->name);
- p = p->next;
- }
- cnt = 0;
- for (x=0;x<DUNDI_TIMING_HISTORY;x++) {
- if (peer->lookups[x]) {
- if (!cnt)
- ast_cli(fd, "Last few query times:\n");
- ast_cli(fd, "-- %d. %s (%d ms)\n", x + 1, peer->lookups[x], peer->lookuptimes[x]);
- cnt++;
- }
- }
- if (cnt)
- ast_cli(fd, "Average query time: %d ms\n", peer->avgms);
- } else
- ast_cli(fd, "No such peer '%s'\n", argv[3]);
- ast_mutex_unlock(&peerlock);
- return RESULT_SUCCESS;
-}
-
-static int dundi_show_peers(int fd, int argc, char *argv[])
-{
-#define FORMAT2 "%-20.20s %-15.15s %-10.10s %-8.8s %-15.15s\n"
-#define FORMAT "%-20.20s %-15.15s %s %-10.10s %-8.8s %-15.15s\n"
- struct dundi_peer *peer;
- char iabuf[INET_ADDRSTRLEN];
- int registeredonly=0;
- char avgms[20];
- char eid_str[20];
- int online_peers = 0;
- int offline_peers = 0;
- int unmonitored_peers = 0;
- int total_peers = 0;
-
- if ((argc != 3) && (argc != 4) && (argc != 5))
- return RESULT_SHOWUSAGE;
- if ((argc == 4)) {
- if (!strcasecmp(argv[3], "registered")) {
- registeredonly = 1;
- } else
- return RESULT_SHOWUSAGE;
- }
- ast_mutex_lock(&peerlock);
- ast_cli(fd, FORMAT2, "EID", "Host", "Model", "AvgTime", "Status");
- for (peer = peers;peer;peer = peer->next) {
- char status[20];
- int print_line = -1;
- char srch[2000];
- total_peers++;
- if (registeredonly && !peer->addr.sin_addr.s_addr)
- continue;
- if (peer->maxms) {
- if (peer->lastms < 0) {
- strcpy(status, "UNREACHABLE");
- offline_peers++;
- }
- else if (peer->lastms > peer->maxms) {
- snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms);
- offline_peers++;
- }
- else if (peer->lastms) {
- snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms);
- online_peers++;
- }
- else {
- strcpy(status, "UNKNOWN");
- offline_peers++;
- }
- } else {
- strcpy(status, "Unmonitored");
- unmonitored_peers++;
- }
- if (peer->avgms)
- snprintf(avgms, sizeof(avgms), "%d ms", peer->avgms);
- else
- strcpy(avgms, "Unavail");
- snprintf(srch, sizeof(srch), FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
- peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
-
- if (argc == 5) {
- if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) {
- print_line = -1;
- } else if (!strcasecmp(argv[3],"exclude") && !strstr(srch,argv[4])) {
- print_line = 1;
- } else if (!strcasecmp(argv[3],"begin") && !strncasecmp(srch,argv[4],strlen(argv[4]))) {
- print_line = -1;
- } else {
- print_line = 0;
- }
- }
-
- if (print_line) {
- ast_cli(fd, FORMAT, dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid),
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
- peer->dynamic ? "(D)" : "(S)", model2str(peer->model), avgms, status);
- }
- }
- ast_cli(fd, "%d dundi peers [%d online, %d offline, %d unmonitored]\n", total_peers, online_peers, offline_peers, unmonitored_peers);
- ast_mutex_unlock(&peerlock);
- return RESULT_SUCCESS;
-#undef FORMAT
-#undef FORMAT2
-}
-
-static int dundi_show_trans(int fd, int argc, char *argv[])
-{
-#define FORMAT2 "%-22.22s %-5.5s %-5.5s %-3.3s %-3.3s %-3.3s\n"
-#define FORMAT "%-16.16s:%5d %-5.5d %-5.5d %-3.3d %-3.3d %-3.3d\n"
- struct dundi_transaction *trans;
- char iabuf[INET_ADDRSTRLEN];
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_mutex_lock(&peerlock);
- ast_cli(fd, FORMAT2, "Remote", "Src", "Dst", "Tx", "Rx", "Ack");
- for (trans = alltrans;trans;trans = trans->allnext) {
- ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), trans->addr.sin_addr),
- ntohs(trans->addr.sin_port), trans->strans, trans->dtrans, trans->oseqno, trans->iseqno, trans->aseqno);
- }
- ast_mutex_unlock(&peerlock);
- return RESULT_SUCCESS;
-#undef FORMAT
-#undef FORMAT2
-}
-
-static int dundi_show_entityid(int fd, int argc, char *argv[])
-{
- char eid_str[20];
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_mutex_lock(&peerlock);
- dundi_eid_to_str(eid_str, sizeof(eid_str), &global_eid);
- ast_mutex_unlock(&peerlock);
- ast_cli(fd, "Global EID for this system is '%s'\n", eid_str);
- return RESULT_SUCCESS;
-}
-
-static int dundi_show_requests(int fd, int argc, char *argv[])
-{
-#define FORMAT2 "%-15s %-15s %-15s %-3.3s %-3.3s\n"
-#define FORMAT "%-15s %-15s %-15s %-3.3d %-3.3d\n"
- struct dundi_request *req;
- char eidstr[20];
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_mutex_lock(&peerlock);
- ast_cli(fd, FORMAT2, "Number", "Context", "Root", "Max", "Rsp");
- for (req = requests;req;req = req->next) {
- ast_cli(fd, FORMAT, req->number, req->dcontext,
- dundi_eid_zero(&req->root_eid) ? "<unspecified>" : dundi_eid_to_str(eidstr, sizeof(eidstr), &req->root_eid), req->maxcount, req->respcount);
- }
- ast_mutex_unlock(&peerlock);
- return RESULT_SUCCESS;
-#undef FORMAT
-#undef FORMAT2
-}
-
-/* Grok-a-dial DUNDi */
-
-static int dundi_show_mappings(int fd, int argc, char *argv[])
-{
-#define FORMAT2 "%-12.12s %-7.7s %-12.12s %-10.10s %-5.5s %-25.25s\n"
-#define FORMAT "%-12.12s %-7d %-12.12s %-10.10s %-5.5s %-25.25s\n"
- struct dundi_mapping *map;
- char fs[256];
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- ast_mutex_lock(&peerlock);
- ast_cli(fd, FORMAT2, "DUNDi Cntxt", "Weight", "Local Cntxt", "Options", "Tech", "Destination");
- for (map = mappings;map;map = map->next) {
- ast_cli(fd, FORMAT, map->dcontext, map->weight,
- ast_strlen_zero(map->lcontext) ? "<none>" : map->lcontext,
- dundi_flags2str(fs, sizeof(fs), map->options), tech2str(map->tech), map->dest);
- }
- ast_mutex_unlock(&peerlock);
- return RESULT_SUCCESS;
-#undef FORMAT
-#undef FORMAT2
-}
-
-static int dundi_show_precache(int fd, int argc, char *argv[])
-{
-#define FORMAT2 "%-12.12s %-12.12s %-10.10s\n"
-#define FORMAT "%-12.12s %-12.12s %02d:%02d:%02d\n"
- struct dundi_precache_queue *qe;
- int h,m,s;
- time_t now;
-
- if (argc != 3)
- return RESULT_SHOWUSAGE;
- time(&now);
- ast_mutex_lock(&pclock);
- ast_cli(fd, FORMAT2, "Number", "Context", "Expiration");
- for (qe = pcq;qe;qe = qe->next) {
- s = qe->expiration - now;
- h = s / 3600;
- s = s % 3600;
- m = s / 60;
- s = s % 60;
- ast_cli(fd, FORMAT, qe->number, qe->context, h,m,s);
- }
- ast_mutex_unlock(&pclock);
- return RESULT_SUCCESS;
-#undef FORMAT
-#undef FORMAT2
-}
-
-static char debug_usage[] =
-"Usage: dundi debug\n"
-" Enables dumping of DUNDi packets for debugging purposes\n";
-
-static char no_debug_usage[] =
-"Usage: dundi no debug\n"
-" Disables dumping of DUNDi packets for debugging purposes\n";
-
-static char store_history_usage[] =
-"Usage: dundi store history\n"
-" Enables storing of DUNDi requests and times for debugging\n"
-"purposes\n";
-
-static char no_store_history_usage[] =
-"Usage: dundi no store history\n"
-" Disables storing of DUNDi requests and times for debugging\n"
-"purposes\n";
-
-static char show_peers_usage[] =
-"Usage: dundi show peers\n"
-" Lists all known DUNDi peers.\n";
-
-static char show_trans_usage[] =
-"Usage: dundi show trans\n"
-" Lists all known DUNDi transactions.\n";
-
-static char show_mappings_usage[] =
-"Usage: dundi show mappings\n"
-" Lists all known DUNDi mappings.\n";
-
-static char show_precache_usage[] =
-"Usage: dundi show precache\n"
-" Lists all known DUNDi scheduled precache updates.\n";
-
-static char show_entityid_usage[] =
-"Usage: dundi show entityid\n"
-" Displays the global entityid for this host.\n";
-
-static char show_peer_usage[] =
-"Usage: dundi show peer [peer]\n"
-" Provide a detailed description of a specifid DUNDi peer.\n";
-
-static char show_requests_usage[] =
-"Usage: dundi show requests\n"
-" Lists all known pending DUNDi requests.\n";
-
-static char lookup_usage[] =
-"Usage: dundi lookup <number>[@context] [bypass]\n"
-" Lookup the given number within the given DUNDi context\n"
-"(or e164 if none is specified). Bypasses cache if 'bypass'\n"
-"keyword is specified.\n";
-
-static char precache_usage[] =
-"Usage: dundi precache <number>[@context]\n"
-" Lookup the given number within the given DUNDi context\n"
-"(or e164 if none is specified) and precaches the results to any\n"
-"upstream DUNDi push servers.\n";
-
-static char query_usage[] =
-"Usage: dundi query <entity>[@context]\n"
-" Attempts to retrieve contact information for a specific\n"
-"DUNDi entity identifier (EID) within a given DUNDi context (or\n"
-"e164 if none is specified).\n";
-
-static char flush_usage[] =
-"Usage: dundi flush [stats]\n"
-" Flushes DUNDi answer cache, used primarily for debug. If\n"
-"'stats' is present, clears timer statistics instead of normal\n"
-"operation.\n";
-
-static struct ast_cli_entry cli_debug =
- { { "dundi", "debug", NULL }, dundi_do_debug, "Enable DUNDi debugging", debug_usage };
-
-static struct ast_cli_entry cli_store_history =
- { { "dundi", "store", "history", NULL }, dundi_do_store_history, "Enable DUNDi historic records", store_history_usage };
-
-static struct ast_cli_entry cli_no_store_history =
- { { "dundi", "no", "store", "history", NULL }, dundi_no_store_history, "Disable DUNDi historic records", no_store_history_usage };
-
-static struct ast_cli_entry cli_flush =
- { { "dundi", "flush", NULL }, dundi_flush, "Flush DUNDi cache", flush_usage };
-
-static struct ast_cli_entry cli_no_debug =
- { { "dundi", "no", "debug", NULL }, dundi_no_debug, "Disable DUNDi debugging", no_debug_usage };
-
-static struct ast_cli_entry cli_show_peers =
- { { "dundi", "show", "peers", NULL }, dundi_show_peers, "Show defined DUNDi peers", show_peers_usage };
-
-static struct ast_cli_entry cli_show_trans =
- { { "dundi", "show", "trans", NULL }, dundi_show_trans, "Show active DUNDi transactions", show_trans_usage };
-
-static struct ast_cli_entry cli_show_entityid =
- { { "dundi", "show", "entityid", NULL }, dundi_show_entityid, "Display Global Entity ID", show_entityid_usage };
-
-static struct ast_cli_entry cli_show_mappings =
- { { "dundi", "show", "mappings", NULL }, dundi_show_mappings, "Show DUNDi mappings", show_mappings_usage };
-
-static struct ast_cli_entry cli_show_precache =
- { { "dundi", "show", "precache", NULL }, dundi_show_precache, "Show DUNDi precache", show_precache_usage };
-
-static struct ast_cli_entry cli_show_requests =
- { { "dundi", "show", "requests", NULL }, dundi_show_requests, "Show DUNDi requests", show_requests_usage };
-
-static struct ast_cli_entry cli_show_peer =
- { { "dundi", "show", "peer", NULL }, dundi_show_peer, "Show info on a specific DUNDi peer", show_peer_usage, complete_peer_4 };
-
-static struct ast_cli_entry cli_lookup =
- { { "dundi", "lookup", NULL }, dundi_do_lookup, "Lookup a number in DUNDi", lookup_usage };
-
-static struct ast_cli_entry cli_precache =
- { { "dundi", "precache", NULL }, dundi_do_precache, "Precache a number in DUNDi", precache_usage };
-
-static struct ast_cli_entry cli_queryeid =
- { { "dundi", "query", NULL }, dundi_do_query, "Query a DUNDi EID", query_usage };
-
-STANDARD_LOCAL_USER;
-
-LOCAL_USER_DECL;
-
-static struct dundi_transaction *create_transaction(struct dundi_peer *p)
-{
- struct dundi_transaction *trans;
- int tid;
-
- /* Don't allow creation of transactions to non-registered peers */
- if (p && !p->addr.sin_addr.s_addr)
- return NULL;
- tid = get_trans_id();
- if (tid < 1)
- return NULL;
- trans = malloc(sizeof(struct dundi_transaction));
- if (trans) {
- memset(trans, 0, sizeof(struct dundi_transaction));
- if (global_storehistory) {
- trans->start = ast_tvnow();
- ast_set_flag(trans, FLAG_STOREHIST);
- }
- trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
- trans->autokillid = -1;
- if (p) {
- apply_peer(trans, p);
- if (!p->sentfullkey)
- ast_set_flag(trans, FLAG_SENDFULLKEY);
- }
- trans->strans = tid;
- trans->allnext = alltrans;
- alltrans = trans;
- }
- return trans;
-}
-
-static int dundi_xmit(struct dundi_packet *pack)
-{
- int res;
- char iabuf[INET_ADDRSTRLEN];
- if (dundidebug)
- dundi_showframe(pack->h, 0, &pack->parent->addr, pack->datalen - sizeof(struct dundi_hdr));
- res = sendto(netsocket, pack->data, pack->datalen, 0, (struct sockaddr *)&pack->parent->addr, sizeof(pack->parent->addr));
- if (res < 0) {
- ast_log(LOG_WARNING, "Failed to transmit to '%s:%d': %s\n",
- ast_inet_ntoa(iabuf, sizeof(iabuf), pack->parent->addr.sin_addr),
- ntohs(pack->parent->addr.sin_port), strerror(errno));
- }
- if (res > 0)
- res = 0;
- return res;
-}
-
-static void destroy_packet(struct dundi_packet *pack, int needfree)
-{
- struct dundi_packet *prev, *cur;
- if (pack->parent) {
- prev = NULL;
- cur = pack->parent->packets;
- while(cur) {
- if (cur == pack) {
- if (prev)
- prev->next = cur->next;
- else
- pack->parent->packets = cur->next;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
- }
- if (pack->retransid > -1)
- ast_sched_del(sched, pack->retransid);
- if (needfree)
- free(pack);
- else {
- pack->retransid = -1;
- pack->next = NULL;
- }
-}
-
-static void destroy_trans(struct dundi_transaction *trans, int fromtimeout)
-{
- struct dundi_transaction *cur, *prev;
- struct dundi_peer *peer;
- int ms;
- int x;
- int cnt;
- char eid_str[20];
- if (ast_test_flag(trans, FLAG_ISREG | FLAG_ISQUAL | FLAG_STOREHIST)) {
- peer = peers;
- while (peer) {
- if (peer->regtrans == trans)
- peer->regtrans = NULL;
- if (peer->keypending == trans)
- peer->keypending = NULL;
- if (peer->qualtrans == trans) {
- if (fromtimeout) {
- if (peer->lastms > -1)
- ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- peer->lastms = -1;
- } else {
- ms = ast_tvdiff_ms(ast_tvnow(), peer->qualtx);
- if (ms < 1)
- ms = 1;
- if (ms < peer->maxms) {
- if ((peer->lastms >= peer->maxms) || (peer->lastms < 0))
- ast_log(LOG_NOTICE, "Peer '%s' has become REACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- } else if (peer->lastms < peer->maxms) {
- ast_log(LOG_NOTICE, "Peer '%s' has become TOO LAGGED (%d ms)\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), ms);
- }
- peer->lastms = ms;
- }
- peer->qualtrans = NULL;
- }
- if (ast_test_flag(trans, FLAG_STOREHIST)) {
- if (trans->parent && !ast_strlen_zero(trans->parent->number)) {
- if (!dundi_eid_cmp(&trans->them_eid, &peer->eid)) {
- peer->avgms = 0;
- cnt = 0;
- if (peer->lookups[DUNDI_TIMING_HISTORY-1])
- free(peer->lookups[DUNDI_TIMING_HISTORY-1]);
- for (x=DUNDI_TIMING_HISTORY-1;x>0;x--) {
- peer->lookuptimes[x] = peer->lookuptimes[x-1];
- peer->lookups[x] = peer->lookups[x-1];
- if (peer->lookups[x]) {
- peer->avgms += peer->lookuptimes[x];
- cnt++;
- }
- }
- peer->lookuptimes[0] = ast_tvdiff_ms(ast_tvnow(), trans->start);
- peer->lookups[0] = malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
- if (peer->lookups[0]) {
- sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
- peer->avgms += peer->lookuptimes[0];
- cnt++;
- }
- if (cnt)
- peer->avgms /= cnt;
- }
- }
- }
- peer = peer->next;
- }
- }
- if (trans->parent) {
- /* Unlink from parent if appropriate */
- prev = NULL;
- cur = trans->parent->trans;
- while(cur) {
- if (cur == trans) {
- if (prev)
- prev->next = trans->next;
- else
- trans->parent->trans = trans->next;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
- if (!trans->parent->trans) {
- /* Wake up sleeper */
- if (trans->parent->pfds[1] > -1) {
- write(trans->parent->pfds[1], "killa!", 6);
- }
- }
- }
- /* Unlink from all trans */
- prev = NULL;
- cur = alltrans;
- while(cur) {
- if (cur == trans) {
- if (prev)
- prev->allnext = trans->allnext;
- else
- alltrans = trans->allnext;
- break;
- }
- prev = cur;
- cur = cur->allnext;
- }
- destroy_packets(trans->packets);
- destroy_packets(trans->lasttrans);
- trans->packets = NULL;
- trans->lasttrans = NULL;
- if (trans->autokillid > -1)
- ast_sched_del(sched, trans->autokillid);
- trans->autokillid = -1;
- if (trans->thread) {
- /* If used by a thread, mark as dead and be done */
- ast_set_flag(trans, FLAG_DEAD);
- } else
- free(trans);
-}
-
-static int dundi_rexmit(void *data)
-{
- struct dundi_packet *pack;
- char iabuf[INET_ADDRSTRLEN];
- int res;
- ast_mutex_lock(&peerlock);
- pack = data;
- if (pack->retrans < 1) {
- pack->retransid = -1;
- if (!ast_test_flag(pack->parent, FLAG_ISQUAL))
- ast_log(LOG_NOTICE, "Max retries exceeded to host '%s:%d' msg %d on call %d\n",
- ast_inet_ntoa(iabuf, sizeof(iabuf), pack->parent->addr.sin_addr),
- ntohs(pack->parent->addr.sin_port), pack->h->oseqno, ntohs(pack->h->strans));
- destroy_trans(pack->parent, 1);
- res = 0;
- } else {
- /* Decrement retransmission, try again */
- pack->retrans--;
- dundi_xmit(pack);
- res = 1;
- }
- ast_mutex_unlock(&peerlock);
- return res;
-}
-
-static int dundi_send(struct dundi_transaction *trans, int cmdresp, int flags, int final, struct dundi_ie_data *ied)
-{
- struct dundi_packet *pack;
- int res;
- int len;
- char eid_str[20];
- len = sizeof(struct dundi_packet) + sizeof(struct dundi_hdr) + (ied ? ied->pos : 0);
- /* Reserve enough space for encryption */
- if (ast_test_flag(trans, FLAG_ENCRYPT))
- len += 384;
- pack = malloc(len);
- if (pack) {
- memset(pack, 0, len);
- pack->h = (struct dundi_hdr *)(pack->data);
- if (cmdresp != DUNDI_COMMAND_ACK) {
- pack->retransid = ast_sched_add(sched, trans->retranstimer, dundi_rexmit, pack);
- pack->retrans = DUNDI_DEFAULT_RETRANS - 1;
- pack->next = trans->packets;
- trans->packets = pack;
- }
- pack->parent = trans;
- pack->h->strans = htons(trans->strans);
- pack->h->dtrans = htons(trans->dtrans);
- pack->h->iseqno = trans->iseqno;
- pack->h->oseqno = trans->oseqno;
- pack->h->cmdresp = cmdresp;
- pack->datalen = sizeof(struct dundi_hdr);
- if (ied) {
- memcpy(pack->h->ies, ied->buf, ied->pos);
- pack->datalen += ied->pos;
- }
- if (final) {
- pack->h->cmdresp |= DUNDI_COMMAND_FINAL;
- ast_set_flag(trans, FLAG_FINAL);
- }
- pack->h->cmdflags = flags;
- if (cmdresp != DUNDI_COMMAND_ACK) {
- trans->oseqno++;
- trans->oseqno = trans->oseqno % 256;
- }
- trans->aseqno = trans->iseqno;
- /* If we have their public key, encrypt */
- if (ast_test_flag(trans, FLAG_ENCRYPT)) {
- switch(cmdresp) {
- case DUNDI_COMMAND_REGREQ:
- case DUNDI_COMMAND_REGRESPONSE:
- case DUNDI_COMMAND_DPDISCOVER:
- case DUNDI_COMMAND_DPRESPONSE:
- case DUNDI_COMMAND_EIDQUERY:
- case DUNDI_COMMAND_EIDRESPONSE:
- case DUNDI_COMMAND_PRECACHERQ:
- case DUNDI_COMMAND_PRECACHERP:
- if (dundidebug)
- dundi_showframe(pack->h, 2, &trans->addr, pack->datalen - sizeof(struct dundi_hdr));
- res = dundi_encrypt(trans, pack);
- break;
- default:
- res = 0;
- }
- } else
- res = 0;
- if (!res)
- res = dundi_xmit(pack);
- if (res)
- ast_log(LOG_NOTICE, "Failed to send packet to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
-
- if (cmdresp == DUNDI_COMMAND_ACK)
- free(pack);
- return res;
- }
- return -1;
-}
-
-static int do_autokill(void *data)
-{
- struct dundi_transaction *trans = data;
- char eid_str[20];
- ast_log(LOG_NOTICE, "Transaction to '%s' took too long to ACK, destroying\n",
- dundi_eid_to_str(eid_str, sizeof(eid_str), &trans->them_eid));
- trans->autokillid = -1;
- destroy_trans(trans, 0); /* We could actually set it to 1 instead of 0, but we won't ;-) */
- return 0;
-}
-
-static void dundi_ie_append_eid_appropriately(struct dundi_ie_data *ied, char *context, dundi_eid *eid, dundi_eid *us)
-{
- struct dundi_peer *p;
- if (!dundi_eid_cmp(eid, us)) {
- dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
- return;
- }
- ast_mutex_lock(&peerlock);
- p = peers;
- while(p) {
- if (!dundi_eid_cmp(&p->eid, eid)) {
- if (has_permission(p->include, context))
- dundi_ie_append_eid(ied, DUNDI_IE_EID_DIRECT, eid);
- else
- dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
- break;
- }
- p = p->next;
- }
- if (!p)
- dundi_ie_append_eid(ied, DUNDI_IE_EID, eid);
- ast_mutex_unlock(&peerlock);
-}
-
-static int dundi_discover(struct dundi_transaction *trans)
-{
- struct dundi_ie_data ied;
- int x;
- if (!trans->parent) {
- ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
- return -1;
- }
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
- if (!dundi_eid_zero(&trans->us_eid))
- dundi_ie_append_eid(&ied, DUNDI_IE_EID_DIRECT, &trans->us_eid);
- for (x=0;x<trans->eidcount;x++)
- dundi_ie_append_eid_appropriately(&ied, trans->parent->dcontext, &trans->eids[x], &trans->us_eid);
- dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number);
- dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
- dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
- if (trans->parent->cbypass)
- dundi_ie_append(&ied, DUNDI_IE_CACHEBYPASS);
- if (trans->autokilltimeout)
- trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
- return dundi_send(trans, DUNDI_COMMAND_DPDISCOVER, 0, 0, &ied);
-}
-
-static int precache_trans(struct dundi_transaction *trans, struct dundi_mapping *maps, int mapcount, int *minexp, int *foundanswers)
-{
- struct dundi_ie_data ied;
- int x, res;
- int max = 999999;
- int expiration = dundi_cache_time;
- int ouranswers=0;
- dundi_eid *avoid[1] = { NULL, };
- int direct[1] = { 0, };
- struct dundi_result dr[MAX_RESULTS];
- struct dundi_hint_metadata hmd;
- if (!trans->parent) {
- ast_log(LOG_WARNING, "Tried to discover a transaction with no parent?!?\n");
- return -1;
- }
- memset(&hmd, 0, sizeof(hmd));
- memset(&dr, 0, sizeof(dr));
- /* Look up the answers we're going to include */
- for (x=0;x<mapcount;x++)
- ouranswers = dundi_lookup_local(dr, maps + x, trans->parent->number, &trans->us_eid, ouranswers, &hmd);
- if (ouranswers < 0)
- ouranswers = 0;
- for (x=0;x<ouranswers;x++) {
- if (dr[x].weight < max)
- max = dr[x].weight;
- }
- if (max) {
- /* If we do not have a canonical result, keep looking */
- res = dundi_lookup_internal(dr + ouranswers, MAX_RESULTS - ouranswers, NULL, trans->parent->dcontext, trans->parent->number, trans->ttl, 1, &hmd, &expiration, 0, 1, &trans->them_eid, avoid, direct);
- if (res > 0) {
- /* Append answer in result */
- ouranswers += res;
- }
- }
-
- if (ouranswers > 0) {
- *foundanswers += ouranswers;
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
- if (!dundi_eid_zero(&trans->us_eid))
- dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
- for (x=0;x<trans->eidcount;x++)
- dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
- dundi_ie_append_str(&ied, DUNDI_IE_CALLED_NUMBER, trans->parent->number);
- dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
- dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
- for (x=0;x<ouranswers;x++) {
- /* Add answers */
- if (dr[x].expiration && (expiration > dr[x].expiration))
- expiration = dr[x].expiration;
- dundi_ie_append_answer(&ied, DUNDI_IE_ANSWER, &dr[x].eid, dr[x].techint, dr[x].flags, dr[x].weight, dr[x].dest);
- }
- dundi_ie_append_hint(&ied, DUNDI_IE_HINT, hmd.flags, hmd.exten);
- dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, expiration);
- if (trans->autokilltimeout)
- trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
- if (expiration < *minexp)
- *minexp = expiration;
- return dundi_send(trans, DUNDI_COMMAND_PRECACHERQ, 0, 0, &ied);
- } else {
- /* Oops, nothing to send... */
- destroy_trans(trans, 0);
- return 0;
- }
-}
-
-static int dundi_query(struct dundi_transaction *trans)
-{
- struct dundi_ie_data ied;
- int x;
- if (!trans->parent) {
- ast_log(LOG_WARNING, "Tried to query a transaction with no parent?!?\n");
- return -1;
- }
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
- if (!dundi_eid_zero(&trans->us_eid))
- dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->us_eid);
- for (x=0;x<trans->eidcount;x++)
- dundi_ie_append_eid(&ied, DUNDI_IE_EID, &trans->eids[x]);
- dundi_ie_append_eid(&ied, DUNDI_IE_REQEID, &trans->parent->query_eid);
- dundi_ie_append_str(&ied, DUNDI_IE_CALLED_CONTEXT, trans->parent->dcontext);
- dundi_ie_append_short(&ied, DUNDI_IE_TTL, trans->ttl);
- if (trans->autokilltimeout)
- trans->autokillid = ast_sched_add(sched, trans->autokilltimeout, do_autokill, trans);
- return dundi_send(trans, DUNDI_COMMAND_EIDQUERY, 0, 0, &ied);
-}
-
-static int discover_transactions(struct dundi_request *dr)
-{
- struct dundi_transaction *trans;
- ast_mutex_lock(&peerlock);
- trans = dr->trans;
- while(trans) {
- dundi_discover(trans);
- trans = trans->next;
- }
- ast_mutex_unlock(&peerlock);
- return 0;
-}
-
-static int precache_transactions(struct dundi_request *dr, struct dundi_mapping *maps, int mapcount, int *expiration, int *foundanswers)
-{
- struct dundi_transaction *trans, *transn;
- /* Mark all as "in thread" so they don't disappear */
- ast_mutex_lock(&peerlock);
- trans = dr->trans;
- while(trans) {
- if (trans->thread)
- ast_log(LOG_WARNING, "This shouldn't happen, really...\n");
- trans->thread = 1;
- trans = trans->next;
- }
- ast_mutex_unlock(&peerlock);
-
- trans = dr->trans;
- while(trans) {
- if (!ast_test_flag(trans, FLAG_DEAD))
- precache_trans(trans, maps, mapcount, expiration, foundanswers);
- trans = trans->next;
- }
-
- /* Cleanup any that got destroyed in the mean time */
- ast_mutex_lock(&peerlock);
- trans = dr->trans;
- while(trans) {
- transn = trans->next;
- trans->thread = 0;
- if (ast_test_flag(trans, FLAG_DEAD)) {
- ast_log(LOG_DEBUG, "Our transaction went away!\n");
- destroy_trans(trans, 0);
- }
- trans = transn;
- }
- ast_mutex_unlock(&peerlock);
- return 0;
-}
-
-static int query_transactions(struct dundi_request *dr)
-{
- struct dundi_transaction *trans;
- ast_mutex_lock(&peerlock);
- trans = dr->trans;
- while(trans) {
- dundi_query(trans);
- trans = trans->next;
- }
- ast_mutex_unlock(&peerlock);
- return 0;
-}
-
-static int optimize_transactions(struct dundi_request *dr, int order)
-{
- /* Minimize the message propagation through DUNDi by
- alerting the network to hops which should be not be considered */
- struct dundi_transaction *trans;
- struct dundi_peer *peer;
- dundi_eid tmp;
- int x;
- int needpush;
- ast_mutex_lock(&peerlock);
- trans = dr->trans;
- while(trans) {
- /* Pop off the true root */
- if (trans->eidcount) {
- tmp = trans->eids[--trans->eidcount];
- needpush = 1;
- } else {
- tmp = trans->us_eid;
- needpush = 0;
- }
-
- peer = peers;
- while(peer) {
- if (has_permission(peer->include, dr->dcontext) &&
- dundi_eid_cmp(&peer->eid, &trans->them_eid) &&
- (peer->order <= order)) {
- /* For each other transaction, make sure we don't
- ask this EID about the others if they're not
- already in the list */
- if (!dundi_eid_cmp(&tmp, &peer->eid))
- x = -1;
- else {
- for (x=0;x<trans->eidcount;x++) {
- if (!dundi_eid_cmp(&trans->eids[x], &peer->eid))
- break;
- }
- }
- if (x == trans->eidcount) {
- /* Nope not in the list, if needed, add us at the end since we're the source */
- if (trans->eidcount < DUNDI_MAX_STACK - needpush) {
- trans->eids[trans->eidcount++] = peer->eid;
- /* Need to insert the real root (or us) at the bottom now as
- a requirement now. */
- needpush = 1;
- }
- }
- }
- peer = peer->next;
- }
- /* If necessary, push the true root back on the end */
- if (needpush)
- trans->eids[trans->eidcount++] = tmp;
- trans = trans->next;
- }
- ast_mutex_unlock(&peerlock);
- return 0;
-}
-
-static int append_transaction(struct dundi_request *dr, struct dundi_peer *p, int ttl, dundi_eid *avoid[])
-{
- struct dundi_transaction *trans;
- int x;
- char eid_str[20];
- char eid_str2[20];
- /* Ignore if not registered */
- if (!p->addr.sin_addr.s_addr)
- return 0;
- if (p->maxms && ((p->lastms < 0) || (p->lastms >= p->maxms)))
- return 0;
- if (ast_strlen_zero(dr->number))
- ast_log(LOG_DEBUG, "Will query peer '%s' for '%s' (context '%s')\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dundi_eid_to_str(eid_str2, sizeof(eid_str2), &dr->query_eid), dr->dcontext);
- else
- ast_log(LOG_DEBUG, "Will query peer '%s' for '%s@%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &p->eid), dr->number, dr->dcontext);
- trans = create_transaction(p);
- if (!trans)
- return -1;
- trans->next = dr->trans;
- trans->parent = dr;
- trans->ttl = ttl;
- for (x=0;avoid[x] && (x <DUNDI_MAX_STACK);x++)
- trans->eids[x] = *avoid[x];
- trans->eidcount = x;
- dr->trans = trans;
- return 0;
-}
-
-static void cancel_request(struct dundi_request *dr)
-{
- struct dundi_transaction *trans, *next;
-
- ast_mutex_lock(&peerlock);
- trans = dr->trans;
-
- while(trans) {
- next = trans->next;
- /* Orphan transaction from request */
- trans->parent = NULL;
- trans->next = NULL;
- /* Send final cancel */
- dundi_send(trans, DUNDI_COMMAND_CANCEL, 0, 1, NULL);
- trans = next;
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static void abort_request(struct dundi_request *dr)
-{
- ast_mutex_lock(&peerlock);
- while(dr->trans)
- destroy_trans(dr->trans, 0);
- ast_mutex_unlock(&peerlock);
-}
-
-static void build_transactions(struct dundi_request *dr, int ttl, int order, int *foundcache, int *skipped, int blockempty, int nocache, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int directs[])
-{
- struct dundi_peer *p;
- int x;
- int res;
- int pass;
- int allowconnect;
- char eid_str[20];
- ast_mutex_lock(&peerlock);
- p = peers;
- while(p) {
- if (modeselect == 1) {
- /* Send the precache to push upstreams only! */
- pass = has_permission(p->permit, dr->dcontext) && (p->pcmodel & DUNDI_MODEL_OUTBOUND);
- allowconnect = 1;
- } else {
- /* Normal lookup / EID query */
- pass = has_permission(p->include, dr->dcontext);
- allowconnect = p->model & DUNDI_MODEL_OUTBOUND;
- }
- if (skip) {
- if (!dundi_eid_cmp(skip, &p->eid))
- pass = 0;
- }
- if (pass) {
- if (p->order <= order) {
- /* Check order first, then check cache, regardless of
- omissions, this gets us more likely to not have an
- affected answer. */
- if((nocache || !(res = cache_lookup(dr, &p->eid, dr->crc32, &dr->expiration)))) {
- res = 0;
- /* Make sure we haven't already seen it and that it won't
- affect our answer */
- for (x=0;avoid[x];x++) {
- if (!dundi_eid_cmp(avoid[x], &p->eid) || !dundi_eid_cmp(avoid[x], &p->us_eid)) {
- /* If not a direct connection, it affects our answer */
- if (directs && !directs[x])
- ast_clear_flag_nonstd(dr->hmd, DUNDI_HINT_UNAFFECTED);
- break;
- }
- }
- /* Make sure we can ask */
- if (allowconnect) {
- if (!avoid[x] && (!blockempty || !dundi_eid_zero(&p->us_eid))) {
- /* Check for a matching or 0 cache entry */
- append_transaction(dr, p, ttl, avoid);
- } else
- ast_log(LOG_DEBUG, "Avoiding '%s' in transaction\n", dundi_eid_to_str(eid_str, sizeof(eid_str), avoid[x]));
- }
- }
- *foundcache |= res;
- } else if (!*skipped || (p->order < *skipped))
- *skipped = p->order;
- }
- p = p->next;
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static int register_request(struct dundi_request *dr, struct dundi_request **pending)
-{
- struct dundi_request *cur;
- int res=0;
- char eid_str[20];
- ast_mutex_lock(&peerlock);
- cur = requests;
- while(cur) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Checking '%s@%s' vs '%s@%s'\n", cur->dcontext, cur->number,
- dr->dcontext, dr->number);
- if (!strcasecmp(cur->dcontext, dr->dcontext) &&
- !strcasecmp(cur->number, dr->number) &&
- (!dundi_eid_cmp(&cur->root_eid, &dr->root_eid) || (cur->crc32 == dr->crc32))) {
- ast_log(LOG_DEBUG, "Found existing query for '%s@%s' for '%s' crc '%08lx'\n",
- cur->dcontext, cur->number, dundi_eid_to_str(eid_str, sizeof(eid_str), &cur->root_eid), cur->crc32);
- *pending = cur;
- res = 1;
- break;
- }
- cur = cur->next;
- }
- if (!res) {
- ast_log(LOG_DEBUG, "Registering request for '%s@%s' on behalf of '%s' crc '%08lx'\n",
- dr->number, dr->dcontext, dundi_eid_to_str(eid_str, sizeof(eid_str), &dr->root_eid), dr->crc32);
- /* Go ahead and link us in since nobody else is searching for this */
- dr->next = requests;
- requests = dr;
- *pending = NULL;
- }
- ast_mutex_unlock(&peerlock);
- return res;
-}
-
-static void unregister_request(struct dundi_request *dr)
-{
- struct dundi_request *cur, *prev;
- ast_mutex_lock(&peerlock);
- prev = NULL;
- cur = requests;
- while(cur) {
- if (cur == dr) {
- if (prev)
- prev->next = cur->next;
- else
- requests = cur->next;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static int check_request(struct dundi_request *dr)
-{
- struct dundi_request *cur;
- int res = 0;
- ast_mutex_lock(&peerlock);
- cur = requests;
- while(cur) {
- if (cur == dr) {
- res = 1;
- break;
- }
- cur = cur->next;
- }
- ast_mutex_unlock(&peerlock);
- return res;
-}
-
-static unsigned long avoid_crc32(dundi_eid *avoid[])
-{
- /* Idea is that we're calculating a checksum which is independent of
- the order that the EID's are listed in */
- unsigned long acrc32 = 0;
- int x;
- for (x=0;avoid[x];x++) {
- /* Order doesn't matter */
- if (avoid[x+1]) {
- acrc32 ^= crc32(0L, (unsigned char *)avoid[x], sizeof(dundi_eid));
- }
- }
- return acrc32;
-}
-
-static int dundi_lookup_internal(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int ttl, int blockempty, struct dundi_hint_metadata *hmd, int *expiration, int cbypass, int modeselect, dundi_eid *skip, dundi_eid *avoid[], int direct[])
-{
- int res;
- struct dundi_request dr, *pending;
- dundi_eid *rooteid=NULL;
- int x;
- int ttlms;
- int ms;
- int foundcache;
- int skipped=0;
- int order=0;
- char eid_str[20];
- struct timeval start;
-
- /* Don't do anthing for a hungup channel */
- if (chan && chan->_softhangup)
- return 0;
-
- ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
-
- for (x=0;avoid[x];x++)
- rooteid = avoid[x];
- /* Now perform real check */
- memset(&dr, 0, sizeof(dr));
- if (pipe(dr.pfds)) {
- ast_log(LOG_WARNING, "pipe failed: %s\n" , strerror(errno));
- return -1;
- }
- dr.dr = result;
- dr.hmd = hmd;
- dr.maxcount = maxret;
- dr.expiration = *expiration;
- dr.cbypass = cbypass;
- dr.crc32 = avoid_crc32(avoid);
- ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
- ast_copy_string(dr.number, number, sizeof(dr.number));
- if (rooteid)
- dr.root_eid = *rooteid;
- res = register_request(&dr, &pending);
- if (res) {
- /* Already a request */
- if (rooteid && !dundi_eid_cmp(&dr.root_eid, &pending->root_eid)) {
- /* This is on behalf of someone else. Go ahead and close this out since
- they'll get their answer anyway. */
- ast_log(LOG_DEBUG, "Oooh, duplicate request for '%s@%s' for '%s'\n",
- dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &dr.root_eid));
- close(dr.pfds[0]);
- close(dr.pfds[1]);
- return -2;
- } else {
- /* Wait for the cache to populate */
- ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n",
- dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
- start = ast_tvnow();
- while(check_request(pending) && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
- /* XXX Would be nice to have a way to poll/select here XXX */
- /* XXX this is a busy wait loop!!! */
- usleep(1);
- }
- /* Continue on as normal, our cache should kick in */
- }
- }
- /* Create transactions */
- do {
- order = skipped;
- skipped = 0;
- foundcache = 0;
- build_transactions(&dr, ttl, order, &foundcache, &skipped, blockempty, cbypass, modeselect, skip, avoid, direct);
- } while (skipped && !foundcache && !dr.trans);
- /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't
- do this earlier because we didn't know if we were going to have transactions
- or not. */
- if (!ttl) {
- ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED);
- abort_request(&dr);
- unregister_request(&dr);
- close(dr.pfds[0]);
- close(dr.pfds[1]);
- return 0;
- }
-
- /* Optimize transactions */
- optimize_transactions(&dr, order);
- /* Actually perform transactions */
- discover_transactions(&dr);
- /* Wait for transaction to come back */
- start = ast_tvnow();
- while(dr.trans && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
- ms = 100;
- ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
- }
- if (chan && chan->_softhangup)
- ast_log(LOG_DEBUG, "Hrm, '%s' hungup before their query for %s@%s finished\n", chan->name, dr.number, dr.dcontext);
- cancel_request(&dr);
- unregister_request(&dr);
- res = dr.respcount;
- *expiration = dr.expiration;
- close(dr.pfds[0]);
- close(dr.pfds[1]);
- return res;
-}
-
-int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number, int cbypass)
-{
- struct dundi_hint_metadata hmd;
- dundi_eid *avoid[1] = { NULL, };
- int direct[1] = { 0, };
- int expiration = dundi_cache_time;
- memset(&hmd, 0, sizeof(hmd));
- hmd.flags = DUNDI_HINT_DONT_ASK | DUNDI_HINT_UNAFFECTED;
- return dundi_lookup_internal(result, maxret, chan, dcontext, number, dundi_ttl, 0, &hmd, &expiration, cbypass, 0, NULL, avoid, direct);
-}
-
-static void reschedule_precache(const char *number, const char *context, int expiration)
-{
- int len;
- struct dundi_precache_queue *qe, *prev=NULL;
- ast_mutex_lock(&pclock);
- qe = pcq;
- while(qe) {
- if (!strcmp(number, qe->number) && !strcasecmp(context, qe->context)) {
- if (prev)
- prev->next = qe->next;
- else
- pcq = qe->next;
- qe->next = NULL;
- break;
- }
- prev = qe;
- qe = qe->next;
- };
- if (!qe) {
- len = sizeof(struct dundi_precache_queue);
- len += strlen(number) + 1;
- len += strlen(context) + 1;
- qe = malloc(len);
- if (qe) {
- memset(qe, 0, len);
- strcpy(qe->number, number);
- qe->context = qe->number + strlen(number) + 1;
- strcpy(qe->context, context);
- }
- }
- time(&qe->expiration);
- qe->expiration += expiration;
- prev = pcq;
- if (prev) {
- while(prev->next && (prev->next->expiration <= qe->expiration))
- prev = prev->next;
- qe->next = prev->next;
- prev->next = qe;
- } else
- pcq = qe;
- ast_mutex_unlock(&pclock);
-
-}
-
-static void dundi_precache_full(void)
-{
- struct dundi_mapping *cur;
- struct ast_context *con;
- struct ast_exten *e;
- cur = mappings;
- while(cur) {
- ast_log(LOG_NOTICE, "Should precache context '%s'\n", cur->dcontext);
- ast_lock_contexts();
- con = ast_walk_contexts(NULL);
- while(con) {
- if (!strcasecmp(cur->lcontext, ast_get_context_name(con))) {
- /* Found the match, now queue them all up */
- ast_lock_context(con);
- e = ast_walk_context_extensions(con, NULL);
- while(e) {
- reschedule_precache(ast_get_extension_name(e), cur->dcontext, 0);
- e = ast_walk_context_extensions(con, e);
- }
- ast_unlock_context(con);
- }
- con = ast_walk_contexts(con);
- }
- ast_unlock_contexts();
- cur = cur->next;
- }
-}
-
-static int dundi_precache_internal(const char *context, const char *number, int ttl, dundi_eid *avoids[])
-{
- struct dundi_request dr;
- struct dundi_hint_metadata hmd;
- struct dundi_result dr2[MAX_RESULTS];
- struct timeval start;
- struct dundi_mapping *maps=NULL, *cur;
- int nummaps;
- int foundanswers;
- int foundcache, skipped, ttlms, ms;
- if (!context)
- context = "e164";
- ast_log(LOG_DEBUG, "Precache internal (%s@%s)!\n", number, context);
-
- ast_mutex_lock(&peerlock);
- nummaps = 0;
- cur = mappings;
- while(cur) {
- if (!strcasecmp(cur->dcontext, context))
- nummaps++;
- cur = cur->next;
- }
- if (nummaps) {
- maps = alloca(nummaps * sizeof(struct dundi_mapping));
- nummaps = 0;
- if (maps) {
- cur = mappings;
- while(cur) {
- if (!strcasecmp(cur->dcontext, context))
- maps[nummaps++] = *cur;
- cur = cur->next;
- }
- }
- }
- ast_mutex_unlock(&peerlock);
- if (!nummaps || !maps)
- return -1;
- ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
- memset(&dr2, 0, sizeof(dr2));
- memset(&dr, 0, sizeof(dr));
- memset(&hmd, 0, sizeof(hmd));
- dr.dr = dr2;
- ast_copy_string(dr.number, number, sizeof(dr.number));
- ast_copy_string(dr.dcontext, context ? context : "e164", sizeof(dr.dcontext));
- dr.maxcount = MAX_RESULTS;
- dr.expiration = dundi_cache_time;
- dr.hmd = &hmd;
- dr.pfds[0] = dr.pfds[1] = -1;
- pipe(dr.pfds);
- build_transactions(&dr, ttl, 0, &foundcache, &skipped, 0, 1, 1, NULL, avoids, NULL);
- optimize_transactions(&dr, 0);
- foundanswers = 0;
- precache_transactions(&dr, maps, nummaps, &dr.expiration, &foundanswers);
- if (foundanswers) {
- if (dr.expiration > 0)
- reschedule_precache(dr.number, dr.dcontext, dr.expiration);
- else
- ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext);
- }
- start = ast_tvnow();
- while(dr.trans && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms)) {
- if (dr.pfds[0] > -1) {
- ms = 100;
- ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
- } else
- usleep(1);
- }
- cancel_request(&dr);
- if (dr.pfds[0] > -1) {
- close(dr.pfds[0]);
- close(dr.pfds[1]);
- }
- return 0;
-}
-
-int dundi_precache(const char *context, const char *number)
-{
- dundi_eid *avoid[1] = { NULL, };
- return dundi_precache_internal(context, number, dundi_ttl, avoid);
-}
-
-static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[])
-{
- int res;
- struct dundi_request dr;
- dundi_eid *rooteid=NULL;
- int x;
- int ttlms;
- int skipped=0;
- int foundcache=0;
- struct timeval start;
-
- ttlms = DUNDI_FLUFF_TIME + ttl * DUNDI_TTL_TIME;
-
- for (x=0;avoid[x];x++)
- rooteid = avoid[x];
- /* Now perform real check */
- memset(&dr, 0, sizeof(dr));
- dr.hmd = hmd;
- dr.dei = dei;
- dr.pfds[0] = dr.pfds[1] = -1;
- ast_copy_string(dr.dcontext, dcontext ? dcontext : "e164", sizeof(dr.dcontext));
- memcpy(&dr.query_eid, eid, sizeof(dr.query_eid));
- if (rooteid)
- dr.root_eid = *rooteid;
- /* Create transactions */
- build_transactions(&dr, ttl, 9999, &foundcache, &skipped, blockempty, 0, 0, NULL, avoid, NULL);
-
- /* If no TTL, abort and return 0 now after setting TTL expired hint. Couldn't
- do this earlier because we didn't know if we were going to have transactions
- or not. */
- if (!ttl) {
- ast_set_flag_nonstd(hmd, DUNDI_HINT_TTL_EXPIRED);
- return 0;
- }
-
- /* Optimize transactions */
- optimize_transactions(&dr, 9999);
- /* Actually perform transactions */
- query_transactions(&dr);
- /* Wait for transaction to come back */
- start = ast_tvnow();
- while(dr.trans && (ast_tvdiff_ms(ast_tvnow(), start) < ttlms))
- usleep(1);
- res = dr.respcount;
- return res;
-}
-
-int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid)
-{
- dundi_eid *avoid[1] = { NULL, };
- struct dundi_hint_metadata hmd;
- memset(&hmd, 0, sizeof(hmd));
- return dundi_query_eid_internal(dei, dcontext, &eid, &hmd, dundi_ttl, 0, avoid);
-}
-
-/*!
- * \ingroup applications
- */
-static int dundi_lookup_exec(struct ast_channel *chan, void *data)
-{
- char *num;
- char *context;
- char *opts;
- int results;
- int x;
- int bypass = 0;
- struct localuser *u;
- struct dundi_result dr[MAX_RESULTS];
- static int dep_warning = 0;
-
- LOCAL_USER_ADD(u);
-
- if (!dep_warning) {
- ast_log(LOG_WARNING, "This application has been deprecated in favor of the DUNDILOOKUP dialplan function.\n");
- dep_warning = 1;
- }
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "DUNDiLookup requires an argument (number)\n");
- LOCAL_USER_REMOVE(u);
- return 0;
- }
-
- num = ast_strdupa(data);
- if (!num) {
- ast_log(LOG_ERROR, "Out of memory!\n");
- LOCAL_USER_REMOVE(u);
- return 0;
- }
-
- context = strchr(num, '|');
- if (context) {
- *context = '\0';
- context++;
- opts = strchr(context, '|');
- if (opts) {
- *opts = '\0';
- opts++;
- if (strchr(opts, 'b'))
- bypass = 1;
- }
- }
-
- if (ast_strlen_zero(context))
- context = "e164";
-
- results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass);
- if (results > 0) {
- sort_results(dr, results);
- for (x = 0; x < results; x++) {
- if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) {
- pbx_builtin_setvar_helper(chan, "DUNDTECH", dr[x].tech);
- pbx_builtin_setvar_helper(chan, "DUNDDEST", dr[x].dest);
- break;
- }
- }
- } else if (option_priority_jumping)
- ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
-
- LOCAL_USER_REMOVE(u);
-
- return 0;
-}
-
-static char *dundifunc_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
-{
- char *num;
- char *context;
- char *opts;
- int results;
- int x;
- int bypass = 0;
- struct localuser *u;
- struct dundi_result dr[MAX_RESULTS];
-
- LOCAL_USER_ACF_ADD(u);
-
- buf[0] = '\0';
-
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "DUNDILOOKUP requires an argument (number)\n");
- LOCAL_USER_REMOVE(u);
- return buf;
- }
-
- num = ast_strdupa(data);
- if (!num) {
- ast_log(LOG_ERROR, "Out of memory!\n");
- LOCAL_USER_REMOVE(u);
- return buf;
- }
-
- context = strchr(num, '|');
- if (context) {
- *context = '\0';
- context++;
- opts = strchr(context, '|');
- if (opts) {
- *opts = '\0';
- opts++;
- if (strchr(opts, 'b'))
- bypass = 1;
- }
- }
-
- if (ast_strlen_zero(context))
- context = "e164";
-
- results = dundi_lookup(dr, MAX_RESULTS, NULL, context, num, bypass);
- if (results > 0) {
- sort_results(dr, results);
- for (x = 0; x < results; x++) {
- if (ast_test_flag(dr + x, DUNDI_FLAG_EXISTS)) {
- snprintf(buf, len, "%s/%s", dr[x].tech, dr[x].dest);
- break;
- }
- }
- }
-
- LOCAL_USER_REMOVE(u);
-
- return buf;
-}
-
-/*! DUNDILOOKUP
- * \ingroup functions
-*/
-
-static struct ast_custom_function dundi_function = {
- .name = "DUNDILOOKUP",
- .synopsis = "Do a DUNDi lookup of a phone number.",
- .syntax = "DUNDILOOKUP(number[|context[|options]])",
- .desc = "This will do a DUNDi lookup of the given phone number.\n"
- "If no context is given, the default will be e164. The result of\n"
- "this function will the Technology/Resource found in the DUNDi\n"
- "lookup. If no results were found, the result will be blank.\n"
- "If the 'b' option is specified, the internal DUNDi cache will\n"
- "be bypassed.\n",
- .read = dundifunc_read,
-};
-
-static void mark_peers(void)
-{
- struct dundi_peer *peer;
- ast_mutex_lock(&peerlock);
- peer = peers;
- while(peer) {
- peer->dead = 1;
- peer = peer->next;
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static void mark_mappings(void)
-{
- struct dundi_mapping *map;
- ast_mutex_lock(&peerlock);
- map = mappings;
- while(map) {
- map->dead = 1;
- map = map->next;
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static void destroy_permissions(struct permission *p)
-{
- struct permission *prev;
- while(p) {
- prev = p;
- p = p->next;
- free(prev);
- }
-}
-
-static void destroy_peer(struct dundi_peer *peer)
-{
- if (peer->registerid > -1)
- ast_sched_del(sched, peer->registerid);
- if (peer->regtrans)
- destroy_trans(peer->regtrans, 0);
- if (peer->keypending)
- destroy_trans(peer->keypending, 0);
- if (peer->qualifyid > -1)
- ast_sched_del(sched, peer->qualifyid);
- destroy_permissions(peer->permit);
- destroy_permissions(peer->include);
- free(peer);
-}
-
-static void destroy_map(struct dundi_mapping *map)
-{
- free(map);
-}
-
-static void prune_peers(void)
-{
- struct dundi_peer *peer, *prev, *next;
- ast_mutex_lock(&peerlock);
- peer = peers;
- prev = NULL;
- while(peer) {
- next = peer->next;
- if (peer->dead) {
- if (prev)
- prev->next = peer->next;
- else
- peers = peer->next;
- destroy_peer(peer);
- } else
- prev = peer;
- peer = next;
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static void prune_mappings(void)
-{
- struct dundi_mapping *map, *prev, *next;
- ast_mutex_lock(&peerlock);
- map = mappings;
- prev = NULL;
- while(map) {
- next = map->next;
- if (map->dead) {
- if (prev)
- prev->next = map->next;
- else
- mappings = map->next;
- destroy_map(map);
- } else
- prev = map;
- map = next;
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static struct permission *append_permission(struct permission *p, char *s, int allow)
-{
- struct permission *start;
- start = p;
- if (p) {
- while(p->next)
- p = p->next;
- }
- if (p) {
- p->next = malloc(sizeof(struct permission) + strlen(s) + 1);
- p = p->next;
- } else {
- p = malloc(sizeof(struct permission) + strlen(s) + 1);
- }
- if (p) {
- memset(p, 0, sizeof(struct permission));
- memcpy(p->name, s, strlen(s) + 1);
- p->allow = allow;
- }
- return start ? start : p;
-}
-
-#define MAX_OPTS 128
-
-static void build_mapping(char *name, char *value)
-{
- char *t, *fields[MAX_OPTS];
- struct dundi_mapping *map;
- int x;
- int y;
- t = ast_strdupa(value);
- if (t) {
- map = mappings;
- while(map) {
- /* Find a double match */
- if (!strcasecmp(map->dcontext, name) &&
- (!strncasecmp(map->lcontext, value, strlen(map->lcontext)) &&
- (!value[strlen(map->lcontext)] ||
- (value[strlen(map->lcontext)] == ','))))
- break;
- map = map->next;
- }
- if (!map) {
- map = malloc(sizeof(struct dundi_mapping));
- if (map) {
- memset(map, 0, sizeof(struct dundi_mapping));
- map->next = mappings;
- mappings = map;
- map->dead = 1;
- }
- }
- if (map) {
- map->options = 0;
- memset(fields, 0, sizeof(fields));
- x = 0;
- while(t && x < MAX_OPTS) {
- fields[x++] = t;
- t = strchr(t, ',');
- if (t) {
- *t = '\0';
- t++;
- }
- } /* Russell was here, arrrr! */
- if ((x == 1) && ast_strlen_zero(fields[0])) {
- /* Placeholder mapping */
- ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
- map->dead = 0;
- } else if (x >= 4) {
- ast_copy_string(map->dcontext, name, sizeof(map->dcontext));
- ast_copy_string(map->lcontext, fields[0], sizeof(map->lcontext));
- if ((sscanf(fields[1], "%d", &map->weight) == 1) && (map->weight >= 0) && (map->weight < 60000)) {
- ast_copy_string(map->dest, fields[3], sizeof(map->dest));
- if ((map->tech = str2tech(fields[2]))) {
- map->dead = 0;
- }
- } else {
- ast_log(LOG_WARNING, "Invalid weight '%s' specified, deleting entry '%s/%s'\n", fields[1], map->dcontext, map->lcontext);
- }
- for (y=4;y<x;y++) {
- if (!strcasecmp(fields[y], "nounsolicited"))
- map->options |= DUNDI_FLAG_NOUNSOLICITED;
- else if (!strcasecmp(fields[y], "nocomunsolicit"))
- map->options |= DUNDI_FLAG_NOCOMUNSOLICIT;
- else if (!strcasecmp(fields[y], "residential"))
- map->options |= DUNDI_FLAG_RESIDENTIAL;
- else if (!strcasecmp(fields[y], "commercial"))
- map->options |= DUNDI_FLAG_COMMERCIAL;
- else if (!strcasecmp(fields[y], "mobile"))
- map->options |= DUNDI_FLAG_MOBILE;
- else if (!strcasecmp(fields[y], "nopartial"))
- map->options |= DUNDI_FLAG_INTERNAL_NOPARTIAL;
- else
- ast_log(LOG_WARNING, "Don't know anything about option '%s'\n", fields[y]);
- }
- } else
- ast_log(LOG_WARNING, "Expected at least %d arguments in map, but got only %d\n", 4, x);
- }
- }
-}
-
-static int do_register(void *data)
-{
- struct dundi_ie_data ied;
- struct dundi_peer *peer = data;
- char eid_str[20];
- char eid_str2[20];
- /* Called with peerlock already held */
- ast_log(LOG_DEBUG, "Register us as '%s' to '%s'\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->us_eid), dundi_eid_to_str(eid_str2, sizeof(eid_str2), &peer->eid));
- peer->registerid = ast_sched_add(sched, default_expiration * 1000, do_register, data);
- /* Destroy old transaction if there is one */
- if (peer->regtrans)
- destroy_trans(peer->regtrans, 0);
- peer->regtrans = create_transaction(peer);
- if (peer->regtrans) {
- ast_set_flag(peer->regtrans, FLAG_ISREG);
- memset(&ied, 0, sizeof(ied));
- dundi_ie_append_short(&ied, DUNDI_IE_VERSION, DUNDI_DEFAULT_VERSION);
- dundi_ie_append_eid(&ied, DUNDI_IE_EID, &peer->regtrans->us_eid);
- dundi_ie_append_short(&ied, DUNDI_IE_EXPIRATION, default_expiration);
- dundi_send(peer->regtrans, DUNDI_COMMAND_REGREQ, 0, 0, &ied);
-
- } else
- ast_log(LOG_NOTICE, "Unable to create new transaction for registering to '%s'!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
-
- return 0;
-}
-
-static int do_qualify(void *data)
-{
- struct dundi_peer *peer;
- peer = data;
- peer->qualifyid = -1;
- qualify_peer(peer, 0);
- return 0;
-}
-
-static void qualify_peer(struct dundi_peer *peer, int schedonly)
-{
- int when;
- if (peer->qualifyid > -1)
- ast_sched_del(sched, peer->qualifyid);
- peer->qualifyid = -1;
- if (peer->qualtrans)
- destroy_trans(peer->qualtrans, 0);
- peer->qualtrans = NULL;
- if (peer->maxms > 0) {
- when = 60000;
- if (peer->lastms < 0)
- when = 10000;
- if (schedonly)
- when = 5000;
- peer->qualifyid = ast_sched_add(sched, when, do_qualify, peer);
- if (!schedonly)
- peer->qualtrans = create_transaction(peer);
- if (peer->qualtrans) {
- peer->qualtx = ast_tvnow();
- ast_set_flag(peer->qualtrans, FLAG_ISQUAL);
- dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL);
- }
- }
-}
-static void populate_addr(struct dundi_peer *peer, dundi_eid *eid)
-{
- char data[256];
- char *c;
- int port, expire;
- char eid_str[20];
- dundi_eid_to_str(eid_str, sizeof(eid_str), eid);
- if (!ast_db_get("dundi/dpeers", eid_str, data, sizeof(data))) {
- c = strchr(data, ':');
- if (c) {
- *c = '\0';
- c++;
- if (sscanf(c, "%d:%d", &port, &expire) == 2) {
- /* Got it! */
- inet_aton(data, &peer->addr.sin_addr);
- peer->addr.sin_family = AF_INET;
- peer->addr.sin_port = htons(port);
- peer->registerexpire = ast_sched_add(sched, (expire + 10) * 1000, do_register_expire, peer);
- }
- }
- }
-}
-
-
-static void build_peer(dundi_eid *eid, struct ast_variable *v, int *globalpcmode)
-{
- struct dundi_peer *peer;
- struct ast_hostent he;
- struct hostent *hp;
- dundi_eid testeid;
- int needregister=0;
- char eid_str[20];
-
- ast_mutex_lock(&peerlock);
- peer = peers;
- while(peer) {
- if (!dundi_eid_cmp(&peer->eid, eid)) {
- break;
- }
- peer = peer->next;
- }
- if (!peer) {
- /* Add us into the list */
- peer = malloc(sizeof(struct dundi_peer));
- if (peer) {
- memset(peer, 0, sizeof(struct dundi_peer));
- peer->registerid = -1;
- peer->registerexpire = -1;
- peer->qualifyid = -1;
- peer->addr.sin_family = AF_INET;
- peer->addr.sin_port = htons(DUNDI_PORT);
- populate_addr(peer, eid);
- peer->next = peers;
- peers = peer;
- }
- }
- if (peer) {
- peer->dead = 0;
- peer->eid = *eid;
- peer->us_eid = global_eid;
- destroy_permissions(peer->permit);
- destroy_permissions(peer->include);
- peer->permit = NULL;
- peer->include = NULL;
- if (peer->registerid > -1)
- ast_sched_del(sched, peer->registerid);
- peer->registerid = -1;
- while(v) {
- if (!strcasecmp(v->name, "inkey")) {
- ast_copy_string(peer->inkey, v->value, sizeof(peer->inkey));
- } else if (!strcasecmp(v->name, "outkey")) {
- ast_copy_string(peer->outkey, v->value, sizeof(peer->outkey));
- } else if (!strcasecmp(v->name, "host")) {
- if (!strcasecmp(v->value, "dynamic")) {
- peer->dynamic = 1;
- } else {
- hp = ast_gethostbyname(v->value, &he);
- if (hp) {
- memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr));
- peer->dynamic = 0;
- } else {
- ast_log(LOG_WARNING, "Unable to find host '%s' at line %d\n", v->value, v->lineno);
- peer->dead = 1;
- }
- }
- } else if (!strcasecmp(v->name, "ustothem")) {
- if (!dundi_str_to_eid(&testeid, v->value))
- peer->us_eid = testeid;
- else
- ast_log(LOG_WARNING, "'%s' is not a valid DUNDi Entity Identifier at line %d\n", v->value, v->lineno);
- } else if (!strcasecmp(v->name, "include")) {
- peer->include = append_permission(peer->include, v->value, 1);
- } else if (!strcasecmp(v->name, "permit")) {
- peer->permit = append_permission(peer->permit, v->value, 1);
- } else if (!strcasecmp(v->name, "noinclude")) {
- peer->include = append_permission(peer->include, v->value, 0);
- } else if (!strcasecmp(v->name, "deny")) {
- peer->permit = append_permission(peer->permit, v->value, 0);
- } else if (!strcasecmp(v->name, "register")) {
- needregister = ast_true(v->value);
- } else if (!strcasecmp(v->name, "order")) {
- if (!strcasecmp(v->value, "primary"))
- peer->order = 0;
- else if (!strcasecmp(v->value, "secondary"))
- peer->order = 1;
- else if (!strcasecmp(v->value, "tertiary"))
- peer->order = 2;
- else if (!strcasecmp(v->value, "quartiary"))
- peer->order = 3;
- else {
- ast_log(LOG_WARNING, "'%s' is not a valid order, should be primary, secondary, tertiary or quartiary at line %d\n", v->value, v->lineno);
- }
- } else if (!strcasecmp(v->name, "qualify")) {
- if (!strcasecmp(v->value, "no")) {
- peer->maxms = 0;
- } else if (!strcasecmp(v->value, "yes")) {
- peer->maxms = DEFAULT_MAXMS;
- } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
- ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of dundi.conf\n",
- dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid), v->lineno);
- peer->maxms = 0;
- }
- } else if (!strcasecmp(v->name, "model")) {
- if (!strcasecmp(v->value, "inbound"))
- peer->model = DUNDI_MODEL_INBOUND;
- else if (!strcasecmp(v->value, "outbound"))
- peer->model = DUNDI_MODEL_OUTBOUND;
- else if (!strcasecmp(v->value, "symmetric"))
- peer->model = DUNDI_MODEL_SYMMETRIC;
- else if (!strcasecmp(v->value, "none"))
- peer->model = 0;
- else {
- ast_log(LOG_WARNING, "Unknown model '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
- v->value, v->lineno);
- }
- } else if (!strcasecmp(v->name, "precache")) {
- if (!strcasecmp(v->value, "inbound"))
- peer->pcmodel = DUNDI_MODEL_INBOUND;
- else if (!strcasecmp(v->value, "outbound"))
- peer->pcmodel = DUNDI_MODEL_OUTBOUND;
- else if (!strcasecmp(v->value, "symmetric"))
- peer->pcmodel = DUNDI_MODEL_SYMMETRIC;
- else if (!strcasecmp(v->value, "none"))
- peer->pcmodel = 0;
- else {
- ast_log(LOG_WARNING, "Unknown pcmodel '%s', should be 'none', 'outbound', 'inbound', or 'symmetric' at line %d\n",
- v->value, v->lineno);
- }
- }
- v = v->next;
- }
- (*globalpcmode) |= peer->pcmodel;
- if (!peer->model && !peer->pcmodel) {
- ast_log(LOG_WARNING, "Peer '%s' lacks a model or pcmodel, discarding!\n",
- dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- peer->dead = 1;
- } else if ((peer->model & DUNDI_MODEL_INBOUND) && (peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
- ast_log(LOG_WARNING, "Peer '%s' may not be both inbound/symmetric model and outbound/symmetric precache model, discarding!\n",
- dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- peer->dead = 1;
- } else if ((peer->model & DUNDI_MODEL_OUTBOUND) && (peer->pcmodel & DUNDI_MODEL_INBOUND)) {
- ast_log(LOG_WARNING, "Peer '%s' may not be both outbound/symmetric model and inbound/symmetric precache model, discarding!\n",
- dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- peer->dead = 1;
- } else if (peer->include && !(peer->model & DUNDI_MODEL_OUTBOUND) && !(peer->pcmodel & DUNDI_MODEL_INBOUND)) {
- ast_log(LOG_WARNING, "Peer '%s' is supposed to be included in outbound searches but isn't an outbound peer or inbound precache!\n",
- dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- } else if (peer->permit && !(peer->model & DUNDI_MODEL_INBOUND) && !(peer->pcmodel & DUNDI_MODEL_OUTBOUND)) {
- ast_log(LOG_WARNING, "Peer '%s' is supposed to have permission for some inbound searches but isn't an inbound peer or outbound precache!\n",
- dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
- } else {
- if (needregister) {
- peer->registerid = ast_sched_add(sched, 2000, do_register, peer);
- }
- qualify_peer(peer, 1);
- }
- }
- ast_mutex_unlock(&peerlock);
-}
-
-static int dundi_helper(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *data, int flag)
-{
- struct dundi_result results[MAX_RESULTS];
- int res;
- int x;
- int found = 0;
- if (!strncasecmp(context, "macro-", 6)) {
- if (!chan) {
- ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
- return -1;
- }
- /* If done as a macro, use macro extension */
- if (!strcasecmp(exten, "s")) {
- exten = pbx_builtin_getvar_helper(chan, "ARG1");
- if (ast_strlen_zero(exten))
- exten = chan->macroexten;
- if (ast_strlen_zero(exten))
- exten = chan->exten;
- if (ast_strlen_zero(exten)) {
- ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
- return -1;
- }
- }
- if (ast_strlen_zero(data))
- data = "e164";
- } else {
- if (ast_strlen_zero(data))
- data = context;
- }
- res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
- for (x=0;x<res;x++) {
- if (ast_test_flag(results + x, flag))
- found++;
- }
- if (found >= priority)
- return 1;
- return 0;
-}
-
-static int dundi_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_EXISTS);
-}
-
-static int dundi_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_CANMATCH);
-}
-
-static int dundi_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
-{
- struct dundi_result results[MAX_RESULTS];
- int res;
- int x=0;
- char req[1024];
- struct ast_app *dial;
-
- if (!strncasecmp(context, "macro-", 6)) {
- if (!chan) {
- ast_log(LOG_NOTICE, "Can't use macro mode without a channel!\n");
- return -1;
- }
- /* If done as a macro, use macro extension */
- if (!strcasecmp(exten, "s")) {
- exten = pbx_builtin_getvar_helper(chan, "ARG1");
- if (ast_strlen_zero(exten))
- exten = chan->macroexten;
- if (ast_strlen_zero(exten))
- exten = chan->exten;
- if (ast_strlen_zero(exten)) {
- ast_log(LOG_WARNING, "Called in Macro mode with no ARG1 or MACRO_EXTEN?\n");
- return -1;
- }
- }
- if (ast_strlen_zero(data))
- data = "e164";
- } else {
- if (ast_strlen_zero(data))
- data = context;
- }
- res = dundi_lookup(results, MAX_RESULTS, chan, data, exten, 0);
- if (res > 0) {
- sort_results(results, res);
- for (x=0;x<res;x++) {
- if (ast_test_flag(results + x, DUNDI_FLAG_EXISTS)) {
- if (!--priority)
- break;
- }
- }
- }
- if (x < res) {
- /* Got a hit! */
- snprintf(req, sizeof(req), "%s/%s", results[x].tech, results[x].dest);
- dial = pbx_findapp("Dial");
- if (dial)
- res = pbx_exec(chan, dial, req, newstack);
- } else
- res = -1;
- return res;
-}
-
-static int dundi_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- return dundi_helper(chan, context, exten, priority, data, DUNDI_FLAG_MATCHMORE);
-}
-
-static struct ast_switch dundi_switch =
-{
- name: "DUNDi",
- description: "DUNDi Discovered Dialplan Switch",
- exists: dundi_exists,
- canmatch: dundi_canmatch,
- exec: dundi_exec,
- matchmore: dundi_matchmore,
-};
-
-static int set_config(char *config_file, struct sockaddr_in* sin)
-{
- struct ast_config *cfg;
- struct ast_variable *v;
- char *cat;
- int format;
- int x;
- char hn[MAXHOSTNAMELEN] = "";
- struct ast_hostent he;
- struct hostent *hp;
- struct sockaddr_in sin2;
- static int last_port = 0;
- int globalpcmodel = 0;
- dundi_eid testeid;
-
- dundi_ttl = DUNDI_DEFAULT_TTL;
- dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME;
- cfg = ast_config_load(config_file);
-
-
- if (!cfg) {
- ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
- return -1;
- }
- ipaddr[0] = '\0';
- if (!gethostname(hn, sizeof(hn)-1)) {
- hp = ast_gethostbyname(hn, &he);
- if (hp) {
- memcpy(&sin2.sin_addr, hp->h_addr, sizeof(sin2.sin_addr));
- ast_inet_ntoa(ipaddr, sizeof(ipaddr), sin2.sin_addr);
- } else
- ast_log(LOG_WARNING, "Unable to look up host '%s'\n", hn);
- } else
- ast_log(LOG_WARNING, "Unable to get host name!\n");
- ast_mutex_lock(&peerlock);
- reset_global_eid();
- global_storehistory = 0;
- ast_copy_string(secretpath, "dundi", sizeof(secretpath));
- v = ast_variable_browse(cfg, "general");
- while(v) {
- if (!strcasecmp(v->name, "port")){
- sin->sin_port = ntohs(atoi(v->value));
- if(last_port==0){
- last_port=sin->sin_port;
- } else if(sin->sin_port != last_port)
- ast_log(LOG_WARNING, "change to port ignored until next asterisk re-start\n");
- } else if (!strcasecmp(v->name, "bindaddr")) {
- struct hostent *hp;
- struct ast_hostent he;
- hp = ast_gethostbyname(v->value, &he);
- if (hp) {
- memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
- } else
- ast_log(LOG_WARNING, "Invalid host/IP '%s'\n", v->value);
- } else if (!strcasecmp(v->name, "authdebug")) {
- authdebug = ast_true(v->value);
- } else if (!strcasecmp(v->name, "ttl")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x < DUNDI_DEFAULT_TTL)) {
- dundi_ttl = x;
- } else {
- ast_log(LOG_WARNING, "'%s' is not a valid TTL at line %d, must be number from 1 to %d\n",
- v->value, v->lineno, DUNDI_DEFAULT_TTL);
- }
- } else if (!strcasecmp(v->name, "autokill")) {
- if (sscanf(v->value, "%d", &x) == 1) {
- if (x >= 0)
- global_autokilltimeout = x;
- else
- ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
- } else if (ast_true(v->value)) {
- global_autokilltimeout = DEFAULT_MAXMS;
- } else {
- global_autokilltimeout = 0;
- }
- } else if (!strcasecmp(v->name, "entityid")) {
- if (!dundi_str_to_eid(&testeid, v->value))
- global_eid = testeid;
- else
- ast_log(LOG_WARNING, "Invalid global endpoint identifier '%s' at line %d\n", v->value, v->lineno);
- } else if (!strcasecmp(v->name, "tos")) {
- if (sscanf(v->value, "%d", &format) == 1)
- tos = format & 0xff;
- else if (!strcasecmp(v->value, "lowdelay"))
- tos = IPTOS_LOWDELAY;
- else if (!strcasecmp(v->value, "throughput"))
- tos = IPTOS_THROUGHPUT;
- else if (!strcasecmp(v->value, "reliability"))
- tos = IPTOS_RELIABILITY;
-#if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
- else if (!strcasecmp(v->value, "mincost"))
- tos = IPTOS_MINCOST;
-#endif
- else if (!strcasecmp(v->value, "none"))
- tos = 0;
- else
-#if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(SOLARIS)
- ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
-#else
- ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', or 'none'\n", v->lineno);
-#endif
- } else if (!strcasecmp(v->name, "department")) {
- ast_copy_string(dept, v->value, sizeof(dept));
- } else if (!strcasecmp(v->name, "organization")) {
- ast_copy_string(org, v->value, sizeof(org));
- } else if (!strcasecmp(v->name, "locality")) {
- ast_copy_string(locality, v->value, sizeof(locality));
- } else if (!strcasecmp(v->name, "stateprov")) {
- ast_copy_string(stateprov, v->value, sizeof(stateprov));
- } else if (!strcasecmp(v->name, "country")) {
- ast_copy_string(country, v->value, sizeof(country));
- } else if (!strcasecmp(v->name, "email")) {
- ast_copy_string(email, v->value, sizeof(email));
- } else if (!strcasecmp(v->name, "phone")) {
- ast_copy_string(phone, v->value, sizeof(phone));
- } else if (!strcasecmp(v->name, "storehistory")) {
- global_storehistory = ast_true(v->value);
- } else if (!strcasecmp(v->name, "cachetime")) {
- if ((sscanf(v->value, "%d", &x) == 1)) {
- dundi_cache_time = x;
- } else {
- ast_log(LOG_WARNING, "'%s' is not a valid cache time at line %d. Using default value '%d'.\n",
- v->value, v->lineno, DUNDI_DEFAULT_CACHE_TIME);
- }
- }
- v = v->next;
- }
- ast_mutex_unlock(&peerlock);
- mark_mappings();
- v = ast_variable_browse(cfg, "mappings");
- while(v) {
- build_mapping(v->name, v->value);
- v = v->next;
- }
- prune_mappings();
- mark_peers();
- cat = ast_category_browse(cfg, NULL);
- while(cat) {
- if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings")) {
- /* Entries */
- if (!dundi_str_to_eid(&testeid, cat))
- build_peer(&testeid, ast_variable_browse(cfg, cat), &globalpcmodel);
- else
- ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);
- }
- cat = ast_category_browse(cfg, cat);
- }
- prune_peers();
- ast_config_destroy(cfg);
- load_password();
- if (globalpcmodel & DUNDI_MODEL_OUTBOUND)
- dundi_precache_full();
- return 0;
-}
-
-int unload_module(void)
-{
- int res;
- STANDARD_HANGUP_LOCALUSERS;
- ast_cli_unregister(&cli_debug);
- ast_cli_unregister(&cli_store_history);
- ast_cli_unregister(&cli_flush);
- ast_cli_unregister(&cli_no_debug);
- ast_cli_unregister(&cli_no_store_history);
- ast_cli_unregister(&cli_show_peers);
- ast_cli_unregister(&cli_show_entityid);
- ast_cli_unregister(&cli_show_trans);
- ast_cli_unregister(&cli_show_requests);
- ast_cli_unregister(&cli_show_mappings);
- ast_cli_unregister(&cli_show_precache);
- ast_cli_unregister(&cli_show_peer);
- ast_cli_unregister(&cli_lookup);
- ast_cli_unregister(&cli_precache);
- ast_cli_unregister(&cli_queryeid);
- ast_unregister_switch(&dundi_switch);
- ast_custom_function_unregister(&dundi_function);
- res = ast_unregister_application(app);
- sched_context_destroy(sched);
- return res;
-}
-
-int reload(void)
-{
- struct sockaddr_in sin;
- set_config("dundi.conf",&sin);
- return 0;
-}
-
-int load_module(void)
-{
- int res = 0;
- struct sockaddr_in sin;
- char iabuf[INET_ADDRSTRLEN];
-
- dundi_set_output(dundi_debug_output);
- dundi_set_error(dundi_error_output);
-
- sin.sin_family = AF_INET;
- sin.sin_port = ntohs(DUNDI_PORT);
- sin.sin_addr.s_addr = INADDR_ANY;
-
- /* Make a UDP socket */
- io = io_context_create();
- sched = sched_context_create();
-
- if (!io || !sched) {
- ast_log(LOG_ERROR, "Out of memory\n");
- return -1;
- }
-
- set_config("dundi.conf",&sin);
-
- netsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
-
- if (netsocket < 0) {
- ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
- return -1;
- }
- if (bind(netsocket,(struct sockaddr *)&sin, sizeof(sin))) {
- ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
- return -1;
- }
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
-
- if (setsockopt(netsocket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))
- ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
-
- res = start_network_thread();
- if (res) {
- ast_log(LOG_ERROR, "Unable to start network thread\n");
- close(netsocket);
- return -1;
- }
-
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "DUNDi Ready and Listening on %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
-
- ast_cli_register(&cli_debug);
- ast_cli_register(&cli_store_history);
- ast_cli_register(&cli_flush);
- ast_cli_register(&cli_no_debug);
- ast_cli_register(&cli_no_store_history);
- ast_cli_register(&cli_show_peers);
- ast_cli_register(&cli_show_entityid);
- ast_cli_register(&cli_show_trans);
- ast_cli_register(&cli_show_requests);
- ast_cli_register(&cli_show_mappings);
- ast_cli_register(&cli_show_precache);
- ast_cli_register(&cli_show_peer);
- ast_cli_register(&cli_lookup);
- ast_cli_register(&cli_precache);
- ast_cli_register(&cli_queryeid);
- if (ast_register_switch(&dundi_switch))
- ast_log(LOG_ERROR, "Unable to register DUNDi switch\n");
- ast_register_application(app, dundi_lookup_exec, synopsis, descrip);
- ast_custom_function_register(&dundi_function);
-
- return res;
-}
-
-char *description(void)
-{
- return tdesc;
-}
-
-int usecount(void)
-{
- int res;
- /* XXX DUNDi cannot be unloaded XXX */
- return 1;
- STANDARD_USECOUNT(res);
- return res;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/pbx/pbx_gtkconsole.c b/1.2-netsec/pbx/pbx_gtkconsole.c
deleted file mode 100644
index f0d118b89..000000000
--- a/1.2-netsec/pbx/pbx_gtkconsole.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief GTK Console monitor -- very kludgy right now
- *
- */
-
-/*
- * I know this might seem somewhat pointless in its current phase, but one
- * of the most important parts of this module is demonstrate that modules
- * can require other external libraries and still be loaded (in this
- * case, a host of libraries involving gtk), so long as they are properly
- * linked (see the Makefile)
- */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#include <gtk/gtk.h>
-#include <glib.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/pbx.h"
-#include "asterisk/config.h"
-#include "asterisk/module.h"
-#include "asterisk/logger.h"
-#include "asterisk/options.h"
-#include "asterisk/cli.h"
-#include "asterisk/utils.h"
-
-AST_MUTEX_DEFINE_STATIC(verb_lock);
-
-static pthread_t console_thread;
-
-static int inuse=0;
-static int clipipe[2];
-static int cleanupid = -1;
-
-static char *dtext = "Asterisk PBX Console (GTK Version)";
-
-static GtkWidget *window;
-static GtkWidget *quit;
-static GtkWidget *closew;
-static GtkWidget *verb;
-static GtkWidget *modules;
-static GtkWidget *statusbar;
-static GtkWidget *cli;
-
-static struct timeval last;
-
-static void update_statusbar(char *msg)
-{
- gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1);
- gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, msg);
-}
-
-int unload_module(void)
-{
- if (inuse) {
- /* Kill off the main thread */
- pthread_cancel(console_thread);
- gdk_threads_enter();
- gtk_widget_destroy(window);
- gdk_threads_leave();
- close(clipipe[0]);
- close(clipipe[1]);
- }
- return 0;
-}
-
-static int cleanup(void *useless)
-{
- gdk_threads_enter();
- gtk_clist_thaw(GTK_CLIST(verb));
- gtk_widget_queue_resize(verb->parent);
- gtk_clist_moveto(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1, 0, 0, 0);
- cleanupid = -1;
- gdk_threads_leave();
- return 0;
-}
-
-
-static void __verboser(const char *stuff, int opos, int replacelast, int complete)
-{
- char *s2[2];
- struct timeval tv;
- int ms;
- s2[0] = (char *)stuff;
- s2[1] = NULL;
- gtk_clist_freeze(GTK_CLIST(verb));
- if (replacelast)
- gtk_clist_remove(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1);
- gtk_clist_append(GTK_CLIST(verb), s2);
- if (!ast_tvzero(last)) {
- gdk_threads_leave();
- gettimeofday(&tv, NULL);
- if (cleanupid > -1)
- gtk_timeout_remove(cleanupid);
- ms = ast_tvdiff_ms(tv, last);
- if (ms < 100) {
- /* We just got a message within 100ms, so just schedule an update
- in the near future */
- cleanupid = gtk_timeout_add(200, cleanup, NULL);
- } else {
- cleanup(&cleanupid);
- }
- last = tv;
- } else {
- gettimeofday(&last, NULL);
- }
-}
-
-static void verboser(const char *stuff, int opos, int replacelast, int complete)
-{
- ast_mutex_lock(&verb_lock);
- /* Lock appropriately if we're really being called in verbose mode */
- __verboser(stuff, opos, replacelast, complete);
- ast_mutex_unlock(&verb_lock);
-}
-
-static void cliinput(void *data, int source, GdkInputCondition ic)
-{
- static char buf[256];
- static int offset = 0;
- int res;
- char *c;
- char *l;
- char n;
- /* Read as much stuff is there */
- res = read(source, buf + offset, sizeof(buf) - 1 - offset);
- if (res > -1)
- buf[res + offset] = '\0';
- /* make sure we've null terminated whatever we have so far */
- c = buf;
- l = buf;
- while(*c) {
- if (*c == '\n') {
- /* Keep the trailing \n */
- c++;
- n = *c;
- *c = '\0';
- __verboser(l, 0, 0, 1);
- *(c - 1) = '\0';
- *c = n;
- l = c;
- } else
- c++;
- }
- if (strlen(l)) {
- /* We have some left over */
- memmove(buf, l, strlen(l) + 1);
- offset = strlen(buf);
- } else {
- offset = 0;
- }
-
-}
-
-
-static void remove_module(void)
-{
- int res;
- char *module;
- char buf[256];
- if (GTK_CLIST(modules)->selection) {
- module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (int) GTK_CLIST(modules)->selection->data);
- gdk_threads_leave();
- res = ast_unload_resource(module, 0);
- gdk_threads_enter();
- if (res) {
- snprintf(buf, sizeof(buf), "Module '%s' is in use", module);
- update_statusbar(buf);
- } else {
- snprintf(buf, sizeof(buf), "Module '%s' removed", module);
- update_statusbar(buf);
- }
- }
-}
-static void reload_module(void)
-{
- int res, x;
- char *module;
- char buf[256];
- if (GTK_CLIST(modules)->selection) {
- module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (int) GTK_CLIST(modules)->selection->data);
- module = strdup(module);
- if (module) {
- gdk_threads_leave();
- res = ast_unload_resource(module, 0);
- gdk_threads_enter();
- if (res) {
- snprintf(buf, sizeof(buf), "Module '%s' is in use", module);
- update_statusbar(buf);
- } else {
- gdk_threads_leave();
- res = ast_load_resource(module);
- gdk_threads_enter();
- if (res) {
- snprintf(buf, sizeof(buf), "Error reloading module '%s'", module);
- } else {
- snprintf(buf, sizeof(buf), "Module '%s' reloaded", module);
- }
- for (x=0; x < GTK_CLIST(modules)->rows; x++) {
- if (!strcmp((char *)gtk_clist_get_row_data(GTK_CLIST(modules), x), module)) {
- gtk_clist_select_row(GTK_CLIST(modules), x, -1);
- break;
- }
- }
- update_statusbar(buf);
-
- }
- free(module);
- }
- }
-}
-
-static void file_ok_sel(GtkWidget *w, GtkFileSelection *fs)
-{
- char tmp[AST_CONFIG_MAX_PATH];
- char *module = gtk_file_selection_get_filename(fs);
- char buf[256];
- snprintf(tmp, sizeof(tmp), "%s/", ast_config_AST_MODULE_DIR);
- if (!strncmp(module, (char *)tmp, strlen(tmp)))
- module += strlen(tmp);
- gdk_threads_leave();
- if (ast_load_resource(module)) {
- snprintf(buf, sizeof(buf), "Error loading module '%s'.", module);
- update_statusbar(buf);
- } else {
- snprintf(buf, sizeof(buf), "Module '%s' loaded", module);
- update_statusbar(buf);
- }
- gdk_threads_enter();
- gtk_widget_destroy(GTK_WIDGET(fs));
-}
-
-static void add_module(void)
-{
- char tmp[AST_CONFIG_MAX_PATH];
- GtkWidget *filew;
- snprintf(tmp, sizeof(tmp), "%s/*.so", ast_config_AST_MODULE_DIR);
- filew = gtk_file_selection_new("Load Module");
- gtk_signal_connect(GTK_OBJECT (GTK_FILE_SELECTION(filew)->ok_button),
- "clicked", GTK_SIGNAL_FUNC(file_ok_sel), filew);
- gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(filew)->cancel_button),
- "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(filew));
- gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), (char *)tmp);
- gtk_widget_show(filew);
-}
-
-static int add_mod(const char *module, const char *description, int usecount, const char *like)
-{
- char use[10];
- char *pass[4];
- int row;
- snprintf(use, sizeof(use), "%d", usecount);
- pass[0] = module;
- pass[1] = description;
- pass[2] = use;
- pass[3] = NULL;
- row = gtk_clist_append(GTK_CLIST(modules), pass);
- gtk_clist_set_row_data(GTK_CLIST(modules), row, module);
- return 0;
-}
-
-static int mod_update(void)
-{
- char *module= NULL;
- /* Update the mod stuff */
- if (GTK_CLIST(modules)->selection) {
- module= (char *)gtk_clist_get_row_data(GTK_CLIST(modules), (int) GTK_CLIST(modules)->selection->data);
- }
- gtk_clist_freeze(GTK_CLIST(modules));
- gtk_clist_clear(GTK_CLIST(modules));
- ast_update_module_list(add_mod, NULL);
- if (module)
- gtk_clist_select_row(GTK_CLIST(modules), gtk_clist_find_row_from_data(GTK_CLIST(modules), module), -1);
- gtk_clist_thaw(GTK_CLIST(modules));
- return 1;
-}
-
-static void exit_now(GtkWidget *widget, gpointer data)
-{
- ast_loader_unregister(mod_update);
- gtk_main_quit();
- inuse--;
- ast_update_use_count();
- ast_unregister_verbose(verboser);
- ast_unload_resource("pbx_gtkconsole", 0);
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "GTK Console Monitor Exiting\n");
- /* XXX Trying to quit after calling this makes asterisk segfault XXX */
-}
-
-static void exit_completely(GtkWidget *widget, gpointer data)
-{
-#if 0
- /* Clever... */
- ast_cli_command(clipipe[1], "quit");
-#else
- kill(getpid(), SIGTERM);
-#endif
-}
-
-static void exit_nicely(GtkWidget *widget, gpointer data)
-{
- fflush(stdout);
- gtk_widget_destroy(window);
-}
-
-static void *consolethread(void *data)
-{
- gtk_widget_show(window);
- gdk_threads_enter();
- gtk_main();
- gdk_threads_leave();
- return NULL;
-}
-
-static int cli_activate(void)
-{
- char buf[256] = "";
- strncpy(buf, gtk_entry_get_text(GTK_ENTRY(cli)), sizeof(buf) - 1);
- gtk_entry_set_text(GTK_ENTRY(cli), "");
- if (strlen(buf)) {
- ast_cli_command(clipipe[1], buf);
- }
- return TRUE;
-}
-
-static int show_console(void)
-{
- GtkWidget *hbox;
- GtkWidget *wbox;
- GtkWidget *notebook;
- GtkWidget *sw;
- GtkWidget *bbox, *hbbox, *add, *removew, *reloadw;
- char *modtitles[3] = { "Module", "Description", "Use Count" };
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- statusbar = gtk_statusbar_new();
- gtk_widget_show(statusbar);
-
- gtk_signal_connect(GTK_OBJECT(window), "delete_event",
- GTK_SIGNAL_FUNC (exit_nicely), window);
- gtk_signal_connect(GTK_OBJECT(window), "destroy",
- GTK_SIGNAL_FUNC (exit_now), window);
- gtk_container_set_border_width(GTK_CONTAINER(window), 10);
-
- quit = gtk_button_new_with_label("Quit Asterisk");
- gtk_signal_connect(GTK_OBJECT(quit), "clicked",
- GTK_SIGNAL_FUNC (exit_completely), window);
- gtk_widget_show(quit);
-
- closew = gtk_button_new_with_label("Close Window");
- gtk_signal_connect(GTK_OBJECT(closew), "clicked",
- GTK_SIGNAL_FUNC (exit_nicely), window);
- gtk_widget_show(closew);
-
- notebook = gtk_notebook_new();
- verb = gtk_clist_new(1);
- gtk_clist_columns_autosize(GTK_CLIST(verb));
- sw = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- gtk_container_add(GTK_CONTAINER(sw), verb);
- gtk_widget_show(verb);
- gtk_widget_show(sw);
- gtk_widget_set_usize(verb, 640, 400);
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, gtk_label_new("Verbose Status"));
-
-
- modules = gtk_clist_new_with_titles(3, modtitles);
- gtk_clist_columns_autosize(GTK_CLIST(modules));
- gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 0, TRUE);
- gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 1, TRUE);
- gtk_clist_set_column_auto_resize(GTK_CLIST(modules), 2, TRUE);
- gtk_clist_set_sort_column(GTK_CLIST(modules), 0);
- gtk_clist_set_auto_sort(GTK_CLIST(modules), TRUE);
- gtk_clist_column_titles_passive(GTK_CLIST(modules));
- sw = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- gtk_container_add(GTK_CONTAINER(sw), modules);
- gtk_clist_set_selection_mode(GTK_CLIST(modules), GTK_SELECTION_BROWSE);
- gtk_widget_show(modules);
- gtk_widget_show(sw);
-
- add = gtk_button_new_with_label("Load...");
- gtk_widget_show(add);
- removew = gtk_button_new_with_label("Unload");
- gtk_widget_show(removew);
- reloadw = gtk_button_new_with_label("Reload");
- gtk_widget_show(reloadw);
- gtk_signal_connect(GTK_OBJECT(removew), "clicked",
- GTK_SIGNAL_FUNC (remove_module), window);
- gtk_signal_connect(GTK_OBJECT(add), "clicked",
- GTK_SIGNAL_FUNC (add_module), window);
- gtk_signal_connect(GTK_OBJECT(reloadw), "clicked",
- GTK_SIGNAL_FUNC (reload_module), window);
-
- bbox = gtk_vbox_new(FALSE, 5);
- gtk_widget_show(bbox);
-
- gtk_widget_set_usize(bbox, 100, -1);
- gtk_box_pack_start(GTK_BOX(bbox), add, FALSE, FALSE, 5);
- gtk_box_pack_start(GTK_BOX(bbox), removew, FALSE, FALSE, 5);
- gtk_box_pack_start(GTK_BOX(bbox), reloadw, FALSE, FALSE, 5);
-
- hbbox = gtk_hbox_new(FALSE, 5);
- gtk_widget_show(hbbox);
-
- gtk_box_pack_start(GTK_BOX(hbbox), sw, TRUE, TRUE, 5);
- gtk_box_pack_start(GTK_BOX(hbbox), bbox, FALSE, FALSE, 5);
-
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook), hbbox, gtk_label_new("Module Information"));
-
- gtk_widget_show(notebook);
-
- wbox = gtk_hbox_new(FALSE, 5);
- gtk_widget_show(wbox);
- gtk_box_pack_end(GTK_BOX(wbox), quit, FALSE, FALSE, 5);
- gtk_box_pack_end(GTK_BOX(wbox), closew, FALSE, FALSE, 5);
-
- hbox = gtk_vbox_new(FALSE, 0);
- gtk_widget_show(hbox);
-
- /* Command line */
- cli = gtk_entry_new();
- gtk_widget_show(cli);
-
- gtk_signal_connect(GTK_OBJECT(cli), "activate",
- GTK_SIGNAL_FUNC (cli_activate), NULL);
-
- gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 5);
- gtk_box_pack_start(GTK_BOX(hbox), wbox, FALSE, FALSE, 5);
- gtk_box_pack_start(GTK_BOX(hbox), cli, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), statusbar, FALSE, FALSE, 0);
- gtk_container_add(GTK_CONTAINER(window), hbox);
- gtk_window_set_title(GTK_WINDOW(window), "Asterisk Console");
- gtk_widget_grab_focus(cli);
- ast_pthread_create(&console_thread, NULL, consolethread, NULL);
- /* XXX Okay, seriously fix me! XXX */
- usleep(100000);
- ast_register_verbose(verboser);
- gtk_clist_freeze(GTK_CLIST(verb));
- ast_loader_register(mod_update);
- gtk_clist_thaw(GTK_CLIST(verb));
- gdk_input_add(clipipe[0], GDK_INPUT_READ, cliinput, NULL);
- mod_update();
- update_statusbar("Asterisk Console Ready");
- return 0;
-}
-
-
-int load_module(void)
-{
- if (pipe(clipipe)) {
- ast_log(LOG_WARNING, "Unable to create CLI pipe\n");
- return -1;
- }
- g_thread_init(NULL);
- if (gtk_init_check(NULL, NULL)) {
- if (!show_console()) {
- inuse++;
- ast_update_use_count();
- if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "Launched GTK Console monitor\n");
- } else
- ast_log(LOG_WARNING, "Unable to start GTK console\n");
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to start GTK console monitor -- ignoring\n");
- else if (option_verbose > 1)
- ast_verbose( VERBOSE_PREFIX_2 "GTK is not available -- skipping monitor\n");
- }
- return 0;
-}
-
-int usecount(void)
-{
- return inuse;
-}
-
-char *description(void)
-{
- return dtext;
-}
-
-char *key(void)
-{
- return ASTERISK_GPL_KEY;
-}
diff --git a/1.2-netsec/pbx/pbx_kdeconsole.cc b/1.2-netsec/pbx/pbx_kdeconsole.cc
deleted file mode 100644
index 6c2817366..000000000
--- a/1.2-netsec/pbx/pbx_kdeconsole.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Asterisk -- A telephony toolkit for Linux.
- *
- * KDE Console monitor -- Class implmementation
- *
- * Copyright (C) 1999, Mark Spencer
- *
- * Mark Spencer <markster@linux-support.net>
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License
- */
-
-#include "pbx_kdeconsole.moc"
-
-KAsteriskConsole::KAsteriskConsole() : KTMainWindow()
-{
- QVBoxLayout *box;
- QFrame *f;
-
- f = new QFrame(this);
-
- setGeometry(100,100,600,400);
- /* Menus */
- file = new QPopupMenu();
- file->insertItem("&Exit", this, SLOT(slotExit()));
-
- help = kapp->getHelpMenu(TRUE, "KDE Asterisk Console\nby Mark Spencer");
-
- setCaption("Asterisk Console");
-
- /* Box */
- box = new QVBoxLayout(f, 20, 5);
-
- /* Menu bar creation */
- menu = new KMenuBar(this);
- menu->insertItem("&File", file);
- menu->insertItem("&Help", help);
- /* Verbose stuff */
- verbose = new QListBox(f, "verbose");
- /* Exit button */
- btnExit = new QPushButton("Exit", f, "exit");
- btnExit->show();
- connect(btnExit, SIGNAL(clicked()), this, SLOT(slotExit()));
-
- box->addWidget(verbose, 1);
- box->addWidget(btnExit, 0);
- setView(f, TRUE);
- statusBar()->message("Ready", 2000);
-}
-
-void KAsteriskConsole::slotExit()
-{
- close();
-}
-
-void KAsteriskConsole::closeEvent(QCloseEvent *)
-{
- kapp->quit();
-}
-
diff --git a/1.2-netsec/pbx/pbx_kdeconsole.h b/1.2-netsec/pbx/pbx_kdeconsole.h
deleted file mode 100644
index df73ab38e..000000000
--- a/1.2-netsec/pbx/pbx_kdeconsole.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Asterisk -- A telephony toolkit for Linux.
- *
- * KDE Console monitor -- Header file
- *
- * Copyright (C) 1999, Mark Spencer
- *
- * Mark Spencer <markster@linux-support.net>
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License
- */
-
-#include <kapp.h>
-#include <ktmainwindow.h>
-#include <qpushbutton.h>
-#include <kmenubar.h>
-#include <qpopupmenu.h>
-#include <qlistbox.h>
-#include <qlayout.h>
-#include <qframe.h>
-
-class KAsteriskConsole : public KTMainWindow
-{
- Q_OBJECT
-public:
- KAsteriskConsole();
- void closeEvent(QCloseEvent *);
- QListBox *verbose;
-public slots:
- void slotExit();
-private:
- void KAsteriskConsole::verboser(char *stuff, int opos, int replacelast, int complete);
- QPushButton *btnExit;
- KMenuBar *menu;
- QPopupMenu *file, *help;
-};
diff --git a/1.2-netsec/pbx/pbx_kdeconsole_main.cc b/1.2-netsec/pbx/pbx_kdeconsole_main.cc
deleted file mode 100644
index 0bb2d73e2..000000000
--- a/1.2-netsec/pbx/pbx_kdeconsole_main.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Asterisk -- A telephony toolkit for Linux.
- *
- * KDE Console monitor -- Mostly glue code
- *
- * Copyright (C) 1999, Mark Spencer
- *
- * Mark Spencer <markster@linux-support.net>
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License
- */
-
-#include "asterisk/module.h"
-#include "asterisk/channel.h"
-#include "asterisk/logger.h"
-#include "asterisk/lock.h"
-#include "pbx_kdeconsole.h"
-
-static char *dtext = "KDE Console Monitor";
-
-static int inuse = 0;
-
-static KAsteriskConsole *w;
-
-static void verboser(char *stuff, int opos, int replacelast, int complete)
-{
- const char *s2[2];
- s2[0] = stuff;
- s2[1] = NULL;
- if (replacelast) {
- printf("Removing %d\n", w->verbose->count());
- w->verbose->removeItem(w->verbose->count());
- }
- w->verbose->insertStrList(s2, 1, -1);
- w->verbose->setBottomItem(w->verbose->count());
-}
-
-static int kde_main(int argc, char *argv[])
-{
- KApplication a ( argc, argv );
- w = new KAsteriskConsole();
- a.setMainWidget(w);
- w->show();
- ast_register_verbose(verboser);
- return a.exec();
-}
-
-static void *kdemain(void *data)
-{
- /* It would appear kde really wants to be main */;
- char *argv[1] = { "asteriskconsole" };
- kde_main(1, argv);
- return NULL;
-}
-
-extern "C" {
-
-int unload_module(void)
-{
- return inuse;
-}
-
-int load_module(void)
-{
- pthread_t t;
- pthread_create(&t, NULL, kdemain, NULL);
- return 0;
-}
-
-int usecount(void)
-{
- return inuse;
-}
-
-char *description(void)
-{
- return dtext;
-}
-
-}
diff --git a/1.2-netsec/pbx/pbx_loopback.c b/1.2-netsec/pbx/pbx_loopback.c
deleted file mode 100644
index 5522e9b09..000000000
--- a/1.2-netsec/pbx/pbx_loopback.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Loopback PBX Module
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/options.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/frame.h"
-#include "asterisk/file.h"
-#include "asterisk/cli.h"
-#include "asterisk/lock.h"
-#include "asterisk/md5.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/chanvars.h"
-#include "asterisk/sched.h"
-#include "asterisk/io.h"
-#include "asterisk/utils.h"
-#include "asterisk/crypto.h"
-#include "asterisk/astdb.h"
-
-static char *tdesc = "Loopback Switch";
-
-/* Loopback switch substitutes ${EXTEN}, ${CONTEXT}, and ${PRIORITY} into
- the data passed to it to try to get a string of the form:
-
- [exten]@context[:priority][/extramatch]
-
- Where exten, context, and priority are another extension, context, and priority
- to lookup and "extramatch" is an extra match restriction the *original* number
- must fit if specified. The "extramatch" begins with _ like an exten pattern
- if it is specified. Note that the search context MUST be a different context
- from the current context or the search will not succeed in an effort to reduce
- the likelihood of loops (they're still possible if you try hard, so be careful!)
-
-*/
-
-
-#define LOOPBACK_COMMON \
- char buf[1024]; \
- int res; \
- char *newexten=(char *)exten, *newcontext=(char *)context; \
- int newpriority=priority; \
- char *newpattern=NULL; \
- loopback_helper(buf, sizeof(buf), exten, context, priority, data); \
- loopback_subst(&newexten, &newcontext, &newpriority, &newpattern, buf); \
- ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \
- if (!strcasecmp(newcontext, context)) return -1
-
-
-static char *loopback_helper(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
-{
- struct ast_var_t *newvariable;
- struct varshead headp;
- char tmp[80];
-
- snprintf(tmp, sizeof(tmp), "%d", priority);
- memset(buf, 0, buflen);
- AST_LIST_HEAD_INIT_NOLOCK(&headp);
- newvariable = ast_var_assign("EXTEN", exten);
- AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
- newvariable = ast_var_assign("CONTEXT", context);
- AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
- newvariable = ast_var_assign("PRIORITY", tmp);
- AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
- pbx_substitute_variables_varshead(&headp, data, buf, buflen);
- /* Substitute variables */
- while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */
- newvariable = AST_LIST_REMOVE_HEAD(&headp, entries);
- ast_var_delete(newvariable);
- }
- return buf;
-}
-
-static void loopback_subst(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
-{
- char *con;
- char *pri;
- *newpattern = strchr(buf, '/');
- if (*newpattern) {
- *(*newpattern) = '\0';
- (*newpattern)++;
- }
- con = strchr(buf, '@');
- if (con) {
- *con = '\0';
- con++;
- pri = strchr(con, ':');
- } else
- pri = strchr(buf, ':');
- if (!ast_strlen_zero(buf))
- *newexten = buf;
- if (!ast_strlen_zero(con))
- *newcontext = con;
- if (!ast_strlen_zero(pri))
- sscanf(pri, "%d", priority);
-}
-
-static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- LOOPBACK_COMMON;
- res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
- if (newpattern && !ast_extension_match(newpattern, exten))
- res = 0;
- return res;
-}
-
-static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- LOOPBACK_COMMON;
- res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
- if (newpattern && !ast_extension_match(newpattern, exten))
- res = 0;
- return res;
-}
-
-static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
-{
- LOOPBACK_COMMON;
- if (newstack)
- res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid);
- else
- res = ast_exec_extension(chan, newcontext, newexten, newpriority, callerid);
- if (newpattern && !ast_extension_match(newpattern, exten))
- res = -1;
- return res;
-}
-
-static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- LOOPBACK_COMMON;
- res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
- if (newpattern && !ast_extension_match(newpattern, exten))
- res = 0;
- return res;
-}
-
-static struct ast_switch loopback_switch =
-{
- name: "Loopback",
- description: "Loopback Dialplan Switch",
- exists: loopback_exists,
- canmatch: loopback_canmatch,
- exec: loopback_exec,
- matchmore: loopback_matchmore,
-};
-
-char *description(void)
-{
- return tdesc;
-}
-
-int usecount(void)
-{
- return 1;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
-
-int unload_module(void)
-{
- ast_unregister_switch(&loopback_switch);
- return 0;
-}
-
-int load_module(void)
-{
- ast_register_switch(&loopback_switch);
- return 0;
-}
-
diff --git a/1.2-netsec/pbx/pbx_realtime.c b/1.2-netsec/pbx/pbx_realtime.c
deleted file mode 100644
index 4e9aba1fe..000000000
--- a/1.2-netsec/pbx/pbx_realtime.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Realtime PBX Module
- *
- * \arg See also: \ref AstARA
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/config.h"
-#include "asterisk/options.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/frame.h"
-#include "asterisk/term.h"
-#include "asterisk/manager.h"
-#include "asterisk/file.h"
-#include "asterisk/cli.h"
-#include "asterisk/lock.h"
-#include "asterisk/md5.h"
-#include "asterisk/linkedlists.h"
-#include "asterisk/chanvars.h"
-#include "asterisk/sched.h"
-#include "asterisk/io.h"
-#include "asterisk/utils.h"
-#include "asterisk/crypto.h"
-#include "asterisk/astdb.h"
-
-#define MODE_MATCH 0
-#define MODE_MATCHMORE 1
-#define MODE_CANMATCH 2
-
-#define EXT_DATA_SIZE 256
-
-static char *tdesc = "Realtime Switch";
-
-/* Realtime switch looks up extensions in the supplied realtime table.
-
- [context@][realtimetable][/options]
-
- If the realtimetable is omitted it is assumed to be "extensions". If no context is
- specified the context is assumed to be whatever is the container.
-
- The realtime table should have entries for context,exten,priority,app,args
-
- The realtime table currently does not support callerid fields.
-
-*/
-
-
-#define REALTIME_COMMON(mode) \
- char *buf; \
- char *opts; \
- const char *cxt; \
- char *table; \
- int res=-1; \
- struct ast_variable *var=NULL; \
- buf = ast_strdupa(data); \
- if (buf) { \
- opts = strchr(buf, '/'); \
- if (opts) { \
- *opts='\0'; \
- opts++; \
- } else \
- opts=""; \
- table = strchr(buf, '@'); \
- if (table) { \
- *table = '\0'; \
- table++;\
- cxt = buf; \
- } else cxt = NULL; \
- if (ast_strlen_zero(cxt)) \
- cxt = context;\
- if (ast_strlen_zero(table)) \
- table = "extensions"; \
- var = realtime_switch_common(table, cxt, exten, priority, mode); \
- } else \
- res = -1;
-
-static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
-{
- struct ast_variable *var;
- struct ast_config *cfg;
- char pri[20];
- char *ematch;
- char rexten[AST_MAX_EXTENSION + 20]="";
- int match;
- snprintf(pri, sizeof(pri), "%d", priority);
- switch(mode) {
- case MODE_MATCHMORE:
- ematch = "exten LIKE";
- snprintf(rexten, sizeof(rexten), "%s_%%", exten);
- break;
- case MODE_CANMATCH:
- ematch = "exten LIKE";
- snprintf(rexten, sizeof(rexten), "%s%%", exten);
- break;
- case MODE_MATCH:
- default:
- ematch = "exten";
- strncpy(rexten, exten, sizeof(rexten) - 1);
- }
- var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, NULL);
- if (!var) {
- cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, NULL);
- if (cfg) {
- char *cat = ast_category_browse(cfg, NULL);
-
- while(cat) {
- switch(mode) {
- case MODE_MATCHMORE:
- match = ast_extension_close(cat, exten, 1);
- break;
- case MODE_CANMATCH:
- match = ast_extension_close(cat, exten, 0);
- break;
- case MODE_MATCH:
- default:
- match = ast_extension_match(cat, exten);
- }
- if (match) {
- var = ast_category_detach_variables(ast_category_get(cfg, cat));
- break;
- }
- cat = ast_category_browse(cfg, cat);
- }
- ast_config_destroy(cfg);
- }
- }
- return var;
-}
-
-static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- REALTIME_COMMON(MODE_MATCH);
- if (var) ast_variables_destroy(var);
- if (var)
- res = 1;
- return res > 0 ? res : 0;
-}
-
-static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- REALTIME_COMMON(MODE_CANMATCH);
- if (var) ast_variables_destroy(var);
- if (var)
- res = 1;
- return res > 0 ? res : 0;
-}
-
-static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
-{
- char app[256];
- char appdata[512]="";
- char *tmp="";
- char tmp1[80];
- char tmp2[80];
- char tmp3[EXT_DATA_SIZE];
- struct ast_app *a;
- struct ast_variable *v;
- REALTIME_COMMON(MODE_MATCH);
- if (var) {
- v = var;
- while(v) {
- if (!strcasecmp(v->name, "app"))
- strncpy(app, v->value, sizeof(app) -1 );
- else if (!strcasecmp(v->name, "appdata"))
- tmp = ast_strdupa(v->value);
- v = v->next;
- }
- ast_variables_destroy(var);
- if (!ast_strlen_zero(app)) {
- a = pbx_findapp(app);
- if (a) {
- if(!ast_strlen_zero(tmp))
- pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1);
- if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\")\n",
- term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
- term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
- term_color(tmp3, (!ast_strlen_zero(appdata) ? (char *)appdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
- manager_event(EVENT_FLAG_CALL, "Newexten",
- "Channel: %s\r\n"
- "Context: %s\r\n"
- "Extension: %s\r\n"
- "Priority: %d\r\n"
- "Application: %s\r\n"
- "AppData: %s\r\n"
- "Uniqueid: %s\r\n",
- chan->name, chan->context, chan->exten, chan->priority, app, appdata ? appdata : "(NULL)", chan->uniqueid);
-
- res = pbx_exec(chan, a, appdata, newstack);
- } else
- ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
- }
- }
- return res;
-}
-
-static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
-{
- REALTIME_COMMON(MODE_MATCHMORE);
- if (var) ast_variables_destroy(var);
- if (var)
- res = 1;
- return res > 0 ? res : 0;
-}
-
-static struct ast_switch realtime_switch =
-{
- name: "Realtime",
- description: "Realtime Dialplan Switch",
- exists: realtime_exists,
- canmatch: realtime_canmatch,
- exec: realtime_exec,
- matchmore: realtime_matchmore,
-};
-
-char *description(void)
-{
- return tdesc;
-}
-
-int usecount(void)
-{
- return 1;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}
-
-int unload_module(void)
-{
- ast_unregister_switch(&realtime_switch);
- return 0;
-}
-
-int load_module(void)
-{
- ast_register_switch(&realtime_switch);
- return 0;
-}
-
diff --git a/1.2-netsec/pbx/pbx_spool.c b/1.2-netsec/pbx/pbx_spool.c
deleted file mode 100644
index a91a7e255..000000000
--- a/1.2-netsec/pbx/pbx_spool.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Full-featured outgoing call spool support
- *
- */
-
-#include <sys/stat.h>
-#include <errno.h>
-#include <time.h>
-#include <utime.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <string.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/lock.h"
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
-#include "asterisk/channel.h"
-#include "asterisk/callerid.h"
-#include "asterisk/pbx.h"
-#include "asterisk/module.h"
-#include "asterisk/options.h"
-#include "asterisk/utils.h"
-
-/*
- * pbx_spool is similar in spirit to qcall, but with substantially enhanced functionality...
- * The spool file contains a header
- */
-
-static char *tdesc = "Outgoing Spool Support";
-static char qdir[255];
-
-struct outgoing {
- char fn[256];
- /* Current number of retries */
- int retries;
- /* Maximum number of retries permitted */
- int maxretries;
- /* How long to wait between retries (in seconds) */
- int retrytime;
- /* How long to wait for an answer */
- int waittime;
- /* PID which is currently calling */
- int callingpid;
-
- /* What to connect to outgoing */
- char tech[256];
- char dest[256];
-
- /* If application */
- char app[256];
- char data[256];
-
- /* If extension/context/priority */
- char exten[256];
- char context[256];
- int priority;
-
- /* CallerID Information */
- char cid_num[256];
- char cid_name[256];
-
- /* account code */
- char account[AST_MAX_ACCOUNT_CODE];
-
- /* Variables and Functions */
- struct ast_variable *vars;
-
- /* Maximum length of call */
- int maxlen;
-};
-
-static void init_outgoing(struct outgoing *o)
-{
- memset(o, 0, sizeof(struct outgoing));
- o->priority = 1;
- o->retrytime = 300;
- o->waittime = 45;
-}
-
-static void free_outgoing(struct outgoing *o)
-{
- free(o);
-}
-
-static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
-{
- char buf[256];
- char *c, *c2;
- int lineno = 0;
- struct ast_variable *var;
-
- while(fgets(buf, sizeof(buf), f)) {
- lineno++;
- /* Trim comments */
- c = buf;
- while ((c = strchr(c, '#'))) {
- if ((c == buf) || (*(c-1) == ' ') || (*(c-1) == '\t'))
- *c = '\0';
- else
- c++;
- }
-
- c = buf;
- while ((c = strchr(c, ';'))) {
- if ((c > buf) && (c[-1] == '\\')) {
- memmove(c - 1, c, strlen(c) + 1);
- c++;
- } else {
- *c = '\0';
- break;
- }
- }
-
- /* Trim trailing white space */
- while(!ast_strlen_zero(buf) && buf[strlen(buf) - 1] < 33)
- buf[strlen(buf) - 1] = '\0';
- if (!ast_strlen_zero(buf)) {
- c = strchr(buf, ':');
- if (c) {
- *c = '\0';
- c++;
- while ((*c) && (*c < 33))
- c++;
-#if 0
- printf("'%s' is '%s' at line %d\n", buf, c, lineno);
-#endif
- if (!strcasecmp(buf, "channel")) {
- strncpy(o->tech, c, sizeof(o->tech) - 1);
- if ((c2 = strchr(o->tech, '/'))) {
- *c2 = '\0';
- c2++;
- strncpy(o->dest, c2, sizeof(o->dest) - 1);
- } else {
- ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn);
- o->tech[0] = '\0';
- }
- } else if (!strcasecmp(buf, "callerid")) {
- ast_callerid_split(c, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
- } else if (!strcasecmp(buf, "application")) {
- strncpy(o->app, c, sizeof(o->app) - 1);
- } else if (!strcasecmp(buf, "data")) {
- strncpy(o->data, c, sizeof(o->data) - 1);
- } else if (!strcasecmp(buf, "maxretries")) {
- if (sscanf(c, "%d", &o->maxretries) != 1) {
- ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
- o->maxretries = 0;
- }
- } else if (!strcasecmp(buf, "context")) {
- strncpy(o->context, c, sizeof(o->context) - 1);
- } else if (!strcasecmp(buf, "extension")) {
- strncpy(o->exten, c, sizeof(o->exten) - 1);
- } else if (!strcasecmp(buf, "priority")) {
- if ((sscanf(c, "%d", &o->priority) != 1) || (o->priority < 1)) {
- ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn);
- o->priority = 1;
- }
- } else if (!strcasecmp(buf, "retrytime")) {
- if ((sscanf(c, "%d", &o->retrytime) != 1) || (o->retrytime < 1)) {
- ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn);
- o->retrytime = 300;
- }
- } else if (!strcasecmp(buf, "waittime")) {
- if ((sscanf(c, "%d", &o->waittime) != 1) || (o->waittime < 1)) {
- ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn);
- o->waittime = 45;
- }
- } else if (!strcasecmp(buf, "retry")) {
- o->retries++;
- } else if (!strcasecmp(buf, "startretry")) {
- if (sscanf(c, "%d", &o->callingpid) != 1) {
- ast_log(LOG_WARNING, "Unable to retrieve calling PID!\n");
- o->callingpid = 0;
- }
- } else if (!strcasecmp(buf, "endretry") || !strcasecmp(buf, "abortretry")) {
- o->callingpid = 0;
- o->retries++;
- } else if (!strcasecmp(buf, "delayedretry")) {
- } else if (!strcasecmp(buf, "setvar") || !strcasecmp(buf, "set")) {
- c2 = c;
- strsep(&c2, "=");
- if (c2) {
- var = ast_variable_new(c, c2);
- if (var) {
- var->next = o->vars;
- o->vars = var;
- }
- } else {
- ast_log(LOG_WARNING, "Malformed Set: argument! Should be Set: Variable=value\n");
- }
- } else if (!strcasecmp(buf, "account")) {
- ast_copy_string(o->account, c, sizeof(o->account));
- } else {
- ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
- }
- } else
- ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn);
- }
- }
- strncpy(o->fn, fn, sizeof(o->fn) - 1);
- if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
- ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
- return -1;
- }
- return 0;
-}
-
-static void safe_append(struct outgoing *o, time_t now, char *s)
-{
- int fd;
- FILE *f;
- struct utimbuf tbuf;
- fd = open(o->fn, O_WRONLY|O_APPEND);
- if (fd > -1) {
- f = fdopen(fd, "a");
- if (f) {
- fprintf(f, "%s: %ld %d (%ld)\n", s, (long)ast_mainpid, o->retries, (long) now);
- fclose(f);
- } else
- close(fd);
- /* Update the file time */
- tbuf.actime = now;
- tbuf.modtime = now + o->retrytime;
- if (utime(o->fn, &tbuf))
- ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", o->fn, strerror(errno));
- }
-}
-
-static void *attempt_thread(void *data)
-{
- struct outgoing *o = data;
- int res, reason;
- if (!ast_strlen_zero(o->app)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
- res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
- } else {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
- res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
- }
- if (res) {
- ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
- if (o->retries >= o->maxretries + 1) {
- /* Max retries exceeded */
- ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
- unlink(o->fn);
- } else {
- /* Notate that the call is still active */
- safe_append(o, time(NULL), "EndRetry");
- }
- } else {
- ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
- ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
- unlink(o->fn);
- }
- free_outgoing(o);
- return NULL;
-}
-
-static void launch_service(struct outgoing *o)
-{
- pthread_t t;
- pthread_attr_t attr;
- int ret;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if ((ret = ast_pthread_create(&t,&attr,attempt_thread, o)) != 0) {
- ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
- free_outgoing(o);
- }
-}
-
-static int scan_service(char *fn, time_t now, time_t atime)
-{
- struct outgoing *o;
- FILE *f;
- o = malloc(sizeof(struct outgoing));
- if (o) {
- init_outgoing(o);
- f = fopen(fn, "r+");
- if (f) {
- if (!apply_outgoing(o, fn, f)) {
-#if 0
- printf("Filename: %s, Retries: %d, max: %d\n", fn, o->retries, o->maxretries);
-#endif
- fclose(f);
- if (o->retries <= o->maxretries) {
- now += o->retrytime;
- if (o->callingpid && (o->callingpid == ast_mainpid)) {
- safe_append(o, time(NULL), "DelayedRetry");
- free_outgoing(o);
- ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn);
- } else {
- /* Increment retries */
- o->retries++;
- /* If someone else was calling, they're presumably gone now
- so abort their retry and continue as we were... */
- if (o->callingpid)
- safe_append(o, time(NULL), "AbortRetry");
-
- safe_append(o, now, "StartRetry");
- launch_service(o);
- }
- return now;
- } else {
- ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
- free_outgoing(o);
- unlink(fn);
- return 0;
- }
- } else {
- free_outgoing(o);
- ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn);
- fclose(f);
- unlink(fn);
- }
- } else {
- free_outgoing(o);
- ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno));
- unlink(fn);
- }
- } else
- ast_log(LOG_WARNING, "Out of memory :(\n");
- return -1;
-}
-
-static void *scan_thread(void *unused)
-{
- struct stat st;
- DIR *dir;
- struct dirent *de;
- char fn[256];
- int res;
- time_t last = 0, next = 0, now;
- for(;;) {
- /* Wait a sec */
- sleep(1);
- time(&now);
- if (!stat(qdir, &st)) {
- if ((st.st_mtime != last) || (next && (now > next))) {
-#if 0
- printf("atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime);
- printf("Ooh, something changed / timeout\n");
-#endif
- next = 0;
- last = st.st_mtime;
- dir = opendir(qdir);
- if (dir) {
- while((de = readdir(dir))) {
- snprintf(fn, sizeof(fn), "%s/%s", qdir, de->d_name);
- if (!stat(fn, &st)) {
- if (S_ISREG(st.st_mode)) {
- if (st.st_mtime <= now) {
- res = scan_service(fn, now, st.st_atime);
- if (res > 0) {
- /* Update next service time */
- if (!next || (res < next)) {
- next = res;
- }
- } else if (res)
- ast_log(LOG_WARNING, "Failed to scan service '%s'\n", fn);
- } else {
- /* Update "next" update if necessary */
- if (!next || (st.st_mtime < next))
- next = st.st_mtime;
- }
- }
- } else
- ast_log(LOG_WARNING, "Unable to stat %s: %s\n", fn, strerror(errno));
- }
- closedir(dir);
- } else
- ast_log(LOG_WARNING, "Unable to open directory %s: %s\n", qdir, strerror(errno));
- }
- } else
- ast_log(LOG_WARNING, "Unable to stat %s\n", qdir);
- }
- return NULL;
-}
-
-int unload_module(void)
-{
- return -1;
-}
-
-int load_module(void)
-{
- pthread_t thread;
- pthread_attr_t attr;
- int ret;
- snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing");
- if (mkdir(qdir, 0700) && (errno != EEXIST)) {
- ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
- return 0;
- }
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if ((ret = ast_pthread_create(&thread,&attr,scan_thread, NULL)) != 0) {
- ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
- return -1;
- }
- return 0;
-}
-
-char *description(void)
-{
- return tdesc;
-}
-
-int usecount(void)
-{
- return 1;
-}
-
-char *key()
-{
- return ASTERISK_GPL_KEY;
-}