Allow nat=never mode to work around buggy UNIDEN UIP200 firmware (bug #1935)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3335 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 22 years ago
parent 5fec7176e0
commit ef0128ec41

@ -475,6 +475,10 @@ static int sip_reloading = 0;
#define REG_STATE_TIMEOUT 5 #define REG_STATE_TIMEOUT 5
#define REG_STATE_NOAUTH 6 #define REG_STATE_NOAUTH 6
#define SIP_NAT_NEVER 0
#define SIP_NAT_RFC3581 1
#define SIP_NAT_ALWAYS 2
/* sip_registry: Registrations with other SIP proxies */ /* sip_registry: Registrations with other SIP proxies */
struct sip_registry { struct sip_registry {
struct sockaddr_in addr; /* Who we connect to for registration purposes */ struct sockaddr_in addr; /* Who we connect to for registration purposes */
@ -523,7 +527,7 @@ static struct ast_register_list {
static int __sip_do_register(struct sip_registry *r); static int __sip_do_register(struct sip_registry *r);
static int sipsock = -1; static int sipsock = -1;
static int globalnat = 0; static int globalnat = SIP_NAT_RFC3581;
static int globalcanreinvite = REINVITE_INVITE; static int globalcanreinvite = REINVITE_INVITE;
@ -569,7 +573,7 @@ static inline int sip_debug_test_pvt(struct sip_pvt *p)
{ {
if (sipdebug == 0) if (sipdebug == 0)
return 0; return 0;
return sip_debug_test_addr((p->nat ? &p->recv : &p->sa)); return sip_debug_test_addr(((p->nat == SIP_NAT_ALWAYS) ? &p->recv : &p->sa));
} }
@ -577,7 +581,7 @@ static inline int sip_debug_test_pvt(struct sip_pvt *p)
static int __sip_xmit(struct sip_pvt *p, char *data, int len) static int __sip_xmit(struct sip_pvt *p, char *data, int len)
{ {
int res; int res;
if (p->nat) if (p->nat == SIP_NAT_ALWAYS)
res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->recv, sizeof(struct sockaddr_in)); res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->recv, sizeof(struct sockaddr_in));
else else
res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in)); res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in));
@ -655,7 +659,7 @@ static int retrans_pkt(void *data)
if (pkt->retrans < MAX_RETRANS) { if (pkt->retrans < MAX_RETRANS) {
pkt->retrans++; pkt->retrans++;
if (sip_debug_test_pvt(pkt->owner)) { if (sip_debug_test_pvt(pkt->owner)) {
if (pkt->owner->nat) if (pkt->owner->nat == SIP_NAT_ALWAYS)
ast_verbose("Retransmitting #%d (NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->recv.sin_addr), ntohs(pkt->owner->recv.sin_port)); ast_verbose("Retransmitting #%d (NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->recv.sin_addr), ntohs(pkt->owner->recv.sin_port));
else else
ast_verbose("Retransmitting #%d (no NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->sa.sin_addr), ntohs(pkt->owner->sa.sin_port)); ast_verbose("Retransmitting #%d (no NAT):\n%s\n to %s:%d\n", pkt->retrans, pkt->data, inet_ntoa(pkt->owner->sa.sin_addr), ntohs(pkt->owner->sa.sin_port));
@ -834,7 +838,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, int reliabl
{ {
int res; int res;
if (sip_debug_test_pvt(p)) { if (sip_debug_test_pvt(p)) {
if (p->nat) if (p->nat == SIP_NAT_ALWAYS)
ast_verbose("%sTransmitting (NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); ast_verbose("%sTransmitting (NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
else else
ast_verbose("%sTransmitting (no NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); ast_verbose("%sTransmitting (no NAT):\n%s\n to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port));
@ -856,7 +860,7 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, int reliable
{ {
int res; int res;
if (sip_debug_test_pvt(p)) { if (sip_debug_test_pvt(p)) {
if (p->nat) if (p->nat == SIP_NAT_ALWAYS)
ast_verbose("%sTransmitting:\n%s (NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); ast_verbose("%sTransmitting:\n%s (NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
else else
ast_verbose("%sTransmitting:\n%s (no NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); ast_verbose("%sTransmitting:\n%s (no NAT) to %s:%d\n", reliable ? "Reliably " : "", req->data, inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port));
@ -1208,12 +1212,12 @@ static int create_addr(struct sip_pvt *r, char *peer)
r->capability = p->capability; r->capability = p->capability;
r->nat = p->nat; r->nat = p->nat;
if (r->rtp) { if (r->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", r->nat); ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (r->nat == SIP_NAT_ALWAYS));
ast_rtp_setnat(r->rtp, r->nat); ast_rtp_setnat(r->rtp, (r->nat == SIP_NAT_ALWAYS));
} }
if (r->vrtp) { if (r->vrtp) {
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", r->nat); ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (r->nat == SIP_NAT_ALWAYS));
ast_rtp_setnat(r->vrtp, r->nat); ast_rtp_setnat(r->vrtp, (r->nat == SIP_NAT_ALWAYS));
} }
strncpy(r->peername, p->username, sizeof(r->peername)-1); strncpy(r->peername, p->username, sizeof(r->peername)-1);
strncpy(r->authname, p->username, sizeof(r->authname)-1); strncpy(r->authname, p->username, sizeof(r->authname)-1);
@ -2232,9 +2236,9 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
/* Setup NAT structure according to global settings if we have an address */ /* Setup NAT structure according to global settings if we have an address */
p->nat = globalnat; p->nat = globalnat;
memcpy(&p->recv, sin, sizeof(p->recv)); memcpy(&p->recv, sin, sizeof(p->recv));
ast_rtp_setnat(p->rtp, p->nat); ast_rtp_setnat(p->rtp, (p->nat == SIP_NAT_ALWAYS));
if (p->vrtp) if (p->vrtp)
ast_rtp_setnat(p->vrtp, p->nat); ast_rtp_setnat(p->vrtp, (p->nat == SIP_NAT_ALWAYS));
} }
if (sin) { if (sin) {
@ -2245,7 +2249,10 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
} }
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch); if (p->nat != SIP_NAT_NEVER)
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch);
else
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch);
if (!callid) if (!callid)
build_callid(p->callid, sizeof(p->callid), p->ourip); build_callid(p->callid, sizeof(p->callid), p->ourip);
else else
@ -2831,19 +2838,10 @@ static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, struct s
for (;;) { for (;;) {
tmp = __get_header(orig, field, &start); tmp = __get_header(orig, field, &start);
if (!ast_strlen_zero(tmp)) { if (!ast_strlen_zero(tmp)) {
if (!copied && p->nat) { if (!copied && (p->nat == SIP_NAT_ALWAYS)) {
/* Whoo hoo! Now we can indicate port address translation too! Just /* Whoo hoo! Now we can indicate port address translation too! Just
another RFC (RFC3581). I'll leave the original comments in for another RFC (RFC3581). I'll leave the original comments in for
posterity. */ posterity. */
#ifdef THE_SIP_AUTHORS_CAN_SUCK_MY_GONADS
/* SLD: FIXME: Nice try, but the received= should not have a port */
/* SLD: FIXME: See RFC2543 BNF in Section 6.40.5 */
/* MAS: Yup, RFC says you can't do it. No way to indicate PAT...
good job fellas. */
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
#endif
snprintf(new, sizeof(new), "%s;received=%s;rport=%d", tmp, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); snprintf(new, sizeof(new), "%s;received=%s;rport=%d", tmp, inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
add_header(req, field, new); add_header(req, field, new);
} else { } else {
@ -3045,7 +3043,10 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, char *msg, int se
if (newbranch) { if (newbranch) {
p->branch ^= rand(); p->branch ^= rand();
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch); if (p->nat != SIP_NAT_NEVER)
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch);
else /* Some implementations (e.g. Uniden UIP200) can't handle rport being in the message!! */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch);
} }
if (!ast_strlen_zero(p->uri)) { if (!ast_strlen_zero(p->uri)) {
@ -3628,7 +3629,10 @@ static int transmit_invite(struct sip_pvt *p, char *cmd, int sdp, char *auth, ch
if (init) { if (init) {
/* Bump branch even on initial requests */ /* Bump branch even on initial requests */
p->branch ^= rand(); p->branch ^= rand();
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch); if (p->nat != SIP_NAT_NEVER)
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch);
else /* Work around buggy UNIDEN UIP200 firmware */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch);
initreqprep(&req, p, cmd, vxml_url); initreqprep(&req, p, cmd, vxml_url);
} else } else
reqprep(&req, p, cmd, 0, 1); reqprep(&req, p, cmd, 0, 1);
@ -3933,7 +3937,10 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth, char
p->ocseq = r->ocseq; p->ocseq = r->ocseq;
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
snprintf(via, sizeof(via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch); if (p->nat != SIP_NAT_NEVER)
snprintf(via, sizeof(via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch);
else /* Work around buggy UNIDEN UIP200 firmware */
snprintf(via, sizeof(via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch);
add_header(&req, "Via", via); add_header(&req, "Via", via);
add_header(&req, "From", from); add_header(&req, "From", from);
add_header(&req, "To", to); add_header(&req, "To", to);
@ -4177,7 +4184,7 @@ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_req
} else } else
port = DEFAULT_SIP_PORT; port = DEFAULT_SIP_PORT;
memcpy(&oldsin, &p->addr, sizeof(oldsin)); memcpy(&oldsin, &p->addr, sizeof(oldsin));
if (!p->nat) { if (p->nat != SIP_NAT_ALWAYS) {
/* XXX This could block for a long time XXX */ /* XXX This could block for a long time XXX */
hp = ast_gethostbyname(n, &ahp); hp = ast_gethostbyname(n, &ahp);
if (!hp) { if (!hp) {
@ -4925,9 +4932,9 @@ static int check_via(struct sip_pvt *p, struct sip_request *req)
p->sa.sin_port = htons(pt ? atoi(pt) : DEFAULT_SIP_PORT); p->sa.sin_port = htons(pt ? atoi(pt) : DEFAULT_SIP_PORT);
c = strstr(via, ";rport"); c = strstr(via, ";rport");
if (c && (c[6] != '=')) if (c && (c[6] != '='))
p->nat = 1; p->nat = SIP_NAT_ALWAYS;
if (sip_debug_test_pvt(p)) { if (sip_debug_test_pvt(p)) {
if (p->nat) if (p->nat == SIP_NAT_ALWAYS)
ast_verbose("Sending to %s : %d (NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); ast_verbose("Sending to %s : %d (NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port));
else else
ast_verbose("Sending to %s : %d (non-NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port)); ast_verbose("Sending to %s : %d (non-NAT)\n", inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port));
@ -5068,12 +5075,12 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd
} }
if (p->rtp) { if (p->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat); ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (p->nat == SIP_NAT_ALWAYS));
ast_rtp_setnat(p->rtp, p->nat); ast_rtp_setnat(p->rtp, (p->nat == SIP_NAT_ALWAYS));
} }
if (p->vrtp) { if (p->vrtp) {
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", p->nat); ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (p->nat == SIP_NAT_ALWAYS));
ast_rtp_setnat(p->vrtp, p->nat); ast_rtp_setnat(p->vrtp, (p->nat == SIP_NAT_ALWAYS));
} }
if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, user->md5secret, cmd, uri, reliable, ignore))) { if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, user->md5secret, cmd, uri, reliable, ignore))) {
sip_cancel_destroy(p); sip_cancel_destroy(p);
@ -5141,12 +5148,12 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd
p->ospauth = peer->ospauth; p->ospauth = peer->ospauth;
#endif #endif
if (p->rtp) { if (p->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat); ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (p->nat == SIP_NAT_ALWAYS));
ast_rtp_setnat(p->rtp, p->nat); ast_rtp_setnat(p->rtp, (p->nat == SIP_NAT_ALWAYS));
} }
if (p->vrtp) { if (p->vrtp) {
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", p->nat); ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (p->nat == SIP_NAT_ALWAYS));
ast_rtp_setnat(p->vrtp, p->nat); ast_rtp_setnat(p->vrtp, (p->nat == SIP_NAT_ALWAYS));
} }
strcpy(p->peersecret, peer->secret); strcpy(p->peersecret, peer->secret);
strcpy(p->peermd5secret, peer->md5secret); strcpy(p->peermd5secret, peer->md5secret);
@ -5294,7 +5301,7 @@ static int sip_show_users(int fd, int argc, char *argv[])
user->accountcode, user->accountcode,
user->context, user->context,
user->ha ? "Yes" : "No", user->ha ? "Yes" : "No",
user->nat ? "Yes" : "No"); user->nat ? ((user->nat == SIP_NAT_ALWAYS) ? "Yes" : "RFC3581" ): "No");
} }
ast_mutex_unlock(&userl.lock); ast_mutex_unlock(&userl.lock);
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -5336,7 +5343,7 @@ static int sip_show_peers(int fd, int argc, char *argv[])
sprintf(srch, FORMAT, name, sprintf(srch, FORMAT, name,
peer->addr.sin_addr.s_addr ? inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", peer->addr.sin_addr.s_addr ? inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
peer->dynamic ? " D " : " ", /* Dynamic or not? */ peer->dynamic ? " D " : " ", /* Dynamic or not? */
peer->nat ? " N " : " ", /* NAT=yes? */ (peer->nat == SIP_NAT_ALWAYS) ? " N " : " ", /* NAT=yes? */
peer->ha ? " A " : " ", /* permit/deny */ peer->ha ? " A " : " ", /* permit/deny */
nm, nm,
ntohs(peer->addr.sin_port), status); ntohs(peer->addr.sin_port), status);
@ -5357,7 +5364,7 @@ static int sip_show_peers(int fd, int argc, char *argv[])
ast_cli(fd, FORMAT, name, ast_cli(fd, FORMAT, name,
peer->addr.sin_addr.s_addr ? inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", peer->addr.sin_addr.s_addr ? inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
peer->dynamic ? " D " : " ", /* Dynamic or not? */ peer->dynamic ? " D " : " ", /* Dynamic or not? */
peer->nat ? " N " : " ", /* NAT=yes? */ (peer->nat == SIP_NAT_ALWAYS) ? " N " : " ", /* NAT=yes? */
peer->ha ? " A " : " ", /* permit/deny */ peer->ha ? " A " : " ", /* permit/deny */
nm, nm,
ntohs(peer->addr.sin_port), status); ntohs(peer->addr.sin_port), status);
@ -5439,7 +5446,7 @@ static int sip_show_peer(int fd, int argc, char *argv[])
ast_cli(fd, " Expire : %d\n", peer->expire); ast_cli(fd, " Expire : %d\n", peer->expire);
ast_cli(fd, " Expiry : %d\n", peer->expiry); ast_cli(fd, " Expiry : %d\n", peer->expiry);
ast_cli(fd, " Insecure : %s\n", (peer->insecure?((peer->insecure == 2)?"Very":"Yes"):"No") ); ast_cli(fd, " Insecure : %s\n", (peer->insecure?((peer->insecure == 2)?"Very":"Yes"):"No") );
ast_cli(fd, " Nat : %s\n", (peer->nat?"Yes":"No")); ast_cli(fd, " Nat : %s\n", (peer->nat?((peer->nat == SIP_NAT_ALWAYS) ? "Yes" : "RFC3581"):"No"));
ast_cli(fd, " ACL : %s\n", (peer->ha?"Yes":"No")); ast_cli(fd, " ACL : %s\n", (peer->ha?"Yes":"No"));
ast_cli(fd, " CanReinvite : %s\n", (peer->canreinvite?"Yes":"No")); ast_cli(fd, " CanReinvite : %s\n", (peer->canreinvite?"Yes":"No"));
ast_cli(fd, " PromiscRedir : %s\n", (peer->promiscredir?"Yes":"No")); ast_cli(fd, " PromiscRedir : %s\n", (peer->promiscredir?"Yes":"No"));
@ -5639,7 +5646,7 @@ static int sip_show_channel(int fd, int argc, char *argv[])
ast_cli(fd, " Format %s\n", ast_getformatname(cur->owner ? cur->owner->nativeformats : 0) ); ast_cli(fd, " Format %s\n", ast_getformatname(cur->owner ? cur->owner->nativeformats : 0) );
ast_cli(fd, " Theoretical Address: %s:%d\n", inet_ntoa(cur->sa.sin_addr), ntohs(cur->sa.sin_port)); ast_cli(fd, " Theoretical Address: %s:%d\n", inet_ntoa(cur->sa.sin_addr), ntohs(cur->sa.sin_port));
ast_cli(fd, " Received Address: %s:%d\n", inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port)); ast_cli(fd, " Received Address: %s:%d\n", inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port));
ast_cli(fd, " NAT Support: %s\n", cur->nat ? "Yes" : "No"); ast_cli(fd, " NAT Support: %s\n", cur->nat ? ((cur->nat == SIP_NAT_ALWAYS) ? "Yes" : "RFC3581"): "No");
ast_cli(fd, " Our Tag: %08d\n", cur->tag); ast_cli(fd, " Our Tag: %08d\n", cur->tag);
ast_cli(fd, " Their Tag: %s\n", cur->theirtag); ast_cli(fd, " Their Tag: %s\n", cur->theirtag);
ast_cli(fd, " SIP User agent: %s\n", cur->useragent); ast_cli(fd, " SIP User agent: %s\n", cur->useragent);
@ -7208,7 +7215,10 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer)
if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip)) if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch); if (p->nat != SIP_NAT_NEVER)
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch);
else /* UNIDEN UIP200 bug */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch);
build_callid(p->callid, sizeof(p->callid), p->ourip); build_callid(p->callid, sizeof(p->callid), p->ourip);
/* Send MWI */ /* Send MWI */
p->outgoing = 1; p->outgoing = 1;
@ -7420,7 +7430,10 @@ static int sip_poke_peer(struct sip_peer *peer)
if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip)) if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch); if (p->nat != SIP_NAT_NEVER)
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch);
else
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch);
build_callid(p->callid, sizeof(p->callid), p->ourip); build_callid(p->callid, sizeof(p->callid), p->ourip);
if (peer->pokeexpire > -1) if (peer->pokeexpire > -1)
@ -7538,7 +7551,10 @@ static struct ast_channel *sip_request(char *type, int format, void *data)
if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip)) if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch); if (p->nat != SIP_NAT_NEVER)
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", inet_ntoa(p->ourip), ourport, p->branch);
else /* UNIDEN bug */
snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", inet_ntoa(p->ourip), ourport, p->branch);
build_callid(p->callid, sizeof(p->callid), p->ourip); build_callid(p->callid, sizeof(p->callid), p->ourip);
if (ext) if (ext)
strncpy(p->username, ext, sizeof(p->username) - 1); strncpy(p->username, ext, sizeof(p->username) - 1);
@ -7612,7 +7628,12 @@ static struct sip_user *build_user(char *name, struct ast_variable *v)
else else
user->canreinvite = ast_true(v->value); user->canreinvite = ast_true(v->value);
} else if (!strcasecmp(v->name, "nat")) { } else if (!strcasecmp(v->name, "nat")) {
user->nat = ast_true(v->value); if (!strcasecmp(v->value, "never"))
user->nat = SIP_NAT_NEVER;
else if (ast_true(v->value))
user->nat = SIP_NAT_ALWAYS;
else
user->nat = SIP_NAT_RFC3581;
} else if (!strcasecmp(v->name, "callerid")) { } else if (!strcasecmp(v->name, "callerid")) {
strncpy(user->callerid, v->value, sizeof(user->callerid)-1); strncpy(user->callerid, v->value, sizeof(user->callerid)-1);
user->hascallerid=1; user->hascallerid=1;
@ -7787,9 +7808,14 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v)
peer->canreinvite = REINVITE_UPDATE; peer->canreinvite = REINVITE_UPDATE;
else else
peer->canreinvite = ast_true(v->value); peer->canreinvite = ast_true(v->value);
} else if (!strcasecmp(v->name, "nat")) } else if (!strcasecmp(v->name, "nat")) {
peer->nat = ast_true(v->value); if (!strcasecmp(v->value, "rfc3581"))
else if (!strcasecmp(v->name, "context")) peer->nat = SIP_NAT_RFC3581;
else if (ast_true(v->value))
peer->nat = SIP_NAT_ALWAYS;
else
peer->nat = SIP_NAT_NEVER;
} else if (!strcasecmp(v->name, "context"))
strncpy(peer->context, v->value, sizeof(peer->context)-1); strncpy(peer->context, v->value, sizeof(peer->context)-1);
else if (!strcasecmp(v->name, "fromdomain")) else if (!strcasecmp(v->name, "fromdomain"))
strncpy(peer->fromdomain, v->value, sizeof(peer->fromdomain)-1); strncpy(peer->fromdomain, v->value, sizeof(peer->fromdomain)-1);
@ -7959,7 +7985,7 @@ static int reload_config(void)
return 0; return 0;
} }
globalnat = 0; globalnat = SIP_NAT_RFC3581;
sip_prefs_free(); sip_prefs_free();
@ -8026,7 +8052,12 @@ static int reload_config(void)
} else if (!strcasecmp(v->name, "fromdomain")) { } else if (!strcasecmp(v->name, "fromdomain")) {
strncpy(fromdomain, v->value, sizeof(fromdomain)-1); strncpy(fromdomain, v->value, sizeof(fromdomain)-1);
} else if (!strcasecmp(v->name, "nat")) { } else if (!strcasecmp(v->name, "nat")) {
globalnat = ast_true(v->value); if (!strcasecmp(v->value, "rfc3581"))
globalnat = SIP_NAT_RFC3581;
else if (ast_true(v->value))
globalnat = SIP_NAT_ALWAYS;
else
globalnat = SIP_NAT_NEVER;
} else if (!strcasecmp(v->name, "autocreatepeer")) { } else if (!strcasecmp(v->name, "autocreatepeer")) {
autocreatepeer = ast_true(v->value); autocreatepeer = ast_true(v->value);
} else if (!strcasecmp(v->name, "srvlookup")) { } else if (!strcasecmp(v->name, "srvlookup")) {

@ -60,6 +60,10 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;trustrpid = no ; If Remote-Party-ID should be trusted ;trustrpid = no ; If Remote-Party-ID should be trusted
;progressinband=no ; If we should generate in-band ringing always ;progressinband=no ; If we should generate in-band ringing always
;useragent=Asterisk PBX ; Allows you to change the user agent string ;useragent=Asterisk PBX ; Allows you to change the user agent string
;nat=no ; NAT settings
; yes = Always ignore info and assume NAT
; no = Use NAT mode only according to RFC3581
; never = Never attempt NAT mode or RFC3581 support
;promiscredir = no ; If yes, allows 302 or REDIR to non-local SIP address ;promiscredir = no ; If yes, allows 302 or REDIR to non-local SIP address
; 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:

Loading…
Cancel
Save