[asterisk-commits] rizzo: branch rizzo/astobj2 r75528 - /team/rizzo/astobj2/channels/chan_sip.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 18 04:02:21 CDT 2007


Author: rizzo
Date: Wed Jul 18 04:02:20 2007
New Revision: 75528

URL: http://svn.digium.com/view/asterisk?view=rev&rev=75528
Log:
more cleanup and documentation in the handling
of bindaddr, externip and internip (formerly __ourip).

Now we should be pretty close to a proper management of
NATted addresses, only missing the periodic stun refreshes
and the management of addresses for media streams.

Modified:
    team/rizzo/astobj2/channels/chan_sip.c

Modified: team/rizzo/astobj2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/channels/chan_sip.c?view=diff&rev=75528&r1=75527&r2=75528
==============================================================================
--- team/rizzo/astobj2/channels/chan_sip.c (original)
+++ team/rizzo/astobj2/channels/chan_sip.c Wed Jul 18 04:02:20 2007
@@ -1388,12 +1388,36 @@
  */
 
 static volatile int sipsock  = -1;			/*!< Main socket for SIP network communication */
-static struct sockaddr_in stunaddr = { 0, };	/*!< stun server address */
 static struct sockaddr_in bindaddr = { 0, };	/*!< The address we bind to */
+
+/*! \brief our (internal) default address/port to put in SIP/SDP messages
+ *  internip is initialized picking a suitable address from one of the
+ * interfaces, and the same port number we bind to. It is used as the
+ * default address/port in SIP messages, and as the default address
+ * (but not port) in SDP messages.
+ */
+static struct sockaddr_in internip;
+
+/*! \brief our external IP address/port for SIP sessions.
+ * externip.sin_addr is only set when we know we might be behind
+ * a NAT, and this is done using a variety of (mutually exclusive)
+ * ways from the config file:
+ *
+ * + with "externip = host[:port]" we specify the address/port explicitly.
+ *   The address is looked up only once when (re)loading the config file;
+ *
+ * + with "externhost = host[:port]" we do a similar thing, but the
+ *   hostname is stored in externhost, and the hostname->IP mapping
+ *   is refreshed every 'externrefresh' seconds;
+ *
+ * + with "stunaddr = host[:port]" we run queries every externrefresh seconds
+ *   to the specified server, and store the result in externip.
+ */
 static struct sockaddr_in externip;		/*!< External IP address if we are behind NAT */
-static char externhost[MAXHOSTNAMELEN];		/*!< External host name (possibly with dynamic DNS and DHCP */
+static char externhost[MAXHOSTNAMELEN];		/*!< External host name */
 static time_t externexpire = 0;			/*!< Expiration counter for re-resolving external host name in dynamic DNS */
 static int externrefresh = 10;
+static struct sockaddr_in stunaddr = { 0, };	/*!< stun server address */
 
 /*! \brief  List of local networks
  * We store "localnet" addresses from the config file into an access list,
@@ -1403,7 +1427,6 @@
  */
 static struct ast_ha *localaddr;
 
-static struct in_addr __ourip;
 static struct sockaddr_in debugaddr;
 
 static struct ast_config *notify_types;		/*!< The list of manual NOTIFY types we know how to send */
@@ -1621,7 +1644,7 @@
 static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
 
 /*--- Internal UA client handling (outbound registrations) */
-static void ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us);
+static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us);
 static int sip_register(char *value, int lineno);
 static const char *regstate2str(enum sipregistrystate regstate) attribute_const;
 static int sip_reregister(void *data);
@@ -2175,42 +2198,54 @@
 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
 	ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
 			ast_inet_ntoa(p->ourip.sin_addr),
-			ntohs(bindaddr.sin_port), p->branch, rport);
-}
-
-/*! \brief NAT fix - decide which IP address to use for ASterisk server?
+			ntohs(p->ourip.sin_port), p->branch, rport);
+}
+
+/*! \brief NAT fix - decide which IP address to use for Asterisk server?
  *
  * Using the localaddr structure built up with localnet statements in sip.conf
  * apply it to their address to see if we need to substitute our
  * externip or can get away with our internal bindaddr
+ * 'us' is always overwritten.
  */
-static void ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us)
-{
-	struct sockaddr_in theirs, ours;
-
-	/* Get our local information */
-	ast_ouraddrfor(them, us);
+static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us)
+{
+	struct sockaddr_in theirs;
+
+	*us = internip;		/* start from something reasonable */
+	/* Start from the address that the system would use */
+	ast_ouraddrfor(them, &us->sin_addr);
 	theirs.sin_addr = *them;
-	ours.sin_addr = *us;
 
 	/* localaddr contains 'internal' addresses marked as 'deny',
 	 * so 'external' addresses will return AST_SENSE_ALLOW.
+	 * In the following, we check if we need to remap the system-supplied
+	 * address to an externally visible one, and use some appropriate
+	 * mechanism to do that.
 	 */
-	if (localaddr && externip.sin_addr.s_addr &&
-	    ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW &&
-	    (!global_matchexterniplocally || !ast_apply_ha(localaddr, &ours))) {
+	if (localaddr /* have a list of internal addresses */
+		&& externip.sin_addr.s_addr /* can remap to something */
+		&& ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW /* it is indeed internal */
+		&& (!global_matchexterniplocally || !ast_apply_ha(localaddr, us)) /* we want to remap */
+			) { 
+		/* if we used externhost, see if it is time to refresh the info */
 		if (externexpire && time(NULL) >= externexpire) {
 			externexpire = time(NULL) + externrefresh;
 			if (ast_parse_arg(externhost, PARSE_INADDR, &externip))
 				ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
 		}
-		*us = externip.sin_addr;
+		/* XXX todo - what if we use stun ? */
+		*us = externip;
 		if (option_debug) {
 			ast_log(LOG_DEBUG, "Target address %s is not local, substituting externip\n", 
 				ast_inet_ntoa(*(struct in_addr *)&them->s_addr));
 		}
-	} else if (bindaddr.sin_addr.s_addr)
-		*us = bindaddr.sin_addr;
+	} else if (bindaddr.sin_addr.s_addr) {
+		/* remapping is not allowed, but we bind to
+		 * a specific address, so use it.
+		 */
+		*us = bindaddr;
+	}
 }
 
 static inline int record_history(const struct sip_pvt *p)
