Index: acl.c =================================================================== RCS file: /usr/cvsroot/asterisk/acl.c,v retrieving revision 1.43 diff -u -r1.43 acl.c --- acl.c 4 May 2005 04:35:27 -0000 1.43 +++ acl.c 15 May 2005 22:09:11 -0000 @@ -368,6 +368,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.278 diff -u -r1.278 chan_iax2.c --- channels/chan_iax2.c 4 May 2005 04:49:32 -0000 1.278 +++ channels/chan_iax2.c 15 May 2005 22:09:14 -0000 @@ -7782,6 +7782,74 @@ } +/*--- 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, + int port) +{ + struct sockaddr_in sin; + int nonlocal = 1; + int sockfd = defaultsockfd; + + if (!ast_get_ip(&sin, srcaddr)) { + 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) { @@ -7790,6 +7858,8 @@ struct ast_ha *oldha = NULL; int maskfound=0; int found=0; + int portno = IAX_DEFAULT_PORTNO; + prev = NULL; ast_mutex_lock(&peerl.lock); if (!temponly) { @@ -7898,6 +7968,10 @@ free(peer); return NULL; } + } else if (!strcasecmp(v->name, "sourceport")){ + portno = atoi(v->value); + } else if (!strcasecmp(v->name, "sourceaddress")) { + peer_set_srcaddr(peer, v->value, portno); } 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 15 May 2005 22:09:15 -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);