"Fossies" - the Fresh Open Source Software Archive

Member "opensips-3.0.1/modules/permissions/hash.c" (29 May 2019, 14497 Bytes) of package /linux/misc/opensips-3.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "hash.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.4.5_vs_3.0.0.

    1 /*
    2  * Hash table functions
    3  *
    4  * Copyright (C) 2009 Irina Stanescu
    5  * Copyright (C) 2009 Voice System
    6  *
    7  * This file is part of opensips, a free SIP server.
    8  *
    9  * opensips is free software; you can redistribute it and/or modify
   10  * it under the terms of the GNU General Public License as published by
   11  * the Free Software Foundation; either version 2 of the License, or
   12  * (at your option) any later version
   13  *
   14  * opensips is distributed in the hope that it will be useful,
   15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  * GNU General Public License for more details.
   18  *
   19  * You should have received a copy of the GNU General Public License
   20  * along with this program; if not, write to the Free Software
   21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
   22  */
   23 
   24 
   25 #include "hash.h"
   26 #include "../../mem/shm_mem.h"
   27 #include "../../hash_func.h"
   28 #include "../../ip_addr.h"
   29 #include "../../ut.h"
   30 #include "../../pvar.h"
   31 #include "../../route_struct.h"
   32 #include "../../resolve.h"
   33 #include "../../socket_info.h"
   34 #include <netinet/in.h>
   35 #include <arpa/inet.h>
   36 #include <fnmatch.h>
   37 //#include <regex.h>
   38 
   39 #define perm_hash(_s)  core_hash( &(_s), 0, PERM_HASH_SIZE)
   40 
   41 struct address_list** hash_create(void) {
   42     struct address_list** ptr;
   43 
   44     /* Initializing hash tables and hash table variable */
   45     ptr = (struct address_list **)shm_malloc
   46         (sizeof(struct address_list*) * PERM_HASH_SIZE);
   47     if (!ptr) {
   48         LM_ERR("no shm memory for hash table\n");
   49         return 0;
   50     }
   51 
   52     memset(ptr, 0, sizeof(struct address_list*) * PERM_HASH_SIZE);
   53     return ptr;
   54 }
   55 
   56 
   57 void hash_destroy(struct address_list** table) {
   58     if (!table) {
   59         LM_ERR("trying to destroy an empty hash table\n");
   60         return;
   61     }
   62     empty_hash(table);
   63     shm_free(table);
   64 }
   65 
   66 int hash_insert(struct address_list** table, struct ip_addr *ip,
   67           unsigned int grp, unsigned int port, int proto, str* pattern,
   68           str* info) {
   69 
   70     struct address_list *node;
   71     unsigned int hash_val;
   72     str str_ip;
   73 
   74     node = (struct address_list*) shm_malloc (sizeof(struct address_list));
   75     if (!node) {
   76         LM_ERR("no shm memory left\n");
   77         return -1;
   78     }
   79 
   80     node->proto = proto;
   81     node->ip = (struct ip_addr *) shm_malloc (sizeof(struct ip_addr));
   82 
   83     if (!node->ip) {
   84         LM_ERR("cannot allocate shm memory for ip_addr struct\n");
   85         shm_free(node);
   86         return -1;
   87     }
   88 
   89     memcpy(node->ip, ip, sizeof(struct ip_addr));
   90 
   91     if (pattern->len) {
   92         node->pattern = (char *) shm_malloc(pattern->len + 1);
   93         if (!node->pattern) {
   94             LM_ERR("cannot allocate shm memory for pattern string\n");
   95             shm_free(node->ip);
   96             shm_free(node);
   97             return -1;
   98         }
   99         memcpy(node->pattern, pattern->s, pattern->len);
  100         node->pattern[pattern->len] = 0;
  101     } else {
  102         node->pattern = NULL;
  103     }
  104 
  105     if (info->len) {
  106         node->info = (char *) shm_malloc(info->len + 1);
  107         if (!node->info) {
  108             LM_CRIT("cannot allocate shm memory for context info string\n");
  109             shm_free(node->ip);
  110             if (node->pattern) shm_free(node->pattern);
  111             shm_free(node);
  112             return -1;
  113         }
  114         memcpy(node->info, info->s, info->len);
  115         node->info[info->len] = '\0';
  116     } else {
  117         node->info = NULL;
  118     }
  119 
  120     node->grp = grp;
  121     node->port = port;
  122 
  123     str_ip.len = ip->len;
  124     str_ip.s = (char*)ip->u.addr;
  125 
  126     hash_val = perm_hash(str_ip);
  127 
  128     node->next = table[hash_val];
  129     table[hash_val] = node;
  130 
  131     return 1;
  132 }
  133 
  134 
  135 int hash_match(struct sip_msg *msg, struct address_list** table,
  136         unsigned int grp, struct ip_addr *ip, unsigned int port, int proto,
  137         char *pattern, pv_spec_t *info) {
  138 
  139     struct address_list *node;
  140     str str_ip;
  141     pv_value_t pvt;
  142     int i, match_res;
  143 
  144     if (grp != GROUP_ANY) {
  145         for (i = 0; i < PERM_HASH_SIZE; i++) {
  146             for (node = table[i]; node; node = node->next) {
  147                 if (node->grp == grp) {
  148                     goto grp_found;
  149                 }
  150             }
  151         }
  152 
  153         /* group not found */
  154         if (!node) {
  155             LM_DBG("specified group %u does not exist in hash table\n", grp);
  156             return -2;
  157         }
  158     }
  159 
  160 grp_found:
  161 
  162     str_ip.len = ip->len;
  163     str_ip.s = (char*)ip->u.addr;
  164 
  165     for (node = table[perm_hash(str_ip)]; node; node = node->next) {
  166 /*          LM_DBG("Comparing (%s %s) , (%d %d) , (%d %d) , (%d %d)\n",
  167                 ip_addr2a(node->ip), ip_addr2a(ip),
  168                 node->proto, proto,
  169                 node->port , port,
  170                 node->grp , grp);
  171 */
  172 
  173         if  ((node->grp == GROUP_ANY || node->grp == grp
  174                     || grp == GROUP_ANY) &&
  175             (node->proto == PROTO_NONE || node->proto == proto
  176                     || proto == PROTO_NONE ) &&
  177             (node->port == PORT_ANY || node->port == port
  178                     || port == PORT_ANY) &&
  179             ip_addr_cmp(ip, node->ip)) {
  180                 if (!node->pattern || !pattern) {
  181                     LM_DBG("no pattern to match\n");
  182                     goto found;
  183                 }
  184 
  185                 match_res = fnmatch(node->pattern, pattern, FNM_PERIOD);
  186                 if (!match_res) {
  187                     LM_DBG("pattern match\n");
  188                     goto found;
  189                 }
  190                 if (match_res != FNM_NOMATCH) {
  191                     LM_ERR("fnmatch failed\n");
  192                     return -1;
  193                 }
  194         }
  195     }
  196 
  197     LM_DBG("no match in the hash table\n");
  198     return -1;
  199 
  200 found:
  201     if (info) {
  202         pvt.flags = PV_VAL_STR;
  203         pvt.rs.s = node->info;
  204         pvt.rs.len = node->info ? strlen(node->info) : 0;
  205 
  206         if (pv_set_value(msg, info, (int)EQ_T, &pvt) < 0) {
  207             LM_ERR("setting of avp failed\n");
  208             return -1;
  209         }
  210     }
  211 
  212     LM_DBG("match found in the hash table\n");
  213     return 1;
  214 }
  215 
  216 
  217 /*
  218  * Check if an ip_addr/port entry exists in hash table in any group.
  219  * Returns first group in which ip_addr/port is found.
  220  * Port 0 in hash table matches any port.
  221  */
  222 int find_group_in_hash_table(struct address_list** table,
  223                           struct ip_addr *ip, unsigned int port)
  224 {
  225     struct address_list *node;
  226     str str_ip;
  227 
  228     if (ip == NULL){
  229         return -1;
  230     }
  231 
  232     str_ip.len = ip->len;
  233     str_ip.s = (char*) ip->u.addr;
  234 
  235     for (node = table[perm_hash(str_ip)]; node; node = node->next) {
  236             if ( (node->port == 0 || node->port == port) &&
  237             ip_addr_cmp(ip, node->ip) )
  238                 return node->grp;
  239     }
  240     return -1;
  241 }
  242 
  243 
  244 
  245 
  246 int hash_mi_print(struct address_list **table, mi_item_t *part_item,
  247         struct pm_part_struct *pm)
  248 {
  249     int i, len;
  250     struct address_list *node;
  251     char *p, prbuf[PROTO_NAME_MAX_SIZE];
  252     mi_item_t *dests_arr, *dest_item;
  253 
  254     dests_arr = add_mi_array(part_item, MI_SSTR("Destinations"));
  255     if (!dests_arr)
  256         return -1;
  257 
  258     for (i = 0; i < PERM_HASH_SIZE; i++) {
  259         for (node = table[i]; node; node=node->next) {
  260             dest_item = add_mi_object(dests_arr, NULL, 0);
  261             if (!dest_item)
  262                 return -1;
  263 
  264             if (add_mi_number(dest_item, MI_SSTR("grp"), node->grp) < 0)
  265                 return -1;
  266 
  267             p = ip_addr2a(node->ip);
  268             if (add_mi_string(dest_item, MI_SSTR("ip"), p, strlen(p)) < 0)
  269                 return -1;
  270 
  271             if (node->ip->af==AF_INET) {
  272                 if (add_mi_string(dest_item, MI_SSTR("mask"), MI_SSTR("32")) < 0)
  273                     return -1;
  274             } else {
  275                 if (add_mi_string(dest_item, MI_SSTR("mask"), MI_SSTR("128")) < 0)
  276                     return -1;
  277             }
  278 
  279             if (add_mi_number(dest_item, MI_SSTR("port"), node->port) < 0)
  280                 return -1;
  281 
  282             if (node->proto == PROTO_NONE) {
  283                 p = "any";
  284                 len = 3;
  285             } else {
  286                 p = proto2str(node->proto, prbuf);
  287                 len = p - prbuf;
  288                 p = prbuf;
  289             }
  290             if (add_mi_string(dest_item, MI_SSTR("proto"), p, len) < 0)
  291                 return -1;
  292 
  293             if (add_mi_string(dest_item, MI_SSTR("pattern"),
  294                 node->pattern,
  295                 node->pattern ? strlen(node->pattern) : 0) < 0)
  296                 return -1;
  297 
  298             if (add_mi_string(dest_item, MI_SSTR("context_info"),
  299                 node->info,
  300                 node->info ? strlen(node->info) : 0) < 0)
  301                 return -1;
  302         }
  303     }
  304 
  305     return 0;
  306 }
  307 
  308 void empty_hash(struct address_list** table) {
  309     int i;
  310 
  311     struct address_list *node = NULL, *next = NULL;
  312 
  313     for (i = 0; i < PERM_HASH_SIZE; i++) {
  314         for (node = table[i]; node; node = next) {
  315             next = node->next;
  316             if (node->ip) shm_free(node->ip);
  317             if (node->pattern) shm_free(node->pattern);
  318             if (node->info) shm_free(node->info);
  319             shm_free(node);
  320         }
  321         table[i] = 0;
  322     }
  323 }
  324 
  325 
  326 /*
  327  * Create and initialize a subnet table
  328  */
  329 struct subnet* new_subnet_table(void)
  330 {
  331     struct subnet* ptr;
  332 
  333     /* subnet record [PERM_MAX_SUBNETS] contains in its grp field
  334        the number of subnet records in the subnet table */
  335     ptr = (struct subnet *)shm_malloc
  336     (sizeof(struct subnet) * (PERM_MAX_SUBNETS + 1));
  337 
  338     if (!ptr) {
  339         LM_ERR("no shm memory for subnet table\n");
  340         return 0;
  341     }
  342 
  343     ptr[PERM_MAX_SUBNETS].grp = 0;
  344     return ptr;
  345 }
  346 
  347 
  348 /*
  349  * Add <grp, subnet, mask, port> into subnet table so that table is
  350  * kept in increasing ordered according to grp.
  351  */
  352 int subnet_table_insert(struct subnet* table, unsigned int grp,
  353             struct net *subnet,
  354             unsigned int port, int proto, str* pattern, str *info)
  355 {
  356     int i;
  357     unsigned int count;
  358 
  359     count = table[PERM_MAX_SUBNETS].grp;
  360 
  361     if (count == PERM_MAX_SUBNETS) {
  362         LM_CRIT("subnet table is full\n");
  363         return 0;
  364     }
  365 
  366     i = count - 1;
  367 
  368     while (i >= 0 && table[i].grp > grp) {
  369         table[i + 1] = table[i];
  370         i--;
  371     }
  372 
  373     table[i + 1].grp = grp;
  374     table[i + 1].port = port;
  375     table[i + 1].proto = proto;
  376 
  377     if (subnet) {
  378         table[i + 1].subnet = (struct net*) shm_malloc(sizeof(struct net));
  379         if (!table[i + 1].subnet) {
  380             LM_ERR("cannot allocate shm memory for table subnet\n");
  381             return -1;
  382         }
  383         memcpy(table[i + 1].subnet, subnet, sizeof(struct net));
  384     }
  385     else
  386         table[i + 1].subnet = NULL;
  387 
  388     if (info->len) {
  389         table[i + 1].info = (char*) shm_malloc(info->len + 1);
  390         if (!table[i + 1].info) {
  391             LM_ERR("cannot allocate shm memory for table info\n");
  392             return -1;
  393         }
  394         memcpy(table[i + 1].info, info->s, info->len);
  395         table[i + 1].info[info->len] = 0;
  396     }
  397     else
  398         table[i + 1].info = NULL;
  399 
  400     if (pattern->len) {
  401         table[i + 1].pattern = (char*) shm_malloc(pattern->len + 1);
  402         if (!table[i + 1].pattern) {
  403             LM_ERR("cannot allocate shm memory for table pattern\n");
  404             return -1;
  405         }
  406         memcpy(table[i + 1].pattern, pattern->s, pattern->len);
  407         table[i + 1].pattern[ pattern->len ] = 0;
  408     }
  409     else
  410         table[i + 1].pattern = NULL;
  411 
  412 
  413     table[PERM_MAX_SUBNETS].grp = count + 1;
  414 
  415     return 1;
  416 }
  417 
  418 
  419 /*
  420  * Check if an entry exists in subnet table that matches given group, ip_addr,
  421  * and port.  Port 0 in subnet table matches any port.
  422  */
  423 int match_subnet_table(struct sip_msg *msg, struct subnet* table,
  424             unsigned int grp, struct ip_addr *ip, unsigned int port, int proto,
  425             char *pattern, pv_spec_t *info)
  426 {
  427         unsigned int count, i;
  428     pv_value_t pvt;
  429     int match_res, found_group = 0;
  430 
  431     count = table[PERM_MAX_SUBNETS].grp;
  432 
  433     if (count == 0) {
  434         LM_DBG("subnet table is empty\n");
  435         return -2;
  436     }
  437 
  438     if (grp != GROUP_ANY) {
  439         for (i = 0; i < count; i++) {
  440             if (table[i].grp == grp) {
  441                 found_group = 1;
  442                 break;
  443             } else if (table[i].grp > grp) {
  444                 break;
  445             }
  446         }
  447 
  448         if (!found_group) {
  449             LM_DBG("specified group %u does not exist in hash table\n", grp);
  450             return -2;
  451         }
  452     }
  453 
  454     i = 0;
  455     do {
  456         if ((table[i].grp == grp || table[i].grp == GROUP_ANY
  457                 || grp == GROUP_ANY) &&
  458             (table[i].port == port || table[i].port == PORT_ANY
  459                 || port == PORT_ANY) &&
  460             (table[i].proto == proto || table[i].proto == PROTO_NONE
  461                 || proto == PROTO_NONE))
  462             {
  463 
  464                 match_res = matchnet(ip, table[i].subnet);
  465 
  466                 if (match_res != 1) {
  467                     i++;
  468                     continue;
  469                 }
  470 
  471                 if (table[i].pattern && pattern) {
  472                     match_res = fnmatch(table[i].pattern, pattern, FNM_PERIOD);
  473 
  474                     if (match_res) {
  475                         i++;
  476                         continue;
  477                     }
  478                 }
  479 
  480                 if (info) {
  481                     pvt.flags = PV_VAL_STR;
  482                     pvt.rs.s = table[i].info;
  483                     pvt.rs.len = table[i].info ? strlen(table[i].info) : 0;
  484 
  485                     if (pv_set_value(msg, info, (int)EQ_T, &pvt) < 0) {
  486                         LM_ERR("setting of avp failed\n");
  487                         return -1;
  488                     }
  489                 }
  490 
  491                 LM_DBG("match found in the subnet table\n");
  492                 return 1;
  493             }
  494 
  495         if (table[i].grp > grp && grp != GROUP_ANY)
  496             break;
  497         i++;
  498 
  499     } while (i < count);
  500 
  501     LM_DBG("no match in the subnet table\n");
  502     return -1;
  503 }
  504 
  505 
  506 /*
  507  * Print subnets stored in subnet table
  508  */
  509 int subnet_table_mi_print(struct subnet* table, mi_item_t *part_item,
  510         struct pm_part_struct *pm)
  511 {
  512     unsigned int count, i;
  513     char *p, *ip, *mask, prbuf[PROTO_NAME_MAX_SIZE];
  514     int len;
  515     static char ip_buff[IP_ADDR_MAX_STR_SIZE];
  516     mi_item_t *dests_arr, *dest_item;
  517 
  518     count = table[PERM_MAX_SUBNETS].grp;
  519 
  520     dests_arr = add_mi_array(part_item, MI_SSTR("Destinations"));
  521     if (!dests_arr)
  522         return -1;
  523 
  524     for (i = 0; i < count; i++) {
  525         dest_item = add_mi_object(dests_arr, NULL, 0);
  526         if (!dest_item)
  527             return -1;
  528 
  529         ip = ip_addr2a(&table[i].subnet->ip);
  530         if (!ip) {
  531             LM_ERR("cannot print ip address\n");
  532             continue;
  533         }
  534         strcpy(ip_buff, ip);
  535         mask = ip_addr2a(&table[i].subnet->mask);
  536         if (!mask) {
  537             LM_ERR("cannot print mask address\n");
  538             continue;
  539         }
  540 
  541         if (add_mi_number(dest_item, MI_SSTR("grp"), table[i].grp) < 0)
  542             return -1;
  543 
  544         if (add_mi_string(dest_item, MI_SSTR("ip"), ip_buff, strlen(ip_buff)) < 0)
  545             return -1;
  546 
  547         if (add_mi_string(dest_item, MI_SSTR("ip"), mask, strlen(mask)) < 0)
  548             return -1;
  549 
  550         if (add_mi_number(dest_item, MI_SSTR("port"), table[i].port) < 0)
  551             return -1;
  552 
  553         if (table[i].proto == PROTO_NONE) {
  554             p = "any";
  555             len = 3;
  556         } else {
  557             p = proto2str(table[i].proto, prbuf);
  558             len = p - prbuf;
  559             p = prbuf;
  560         }
  561         if (add_mi_string(dest_item, MI_SSTR("proto"), p, len) < 0)
  562             return -1;
  563 
  564         if (add_mi_string(dest_item, MI_SSTR("pattern"),
  565             table[i].pattern,
  566             table[i].pattern ? strlen(table[i].pattern) : 0) < 0)
  567             return -1;
  568 
  569         if (add_mi_string(dest_item, MI_SSTR("context_info"),
  570             table[i].info,
  571             table[i].info ? strlen(table[i].info) : 0) < 0)
  572             return -1;
  573     }
  574 
  575     return 0;
  576 }
  577 
  578 
  579 /*
  580  * Check if an entry exists in subnet table that matches given ip_addr,
  581  * and port.  Port 0 in subnet table matches any port.  Return group of
  582  * first match or -1 if no match is found.
  583  */
  584 int find_group_in_subnet_table(struct subnet* table,
  585                            struct ip_addr *ip, unsigned int port)
  586 {
  587     unsigned int count, i, match_res;
  588 
  589     count = table[PERM_MAX_SUBNETS].grp;
  590 
  591     i = 0;
  592     while (i < count) {
  593         if  (table[i].port == port || table[i].port == 0) {
  594             match_res = matchnet(ip, table[i].subnet);
  595 
  596             if (match_res == 1)
  597                 return table[i].grp;
  598 
  599         }
  600         i++;
  601     }
  602 
  603     return -1;
  604 }
  605 
  606 
  607 /*
  608  * Empty contents of subnet table
  609  */
  610 void empty_subnet_table(struct subnet *table)
  611 {
  612     int count, i;
  613 
  614     if (!table)
  615         return;
  616 
  617     count = table[PERM_MAX_SUBNETS].grp;
  618 
  619     for (i = 0; i < count; i++) {
  620         if (table[i].info)
  621                     shm_free(table[i].info);
  622         if (table[i].subnet)
  623                 shm_free(table[i].subnet);
  624     }
  625 
  626     table[PERM_MAX_SUBNETS].grp = 0;
  627 }
  628 
  629 
  630 /*
  631  * Release memory allocated for a subnet table
  632  */
  633 void free_subnet_table(struct subnet* table)
  634 {
  635     empty_subnet_table(table);
  636 
  637     if (table)
  638         shm_free(table);
  639 }
  640 
  641 
  642 
  643