Add option to register extensions on IAX or SIP registration

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3746 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 21 years ago
parent c6025e41c6
commit 879c401544

@ -3,7 +3,7 @@
* *
* Implementation of Inter-Asterisk eXchange Version 2 * Implementation of Inter-Asterisk eXchange Version 2
* *
* Copyright (C) 2003, Digium * Copyright (C) 2003-2004, Digium, Inc.
* *
* Mark Spencer <markster@digium.com> * Mark Spencer <markster@digium.com>
* *
@ -114,6 +114,7 @@ static char *type = "IAX2";
static char context[80] = "default"; static char context[80] = "default";
static char language[MAX_LANGUAGE] = ""; static char language[MAX_LANGUAGE] = "";
static char regcontext[AST_MAX_EXTENSION] = "";
static int max_retries = 4; static int max_retries = 4;
static int ping_time = 20; static int ping_time = 20;
@ -219,6 +220,7 @@ struct iax2_peer {
char secret[80]; char secret[80];
char outkey[80]; /* What key we use to talk to this peer */ char outkey[80]; /* What key we use to talk to this peer */
char context[AST_MAX_EXTENSION]; /* Default context (for transfer really) */ 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 peercontext[AST_MAX_EXTENSION]; /* Context to pass to peer */
char mailbox[AST_MAX_EXTENSION]; /* Mailbox */ char mailbox[AST_MAX_EXTENSION]; /* Mailbox */
struct sockaddr_in addr; struct sockaddr_in addr;
@ -4211,6 +4213,22 @@ static int iax2_register(char *value, int lineno)
return 0; 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) static int expire_registry(void *data)
{ {
struct iax2_peer *p = data; struct iax2_peer *p = data;
@ -4221,6 +4239,7 @@ static int expire_registry(void *data)
/* Reset expirey value */ /* Reset expirey value */
p->expirey = expirey; p->expirey = expirey;
ast_db_del("IAX/Registry", p->name); ast_db_del("IAX/Registry", p->name);
register_peer_exten(p, 0);
if (iax2_regfunk) if (iax2_regfunk)
iax2_regfunk(p->name, 0); iax2_regfunk(p->name, 0);
return 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); p->expire = ast_sched_add(sched, p->expirey * 1000, expire_registry, (void *)p);
if (iax2_regfunk) if (iax2_regfunk)
iax2_regfunk(p->name, 1); 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) if (iax2_regfunk)
iax2_regfunk(p->name, 1); 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); 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) { if (sin->sin_addr.s_addr) {
ast_db_put("IAX/Registry", p->name, data);
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Registered '%s' (%s) at %s:%d\n", p->name, 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)); 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 { } else {
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Unregistered '%s' (%s)\n", p->name, ast_verbose(VERBOSE_PREFIX_3 "Unregistered '%s' (%s)\n", p->name,
iaxs[callno]->state & IAX_STATE_AUTHENTICATED ? "AUTHENTICATED" : "UNAUTHENTICATED"); iaxs[callno]->state & IAX_STATE_AUTHENTICATED ? "AUTHENTICATED" : "UNAUTHENTICATED");
register_peer_exten(p, 0);
ast_db_del("IAX/Registry", p->name);
} }
/* Update the host */ /* Update the host */
memcpy(&p->addr, sin, sizeof(p->addr)); 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")) { } else if (!strcasecmp(v->name, "context")) {
if (ast_strlen_zero(peer->context)) if (ast_strlen_zero(peer->context))
strncpy(peer->context, v->value, sizeof(peer->context) - 1); 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")) { } else if (!strcasecmp(v->name, "peercontext")) {
if (ast_strlen_zero(peer->peercontext)) if (ast_strlen_zero(peer->peercontext))
strncpy(peer->peercontext, v->value, sizeof(peer->peercontext) - 1); strncpy(peer->peercontext, v->value, sizeof(peer->peercontext) - 1);
@ -6552,6 +6577,7 @@ static void prune_peers(void){
ast_sched_del(sched, peer->pokeexpire); ast_sched_del(sched, peer->pokeexpire);
if (peer->callno > 0) if (peer->callno > 0)
iax2_destroy(peer->callno); iax2_destroy(peer->callno);
register_peer_exten(peer, 0);
free(peer); free(peer);
if (peerlast) if (peerlast)
peerlast->next = peernext; peerlast->next = peernext;
@ -6669,6 +6695,11 @@ static int set_config(char *config_file, struct sockaddr_in* sin){
iax2_register(v->value, v->lineno); iax2_register(v->value, v->lineno);
} else if (!strcasecmp(v->name, "iaxcompat")) { } else if (!strcasecmp(v->name, "iaxcompat")) {
iaxcompat = ast_true(v->value); 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")) { } else if (!strcasecmp(v->name, "tos")) {
if (sscanf(v->value, "%i", &format) == 1) if (sscanf(v->value, "%i", &format) == 1)
tos = format & 0xff; tos = format & 0xff;

@ -203,6 +203,7 @@ static int global_promiscredir;
static char global_musicclass[MAX_LANGUAGE] = ""; /* Global music on hold class */ static char global_musicclass[MAX_LANGUAGE] = ""; /* Global music on hold class */
static char global_realm[AST_MAX_EXTENSION] = "asterisk"; /* Default realm */ static char global_realm[AST_MAX_EXTENSION] = "asterisk"; /* Default realm */
static char regcontext[AST_MAX_EXTENSION] = "";
/* Expire slowly */ /* Expire slowly */
static int expiry = 900; static int expiry = 900;
@ -422,6 +423,7 @@ struct sip_peer {
char context[80]; /* JK02: peers need context too to allow parking etc */ char context[80]; /* JK02: peers need context too to allow parking etc */
char username[80]; char username[80];
char tohost[80]; char tohost[80];
char regexten[AST_MAX_EXTENSION]; /* Extension to register (if regcontext is used) */
char fromuser[80]; char fromuser[80];
char fromdomain[80]; char fromdomain[80];
char fullcontact[128]; 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); 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 ---*/ /*--- expire_register: Expire registration of SIP peer ---*/
static int expire_register(void *data) static int expire_register(void *data)
{ {
struct sip_peer *p = data; struct sip_peer *p = data;
memset(&p->addr, 0, sizeof(p->addr)); memset(&p->addr, 0, sizeof(p->addr));
ast_db_del("SIP/Registry", p->name); ast_db_del("SIP/Registry", p->name);
register_peer_exten(p, 0);
p->expire = -1; p->expire = -1;
ast_device_state_changed("SIP/%s", p->name); ast_device_state_changed("SIP/%s", p->name);
if (p->selfdestruct) { if (p->selfdestruct) {
@ -4269,6 +4288,7 @@ static void reg_source_db(struct sip_peer *p)
if (p->expire > -1) if (p->expire > -1)
ast_sched_del(sched, p->expire); ast_sched_del(sched, p->expire);
p->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, (void *)p); 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); ast_sched_del(sched, p->expire);
p->expire = -1; p->expire = -1;
ast_db_del("SIP/Registry", p->name); ast_db_del("SIP/Registry", p->name);
register_peer_exten(p, 0);
p->fullcontact[0] = '\0'; p->fullcontact[0] = '\0';
p->useragent[0] = '\0'; p->useragent[0] = '\0';
p->lastms = 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); sip_poke_peer(p);
if (option_verbose > 2) 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); 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 */ /* 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); strncpy(peer->username, v->value, sizeof(peer->username)-1);
} else if (!strcasecmp(v->name, "language")) { } else if (!strcasecmp(v->name, "language")) {
strncpy(peer->language, v->value, sizeof(peer->language)-1); 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")) { } else if (!strcasecmp(v->name, "musiconhold")) {
strncpy(peer->musicclass, v->value, sizeof(peer->musicclass)-1); strncpy(peer->musicclass, v->value, sizeof(peer->musicclass)-1);
} else if (!strcasecmp(v->name, "mailbox")) { } else if (!strcasecmp(v->name, "mailbox")) {
@ -8425,6 +8449,11 @@ static int reload_config(void)
strncpy(global_musicclass, v->value, sizeof(global_musicclass) - 1); strncpy(global_musicclass, v->value, sizeof(global_musicclass) - 1);
} else if (!strcasecmp(v->name, "language")) { } else if (!strcasecmp(v->name, "language")) {
strncpy(default_language, v->value, sizeof(default_language)-1); 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")) { } else if (!strcasecmp(v->name, "callerid")) {
strncpy(default_callerid, v->value, sizeof(default_callerid)-1); strncpy(default_callerid, v->value, sizeof(default_callerid)-1);
} else if (!strcasecmp(v->name, "fromdomain")) { } else if (!strcasecmp(v->name, "fromdomain")) {
@ -8834,6 +8863,7 @@ static void prune_peers(void)
ast_sched_del(sched, peer->expire); ast_sched_del(sched, peer->expire);
if (peer->pokeexpire > -1) if (peer->pokeexpire > -1)
ast_sched_del(sched, peer->pokeexpire); ast_sched_del(sched, peer->pokeexpire);
register_peer_exten(peer, 0);
free(peer); free(peer);
if (peerlast) if (peerlast)
peerlast->next = peernext; peerlast->next = peernext;

@ -152,6 +152,15 @@ tos=lowdelay
; ;
;mailboxdetail=yes ;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 ; Guest sections for unauthenticated connection attempts. Just
; specify an empty secret, or provide no secret section. ; specify an empty secret, or provide no secret section.
; ;
@ -262,6 +271,7 @@ host=216.207.245.47
;[marko] ;[marko]
;type=friend ;type=friend
;host=dynamic ;host=dynamic
;regexten=1234
;secret=moofoo ;secret=moofoo
;context=default ;context=default
;permit=0.0.0.0/0.0.0.0 ;permit=0.0.0.0/0.0.0.0

@ -71,6 +71,16 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; ; Note that promiscredir when redirects are made to the ; ; Note that promiscredir when redirects are made to the
; ; local system will cause loops since SIP is incapable ; ; local system will cause loops since SIP is incapable
; ; of performing a "hairpin" call. ; ; 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) ; Asterisk can register as a SIP user agent to a SIP proxy (provider)
; Format for the register statement is: ; Format for the register statement is:
; register => user[:secret[:authuser]]@host[:port][/extension] ; register => user[:secret[:authuser]]@host[:port][/extension]
@ -145,6 +155,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; username ; username
; template ; template
; fromdomain ; fromdomain
; regexten
; fromuser ; fromuser
; host ; host
; mask ; mask
@ -190,6 +201,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;Turn off silence suppression in X-Lite ("Transmit Silence"=YES)! ;Turn off silence suppression in X-Lite ("Transmit Silence"=YES)!
;Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed ;Note that Xlite sends NAT keep-alive packets, so qualify=yes is not needed
;type=friend ;type=friend
;regexten=1234 ; When they register, create extension 1234
;username=xlite1 ;username=xlite1
;callerid="Jane Smith" <5678> ;callerid="Jane Smith" <5678>
;host=dynamic ;host=dynamic

Loading…
Cancel
Save