address.c

Go to the documentation of this file.
00001 /*
00002  *
00003  * allow_address related functions
00004  *
00005  * Copyright (C) 2006 Juha Heinanen
00006  *
00007  * This file is part of Kamailio, a free SIP server.
00008  *
00009  * Kamailio is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * Kamailio is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License 
00020  * along with this program; if not, write to the Free Software 
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * History:
00024  * --------
00025  *  2006-09-01  Introduced allow_address function
00026  */
00027 
00028 #include <sys/types.h>
00029 #include <regex.h>
00030 #include <string.h>
00031 #include <arpa/inet.h>
00032 
00033 #include "permissions.h"
00034 #include "hash.h"
00035 #include "../../config.h"
00036 #include "../../db/db.h"
00037 #include "../../ip_addr.h"
00038 #include "../../mem/shm_mem.h"
00039 #include "../../parser/msg_parser.h"
00040 #include "../../parser/parse_from.h"
00041 #include "../../usr_avp.h"
00042 #include "../../mod_fix.h"
00043 #include "../../ut.h"
00044 #include "../../resolve.h"
00045 
00046 #define TABLE_VERSION 3
00047 
00048 struct addr_list ***addr_hash_table; /* Ptr to current hash table ptr */
00049 struct addr_list **addr_hash_table_1;     /* Pointer to hash table 1 */
00050 struct addr_list **addr_hash_table_2;     /* Pointer to hash table 2 */
00051 
00052 struct subnet **subnet_table;        /* Ptr to current subnet table */
00053 struct subnet *subnet_table_1;       /* Ptr to subnet table 1 */
00054 struct subnet *subnet_table_2;       /* Ptr to subnet table 2 */
00055 
00056 static db_con_t* db_handle = 0;
00057 static db_func_t perm_dbf;
00058 
00059 
00060 /*
00061  * Reload addr table to new hash table and when done, make new hash table
00062  * current one.
00063  */
00064 int reload_address_table(void)
00065 {
00066     db_key_t cols[4];
00067     db_res_t* res = NULL;
00068     db_row_t* row;
00069     db_val_t* val;
00070 
00071     struct addr_list **new_hash_table;
00072     struct subnet *new_subnet_table;
00073     int i;
00074     struct in_addr ip_addr;
00075 
00076     cols[0] = &grp_col;
00077     cols[1] = &ip_addr_col;
00078     cols[2] = &mask_col;
00079     cols[3] = &port_col;
00080 
00081     if (perm_dbf.use_table(db_handle, &address_table) < 0) {
00082        LM_ERR("failed to use table\n");
00083       return -1;
00084     }
00085 
00086     if (perm_dbf.query(db_handle, NULL, 0, NULL, cols, 0, 4, 0, &res) < 0) {
00087        LM_ERR("failed to query database\n");
00088       return -1;
00089     }
00090 
00091     /* Choose new hash table and free its old contents */
00092     if (*addr_hash_table == addr_hash_table_1) {
00093    empty_addr_hash_table(addr_hash_table_2);
00094    new_hash_table = addr_hash_table_2;
00095     } else {
00096    empty_addr_hash_table(addr_hash_table_1);
00097    new_hash_table = addr_hash_table_1;
00098     }
00099 
00100     /* Choose new subnet table */
00101     if (*subnet_table == subnet_table_1) {
00102    empty_subnet_table(subnet_table_2);
00103    new_subnet_table = subnet_table_2;
00104     } else {
00105    empty_subnet_table(subnet_table_1);
00106    new_subnet_table = subnet_table_1;
00107     }
00108 
00109     row = RES_ROWS(res);
00110 
00111     LM_DBG("Number of rows in address table: %d\n", RES_ROW_N(res));
00112       
00113     for (i = 0; i < RES_ROW_N(res); i++) {
00114    val = ROW_VALUES(row + i);
00115    if ((ROW_N(row + i) == 4) &&
00116        (VAL_TYPE(val) == DB_INT) && !VAL_NULL(val) &&
00117        (VAL_TYPE(val + 1) == DB_STRING) && !VAL_NULL(val + 1) &&
00118        inet_aton((char *)VAL_STRING(val + 1), &ip_addr) != 0 &&
00119        (VAL_TYPE(val + 2) == DB_INT) && !VAL_NULL(val + 2) && 
00120        ((unsigned int)VAL_INT(val + 2) > 0) && 
00121        ((unsigned int)VAL_INT(val + 2) <= 32) &&
00122        (VAL_TYPE(val + 3) == DB_INT) && !VAL_NULL(val + 3)) {
00123        if ((unsigned int)VAL_INT(val + 2) == 32) {
00124       if (addr_hash_table_insert(new_hash_table,
00125                   (unsigned int)VAL_INT(val),
00126                   (unsigned int)ip_addr.s_addr,
00127                   (unsigned int)VAL_INT(val + 3))
00128           == -1) {
00129           LM_ERR("hash table problem\n");
00130           perm_dbf.free_result(db_handle, res);
00131           return -1;
00132       }
00133       LM_DBG("Tuple <%u, %s, %u> inserted into address hash "
00134           "table\n", (unsigned int)VAL_INT(val),
00135           (char *)VAL_STRING(val + 1),
00136           (unsigned int)VAL_INT(val + 2));
00137        } else {
00138       if (subnet_table_insert(new_subnet_table,
00139                (unsigned int)VAL_INT(val),
00140                (unsigned int)ip_addr.s_addr,
00141                (unsigned int)VAL_INT(val + 2),
00142                (unsigned int)VAL_INT(val + 3))
00143           == -1) {
00144           LM_ERR("subnet table problem\n");
00145           perm_dbf.free_result(db_handle, res);
00146           return -1;
00147       }
00148       LM_DBG("Tuple <%u, %s, %u, %u> inserted into subnet "
00149           "table\n", (unsigned int)VAL_INT(val),
00150           (char *)VAL_STRING(val + 1),
00151           (unsigned int)VAL_INT(val + 2),
00152           (unsigned int)VAL_INT(val + 3));
00153        }
00154    } else {
00155        LM_ERR("database problem\n");
00156        perm_dbf.free_result(db_handle, res);
00157        return -1;
00158    }
00159     }
00160 
00161     perm_dbf.free_result(db_handle, res);
00162 
00163     *addr_hash_table = new_hash_table;
00164     *subnet_table = new_subnet_table;
00165 
00166     LM_DBG("address table reloaded successfully.\n");
00167    
00168     return 1;
00169 }
00170 
00171 
00172 /*
00173  * Initialize data structures
00174  */
00175 int init_addresses(void)
00176 {
00177     if (!db_url.s) {
00178    LM_INFO("db_url parameter of permissions module not set, "
00179        "disabling allow_address\n");
00180    return 0;
00181     } else {
00182    if (db_bind_mod(&db_url, &perm_dbf) < 0) {
00183        LM_ERR("load a database support module\n");
00184        return -1;
00185    }
00186 
00187    if (!DB_CAPABILITY(perm_dbf, DB_CAP_QUERY)) {
00188        LM_ERR("database module does not implement 'query' function\n");
00189        return -1;
00190    }
00191     }
00192 
00193     addr_hash_table_1 = addr_hash_table_2 = 0;
00194     addr_hash_table = 0;
00195    
00196     db_handle = perm_dbf.init(&db_url);
00197     if (!db_handle) {
00198       LM_ERR("unable to connect database\n");
00199       return -1;
00200     }
00201 
00202     if(db_check_table_version(&perm_dbf, db_handle, &address_table, TABLE_VERSION) < 0) {
00203       LM_ERR("error during table version check.\n");
00204       perm_dbf.close(db_handle);
00205       return -1;
00206     }
00207 
00208     addr_hash_table_1 = new_addr_hash_table();
00209     if (!addr_hash_table_1) return -1;
00210 
00211     addr_hash_table_2  = new_addr_hash_table();
00212     if (!addr_hash_table_2) goto error;
00213       
00214     addr_hash_table = (struct addr_list ***)shm_malloc
00215    (sizeof(struct addr_list **));
00216     if (!addr_hash_table) goto error;
00217 
00218     *addr_hash_table = addr_hash_table_1;
00219 
00220     subnet_table_1 = new_subnet_table();
00221     if (!subnet_table_1) goto error;
00222 
00223     subnet_table_2 = new_subnet_table();
00224     if (!subnet_table_2) goto error;
00225 
00226     subnet_table = (struct subnet **)shm_malloc(sizeof(struct subnet *));
00227     if (!subnet_table) goto error;
00228 
00229     *subnet_table = subnet_table_1;
00230 
00231     if (reload_address_table() == -1) {
00232    LM_CRIT("reload of address table failed\n");
00233    goto error;
00234     }
00235 
00236     perm_dbf.close(db_handle);
00237     db_handle = 0;
00238 
00239     return 0;
00240 
00241 error:
00242    LM_ERR("no more shm memory\n");
00243     if (addr_hash_table_1) {
00244    free_addr_hash_table(addr_hash_table_1);
00245    addr_hash_table_1 = 0;
00246     }
00247     if (addr_hash_table_2) {
00248    free_addr_hash_table(addr_hash_table_2);
00249    addr_hash_table_2 = 0;
00250     }
00251     if (addr_hash_table) {
00252    shm_free(addr_hash_table);
00253    addr_hash_table = 0;
00254     }
00255     if (subnet_table_1) {
00256    free_subnet_table(subnet_table_1);
00257    subnet_table_1 = 0;
00258     }
00259     if (subnet_table_2) {
00260    free_subnet_table(subnet_table_2);
00261    subnet_table_2 = 0;
00262     }
00263     if (subnet_table) {
00264    shm_free(subnet_table);
00265    subnet_table = 0;
00266     }
00267     perm_dbf.close(db_handle);
00268     db_handle = 0;
00269     return -1;
00270 }
00271 
00272 
00273 
00274 /*
00275  * Open database connection if necessary
00276  */
00277 int mi_init_addresses(void)
00278 {
00279     if (!db_url.s || db_handle) return 0;
00280     db_handle = perm_dbf.init(&db_url);
00281     if (!db_handle) {
00282    LM_ERR("unable to connect database\n");
00283    return -1;
00284     }
00285     return 0;
00286 }
00287 
00288 
00289 /*
00290  * Close connections and release memory
00291  */
00292 void clean_addresses(void)
00293 {
00294     if (addr_hash_table_1) free_addr_hash_table(addr_hash_table_1);
00295     if (addr_hash_table_2) free_addr_hash_table(addr_hash_table_2);
00296     if (addr_hash_table) shm_free(addr_hash_table);
00297     if (subnet_table_1) free_subnet_table(subnet_table_1);
00298     if (subnet_table_2) free_subnet_table(subnet_table_2);
00299     if (subnet_table) shm_free(subnet_table);
00300 }
00301 
00302 
00303 /*
00304  * Checks if an entry exists in cached address table that belongs to a
00305  * given address group and has given ip address and port.  Port value
00306  * 0 in cached address table matches any port.
00307  */
00308 int allow_address(struct sip_msg* _msg, char* _addr_group, char* _addr_sp,
00309         char* _port_sp)
00310 {
00311     pv_spec_t *addr_sp, *port_sp;
00312     pv_value_t pv_val;
00313 
00314     unsigned int addr, port;
00315     int addr_group;
00316     struct ip_addr *ip;
00317 
00318     addr_sp = (pv_spec_t *)_addr_sp;
00319     port_sp = (pv_spec_t *)_port_sp;
00320 
00321     if(fixup_get_ivalue(_msg, (gparam_p)_addr_group, &addr_group) !=0 ) {
00322    LM_ERR("cannot get group value\n");
00323    return -1;
00324     }
00325 
00326    if (addr_sp && (pv_get_spec_value(_msg, addr_sp, &pv_val) == 0)) {
00327       if (pv_val.flags & PV_VAL_INT) {
00328          addr = pv_val.ri;
00329       } else if (pv_val.flags & PV_VAL_STR) {
00330          if ( (ip=str2ip( &pv_val.rs)) == NULL) {
00331             LM_ERR("failed to convert IP address string to in_addr\n");
00332             return -1;
00333          } else {
00334             addr = ip->u.addr32[0];
00335          }
00336       } else {
00337          LM_ERR("IP address PV empty value\n");
00338          return -1;
00339       }
00340    } else {
00341       LM_ERR("cannot get value of address pvar\n");
00342          return -1;
00343    }
00344 
00345     if (port_sp && (pv_get_spec_value(_msg, port_sp, &pv_val) == 0)) {
00346    if (pv_val.flags & PV_VAL_INT) {
00347        port = pv_val.ri;
00348    } else if (pv_val.flags & PV_VAL_STR) {
00349        if (str2int(&(pv_val.rs), &port) == -1) {
00350       LM_ERR("failed to convert port string to int\n");
00351       return -1;
00352        }
00353    } else {
00354        LM_ERR("failed to convert port string to int\n");
00355        return -1;
00356    }
00357     } else {
00358    LM_ERR("cannot get value of port pvar\n");
00359    return -1;
00360     }
00361 
00362     if (match_addr_hash_table(*addr_hash_table, addr_group, addr, port) == 1)
00363    return 1;
00364     else
00365    return match_subnet_table(*subnet_table, addr_group, addr, port);
00366 }
00367 
00368 
00369 /*
00370  * allow_source_address("group") equals to allow_address("group", "$si", "$sp")
00371  * but is faster.
00372  */
00373 int allow_source_address(struct sip_msg* _msg, char* _addr_group, char* _str2) 
00374 {
00375     int addr_group = 0;
00376 
00377     if(fixup_get_ivalue(_msg, (gparam_p)_addr_group, &addr_group) !=0 ) {
00378    LM_ERR("cannot get group value\n");
00379    return -1;
00380     }
00381 
00382     LM_DBG("looking for <%u, %x, %u>\n",
00383    addr_group, _msg->rcv.src_ip.u.addr32[0], _msg->rcv.src_port);
00384 
00385     if (match_addr_hash_table(*addr_hash_table, addr_group,
00386                _msg->rcv.src_ip.u.addr32[0],
00387                _msg->rcv.src_port) == 1)
00388    return 1;
00389     else
00390    return match_subnet_table(*subnet_table, addr_group,
00391               _msg->rcv.src_ip.u.addr32[0],
00392               _msg->rcv.src_port);
00393 }
00394 
00395 
00396 /*
00397  * Checks if source address/port is found in cached address or
00398  * subnet table in any group. If yes, returns that group. If not returns -1.
00399  * Port value 0 in cached address and group table matches any port.
00400  */
00401 int allow_source_address_group(struct sip_msg* _msg, char* _str1, char* _str2) 
00402 {
00403     int group;
00404 
00405     LM_DBG("looking for <%x, %u> in address table\n",
00406       _msg->rcv.src_ip.u.addr32[0], _msg->rcv.src_port);
00407     group = find_group_in_addr_hash_table(*addr_hash_table,
00408                  _msg->rcv.src_ip.u.addr32[0],
00409                  _msg->rcv.src_port);
00410     LM_DBG("Found <%d>\n", group);
00411 
00412     if (group != -1) return group;
00413 
00414     LM_DBG("looking for <%x, %u> in subnet table\n",
00415       _msg->rcv.src_ip.u.addr32[0], _msg->rcv.src_port);
00416     group = find_group_in_subnet_table(*subnet_table,
00417                    _msg->rcv.src_ip.u.addr32[0],
00418                   _msg->rcv.src_port);
00419     LM_DBG("Found <%d>\n", group);
00420     return group;
00421     
00422 }

Generated on Thu May 17 12:00:24 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6