From cafa29f67373a97017a8c5c3cf046208b805278c Mon Sep 17 00:00:00 2001 From: markster Date: Tue, 7 Sep 2004 23:45:34 +0000 Subject: Add option to register extensions on IAX or SIP registration git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3746 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_iax2.c | 35 +++++++++++++++++++++++++++++++++-- channels/chan_sip.c | 30 ++++++++++++++++++++++++++++++ configs/iax.conf.sample | 10 ++++++++++ configs/sip.conf.sample | 12 ++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 44a0f3ce0..d218c88ad 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -3,7 +3,7 @@ * * Implementation of Inter-Asterisk eXchange Version 2 * - * Copyright (C) 2003, Digium + * Copyright (C) 2003-2004, Digium, Inc. * * Mark Spencer * @@ -114,6 +114,7 @@ static char *type = "IAX2"; static char context[80] = "default"; static char language[MAX_LANGUAGE] = ""; +static char regcontext[AST_MAX_EXTENSION] = ""; static int max_retries = 4; static int ping_time = 20; @@ -219,6 +220,7 @@ struct iax2_peer { char secret[80]; char outkey[80]; /* What key we use to talk to this peer */ char context[AST_MAX_EXTENSION]; /* Default context (for transfer really) */ + char regexten[AST_MAX_EXTENSION]; /* Extension to register (if regcontext is used) */ char peercontext[AST_MAX_EXTENSION]; /* Context to pass to peer */ char mailbox[AST_MAX_EXTENSION]; /* Mailbox */ struct sockaddr_in addr; @@ -4211,6 +4213,22 @@ static int iax2_register(char *value, int lineno) return 0; } +static void register_peer_exten(struct iax2_peer *peer, int onoff) +{ + unsigned char multi[256]=""; + char *stringp, *ext; + if (!ast_strlen_zero(regcontext)) { + strncpy(multi, ast_strlen_zero(peer->regexten) ? peer->name : peer->regexten, sizeof(multi) - 1); + stringp = multi; + while((ext = strsep(&stringp, "&"))) { + if (onoff) + ast_add_extension(regcontext, 1, ext, 1, NULL, "Noop", strdup(peer->name), free, type); + else + ast_context_remove_extension(regcontext, ext, 1, NULL); + } + } +} + static int expire_registry(void *data) { struct iax2_peer *p = data; @@ -4221,6 +4239,7 @@ static int expire_registry(void *data) /* Reset expirey value */ p->expirey = expirey; ast_db_del("IAX/Registry", p->name); + register_peer_exten(p, 0); if (iax2_regfunk) iax2_regfunk(p->name, 0); return 0; @@ -4259,6 +4278,7 @@ static void reg_source_db(struct iax2_peer *p) p->expire = ast_sched_add(sched, p->expirey * 1000, expire_registry, (void *)p); if (iax2_regfunk) iax2_regfunk(p->name, 1); + register_peer_exten(p, 1); } } @@ -4294,15 +4314,18 @@ static int update_registry(char *name, struct sockaddr_in *sin, int callno, char if (iax2_regfunk) iax2_regfunk(p->name, 1); snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port), p->expirey); - ast_db_put("IAX/Registry", p->name, data); if (sin->sin_addr.s_addr) { + ast_db_put("IAX/Registry", p->name, data); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Registered '%s' (%s) at %s:%d\n", p->name, iaxs[callno]->state & IAX_STATE_AUTHENTICATED ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port)); + register_peer_exten(p, 1); } else { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Unregistered '%s' (%s)\n", p->name, iaxs[callno]->state & IAX_STATE_AUTHENTICATED ? "AUTHENTICATED" : "UNAUTHENTICATED"); + register_peer_exten(p, 0); + ast_db_del("IAX/Registry", p->name); } /* Update the host */ memcpy(&p->addr, sin, sizeof(p->addr)); @@ -6291,6 +6314,8 @@ static struct iax2_peer *build_peer(char *name, struct ast_variable *v) } else if (!strcasecmp(v->name, "context")) { if (ast_strlen_zero(peer->context)) strncpy(peer->context, v->value, sizeof(peer->context) - 1); + } else if (!strcasecmp(v->name, "regexten")) { + strncpy(peer->regexten, v->value, sizeof(peer->regexten) - 1); } else if (!strcasecmp(v->name, "peercontext")) { if (ast_strlen_zero(peer->peercontext)) strncpy(peer->peercontext, v->value, sizeof(peer->peercontext) - 1); @@ -6552,6 +6577,7 @@ static void prune_peers(void){ ast_sched_del(sched, peer->pokeexpire); if (peer->callno > 0) iax2_destroy(peer->callno); + register_peer_exten(peer, 0); free(peer); if (peerlast) peerlast->next = peernext; @@ -6669,6 +6695,11 @@ static int set_config(char *config_file, struct sockaddr_in* sin){ iax2_register(v->value, v->lineno); } else if (!strcasecmp(v->name, "iaxcompat")) { iaxcompat = ast_true(v->value); + } else if (!strcasecmp(v->name, "regcontext")) { + strncpy(regcontext, v->value, sizeof(regcontext) - 1); + /* Create context if it doesn't exist already */ + if (!ast_context_find(regcontext)) + ast_context_create(NULL, regcontext, type); } else if (!strcasecmp(v->name, "tos")) { if (sscanf(v->value, "%i", &format) == 1) tos = format & 0xff; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 5659b0bce..c14fd44d0 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -203,6 +203,7 @@ static int global_promiscredir; static char global_musicclass[MAX_LANGUAGE] = ""; /* Global music on hold class */ static char global_realm[AST_MAX_EXTENSION] = "asterisk"; /* Default realm */ +static char regcontext[AST_MAX_EXTENSION] = ""; /* Expire slowly */ static int expiry = 900; @@ -422,6 +423,7 @@ struct sip_peer { char context[80]; /* JK02: peers need context too to allow parking etc */ char username[80]; char tohost[80]; + char regexten[AST_MAX_EXTENSION]; /* Extension to register (if regcontext is used) */ char fromuser[80]; char fromdomain[80]; char fullcontact[128]; @@ -4210,12 +4212,29 @@ static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int seqno, i return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); } +static void register_peer_exten(struct sip_peer *peer, int onoff) +{ + unsigned char multi[256]=""; + char *stringp, *ext; + if (!ast_strlen_zero(regcontext)) { + strncpy(multi, ast_strlen_zero(peer->regexten) ? peer->name : peer->regexten, sizeof(multi) - 1); + stringp = multi; + while((ext = strsep(&stringp, "&"))) { + if (onoff) + ast_add_extension(regcontext, 1, ext, 1, NULL, "Noop", strdup(peer->name), free, type); + else + ast_context_remove_extension(regcontext, ext, 1, NULL); + } + } +} + /*--- expire_register: Expire registration of SIP peer ---*/ static int expire_register(void *data) { struct sip_peer *p = data; memset(&p->addr, 0, sizeof(p->addr)); ast_db_del("SIP/Registry", p->name); + register_peer_exten(p, 0); p->expire = -1; ast_device_state_changed("SIP/%s", p->name); if (p->selfdestruct) { @@ -4269,6 +4288,7 @@ static void reg_source_db(struct sip_peer *p) if (p->expire > -1) ast_sched_del(sched, p->expire); p->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, (void *)p); + register_peer_exten(p, 1); } } @@ -4318,6 +4338,7 @@ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_req ast_sched_del(sched, p->expire); p->expire = -1; ast_db_del("SIP/Registry", p->name); + register_peer_exten(p, 0); p->fullcontact[0] = '\0'; p->useragent[0] = '\0'; p->lastms = 0; @@ -4387,6 +4408,7 @@ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_req sip_poke_peer(p); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Registered SIP '%s' at %s port %d expires %d\n", p->name, ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr), ntohs(p->addr.sin_port), expiry); + register_peer_exten(p, 1); } /* Save User agent */ @@ -8254,6 +8276,8 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v) strncpy(peer->username, v->value, sizeof(peer->username)-1); } else if (!strcasecmp(v->name, "language")) { strncpy(peer->language, v->value, sizeof(peer->language)-1); + } else if (!strcasecmp(v->name, "regexten")) { + strncpy(peer->regexten, v->value, sizeof(peer->regexten)-1); } else if (!strcasecmp(v->name, "musiconhold")) { strncpy(peer->musicclass, v->value, sizeof(peer->musicclass)-1); } else if (!strcasecmp(v->name, "mailbox")) { @@ -8425,6 +8449,11 @@ static int reload_config(void) strncpy(global_musicclass, v->value, sizeof(global_musicclass) - 1); } else if (!strcasecmp(v->name, "language")) { strncpy(default_language, v->value, sizeof(default_language)-1); + } else if (!strcasecmp(v->name, "regcontext")) { + strncpy(regcontext, v->value, sizeof(regcontext) - 1); + /* Create context if it doesn't exist already */ + if (!ast_context_find(regcontext)) + ast_context_create(NULL, regcontext, type); } else if (!strcasecmp(v->name, "callerid")) { strncpy(default_callerid, v->value, sizeof(default_callerid)-1); } else if (!strcasecmp(v->name, "fromdomain")) { @@ -8834,6 +8863,7 @@ static void prune_peers(void) ast_sched_del(sched, peer->expire); if (peer->pokeexpire > -1) ast_sched_del(sched, peer->pokeexpire); + register_peer_exten(peer, 0); free(peer); if (peerlast) peerlast->next = peernext; diff --git a/configs/iax.conf.sample b/configs/iax.conf.sample index ff1543f0f..6068ce613 100755 --- a/configs/iax.conf.sample +++ b/configs/iax.conf.sample @@ -152,6 +152,15 @@ tos=lowdelay ; ;mailboxdetail=yes ; +; If regcontext is specified, Asterisk will dynamically +; create and destroy a NoOp priority 1 extension for a given +; peer who registers or unregisters with us. The actual extension +; is the 'regexten' parameter of the registering peer or its +; name if 'regexten' is not provided. More than one regexten may be supplied +; if they are separated by '&'. Patterns may be used in regexten. +; +;regcontext=iaxregistrations +; ; Guest sections for unauthenticated connection attempts. Just ; specify an empty secret, or provide no secret section. ; @@ -262,6 +271,7 @@ host=216.207.245.47 ;[marko] ;type=friend ;host=dynamic +;regexten=1234 ;secret=moofoo ;context=default ;permit=0.0.0.0/0.0.0.0 diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 8dc3d32e2..de46d9439 100755 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -71,6 +71,16 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; ; Note that promiscredir when redirects are made to the ; ; local system will cause loops since SIP is incapable ; ; of performing a "hairpin" call. +; +; If regcontext is specified, Asterisk will dynamically +; create and destroy a NoOp priority 1 extension for a given +; peer who registers or unregisters with us. The actual extension +; is the 'regexten' parameter of the registering peer or its +; name if 'regexten' is not provided. More than one regexten may be supplied +; if they are separated by '&'. Patterns may be used in regexten. +; +;regcontext=iaxregistrations +; ; Asterisk can register as a SIP user agent to a SIP proxy (provider) ; Format for the register statement is: ; register => user[:secret[:authuser]]@host[:port][/extension] @@ -145,6 +155,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; username ; template ; fromdomain +; regexten ; fromuser ; host ; mask @@ -190,6 +201,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;Turn off silence suppression in X-Lite ("Transmit Silence"=YES)! ;Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed ;type=friend +;regexten=1234 ; When they register, create extension 1234 ;username=xlite1 ;callerid="Jane Smith" <5678> ;host=dynamic -- cgit v1.2.3