]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
swatting at NAT
authorAnthony Minessale <anthony.minessale@gmail.com>
Wed, 21 May 2008 21:49:27 +0000 (21:49 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Wed, 21 May 2008 21:49:27 +0000 (21:49 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8511 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_presence.c
src/mod/endpoints/mod_sofia/sofia_reg.c

index df413013dc5513041fb01bbe905edcfdf3c4207a..de06c17c9ceb89d10ee58f0607618a70ef008bcb 100644 (file)
@@ -556,7 +556,7 @@ int sofia_glue_get_user_host(char *in, char **user, char **host);
 switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status);
 void sofia_glue_do_xfer_invite(switch_core_session_t *session);
 uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip, 
-                                                                 sofia_regtype_t regtype, char *key, uint32_t keylen, switch_event_t **v_event);
+                                                                 sofia_regtype_t regtype, char *key, uint32_t keylen, switch_event_t **v_event, const char *is_nat);
 extern switch_endpoint_interface_t *sofia_endpoint_interface;
 void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip);
 switch_status_t sofia_on_hangup(switch_core_session_t *session);
index f5b7359906ef5fccf7e984945aef29fc11ad6f81..9c1655f8fa75bac9746cb2c06252437876318550 100644 (file)
@@ -2670,7 +2670,9 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
                        const char *port = sip->sip_via->v_port;
                        const char *host = sip->sip_via->v_host;
                        
