diff --git a/CHANGES b/CHANGES index f8e0cadeb7..1a443ca971 100755 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,4 @@ + -- Add "NAT" option to sip user, peer, friend -- Add experimental "IAX2" protocol -- Add "Enhanced" AGI with audio pass-through (voice recognition anyone?) -- Choose best priority from codec from allow/disallow diff --git a/apps/app_dial.c b/apps/app_dial.c index 754895f4d2..cd26974fd2 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -120,7 +120,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu int ringind=0; struct ast_channel *winner; - single = (outgoing && !outgoing->next); + single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly); if (single) { /* If we are calling a single channel, make them compatible for in-band tone purpose */ diff --git a/apps/app_lookupblacklist.c b/apps/app_lookupblacklist.c index d82a950f2d..9cc9e1e640 100755 --- a/apps/app_lookupblacklist.c +++ b/apps/app_lookupblacklist.c @@ -38,7 +38,8 @@ static char *descrip = "where 'n' is the priority of the current instance, then the\n" "channel will be setup to continue at that priority level.\n" "Otherwise, it returns 0. Does nothing if no Caller*ID was received on the\n" - "channel.\n"; + "channel.\n" + "Example: database put blacklist 1\n"; STANDARD_LOCAL_USER; @@ -47,66 +48,67 @@ LOCAL_USER_DECL; static int lookupblacklist_exec (struct ast_channel *chan, void *data) { - char old_cid[144] = "", *num, *name; - char blacklist[1]; - char shrunknum[64] = ""; - struct localuser *u; - int bl = 0; + char old_cid[144] = "", *num, *name; + char blacklist[1]; + char shrunknum[64] = ""; + struct localuser *u; + int bl = 0; - LOCAL_USER_ADD (u); - if (chan->callerid) - { - strncpy (old_cid, chan->callerid, sizeof (old_cid) - 1); - ast_callerid_parse (old_cid, &name, &num); /* this destroys the original string */ - if (num) /* It's possible to get an empty number */ - strncpy (shrunknum, num, sizeof (shrunknum) - 1); - else - num = shrunknum; - ast_shrink_phone_number (shrunknum); - if (!ast_db_get ("blacklist", shrunknum, blacklist, sizeof (blacklist))) + LOCAL_USER_ADD (u); + if (chan->callerid) { - if (option_verbose > 2) - ast_verbose (VERBOSE_PREFIX_3 "Blacklisted number %s found\n",shrunknum); - bl = 1; + strncpy (old_cid, chan->callerid, sizeof (old_cid) - 1); + ast_callerid_parse (old_cid, &name, &num); + if (num) + strncpy (shrunknum, num, sizeof (shrunknum) - 1); + else + num = shrunknum; + + ast_shrink_phone_number (shrunknum); + if (!ast_db_get ("blacklist", shrunknum, blacklist, sizeof (blacklist))) + { + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 "Blacklisted number %s found\n",shrunknum); + bl = 1; + } + else if (!ast_db_get ("blacklist", name, blacklist, sizeof (blacklist))) + { + if (option_verbose > 2) + ast_verbose (VERBOSE_PREFIX_3 "Blacklisted name \"%s\" found\n",name); + bl = 1; + } } - - } - if (bl && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid)) - chan->priority+=100; - LOCAL_USER_REMOVE (u); - return 0; + + if (bl && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid)) + chan->priority+=100; + LOCAL_USER_REMOVE (u); + return 0; } -int -unload_module (void) +int unload_module (void) { - STANDARD_HANGUP_LOCALUSERS; - return ast_unregister_application (app); + STANDARD_HANGUP_LOCALUSERS; + return ast_unregister_application (app); } -int -load_module (void) +int load_module (void) { - return ast_register_application (app, lookupblacklist_exec, synopsis, - descrip); + return ast_register_application (app, lookupblacklist_exec, synopsis,descrip); } -char * -description (void) +char *description (void) { - return tdesc; + return tdesc; } -int -usecount (void) +int usecount (void) { - int res; - STANDARD_USECOUNT (res); - return res; + int res; + STANDARD_USECOUNT (res); + return res; } -char * -key () +char *key () { - return ASTERISK_GPL_KEY; + return ASTERISK_GPL_KEY; } diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 3ea6cff461..4af888f1fc 100755 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -564,9 +564,10 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, int silent, int get_date(date, sizeof(date)); time(&start); fprintf(txt, -"#\n" -"# Message Information file\n" -"#\n" +";\n" +"; Message Information file\n" +";\n" +"[message]\n" "origmailbox=%s\n" "context=%s\n" "exten=%s\n" @@ -992,6 +993,11 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi) static void adsi_begin(struct ast_channel *chan, int *useadsi) { int x; + if(!strcasecmp(chan->type, "sip")){ + *useadsi = 0; + return; + } + x = adsi_load_session(chan, adapp, adver, 1); if (x < 0) return; @@ -1303,6 +1309,9 @@ static void adsi_goodbye(struct ast_channel *chan) { char buf[256]; int bytes=0; + if(!strcasecmp(chan->type, "sip")){ + return; + } if (!adsi_available(chan)) return; bytes += adsi_logo(buf + bytes); @@ -1345,13 +1354,19 @@ static int get_folder(struct ast_channel *chan, int start) } static int -forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int curmsg) +forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int curmsg, char* myusername) { char username[70]; char sys[256]; char todir[256]; int todircount=0; - + struct ast_config *mif; + char miffile[256]; + char *copy, *name, *passwd, *email; + char *mycopy, *myname, *mypasswd, *myemail; + char fn[256]; + char callerid[512]; + while(1) { ast_streamfile(chan, "vm-extension", chan->language); @@ -1359,8 +1374,9 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int return 0; if (ast_variable_retrieve(cfg, NULL, username)) { printf("Got %d\n", atoi(username)); - if (play_and_wait(chan, "vm-savedto")) + /* if (play_and_wait(chan, "vm-savedto")) break; + */ snprintf(todir, sizeof(todir), "%s/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR,"vm", username); snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir); @@ -1373,13 +1389,69 @@ forward_message(struct ast_channel *chan, struct ast_config *cfg, char *dir, int puts(sys); system(sys); + /* TODO: use config to determine what other formats to copy the message in */ + snprintf(sys, sizeof(sys), "cp %s/msg%04d.wav %s/msg%04d.wav\n", dir, curmsg, todir, todircount); + puts(sys); + system(sys); + + /* copy the message information file too */ + snprintf(sys, sizeof(sys), "cp %s/msg%04d.txt %s/msg%04d.txt\n", dir, curmsg, todir, todircount); + puts(sys); + system(sys); + + snprintf(fn, sizeof(fn), "%s/msg%04d", todir,todircount); + + /* load the information on the source message so we can send an e-mail like a new message */ + snprintf(miffile, sizeof(miffile), "%s/msg%04d.txt", dir, curmsg); + if ((mif=ast_load(miffile))) { + + /* send an e-mail like it was a new message if appropriate */ + if ((copy = ast_variable_retrieve(cfg, NULL, username))) { + char *stringp=NULL; + /* Make sure they have an entry in the config */ + copy = strdup(copy); + stringp=copy; + passwd = strsep(&stringp, ","); + name = strsep(&stringp, ","); + email = strsep(&stringp, ","); + } + + if ((mycopy = ast_variable_retrieve(cfg, NULL, myusername))) { + char *mystringp=NULL; + /* Make sure they have an entry in the config */ + mycopy = strdup(mycopy); + mystringp=mycopy; + mypasswd = strsep(&mystringp, ","); + myname = strsep(&mystringp, ","); + myemail = strsep(&mystringp, ","); + } + + if (email) { + snprintf(callerid, sizeof(callerid), "FWD from: %s from %s", myname, ast_variable_retrieve(mif, NULL, "callerid")); + sendmail(ast_variable_retrieve(cfg, "general", "serveremail"), + email, name, todircount, username, + callerid, + fn, + "wav", + atol(ast_variable_retrieve(mif, NULL, "duration")) + ); + } + + free(copy); /* no leaks here */ + free(mycopy); /* or here */ + ast_destroy(mif); /* or here */ + } + + /* give confirmatopm that the message was saved */ + if (play_and_wait(chan, "vm-message")) break; + if (play_and_wait(chan, "vm-saved")) break; + break; } else { if ( play_and_wait(chan, "pbx-invalid")) break; } } - return 0; } @@ -1920,7 +1992,7 @@ cmd: goto instructions; case '8': if(lastmsg > -1) - if(forward_message(chan, cfg, curdir, curmsg) < 0) + if(forward_message(chan, cfg, curdir, curmsg, username) < 0) goto out; goto instructions; case '9': diff --git a/channels/chan_sip.c b/channels/chan_sip.c index adf23a40c1..c4e0d20468 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -145,7 +145,9 @@ static struct sip_pvt { int canreinvite; /* Do we support reinvite */ int progress; /* Have sent 183 message progress */ int tag; /* Another random number */ + int nat; /* Whether to try to support NAT */ struct sockaddr_in sa; /* Our peer */ + struct sockaddr_in recv; /* Received as */ struct in_addr ourip; /* Our IP */ struct ast_channel *owner; /* Who owns us */ char exten[AST_MAX_EXTENSION]; /* Extention where to start */ @@ -193,6 +195,7 @@ struct sip_user { char callerid[80]; char methods[80]; char accountcode[80]; + int nat; int hascallerid; int amaflags; int insecure; @@ -215,6 +218,7 @@ struct sip_peer { int expirey; int capability; int insecure; + int nat; int canreinvite; struct sockaddr_in addr; struct in_addr mask; @@ -290,7 +294,10 @@ static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req); static int __sip_xmit(struct sip_pvt *p, char *data, int len) { int res; - res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in)); + if (p->nat) + res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->recv, sizeof(struct sockaddr_in)); + else + res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in)); if (res != len) { ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, inet_ntoa(p->sa.sin_addr), res, strerror(errno)); } @@ -300,8 +307,12 @@ static int __sip_xmit(struct sip_pvt *p, char *data, int len) static int send_response(struct sip_pvt *p, struct sip_request *req) { int res; - if (sipdebug) - ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + if (sipdebug) { + if (p->nat) + ast_verbose("Transmitting (NAT):\n%s\n to %s:%d\n", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); + else + ast_verbose("Transmitting (no NAT):\n%s\n to %s:%d\n", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + } res = __sip_xmit(p, req->data, req->len); if (res > 0) res = 0; @@ -311,8 +322,12 @@ static int send_response(struct sip_pvt *p, struct sip_request *req) static int send_request(struct sip_pvt *p, struct sip_request *req) { int res; - if (sipdebug) - ast_verbose("XXX Need to handle Retransmitting XXX:\n%s to %s:%d\n", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + if (sipdebug) { + if (p->nat) + ast_verbose("XXX Need to handle Retransmitting XXX:\n%s (NAT) to %s:%d\n", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); + else + ast_verbose("XXX Need to handle Retransmitting XXX:\n%s (no NAT) to %s:%d\n", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + } res = __sip_xmit(p, req->data, req->len); return res; } @@ -378,6 +393,7 @@ static int create_addr(struct sip_pvt *r, char *peer) r->sa.sin_addr = p->defaddr.sin_addr; r->sa.sin_port = p->defaddr.sin_port; } + memcpy(&r->recv, &r->sa, sizeof(r->recv)); break; } } @@ -389,6 +405,7 @@ static int create_addr(struct sip_pvt *r, char *peer) if (hp) { memcpy(&r->sa.sin_addr, hp->h_addr, sizeof(r->sa.sin_addr)); r->sa.sin_port = htons(DEFAULT_SIP_PORT); + memcpy(&r->recv, &r->sa, sizeof(r->recv)); return 0; } else { ast_log(LOG_WARNING, "No such host: %s\n", peer); @@ -1451,6 +1468,7 @@ static int copy_header(struct sip_request *req, struct sip_request *orig, char * return -1; } +#if 0 static int copy_all_header(struct sip_request *req, struct sip_request *orig, char *field) { char *tmp; @@ -1471,6 +1489,36 @@ static int copy_all_header(struct sip_request *req, struct sip_request *orig, ch } return 0; } +#endif +static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, struct sip_request *orig, char *field) +{ + char *tmp; + int start = 0; + int copied = 0; + char new[256]; + for (;;) { + tmp = __get_header(orig, field, &start); + if (strlen(tmp)) { + if (!copied) { + if (ntohs(p->recv.sin_port) != DEFAULT_SIP_PORT) + snprintf(new, sizeof(new), "%s;received=%s:%d", tmp, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); + else + snprintf(new, sizeof(new), "%s;received=%s", tmp, inet_ntoa(p->recv.sin_addr)); + add_header(req, field, new); + } else { + /* Add what we're responding to */ + add_header(req, field, tmp); + } + copied++; + } else + break; + } + if (!copied) { + ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field); + return -1; + } + return 0; +} static int init_resp(struct sip_request *req, char *resp, struct sip_request *orig) { @@ -1511,7 +1559,7 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru char newto[256] = "", *ot; memset(resp, 0, sizeof(*resp)); init_resp(resp, msg, req); - copy_all_header(resp, req, "Via"); + copy_via_headers(p, resp, req, "Via"); copy_header(resp, req, "From"); ot = get_header(req, "To"); if (!strstr(ot, "tag=")) { @@ -2035,6 +2083,16 @@ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_req if (n) *n = '\0'; } + if (!strcasecmp(c, "*")) { + /* This means remove all registrations and return OK */ + memset(&p->addr, 0, sizeof(p->addr)); + if (p->expire > -1) + ast_sched_del(sched, p->expire); + p->expire = -1; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Unegistered SIP '%s'\n", p->username); + return 0; + } /* Make sure it's a SIP URL */ if (strncasecmp(c, "sip:", 4)) { ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", c); @@ -2108,7 +2166,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata /* Always OK if no secret */ if (!strlen(secret)) return 0; - if (!strlen(randdata)) { + if (!strlen(randdata) || !strlen(get_header(req, "Proxy-Authorization"))) { snprintf(randdata, randlen, "%08x", rand()); transmit_response_with_auth(p, "407 Proxy Authentication Required", req, randdata); res = 1; @@ -2215,6 +2273,8 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si peer = peerl.peers; while(peer) { if (!strcasecmp(peer->name, name) && peer->dynamic) { + p->nat = peer->nat; + transmit_response(p, "100 Trying", req); if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, "REGISTER", uri))) { if (parse_contact(p, peer, req)) { ast_log(LOG_WARNING, "Failed to parse contact info\n"); @@ -2412,10 +2472,14 @@ static int check_via(struct sip_pvt *p, struct sip_request *req) } memset(&p->sa, 0, sizeof(p->sa)); p->sa.sin_family = AF_INET; - p->sa.sin_port = htons(pt ? atoi(pt) : DEFAULT_SIP_PORT); memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); - if (sipdebug) - ast_verbose("Sending to %s : %d\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + p->sa.sin_port = htons(pt ? atoi(pt) : DEFAULT_SIP_PORT); + if (sipdebug) { + if (p->nat) + ast_verbose("Sending to %s : %d (NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + else + ast_verbose("Sending to %s : %d (non-NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); + } } return 0; } @@ -2450,6 +2514,7 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha user = userl.users; while(user) { if (!strcasecmp(user->name, of)) { + p->nat = user->nat; if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, cmd, uri))) { strncpy(p->context, user->context, sizeof(p->context) - 1); if (strlen(user->callerid) && strlen(p->callerid)) @@ -3331,7 +3396,6 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc ast_verbose("Using latest request as basis request\n"); copy_request(&p->initreq, req); check_via(p, req); - transmit_response(p, "100 Trying", req); if ((res = register_verify(p, sin, req, e)) < 0) ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s'\n", get_header(req, "To"), inet_ntoa(sin->sin_addr)); if (res < 1) { @@ -3390,6 +3454,7 @@ static int sipsock_read(int *id, int fd, short events, void *ignore) ast_pthread_mutex_lock(&netlock); p = find_call(&req, &sin); if (p) { + memcpy(&p->recv, &sin, sizeof(p->recv)); handle_request(p, &req, &sin); } ast_pthread_mutex_unlock(&netlock); @@ -3573,6 +3638,7 @@ static int sip_poke_peer(struct sip_peer *peer) return -1; } memcpy(&p->sa, &peer->addr, sizeof(p->sa)); + memcpy(&p->recv, &peer->addr, sizeof(p->sa)); /* Recalculate our side, and recalculate Call ID */ memcpy(&p->ourip, myaddrfor(&p->sa.sin_addr), sizeof(p->ourip)); @@ -3674,6 +3740,8 @@ static struct sip_user *build_user(char *name, struct ast_variable *v) strncpy(user->secret, v->value, sizeof(user->secret)-1); } else if (!strcasecmp(v->name, "canreinvite")) { user->canreinvite = ast_true(v->value); + } else if (!strcasecmp(v->name, "nat")) { + user->nat = ast_true(v->value); } else if (!strcasecmp(v->name, "callerid")) { strncpy(user->callerid, v->value, sizeof(user->callerid)-1); user->hascallerid=1; @@ -3750,6 +3818,8 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v) strncpy(peer->methods, v->value, sizeof(peer->methods)-1); else if (!strcasecmp(v->name, "canreinvite")) peer->canreinvite = ast_true(v->value); + else if (!strcasecmp(v->name, "nat")) + peer->nat = ast_true(v->value); else if (!strcasecmp(v->name, "context")) strncpy(peer->context, v->value, sizeof(peer->context)-1); else if (!strcasecmp(v->name, "host")) { @@ -3833,7 +3903,7 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v) return peer; } -static int reload_config() +static int reload_config(void) { struct ast_config *cfg; struct ast_variable *v;