From 41d5807a297095003997765c44424398f3e8a737 Mon Sep 17 00:00:00 2001 From: kpfleming Date: Sat, 12 Nov 2005 02:57:43 +0000 Subject: issue #5712 git-svn-id: http://svn.digium.com/svn/asterisk/trunk@7086 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'channels/chan_sip.c') diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 399e10149..3c7aef5af 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -384,6 +384,7 @@ static int global_mwitime = DEFAULT_MWITIME; /*!< Time between MWI checks for pe static int usecnt =0; AST_MUTEX_DEFINE_STATIC(usecnt_lock); +AST_MUTEX_DEFINE_STATIC(rand_lock); /*! \brief Protect the interface list (of sip_pvt's) */ AST_MUTEX_DEFINE_STATIC(iflock); @@ -943,6 +944,24 @@ static const struct ast_channel_tech sip_tech = { .send_text = sip_sendtext, }; +/*! + \brief Thread-safe random number generator + \return a random number + + This function uses a mutex lock to guarantee that no + two threads will receive the same random number. + */ +static force_inline int thread_safe_rand(void) +{ + int val; + + ast_mutex_lock(&rand_lock); + val = rand(); + ast_mutex_unlock(&rand_lock); + + return val; +} + /*! \brief find_sip_method: Find SIP method from header * Strictly speaking, SIP methods are case SENSITIVE, but we don't check * following Jon Postel's rule: Be gentle in what you accept, strict with what you send */ @@ -2721,7 +2740,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title) fmt = ast_best_codec(tmp->nativeformats); if (title) - snprintf(tmp->name, sizeof(tmp->name), "SIP/%s-%04x", title, rand() & 0xffff); + snprintf(tmp->name, sizeof(tmp->name), "SIP/%s-%04x", title, thread_safe_rand() & 0xffff); else if (strchr(i->fromdomain,':')) snprintf(tmp->name, sizeof(tmp->name), "SIP/%s-%08x", strchr(i->fromdomain,':')+1, (int)(long)(i)); else @@ -2974,7 +2993,7 @@ static void build_callid(char *callid, int len, struct in_addr ourip, char *from int x; char iabuf[INET_ADDRSTRLEN]; for (x=0; x<4; x++) { - val = rand(); + val = thread_safe_rand(); res = snprintf(callid, len, "%08x", val); len -= res; callid += res; @@ -2988,7 +3007,7 @@ static void build_callid(char *callid, int len, struct in_addr ourip, char *from static void make_our_tag(char *tagbuf, size_t len) { - snprintf(tagbuf, len, "as%08x", rand()); + snprintf(tagbuf, len, "as%08x", thread_safe_rand()); } /*! \brief sip_alloc: Allocate SIP_PVT structure and set defaults ---*/ @@ -3021,7 +3040,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); } - p->branch = rand(); + p->branch = thread_safe_rand(); make_our_tag(p->tag, sizeof(p->tag)); /* Start with 101 instead of 1 */ p->ocseq = 101; @@ -4009,7 +4028,7 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in } if (newbranch) { - p->branch ^= rand(); + p->branch ^= thread_safe_rand(); build_via(p, p->via, sizeof(p->via)); } @@ -4826,7 +4845,7 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init) req.method = sipmethod; if (init) { /* Bump branch even on initial requests */ - p->branch ^= rand(); + p->branch ^= thread_safe_rand(); build_via(p, p->via, sizeof(p->via)); if (init > 1) initreqprep(&req, p, sipmethod); @@ -5400,7 +5419,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, char *auth, snprintf(addr, sizeof(addr), "sip:%s", r->hostname); ast_copy_string(p->uri, addr, sizeof(p->uri)); - p->branch ^= rand(); + p->branch ^= thread_safe_rand(); memset(&req, 0, sizeof(req)); init_req(&req, sipmethod, addr); @@ -5670,7 +5689,7 @@ static void reg_source_db(struct sip_peer *peer) /* SIP isn't up yet, so schedule a poke only, pretty soon */ if (peer->pokeexpire > -1) ast_sched_del(sched, peer->pokeexpire); - peer->pokeexpire = ast_sched_add(sched, rand() % 5000 + 1, sip_poke_peer_s, peer); + peer->pokeexpire = ast_sched_add(sched, thread_safe_rand() % 5000 + 1, sip_poke_peer_s, peer); } else sip_poke_peer(peer); if (peer->expire > -1) @@ -6131,7 +6150,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata res = 1; } } else if (ast_strlen_zero(randdata) || ast_strlen_zero(authtoken)) { - snprintf(randdata, randlen, "%08x", rand()); + snprintf(randdata, randlen, "%08x", thread_safe_rand()); transmit_response_with_auth(p, response, req, randdata, reliable, respheader, 0); /* Schedule auto destroy in 15 seconds */ sip_scheddestroy(p, 15000); @@ -6247,7 +6266,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata if (wrongnonce) { - snprintf(randdata, randlen, "%08x", rand()); + snprintf(randdata, randlen, "%08x", thread_safe_rand()); if (ua_hash && !strncasecmp(ua_hash, resp_hash, strlen(resp_hash))) { if (sipdebug) ast_log(LOG_NOTICE, "stale nonce received from '%s'\n", get_header(req, "To")); @@ -8962,7 +8981,7 @@ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int d else snprintf(uri, sizeof(uri), "sip:%s@%s",p->username, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr)); - snprintf(cnonce, sizeof(cnonce), "%08x", rand()); + snprintf(cnonce, sizeof(cnonce), "%08x", thread_safe_rand()); /* Check if we have separate auth credentials */ if ((auth = find_realm_authentication(authl, p->realm))) { -- cgit v1.2.3