[Asterisk-cvs] asterisk/channels chan_sip.c,1.274,1.275
jeremy at lists.digium.com
jeremy at lists.digium.com
Mon Jan 12 19:39:55 CST 2004
Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv22394/channels
Modified Files:
chan_sip.c
Log Message:
Implement NAT trick for outbound SIP connections
Index: chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.274
retrieving revision 1.275
diff -u -d -r1.274 -r1.275
--- chan_sip.c 12 Jan 2004 21:42:51 -0000 1.274
+++ chan_sip.c 13 Jan 2004 01:31:42 -0000 1.275
@@ -394,9 +394,12 @@
static int sipsock = -1;
static int globalnat = 0;
static int globalcanreinvite = REINVITE_INVITE;
-static int use_external_ip = 0;
+
static struct sockaddr_in bindaddr;
+static struct sockaddr_in localnet;
+static struct sockaddr_in localmask;
+static struct sockaddr_in externip;
static struct ast_frame *sip_read(struct ast_channel *ast);
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
@@ -434,14 +437,18 @@
static int ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us)
{
- if (use_external_ip) {
- return -1;
- } else {
- if (bindaddr.sin_addr.s_addr)
- memcpy(us, &bindaddr.sin_addr, sizeof(struct in_addr));
- else
- return ast_ouraddrfor(them, us);
- }
+ /*
+ check to see if them is contained in our localnet/mask,
+ if not, use our externip for us, otherwise use the
+ real internal address in bindaddr
+ */
+ if (localnet.sin_addr.s_addr && externip.sin_addr.s_addr &&
+ ((htonl(them->s_addr) & htonl(localnet.sin_addr.s_addr)) != htonl(localnet.sin_addr.s_addr)))
+ memcpy(us, &externip.sin_addr, sizeof(struct in_addr));
+ else if (bindaddr.sin_addr.s_addr)
+ memcpy(us, &bindaddr.sin_addr, sizeof(struct in_addr));
+ else
+ return ast_ouraddrfor(them, us);
return 0;
}
@@ -3018,6 +3025,8 @@
char via[80];
char addr[80];
struct sip_pvt *p;
+ struct hostent *hp;
+
/* exit if we are already in process with this registrar ?*/
if ( r == NULL || ((auth==NULL) && (r->regstate==REG_STATE_REGSENT || r->regstate==REG_STATE_AUTHSENT))) {
ast_log(LOG_NOTICE, "Strange, trying to register when registration already pending\n");
@@ -3051,9 +3060,16 @@
strncpy(p->peername, r->username, sizeof(p->peername)-1);
strncpy(p->username, r->username, sizeof(p->username)-1);
strncpy(p->exten, r->contact, sizeof(p->exten) - 1);
- /* Always bind to our IP if specified */
- if (!use_external_ip && bindaddr.sin_addr.s_addr)
- memcpy(&p->ourip, &bindaddr.sin_addr, sizeof(p->ourip));
+
+ /*
+ check which address we should use in our contact header
+ based on whether the remote host is on the external or
+ internal network so we can register through nat
+ */
+ if ((hp = gethostbyname(r->hostname))) {
+ if (ast_sip_ouraddrfor((struct in_addr *)hp->h_addr, &p->ourip))
+ memcpy(&p->ourip, &bindaddr.sin_addr, sizeof(p->ourip));
+ }
build_contact(p);
}
@@ -6135,6 +6151,10 @@
sip_prefs_free();
memset(&bindaddr, 0, sizeof(bindaddr));
+ memset(&localnet, 0, sizeof(localnet));
+ memset(&localmask, 0, sizeof(localmask));
+ memset(&externip, 0, sizeof(externip));
+
/* Initialize some reasonable defaults */
strncpy(context, "default", sizeof(context) - 1);
strcpy(language, "");
@@ -6195,13 +6215,21 @@
} else {
memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
}
+ } else if (!strcasecmp(v->name, "localnet")) {
+ if (!(hp = gethostbyname(v->value)))
+ ast_log(LOG_WARNING, "Invalid localnet keyword: %s\n", v->value);
+ else
+ memcpy(&localnet.sin_addr, hp->h_addr, sizeof(localnet.sin_addr));
+ } else if (!strcasecmp(v->name, "localmask")) {
+ if (!(hp = gethostbyname(v->value)))
+ ast_log(LOG_WARNING, "Invalid localmask keyword: %s\n", v->value);
+ else
+ memcpy(&localmask.sin_addr, hp->h_addr, sizeof(localmask.sin_addr));
} else if (!strcasecmp(v->name, "externip")) {
- if (!(hp = gethostbyname(v->value))) {
+ if (!(hp = gethostbyname(v->value)))
ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value);
- } else {
- memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
- use_external_ip = 1;
- }
+ else
+ memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
} else if (!strcasecmp(v->name, "allow")) {
format = ast_getformatbyname(v->value);
if (format < 1)
@@ -6276,17 +6304,16 @@
}
cat = ast_category_browse(cfg, cat);
}
- if (!use_external_ip) {
- if (ntohl(bindaddr.sin_addr.s_addr)) {
- memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
- } else {
- hp = gethostbyname(ourhost);
- if (!hp) {
- ast_log(LOG_WARNING, "Unable to get IP address for %s, SIP disabled\n", ourhost);
- return 0;
- }
- memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
+
+ if (ntohl(bindaddr.sin_addr.s_addr)) {
+ memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
+ } else {
+ hp = gethostbyname(ourhost);
+ if (!hp) {
+ ast_log(LOG_WARNING, "Unable to get IP address for %s, SIP disabled\n", ourhost);
+ return 0;
}
+ memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
}
if (!ntohs(bindaddr.sin_port))
bindaddr.sin_port = ntohs(DEFAULT_SIP_PORT);
More information about the svn-commits
mailing list