Index: acl.c =================================================================== RCS file: /usr/cvsroot/asterisk/acl.c,v retrieving revision 1.46 diff -u -r1.46 acl.c --- acl.c 6 Jun 2005 22:12:18 -0000 1.46 +++ acl.c 29 Jun 2005 21:47:35 -0000 @@ -372,6 +372,25 @@ return 0; } +struct ast_netsock *ast_netsock_find(struct ast_netsock_list *list, + struct sockaddr_in *sa) +{ + int cont = 1; + struct ast_netsock *sock = NULL; + + ASTOBJ_CONTAINER_TRAVERSE(list,cont, { + ASTOBJ_RDLOCK(iterator); + if (!inaddrcmp(&iterator->bindaddr, sa)) { + cont = 0; + sock = iterator; + } + ASTOBJ_UNLOCK(iterator); + } ); + + return sock; +} + + const struct sockaddr_in *ast_netsock_boundaddr(struct ast_netsock *ns) { return &(ns->bindaddr); Index: channels/chan_iax2.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v retrieving revision 1.314 diff -u -r1.314 chan_iax2.c --- channels/chan_iax2.c 24 Jun 2005 04:38:59 -0000 1.314 +++ channels/chan_iax2.c 29 Jun 2005 21:47:39 -0000 @@ -7826,6 +7826,94 @@ } +/*--- check_src_ip: Check if address can be used as packet source. + returns: + 0 address available + 1 address unavailable +-1 error +*/ +static int check_srcaddr(struct sockaddr *sa, socklen_t salen) +{ + int sd; + int res; + + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0) { + ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); + return -1; + } + + res = bind(sd, sa, salen); + if (res < 0) { + ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno)); + close(sd); + return 1; + } + + close(sd); + return 0; +} + +/*--- peer_set_srcaddr: Parse the "sourceaddress" value, + lookup in netsock list and set peer's sockfd. Defaults to defaultsockfd if + not found. */ +static int peer_set_srcaddr(struct iax2_peer *peer, const char *srcaddr) +{ + struct sockaddr_in sin; + int nonlocal = 1; + int port = IAX_DEFAULT_PORTNO; + int sockfd = defaultsockfd; + char *tmp; + char *portstr; + + tmp = ast_strdupa(srcaddr); + if (!tmp) { + ast_log(LOG_WARNING, "Out of memory!\n"); + return -1; + } + + + portstr = strchr(tmp, ':'); + if (portstr) { + int i; + + *portstr = '\0'; + portstr++; + i = atoi(portstr); + if (i > 0) + port = i; + } + + if (!ast_get_ip(&sin, tmp)) { + struct ast_netsock *sock; + int res; + + sin.sin_port = 0; + res = check_srcaddr((struct sockaddr*)&sin, sizeof(sin)); + if (res == 0) { + /* ip address valid. */ + sin.sin_port = htons(port); + sock = ast_netsock_find(&netsock, &sin); + if (sock) { + sockfd = ast_netsock_sockfd(sock); + nonlocal = 0; + } + } + } + + peer->sockfd = sockfd; + + if (nonlocal) { + ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", + srcaddr, peer->name); + return -1; + } else { + ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); + return 0; + } +} + + /*--- build_peer: Create peer structure based on configuration */ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, int temponly) { @@ -7942,6 +8030,8 @@ free(peer); return NULL; } + } else if (!strcasecmp(v->name, "sourceaddress")) { + peer_set_srcaddr(peer, v->value); } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { peer->ha = ast_append_ha(v->name, v->value, peer->ha); Index: include/asterisk/acl.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/acl.h,v retrieving revision 1.12 diff -u -r1.12 acl.h --- include/asterisk/acl.h 21 Apr 2005 06:02:44 -0000 1.12 +++ include/asterisk/acl.h 29 Jun 2005 21:47:39 -0000 @@ -49,6 +49,8 @@ extern struct ast_netsock *ast_netsock_bindaddr(struct ast_netsock_list *list, struct io_context *ioc, struct sockaddr_in *bindaddr, int tos, ast_io_cb callback, void *data); extern int ast_netsock_free(struct ast_netsock_list *list, struct ast_netsock *netsock); extern int ast_netsock_release(struct ast_netsock_list *list); +extern struct ast_netsock *ast_netsock_find(struct ast_netsock_list *list, + struct sockaddr_in *sa); extern int ast_netsock_sockfd(struct ast_netsock *ns); extern const struct sockaddr_in *ast_netsock_boundaddr(struct ast_netsock *ns); extern void *ast_netsock_data(struct ast_netsock *ns);