aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authordvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-09-04 19:51:22 +0000
committerdvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-09-04 19:51:22 +0000
commitf84257d3e57e02cdf3cebee89c1fd8415a201335 (patch)
tree0748d571ace36689c83daa7538135db7df96c0b3 /channels
parent0a895788d85c56b5a23aa2be6297849b06f2bc67 (diff)
Merged revisions 216594 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r216594 | dvossel | 2009-09-04 14:32:07 -0500 (Fri, 04 Sep 2009) | 7 lines sip peer matching by address only with TCP/TLS This patch removes the contact header matching logic and adds logic to match all tcp/tls connections by ip only Review: https://reviewboard.asterisk.org/r/354/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.1@216599 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c84
1 files changed, 34 insertions, 50 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 418336d19..9d81ead2f 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1682,7 +1682,7 @@ static int peer_cmp_cb(void *obj, void *arg, int flags)
}
/*!
- * \note the peer's addr struct provides to fields combined to make a key: the sin_addr.s_addr and sin_port fields.
+ * \note the peer's ip address field is used to create key.
*/
static int peer_iphash_cb(const void *obj, const int flags)
{
@@ -1690,12 +1690,8 @@ static int peer_iphash_cb(const void *obj, const int flags)
int ret1 = peer->addr.sin_addr.s_addr;
if (ret1 < 0)
ret1 = -ret1;
-
- if (ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT)) {
- return ret1;
- } else {
- return ret1 + peer->addr.sin_port;
- }
+
+ return ret1;
}
/*!
@@ -1712,6 +1708,8 @@ static int peer_iphash_cb(const void *obj, const int flags)
* pass for full IP+port matching, and a second pass in case there is a match
* that meets the insecure=port criteria.
*
+ * \note Connections coming in over TCP or TLS should never be matched by port.
+ *
* \note the peer's addr struct provides to fields combined to make a key: the sin_addr.s_addr and sin_port fields.
*/
static int peer_ipcmp_cb(void *obj, void *arg, int flags)
@@ -1723,17 +1721,18 @@ static int peer_ipcmp_cb(void *obj, void *arg, int flags)
return 0;
}
- /* We matched the IP, now check the port if appropriate. */
-
- if (ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT)) {
+ /* We matched the IP, check to see if we need to match by port as well. */
+ if ((peer->transports & peer2->transports) & (SIP_TRANSPORT_TLS | SIP_TRANSPORT_TCP)) {
+ /* peer matching on port is not possible with TCP/TLS */
+ return CMP_MATCH | CMP_STOP;
+ } else if (ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT)) {
/* We are allowing match without port for peers configured that
* way in this pass through the peers. */
return ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT) ?
(CMP_MATCH | CMP_STOP) : 0;
}
- /* Only return a match if the port matches, as well. */
-
+ /* Now only return a match if the port matches, as well. */
return peer->addr.sin_port == peer2->addr.sin_port ? (CMP_MATCH | CMP_STOP) : 0;
}
@@ -2111,7 +2110,7 @@ static void sip_destroy_peer_fn(void *peer);
static void set_peer_defaults(struct sip_peer *peer);
static struct sip_peer *temp_peer(const char *name);
static void register_peer_exten(struct sip_peer *peer, int onoff);
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only);
+static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only, int transport);
static int sip_poke_peer_s(const void *data);
static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req);
static void reg_source_db(struct sip_peer *peer);
@@ -4345,7 +4344,7 @@ static int find_by_name(void *obj, void *arg, int flags)
* \note Avoid using this function in new functions if there is a way to avoid it,
* since it might cause a database lookup.
*/
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only)
+static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only, int transport)
{
struct sip_peer *p = NULL;
@@ -4360,6 +4359,7 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int
tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr;
tmp_peer.addr.sin_port = sin->sin_port;
tmp_peer.flags[0].flags = 0;
+ tmp_peer.transports = transport;
p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
if (!p) {
ast_set_flag(&tmp_peer.flags[0], SIP_INSECURE_PORT);
@@ -4627,7 +4627,7 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct sockadd
dialog->sa.sin_family = AF_INET;
dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */
dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
- peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE);
+ peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0);
if (peer) {
int res;
@@ -4978,7 +4978,7 @@ static int update_call_counter(struct sip_pvt *fup, int event)
ast_copy_string(name, fup->username, sizeof(name));
/* Check the list of devices */
- if ( (p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, TRUE, FINDALLDEVICES, FALSE) ) ) { /* Try to find peer */
+ if ((p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, TRUE, FINDALLDEVICES, FALSE, 0))) { /* Try to find peer */
inuse = &p->inUse;
call_limit = &p->call_limit;
inringing = &p->inRinging;
@@ -10336,7 +10336,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
if (r->dnsmgr == NULL) {
char transport[MAXHOSTNAMELEN];
- peer = find_peer(r->hostname, NULL, TRUE, FINDPEERS, FALSE);
+ peer = find_peer(r->hostname, NULL, TRUE, FINDPEERS, FALSE, 0);
snprintf(transport, sizeof(transport), "_sip._%s", get_transport(r->transport)); /* have to use static get_transport function */
ast_dnsmgr_lookup(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, global_srvlookup ? transport : NULL);
if (peer) {
@@ -10371,7 +10371,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname);
if (!ast_strlen_zero(r->peername)) {
- if (!(peer = find_peer(r->peername, NULL, 1, FINDPEERS, FALSE))) {
+ if (!(peer = find_peer(r->peername, NULL, 1, FINDPEERS, FALSE, 0))) {
ast_log(LOG_WARNING, "Could not find peer %s in transmit_register\n", r->peername);
}
}
@@ -11477,7 +11477,7 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request *
/*! \brief Change onhold state of a peer using a pvt structure */
static void sip_peer_hold(struct sip_pvt *p, int hold)
{
- struct sip_peer *peer = find_peer(p->peername, NULL, 1, FINDALLDEVICES, FALSE);
+ struct sip_peer *peer = find_peer(p->peername, NULL, 1, FINDALLDEVICES, FALSE, 0);
if (!peer)
return;
@@ -11712,7 +11712,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
ast_string_field_set(p, exten, name);
build_contact(p);
- peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE);
+ peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE, 0);
if (!(peer && ast_apply_ha(peer->ha, sin))) {
/* Peer fails ACL check */
if (peer) {
@@ -12630,30 +12630,14 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
/* For subscribes, match on device name only; for other methods,
* match on IP address-port of the incoming request.
*/
- peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE);
+ peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE, 0);
} else {
/* First find devices based on username (avoid all type=peer's) */
- peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE);
+ peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE, 0);
/* Then find devices based on IP */
if (!peer) {
- peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE);
- }
-
- /* If the peer is still not found, try the address and port from the
- * contact header. If the transport type is TCP or TLS it is not possible
- * to find the peer using p->recv. Because of the way TCP works, the received
- * packet's destination port will not match the one the peer table is
- * built with. */
- if (!peer && (p->socket.type != SIP_TRANSPORT_UDP)) {
- struct sockaddr_in tmpsin;
- char contact[SIPBUFSIZE];
- char *tmp;
- memcpy(&tmpsin, &p->recv, sizeof(tmpsin));
- ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
- tmp = get_in_brackets(contact);
- __set_address_from_contact(tmp, &tmpsin, 1);
- peer = find_peer(NULL, &tmpsin, TRUE, FINDPEERS, FALSE);
+ peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type);
}
}
@@ -13982,7 +13966,7 @@ static char *_sip_qualify_peer(int type, int fd, struct mansession *s, const str
return CLI_SHOWUSAGE;
load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
- if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE))) {
+ if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0))) {
sip_poke_peer(peer, 1);
unref_peer(peer, "qualify: done with peer");
} else if (type == 0) {
@@ -14064,7 +14048,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
return CLI_SHOWUSAGE;
load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
- peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE);
+ peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0);
if (s) { /* Manager */
if (peer) {
@@ -14342,7 +14326,7 @@ static char *sip_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args
/* Load from realtime storage? */
load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? TRUE : FALSE;
- if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE))) {
+ if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE, 0))) {
ao2_lock(user);
ast_cli(a->fd, "\n\n");
ast_cli(a->fd, " * Name : %s\n", user->name);
@@ -14501,7 +14485,7 @@ static char *sip_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
if (a->argc != 3)
return CLI_SHOWUSAGE;
- if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE))) {
+ if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE, 0))) {
if (peer->expire > 0) {
AST_SCHED_DEL_UNREF(sched, peer->expire,
unref_peer(peer, "remove register expire ref"));
@@ -15473,7 +15457,7 @@ static char *sip_do_debug_ip(int fd, char *arg)
/*! \brief Turn on SIP debugging for a given peer */
static char *sip_do_debug_peer(int fd, char *arg)
{
- struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE);
+ struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE, 0);
if (!peer)
ast_cli(fd, "No such peer '%s'\n", arg);
else if (peer->addr.sin_addr.s_addr == 0)
@@ -15969,7 +15953,7 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat
else
colname = "ip";
- if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE)))
+ if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE, 0)))
return -1;
if (!strcasecmp(colname, "ip")) {
@@ -21181,7 +21165,7 @@ int st_get_se(struct sip_pvt *p, int max)
if (p->stimer->st_cached_max_se) {
return p->stimer->st_cached_max_se;
} else if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0);
if (pp) {
p->stimer->st_cached_max_se = pp->stimer.st_max_se;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_se");
@@ -21194,7 +21178,7 @@ int st_get_se(struct sip_pvt *p, int max)
if (p->stimer->st_cached_min_se) {
return p->stimer->st_cached_min_se;
} else if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0);
if (pp) {
p->stimer->st_cached_min_se = pp->stimer.st_min_se;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_se (2)");
@@ -21216,7 +21200,7 @@ enum st_refresher st_get_refresher(struct sip_pvt *p)
return p->stimer->st_cached_ref;
if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0);
if (pp) {
p->stimer->st_cached_ref = pp->stimer.st_ref;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_refresher");
@@ -21241,7 +21225,7 @@ enum st_mode st_get_mode(struct sip_pvt *p)
return p->stimer->st_cached_mode;
if (p->peername) {
- struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
+ struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0);
if (pp) {
p->stimer->st_cached_mode = pp->stimer.st_mode_oper;
unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode");
@@ -21432,7 +21416,7 @@ static int sip_devicestate(void *data)
* load it BACK into memory, thus defeating the point of trying to clear dead
* hosts out of memory.
*/
- if ((p = find_peer(host, NULL, FALSE, FINDALLDEVICES, TRUE))) {
+ if ((p = find_peer(host, NULL, FALSE, FINDALLDEVICES, TRUE, 0))) {
if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) {
/* we have an address for the peer */