@@ -4912,12 +4947,11 @@
 	if (intended_method != SIP_OPTIONS)	/* Peerpoke has it's own system */
 		p->timer_t1 = SIP_TIMER_T1;	/* Default SIP retransmission timer T1 (RFC 3261) */
 
-	p->ourip.sin_port = bindaddr.sin_port; /* XXX later, update with stun or similar */
+	p->ourip = internip;
 	if (sin) {
 		p->sa = *sin;
-		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip.sin_addr);
-	} else
-		p->ourip.sin_addr = __ourip;
+		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
+	}
 
 	/* Copy global flags to this PVT at setup. */
 	ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
@@ -6622,13 +6656,11 @@
 	/* Initialize the bare minimum */
 	p->method = intended_method;
 
-	p->ourip.sin_port = bindaddr.sin_port;
+	p->ourip = internip;
 	if (sin) {
 		p->sa = *sin;
-		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip.sin_addr);
-	} else
-		p->ourip.sin_addr = __ourip;
-
+		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
+	}
 	p->branch = ast_random();
 	make_our_tag(p->tag, sizeof(p->tag));
 	p->ocseq = INITIAL_CSEQ;
@@ -8173,7 +8205,7 @@
 	} else {
 		/* Build callid for registration if we haven't registered before */
 		if (!r->callid_valid) {
-			build_callid_registry(r, __ourip, default_fromdomain);
+			build_callid_registry(r, internip.sin_addr, default_fromdomain);
 			r->callid_valid = TRUE;
 		}
 		/* Allocate SIP dialog for registration */
@@ -8227,8 +8259,7 @@
 		  based on whether the remote host is on the external or
 		  internal network so we can register through nat
 		 */
-		p->ourip.sin_port = bindaddr.sin_port; /* XXX nat... */
-		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip.sin_addr);
+		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
 		build_contact(p);
 	}
 
@@ -12322,8 +12353,7 @@
 			add_header(&req, var->name, var->value);
 
 		/* Recalculate our side, and recalculate Call ID */
-		p->ourip.sin_port = bindaddr.sin_port; /* XXX nat */
-		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip.sin_addr);
+		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
 		build_via(p);
 		build_callid_pvt(p);
 		ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
@@ -16459,8 +16489,7 @@
 			return 0;
 		}
 		/* Recalculate our side, and recalculate Call ID */
-		p->ourip.sin_port = bindaddr.sin_port;
-		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip.sin_addr);
+		ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
 		build_via(p);
 		build_callid_pvt(p);
 		/* Destroy this session after 32 secs */
@@ -16721,8 +16750,7 @@
 		ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr));
 
 	/* Recalculate our side, and recalculate Call ID */
-	p->ourip.sin_port = bindaddr.sin_port;
-	ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip.sin_addr);
+	ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
 	build_via(p);
 	build_callid_pvt(p);
 
@@ -16897,8 +16925,7 @@
 	if (ast_strlen_zero(p->peername) && ext)
 		ast_string_field_set(p, peername, ext);
 	/* Recalculate our side, and recalculate Call ID */
-	p->ourip.sin_port = bindaddr.sin_port;
-	ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip.sin_addr);
+	ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip);
 	build_via(p);
 	build_callid_pvt(p);
 	
@@ -17711,6 +17738,7 @@
 
 	/* Reset IP addresses  */
 	memset(&bindaddr, 0, sizeof(bindaddr));
+	memset(&internip, 0, sizeof(internip));
 	memset(&localaddr, 0, sizeof(localaddr));
 	memset(&externip, 0, sizeof(externip));
 	memset(&default_prefs, 0 , sizeof(default_prefs));
@@ -18076,13 +18104,12 @@
 			}
 		}
 	}
-	if (ast_find_ourip(&__ourip, bindaddr)) {
+	bindaddr.sin_family = AF_INET;
+	internip = bindaddr;
+	if (ast_find_ourip(&internip.sin_addr, bindaddr)) {
 		ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n");
 		return 0;
 	}
-	if (!ntohs(bindaddr.sin_port))
-		bindaddr.sin_port = ntohs(STANDARD_SIP_PORT);
-	bindaddr.sin_family = AF_INET;
 	/*
 	 * handle changes in the socket used for communications.
 	 * At the beginning, sipsock = -1 and old_bindaddr = 0:0 so




More information about the asterisk-commits mailing list