-                       if (host && strcmp(network_ip, host)) {
+                       if (host && sip->sip_via->v_received) {
+                               is_nat = "via received";
+                       } else if (host && strcmp(network_ip, host)) {
                                is_nat = "via host";
                        } else if (port && atoi(port) != network_port) {
                                is_nat = "via port";
@@ -2737,7 +2739,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
                if (!strcmp(network_ip, profile->sipip) && network_port == profile->sip_port) {
                        calling_myself++;
                } else {
-                       if (sofia_reg_handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key), &v_event)) {
+                       if (sofia_reg_handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key), &v_event, NULL)) {
                                if (v_event) {
                                        switch_event_destroy(&v_event);
                                }
index d414ded6d83a2e9cbb8a26732b24464af73776a9..8c5727ef3d0340abdf2773e30277e31cf25695dc 100644 (file)
@@ -1136,7 +1136,7 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char
        char *sub_to_user = argv[0];
        char *sub_to_host = argv[1];
        char *event = "message-summary";
-       char *contact = argv[2];
+       char *contact, *o_contact = argv[2];
        char *body = argv[3];
        char *id = NULL;
        nua_handle_t *nh;
@@ -1145,7 +1145,7 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char
        
        id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
 
-       contact = sofia_glue_get_url_from_contact(contact, 0);
+       contact = sofia_glue_get_url_from_contact(o_contact, 1);
        
        nh = nua_handle(h->profile->nua, NULL,
                                        NUTAG_URL(contact),
@@ -1156,8 +1156,10 @@ static int sofia_presence_mwi_callback2(void *pArg, int argc, char **argv, char
        
        nua_notify(nh,
                           NUTAG_NEWSUB(1),
+                          TAG_IF(strstr(o_contact, ";nat"), NUTAG_PROXY(contact)),
                           SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), SIPTAG_PAYLOAD_STR(body), TAG_END());
-
+       
+       switch_safe_free(contact);
        switch_safe_free(id);
        
        return 0;
@@ -1189,40 +1191,97 @@ void sofia_presence_handle_sip_i_subscribe(int status,
                switch_event_t *sevent;
                int sub_state;
                int sent_reply = 0;
+               su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
+               int network_port = 0;
+               char network_ip[80];
+               const char *contact_host, *contact_user;
+               char *port;
+               char new_port[25] = "";
+               char *is_nat = NULL;
+
+               if (!(contact && sip->sip_contact->m_url)) {
+                       nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END());
+                       return;
+               }
+
+               get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
+               network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
 
                tl_gets(tags,
                                NUTAG_SUBSTATE_REF(sub_state), TAG_END());
 
                event = sip_header_as_string(profile->home, (void *) sip->sip_event);
 
-               if (contact) {
-                       char *port = (char *) contact->m_url->url_port;
-                       char new_port[25] = "";
-
-                       display = contact->m_display;
+               port = (char *) contact->m_url->url_port;
+               contact_host = sip->sip_contact->m_url->url_host;
+               contact_user = sip->sip_contact->m_url->url_user;
+                       
+               display = contact->m_display;
 
-                       if (switch_strlen_zero(display)) {
-                               if (from) {
-                                       display = from->a_display;
-                                       if (switch_strlen_zero(display)) {
-                                               display = "\"user\"";
-                                       }
+               if (switch_strlen_zero(display)) {
+                       if (from) {
+                               display = from->a_display;
+                               if (switch_strlen_zero(display)) {
+                                       display = "\"user\"";
                                }
-                       } else {
-                               display = "\"user\"";
                        }
-
-                       if (port) {
-                               switch_snprintf(new_port, sizeof(new_port), ":%s", port);
+               } else {
+                       display = "\"user\"";
+               }
+                       
+               if ((profile->pflags & PFLAG_AGGRESSIVE_NAT_DETECTION)) {
+                       if (sip && sip->sip_via) {
+                               const char *port = sip->sip_via->v_port;
+                               const char *host = sip->sip_via->v_host;
+                                       
+                               if (host && sip->sip_via->v_received) {
+                                       is_nat = "via received";
+                               } else if (host && strcmp(network_ip, host)) {
+                                       is_nat = "via host";
+                               } else if (port && atoi(port) != network_port) {
+                                       is_nat = "via port";
+                               }
                        }
+               }
                        
-                       if (contact->m_url->url_params) {
-                               contact_str = switch_mprintf("%s <sip:%s@%s%s;%s>",
-                                                                                        display, contact->m_url->url_user, contact->m_url->url_host, new_port, contact->m_url->url_params);
-                       } else {
-                               contact_str = switch_mprintf("%s <sip:%s@%s%s>", display, contact->m_url->url_user, contact->m_url->url_host, new_port);
+               if (!is_nat && profile->nat_acl_count) {
+                       uint32_t x = 0;
+                       int ok = 1;
+                       char *last_acl = NULL;
+                               
+                       if (!switch_strlen_zero(contact_host)) {
+                               for (x = 0 ; x < profile->nat_acl_count; x++) {
+                                       last_acl = profile->nat_acl[x];
+                                       if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
+                                               break;
+                                       }
+                               }
+                                       
+                               if (ok) {
+                                       is_nat = last_acl;
+                               }
                        }
                }
+                       
+                       
+               if (is_nat) {
+                       contact_host = network_ip;
+                       switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
+                       port = NULL;
+               }
+
+
+               if (port) {
+                       switch_snprintf(new_port, sizeof(new_port), ":%s", port);
+               }
+                       
+               if (contact->m_url->url_params) {
+                       contact_str = switch_mprintf("%s <sip:%s@%s%s;%s>%s",
+                                                                                display, contact->m_url->url_user, contact_host, new_port, contact->m_url->url_params, is_nat ? ";nat" : "");
+               } else {
+                       contact_str = switch_mprintf("%s <sip:%s@%s%s>%s", display, contact->m_url->url_user, contact_host, new_port, is_nat ? ";nat" : "");
+               }
+               
 
                if (to) {
                        to_str = switch_mprintf("sip:%s@%s", to->a_url->url_user, to->a_url->url_host); //, to->a_url->url_port);
@@ -1336,14 +1395,25 @@ void sofia_presence_handle_sip_i_subscribe(int status,
        
                switch_mutex_unlock(profile->ireg_mutex);
 
+
                if (status < 200) {
-                       nua_respond(nh, SIP_202_ACCEPTED,
+                       char *sticky = NULL;
+                       
+                       if (is_nat) {
+                               sticky = switch_mprintf("sip:%s@%s:%d", contact_user, network_ip, network_port);
+                       }
+
+                       nua_respond(nh, SIP_202_ACCEPTED,                                               
                                                NUTAG_WITH_THIS(nua),
                                                SIPTAG_SUBSCRIPTION_STATE_STR(sstr), 
+                                               TAG_IF(sticky, NUTAG_PROXY(sticky)),
                                                //SIPTAG_FROM(sip->sip_to),
                                                //SIPTAG_TO(sip->sip_from),
                                                //SIPTAG_CONTACT_STR(contact_str),
                                                TAG_END());
+
+                       switch_safe_free(sticky);
+
                }
                
                sent_reply++;
index cf38438fda38d1cdcca0e7ad77f7e83a7236a184..1db26a16d0eff9f43dd879983bc900f463af960c 100644 (file)
@@ -333,7 +333,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now)
        
 
        if (now) {
-               switch_snprintf(sql, sizeof(sql), "select * from sip_registrations where status like '%%NATHACK%%'");
+               switch_snprintf(sql, sizeof(sql), "select * from sip_registrations where status like '%%AUTO-NAT%%'");
                sofia_glue_execute_sql_callback(profile,
                                                                                SWITCH_TRUE,
                                                                                NULL,
@@ -414,7 +414,7 @@ void sofia_reg_auth_challange(nua_t *nua, sofia_profile_t *profile, nua_handle_t
 }
 
 uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, sip_t const *sip, sofia_regtype_t regtype, char *key,
-                                                                 uint32_t keylen, switch_event_t **v_event)
+                                                                 uint32_t keylen, switch_event_t **v_event, const char *is_nat)
 {
        sip_to_t const *to = NULL;
        sip_expires_t const *expires = NULL;
@@ -466,7 +466,15 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han
                const char *port = contact->m_url->url_port;
                char new_port[25] = "";
                display = contact->m_display;
-
+               const char *contact_host = contact->m_url->url_host;
+               
+               if (is_nat) {
+                       reg_desc = "Registered(AUTO-NAT)";
+                       contact_host = network_ip;
+                       switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
+                       port = NULL;
+               }
+               
                if (switch_strlen_zero(display)) {
                        if (to) {
                                display = to->a_display;
@@ -481,10 +489,10 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han
                }
 
                if (contact->m_url->url_params) {
-                       switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s%s;%s>",
-                                                       display, contact->m_url->url_user, contact->m_url->url_host, new_port, contact->m_url->url_params);
+                       switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s%s;%s>%s",
+                                                       display, contact->m_url->url_user, contact_host, new_port, contact->m_url->url_params, is_nat ? ";nat" : "");
                } else {
-                       switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s%s>", display, contact->m_url->url_user, contact->m_url->url_host, new_port);
+                       switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s%s>%s", display, contact->m_url->url_user, contact_host, new_port, is_nat ? ";nat" : "");
                }
        }
 
@@ -537,7 +545,7 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han
                                        if (strstr(v_contact_str, "tls")) {
                                                reg_desc = "Registered(TLSHACK)";
                                        } else {
-                                               reg_desc = "Registered(NATHACK)";
+                                               reg_desc = "Registered(AUTO-NAT)";
                                                exptime = 20;
                                        }
                                        nat_hack = 1;
@@ -609,8 +617,6 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_han
                sql = switch_mprintf("insert into sip_registrations values ('%q', '%q','%q','%q','%q', '%q', %ld, '%q')", call_id,
                                                         to_user, to_host, contact_str, reg_desc,
                                                         rpid, (long) switch_timestamp(NULL) + (long) exptime * 2, agent);
-
-               
                if (sql) {
                        sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
                }
@@ -747,6 +753,7 @@ void sofia_reg_handle_sip_i_register(nua_t * nua, sofia_profile_t *profile, nua_
        su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
        sofia_regtype_t type = REG_REGISTER;
        int network_port = 0;
+       char *is_nat = NULL;
 
        get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
        network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
@@ -765,6 +772,45 @@ void sofia_reg_handle_sip_i_register(nua_t * nua, sofia_profile_t *profile, nua_
                goto end;
        }
 
+       if ((profile->pflags & PFLAG_AGGRESSIVE_NAT_DETECTION)) {
+               if (sip && sip->sip_via) {
+                       const char *port = sip->sip_via->v_port;
+                       const char *host = sip->sip_via->v_host;
+                       
+                       if (host && sip->sip_via->v_received) {
+                               is_nat = "via received";
+                       } else if (host && strcmp(network_ip, host)) {
+                               is_nat = "via host";
+                       } else if (port && atoi(port) != network_port) {
+                               is_nat = "via port";
+                       }
+               }
+       }
+
+       if (!is_nat && profile->nat_acl_count) {
+               uint32_t x = 0;
+               int ok = 1;
+               char *last_acl = NULL;
+               const char *contact_host = NULL;
+
+               if (sip && sip->sip_contact && sip->sip_contact->m_url) {
+                       contact_host = sip->sip_contact->m_url->url_host;
+               }
+
+               if (!switch_strlen_zero(contact_host)) {
+                       for (x = 0 ; x < profile->nat_acl_count; x++) {
+                               last_acl = profile->nat_acl[x];
+                               if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
+                                       break;
+                               }
+                       }
+                       
+                       if (ok) {
+                               is_nat = last_acl;
+                       }
+               }
+       }
+
        if (profile->reg_acl_count) {
                uint32_t x = 0;
                int ok = 1;
@@ -796,7 +842,7 @@ void sofia_reg_handle_sip_i_register(nua_t * nua, sofia_profile_t *profile, nua_
                goto end;
        }
 
-       sofia_reg_handle_register(nua, profile, nh, sip, type, key, sizeof(key), &v_event);
+       sofia_reg_handle_register(nua, profile, nh, sip, type, key, sizeof(key), &v_event, is_nat);
 
        if (v_event) {
                switch_event_fire(&v_event);