From c2c4f86c729294a26ec9138f8f1e5288f89b01e6 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sat, 16 Sep 2006 23:53:58 +0000 Subject: merge markster's usersconf branch with some slight changes git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43052 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_iax2.c | 200 +++++++++++++++++++------- channels/chan_sip.c | 86 +++++++++-- channels/chan_zap.c | 392 +++++++++++++++++++++++++++------------------------ 3 files changed, 436 insertions(+), 242 deletions(-) (limited to 'channels') diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 6400ca22f..501f28d02 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -798,8 +798,8 @@ static int send_command_locked(unsigned short callno, char, int, unsigned int, c static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int); static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause); static struct ast_frame *iax2_read(struct ast_channel *c); -static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, int temponly); -static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly); +static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly); +static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly); static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, time_t regtime); static void destroy_user(struct iax2_user *user); static void prune_peers(void); @@ -2446,7 +2446,7 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in if (!var) return NULL; - peer = build_peer(peername, var, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); + peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); if (!peer) return NULL; @@ -2534,7 +2534,7 @@ static struct iax2_user *realtime_user(const char *username) tmp = tmp->next; } - user = build_user(username, var, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); + user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); if (!user) return NULL; @@ -8216,17 +8216,20 @@ static int peer_set_srcaddr(struct iax2_peer *peer, const char *srcaddr) /*! \brief Create peer structure based on configuration */ -static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, int temponly) +static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) { struct iax2_peer *peer = NULL; struct ast_ha *oldha = NULL; int maskfound=0; int found=0; + int firstpass=1; AST_LIST_LOCK(&peers); if (!temponly) { AST_LIST_TRAVERSE(&peers, peer, entry) { if (!strcmp(peer->name, name)) { + if (!ast_test_flag(peer, IAX_DELME)) + firstpass = 0; break; } } @@ -8234,8 +8237,10 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in peer = NULL; if (peer) { found++; - oldha = peer->ha; - peer->ha = NULL; + if (firstpass) { + oldha = peer->ha; + peer->ha = NULL; + } AST_LIST_REMOVE(&peers, peer, entry); AST_LIST_UNLOCK(&peers); } else { @@ -8251,25 +8256,29 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in } } if (peer) { - ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); - peer->encmethods = iax2_encryption; - peer->adsi = adsi; - /* NOT ANY MORE: peer->secret[0] = '\0'; */ - ast_string_field_set(peer,secret,""); - if (!found) { - ast_string_field_set(peer, name, name); - peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); - peer->expiry = min_reg_expire; - } - peer->prefs = prefs; - peer->capability = iax2_capability; - peer->smoothing = 0; - peer->pokefreqok = DEFAULT_FREQ_OK; - peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; - /* NO MORE: peer->context[0] = '\0'; - peer->peercontext[0] = '\0'; */ - ast_string_field_set(peer,context,""); - ast_string_field_set(peer,peercontext,""); + if (firstpass) { + ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); + peer->encmethods = iax2_encryption; + peer->adsi = adsi; + ast_string_field_set(peer,secret,""); + if (!found) { + ast_string_field_set(peer, name, name); + peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); + peer->expiry = min_reg_expire; + } + peer->prefs = prefs; + peer->capability = iax2_capability; + peer->smoothing = 0; + peer->pokefreqok = DEFAULT_FREQ_OK; + peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; + ast_string_field_set(peer,context,""); + ast_string_field_set(peer,peercontext,""); + } + + if (!v) { + v = alt; + alt = NULL; + } while(v) { if (!strcasecmp(v->name, "secret")) { ast_string_field_set(peer, secret, v->value); @@ -8376,6 +8385,12 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in ast_string_field_set(peer, cid_name, name2); ast_string_field_set(peer, cid_num, num2); ast_set_flag(peer, IAX_HASCALLERID); + } else if (!strcasecmp(v->name, "fullname")) { + ast_string_field_set(peer, cid_name, v->value); + ast_set_flag(peer, IAX_HASCALLERID); + } else if (!strcasecmp(v->name, "cid_number")) { + ast_string_field_set(peer, cid_num, v->value); + ast_set_flag(peer, IAX_HASCALLERID); } else if (!strcasecmp(v->name, "sendani")) { ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); } else if (!strcasecmp(v->name, "inkeys")) { @@ -8407,7 +8422,11 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in peer->adsi = ast_true(v->value); }/* else if (strcasecmp(v->name,"type")) */ /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ - v=v->next; + v = v->next; + if (!v) { + v = alt; + alt = NULL; + } } if (!peer->authmethods) peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; @@ -8421,13 +8440,14 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in } /*! \brief Create in-memory user structure from configuration */ -static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly) +static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) { struct iax2_user *user = NULL; struct iax2_context *con, *conl = NULL; struct ast_ha *oldha = NULL; struct iax2_context *oldcon = NULL; int format; + int firstpass=1; int oldcurauthreq = 0; char *varname = NULL, *varval = NULL; struct ast_variable *tmpvar = NULL; @@ -8436,18 +8456,22 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in if (!temponly) { AST_LIST_TRAVERSE(&users, user, entry) { if (!strcmp(user->name, name)) { + if (!ast_test_flag(user, IAX_DELME)) + firstpass = 0; break; } } } else user = NULL; - + if (user) { - oldcurauthreq = user->curauthreq; - oldha = user->ha; - oldcon = user->contexts; - user->ha = NULL; - user->contexts = NULL; + if (firstpass) { + oldcurauthreq = user->curauthreq; + oldha = user->ha; + oldcon = user->contexts; + user->ha = NULL; + user->contexts = NULL; + } /* Already in the list, remove it and it will be added back (or FREE'd) */ AST_LIST_REMOVE(&users, user, entry); AST_LIST_UNLOCK(&users); @@ -8455,22 +8479,30 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in AST_LIST_UNLOCK(&users); /* This is going to memset'd to 0 in the next block */ user = ast_calloc(sizeof(*user),1); - if (ast_string_field_init(user, 32)) { - free(user); - user = NULL; - } } if (user) { - user->maxauthreq = maxauthreq; - user->curauthreq = oldcurauthreq; - user->prefs = prefs; - user->capability = iax2_capability; - user->encmethods = iax2_encryption; - user->adsi = adsi; - ast_string_field_set(user, name, name); - ast_string_field_set(user, language, language); - ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); + if (firstpass) { + ast_string_field_free_all(user); + memset(user, 0, sizeof(struct iax2_user)); + if (ast_string_field_init(user, 32)) { + free(user); + user = NULL; + } + user->maxauthreq = maxauthreq; + user->curauthreq = oldcurauthreq; + user->prefs = prefs; + user->capability = iax2_capability; + user->encmethods = iax2_encryption; + user->adsi = adsi; + ast_string_field_set(user, name, name); + ast_string_field_set(user, language, language); + ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); + } + if (!v) { + v = alt; + alt = NULL; + } while(v) { if (!strcasecmp(v->name, "context")) { con = build_context(v->value); @@ -8550,6 +8582,12 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in ast_string_field_set(user, cid_name, name2); ast_string_field_set(user, cid_num, num2); ast_set_flag(user, IAX_HASCALLERID); + } else if (!strcasecmp(v->name, "fullname")) { + ast_string_field_set(user, cid_name, v->value); + ast_set_flag(user, IAX_HASCALLERID); + } else if (!strcasecmp(v->name, "cid_number")) { + ast_string_field_set(user, cid_num, v->value); + ast_set_flag(user, IAX_HASCALLERID); } else if (!strcasecmp(v->name, "accountcode")) { ast_string_field_set(user, accountcode, v->value); } else if (!strcasecmp(v->name, "mohinterpret")) { @@ -8576,6 +8614,10 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in }/* else if (strcasecmp(v->name,"type")) */ /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ v = v->next; + if (!v) { + v = alt; + alt = NULL; + } } if (!user->authmethods) { if (!ast_strlen_zero(user->secret)) { @@ -8722,7 +8764,7 @@ static void set_timing(void) /*! \brief Load configuration */ static int set_config(char *config_file, int reload) { - struct ast_config *cfg; + struct ast_config *cfg, *ucfg; int capability=iax2_capability; struct ast_variable *v; char *cat; @@ -8975,13 +9017,71 @@ static int set_config(char *config_file, int reload) min_reg_expire = max_reg_expire; } iax2_capability = capability; + + ucfg = ast_config_load("users.conf"); + if (ucfg) { + struct ast_variable *gen; + int genhasiax; + int genregisteriax; + char *hasiax, *registeriax; + + genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); + genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); + gen = ast_variable_browse(ucfg, "general"); + cat = ast_category_browse(ucfg, NULL); + while (cat) { + if (strcasecmp(cat, "general")) { + hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); + registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); + if (ast_true(hasiax) || (!hasiax && genhasiax)) { + /* Start with general parameters, then specific parameters, user and peer */ + user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); + if (user) { + AST_LIST_LOCK(&users); + AST_LIST_INSERT_HEAD(&users, user, entry); + AST_LIST_UNLOCK(&users); + } + peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); + if (peer) { + AST_LIST_LOCK(&peers); + AST_LIST_INSERT_HEAD(&peers, peer, entry); + AST_LIST_UNLOCK(&peers); + if (ast_test_flag(peer, IAX_DYNAMIC)) + reg_source_db(peer); + } + } + if (ast_true(registeriax) || (!registeriax && genregisteriax)) { + char tmp[256]; + char *host = ast_variable_retrieve(ucfg, cat, "host"); + char *username = ast_variable_retrieve(ucfg, cat, "username"); + char *secret = ast_variable_retrieve(ucfg, cat, "secret"); + if (!host) + host = ast_variable_retrieve(ucfg, "general", "host"); + if (!username) + username = ast_variable_retrieve(ucfg, "general", "username"); + if (!secret) + secret = ast_variable_retrieve(ucfg, "general", "secret"); + if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { + if (!ast_strlen_zero(secret)) + snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); + else + snprintf(tmp, sizeof(tmp), "%s@%s", username, host); + iax2_register(tmp, 0); + } + } + } + cat = ast_category_browse(ucfg, cat); + } + ast_config_destroy(ucfg); + } + cat = ast_category_browse(cfg, NULL); while(cat) { if (strcasecmp(cat, "general")) { utype = ast_variable_retrieve(cfg, cat, "type"); if (utype) { if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { - user = build_user(cat, ast_variable_browse(cfg, cat), 0); + user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); if (user) { AST_LIST_LOCK(&users); AST_LIST_INSERT_HEAD(&users, user, entry); @@ -8989,7 +9089,7 @@ static int set_config(char *config_file, int reload) } } if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { - peer = build_peer(cat, ast_variable_browse(cfg, cat), 0); + peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); if (peer) { AST_LIST_LOCK(&peers); AST_LIST_INSERT_HEAD(&peers, peer, entry); diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 362713293..a9de2e3f0 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1365,7 +1365,7 @@ static void sip_dump_history(struct sip_pvt *dialog); /*--- Device object handling */ static struct sip_peer *temp_peer(const char *name); -static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime); +static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime); static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime); static int update_call_counter(struct sip_pvt *fup, int event); static void sip_destroy_peer(struct sip_peer *peer); @@ -2357,7 +2357,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i } /* Peer found in realtime, now build it in memory */ - peer = build_peer(newpeername, var, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)); + peer = build_peer(newpeername, var, NULL, !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)); if (!peer) { ast_variables_destroy(var); return NULL; @@ -15118,6 +15118,10 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, int ast_copy_string(user->md5secret, v->value, sizeof(user->md5secret)); } else if (!strcasecmp(v->name, "callerid")) { ast_callerid_split(v->value, user->cid_name, sizeof(user->cid_name), user->cid_num, sizeof(user->cid_num)); + } else if (!strcasecmp(v->name, "fullname")) { + ast_copy_string(user->cid_name, v->value, sizeof(user->cid_name)); + } else if (!strcasecmp(v->name, "cid_number")) { + ast_copy_string(user->cid_num, v->value, sizeof(user->cid_num)); } else if (!strcasecmp(v->name, "callgroup")) { user->callgroup = ast_get_group(v->value); } else if (!strcasecmp(v->name, "pickupgroup")) { @@ -15243,12 +15247,13 @@ static struct sip_peer *temp_peer(const char *name) } /*! \brief Build peer from configuration (file or realtime static/dynamic) */ -static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime) +static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) { struct sip_peer *peer = NULL; struct ast_ha *oldha = NULL; int obproxyfound=0; int found=0; + int firstpass=1; int format=0; /* Ama flags */ time_t regseconds = 0; char *varname = NULL, *varval = NULL; @@ -15268,6 +15273,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int if (peer) { /* Already in the list, remove it and it will be added back (or FREE'd) */ found++; + if (!(peer->objflags & ASTOBJ_FLAG_MARKED)) + firstpass = 0; } else { if (!(peer = ast_calloc(1, sizeof(*peer)))) return NULL; @@ -15279,11 +15286,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int ASTOBJ_INIT(peer); } /* Note that our peer HAS had its reference count incrased */ - - peer->lastmsgssent = -1; - oldha = peer->ha; - peer->ha = NULL; - set_peer_defaults(peer); /* Set peer defaults */ + if (firstpass) { + peer->lastmsgssent = -1; + oldha = peer->ha; + peer->ha = NULL; + set_peer_defaults(peer); /* Set peer defaults */ + } if (!found && name) ast_copy_string(peer->name, name, sizeof(peer->name)); @@ -15293,7 +15301,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int peer->chanvars = NULL; /* XXX should unregister ? */ } - for (; v; v = v->next) { + for (; v || ((v = alt) && !(alt=NULL)); v = v->next) { if (handle_common_options(&peerflags[0], &mask[0], v)) continue; if (realtime && !strcasecmp(v->name, "regseconds")) { @@ -15313,6 +15321,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno); else if (!strcasecmp(v->name, "callerid")) { ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num)); + } else if (!strcasecmp(v->name, "fullname")) { + ast_copy_string(peer->cid_name, v->value, sizeof(peer->cid_name)); + } else if (!strcasecmp(v->name, "cid_number")) { + ast_copy_string(peer->cid_num, v->value, sizeof(peer->cid_num)); } else if (!strcasecmp(v->name, "context")) { ast_copy_string(peer->context, v->value, sizeof(peer->context)); } else if (!strcasecmp(v->name, "subscribecontext")) { @@ -15501,7 +15513,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int */ static int reload_config(enum channelreloadreason reason) { - struct ast_config *cfg; + struct ast_config *cfg, *ucfg; struct ast_variable *v; struct sip_peer *peer; struct sip_user *user; @@ -15863,6 +15875,58 @@ static int reload_config(enum channelreloadreason reason) authl = add_realm_authentication(authl, v->value, v->lineno); } + ucfg = ast_config_load("users.conf"); + if (ucfg) { + struct ast_variable *gen; + int genhassip, genregistersip; + char *hassip, *registersip; + + genhassip = ast_true(ast_variable_retrieve(ucfg, "general", "hassip")); + genregistersip = ast_true(ast_variable_retrieve(ucfg, "general", "registersip")); + gen = ast_variable_browse(ucfg, "general"); + cat = ast_category_browse(ucfg, NULL); + while (cat) { + if (strcasecmp(cat, "general")) { + hassip = ast_variable_retrieve(ucfg, cat, "hassip"); + registersip = ast_variable_retrieve(ucfg, cat, "registersip"); + if (ast_true(hassip) || (!hassip && genhassip)) { + peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); + if (peer) { + ASTOBJ_CONTAINER_LINK(&peerl,peer); + ASTOBJ_UNREF(peer, sip_destroy_peer); + peer_count++; + } + } + if (ast_true(registersip) || (!registersip && genregistersip)) { + char tmp[256]; + char *host = ast_variable_retrieve(ucfg, cat, "host"); + char *username = ast_variable_retrieve(ucfg, cat, "username"); + char *secret = ast_variable_retrieve(ucfg, cat, "secret"); + char *contact = ast_variable_retrieve(ucfg, cat, "contact"); + if (!host) + host = ast_variable_retrieve(ucfg, "general", "host"); + if (!username) + username = ast_variable_retrieve(ucfg, "general", "username"); + if (!secret) + secret = ast_variable_retrieve(ucfg, "general", "secret"); + if (!contact) + contact = "s"; + if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { + if (!ast_strlen_zero(secret)) + snprintf(tmp, sizeof(tmp), "%s:%s@%s/%s", username, secret, host, contact); + else + snprintf(tmp, sizeof(tmp), "%s@%s/%s", username, host, contact); + if (sip_register(tmp, 0) == 0) + registry_count++; + } + } + } + cat = ast_category_browse(ucfg, cat); + } + ast_config_destroy(ucfg); + } + + /* Load peers, users and friends */ cat = NULL; while ( (cat = ast_category_browse(cfg, cat)) ) { @@ -15894,7 +15958,7 @@ static int reload_config(enum channelreloadreason reason) } } if (is_peer) { - peer = build_peer(cat, ast_variable_browse(cfg, cat), 0); + peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); if (peer) { ASTOBJ_CONTAINER_LINK(&peerl,peer); ASTOBJ_UNREF(peer, sip_destroy_peer); diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 05e062336..4d8f010cc 100644 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -219,6 +219,7 @@ static int use_callerid = 1; static int cid_signalling = CID_SIG_BELL; static int cid_start = CID_START_RING; static int zaptrcallerid = 0; +static int cur_radio = 0; static int cur_signalling = -1; static int cur_outsignalling = -1; @@ -10282,202 +10283,115 @@ static int unload_module(void) #endif return __unload_module(); } - -static int setup_zap(int reload) + +static int build_channels(int iscrv, char *value, int reload, int lineno, int *found_pseudo) { - struct ast_config *cfg; - struct ast_variable *v; - struct ast_variable *vjb; + char *c, *chan; + int x, y, start, finish; struct zt_pvt *tmp; - char *chan; - char *c; - char *ringc; - int start, finish,x; - int y; - int found_pseudo = 0; - int cur_radio = 0; #ifdef HAVE_PRI - int spanno; - int i; - int logicalspan; - int trunkgroup; - int dchannels[NUM_DCHANS]; struct zt_pri *pri; + int trunkgroup; #endif - - cfg = ast_config_load(config); - - /* Error if we have no config file */ - if (!cfg) { - ast_log(LOG_ERROR, "Unable to load config %s\n", config); - return 0; + + if ((reload == 0) && (cur_signalling < 0)) { + ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); + return -1; } - /* It's a little silly to lock it, but we mind as well just to be sure */ - ast_mutex_lock(&iflock); + c = value; + #ifdef HAVE_PRI - if (!reload) { - /* Process trunkgroups first */ - v = ast_variable_browse(cfg, "trunkgroups"); - while (v) { - if (!strcasecmp(v->name, "trunkgroup")) { - trunkgroup = atoi(v->value); - if (trunkgroup > 0) { - if ((c = strchr(v->value, ','))) { - i = 0; - memset(dchannels, 0, sizeof(dchannels)); - while (c && (i < NUM_DCHANS)) { - dchannels[i] = atoi(c + 1); - if (dchannels[i] < 0) { - ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of zapata.conf\n", trunkgroup, v->lineno); - } else - i++; - c = strchr(c + 1, ','); - } - if (i) { - if (pri_create_trunkgroup(trunkgroup, dchannels)) { - ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannels[0], v->lineno); - } else if (option_verbose > 1) - ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s"); - } else - ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno); - } else - ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno); - } else - ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno); - } else if (!strcasecmp(v->name, "spanmap")) { - spanno = atoi(v->value); - if (spanno > 0) { - if ((c = strchr(v->value, ','))) { - trunkgroup = atoi(c + 1); - if (trunkgroup > 0) { - if ((c = strchr(c + 1, ','))) - logicalspan = atoi(c + 1); - else - logicalspan = 0; - if (logicalspan >= 0) { - if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { - ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); - } else if (option_verbose > 1) - ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); - } else - ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno); - } else - ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno); - } else - ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno); - } else - ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno); - } else { - ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); + pri = NULL; + if (iscrv) { + if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { + ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); + return -1; + } + if (trunkgroup < 1) { + ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); + return -1; + } + c += y; + for (y = 0; y < NUM_SPANS; y++) { + if (pris[y].trunkgroup == trunkgroup) { + pri = pris + y; + break; } - v = v->next; + } + if (!pri) { + ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); + return -1; } } -#endif - v = ast_variable_browse(cfg, "channels"); - /* Copy the default jb config over global_jbconf */ - memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); - /* Traverse all variables to handle jb conf */ - for (vjb = v; vjb; vjb = vjb->next) - ast_jb_read_conf(&global_jbconf, vjb->name, vjb->value); - while(v) { - /* Create the interface list */ - if (!strcasecmp(v->name, "channel") +#endif + + while ((chan = strsep(&c, ","))) { + if (sscanf(chan, "%d-%d", &start, &finish) == 2) { + /* Range */ + } else if (sscanf(chan, "%d", &start)) { + /* Just one */ + finish = start; + } else if (!strcasecmp(chan, "pseudo")) { + finish = start = CHAN_PSEUDO; + if (found_pseudo) + *found_pseudo = 1; + } else { + ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); + return -1; + } + if (finish < start) { + ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); + x = finish; + finish = start; + start = x; + } + + for (x = start; x <= finish; x++) { #ifdef HAVE_PRI - || !strcasecmp(v->name, "crv") + tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, pri, reload); +#else + tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, NULL, reload); #endif - ) { - if (reload == 0) { - if (cur_signalling < 0) { - ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); - ast_config_destroy(cfg); - ast_mutex_unlock(&iflock); - return -1; - } - } - c = v->value; + if (tmp) { + if (option_verbose > 2) { #ifdef HAVE_PRI - pri = NULL; - if (!strcasecmp(v->name, "crv")) { - if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { - ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", v->lineno); - ast_config_destroy(cfg); - ast_mutex_unlock(&iflock); - return -1; - } - if (trunkgroup < 1) { - ast_log(LOG_WARNING, "CRV trunk group must be a postive number at line %d\n", v->lineno); - ast_config_destroy(cfg); - ast_mutex_unlock(&iflock); - return -1; - } - c += y; - for (y = 0; y < NUM_SPANS; y++) { - if (pris[y].trunkgroup == trunkgroup) { - pri = pris + y; - break; - } - } - if (!pri) { - ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, v->lineno); - ast_config_destroy(cfg); - ast_mutex_unlock(&iflock); - return -1; + if (pri) + ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); + else +#endif + ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); } + } else { + ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", + (reload == 1) ? "reconfigure" : "register", value); + return -1; } -#endif - chan = strsep(&c, ","); - while (chan) { - if (sscanf(chan, "%d-%d", &start, &finish) == 2) { - /* Range */ - } else if (sscanf(chan, "%d", &start)) { - /* Just one */ - finish = start; - } else if (!strcasecmp(chan, "pseudo")) { - finish = start = CHAN_PSEUDO; - found_pseudo = 1; - } else { - ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", v->value, chan); - ast_config_destroy(cfg); - ast_mutex_unlock(&iflock); - return -1; - } - if (finish < start) { - ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); - x = finish; - finish = start; - start = x; - } + } + } - for (x = start; x <= finish; x++) { -#ifdef HAVE_PRI - tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, pri, reload); -#else - tmp = mkintf(x, cur_signalling, cur_outsignalling, cur_radio, NULL, reload); -#endif + return 0; +} - if (tmp) { - if (option_verbose > 2) { +static int process_zap(struct ast_variable *v, int reload, int skipchannels) +{ + struct zt_pvt *tmp; + char *ringc; + int y; + int found_pseudo = 0; + char *c; + + while(v) { + /* Create the interface list */ + if (!strcasecmp(v->name, "channel") #ifdef HAVE_PRI - if (pri) - ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup,x, sig2str(tmp->sig)); - else -#endif - ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); - } - } else { - if (reload == 1) - ast_log(LOG_ERROR, "Unable to reconfigure channel '%s'\n", v->value); - else - ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); - ast_config_destroy(cfg); - ast_mutex_unlock(&iflock); - return -1; - } - } - chan = strsep(&c, ","); + || !strcasecmp(v->name, "crv") +#endif + ) { + if (!skipchannels) { + if (build_channels(!strcasecmp(v->name, "crv"), v->value, reload, v->lineno, &found_pseudo)) + return -1; } } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { if (ast_true(v->value)) @@ -10645,7 +10559,11 @@ static int setup_zap(int reload) cid_name[0] = '\0'; } else { ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); - } + } + } else if (!strcasecmp(v->name, "fullname")) { + ast_copy_string(cid_name, v->value, sizeof(cid_name)); + } else if (!strcasecmp(v->name, "cid_number")) { + ast_copy_string(cid_num, v->value, sizeof(cid_num)); } else if (!strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { zaptrcallerid = ast_true(v->value); } else if (!strcasecmp(v->name, "restrictcid")) { @@ -10870,8 +10788,6 @@ static int setup_zap(int reload) switchtype = PRI_SWITCH_QSIG; else { ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); - ast_config_destroy(cfg); - ast_mutex_unlock(&iflock); return -1; } } else if (!strcasecmp(v->name, "nsf")) { @@ -11084,12 +11000,11 @@ static int setup_zap(int reload) } else if (!strcasecmp(v->name, "defaultozz")) { ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); } - } else + } else if (!skipchannels) ast_log(LOG_WARNING, "Ignoring %s\n", v->name); v = v->next; } if (!found_pseudo && reload == 0) { - /* Make sure pseudo isn't a member of any groups if we're automatically making it. */ cur_group = 0; @@ -11105,8 +11020,123 @@ static int setup_zap(int reload) ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); } } + return 0; +} + +static int setup_zap(int reload) +{ + int x; + struct ast_config *cfg; + struct ast_variable *v; + struct ast_variable *vjb; + char *c; + int res; + +#ifdef HAVE_PRI + int spanno; + int i; + int logicalspan; + int trunkgroup; + int dchannels[NUM_DCHANS]; +#endif + + cfg = ast_config_load(config); + + /* Error if we have no config file */ + if (!cfg) { + ast_log(LOG_ERROR, "Unable to load config %s\n", config); + return 0; + } + + /* It's a little silly to lock it, but we mind as well just to be sure */ + ast_mutex_lock(&iflock); +#ifdef HAVE_PRI + if (!reload) { + /* Process trunkgroups first */ + v = ast_variable_browse(cfg, "trunkgroups"); + while (v) { + if (!strcasecmp(v->name, "trunkgroup")) { + trunkgroup = atoi(v->value); + if (trunkgroup > 0) { + if ((c = strchr(v->value, ','))) { + i = 0; + memset(dchannels, 0, sizeof(dchannels)); + while (c && (i < NUM_DCHANS)) { + dchannels[i] = atoi(c + 1); + if (dchannels[i] < 0) { + ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of zapata.conf\n", trunkgroup, v->lineno); + } else + i++; + c = strchr(c + 1, ','); + } + if (i) { + if (pri_create_trunkgroup(trunkgroup, dchannels)) { + ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of zapata.conf\n", trunkgroup, dchannels[0], v->lineno); + } else if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s"); + } else + ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of zapata.conf\n", trunkgroup, v->lineno); + } else + ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of zapata.conf\n", trunkgroup, v->lineno); + } else + ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of zapata.conf\n", v->lineno); + } else if (!strcasecmp(v->name, "spanmap")) { + spanno = atoi(v->value); + if (spanno > 0) { + if ((c = strchr(v->value, ','))) { + trunkgroup = atoi(c + 1); + if (trunkgroup > 0) { + if ((c = strchr(c + 1, ','))) + logicalspan = atoi(c + 1); + else + logicalspan = 0; + if (logicalspan >= 0) { + if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { + ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); + } else if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); + } else + ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of zapata.conf\n", v->lineno); + } else + ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of zapata.conf\n", v->lineno); + } else + ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of zapata.conf\n", v->lineno); + } else + ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of zapata.conf\n", v->lineno); + } else { + ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); + } + v = v->next; + } + } +#endif + v = ast_variable_browse(cfg, "channels"); + /* Copy the default jb config over global_jbconf */ + memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); + /* Traverse all variables to handle jb conf */ + for (vjb = v; vjb; vjb = vjb->next) + ast_jb_read_conf(&global_jbconf, vjb->name, vjb->value); + res = process_zap(v, reload, 0); ast_mutex_unlock(&iflock); ast_config_destroy(cfg); + if (res) + return res; + cfg = ast_config_load("users.conf"); + if (cfg) { + char *cat; + char *chans; + process_zap(ast_variable_browse(cfg, "general"), 1, 1); + for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { + if (!strcasecmp(cat, "general")) + continue; + chans = ast_variable_retrieve(cfg, cat, "zapchan"); + if (!ast_strlen_zero(chans)) { + process_zap(ast_variable_browse(cfg, cat), 1, 1); + build_channels(0, chans, 1, 0, NULL); + } + } + ast_config_destroy(cfg); + } #ifdef HAVE_PRI if (!reload) { for (x = 0; x < NUM_SPANS; x++) { -- cgit v1.2.3