Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

ipmatch.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ipmatch.c,v 1.3 2007/10/19 16:58:37 tirpi Exp $
00003  *
00004  * Copyright (C) 2006 iptelorg GmbH
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  */
00028 
00029 #include "../../onsend.h"
00030 #include "../../parser/parse_fline.h"
00031 #include "../../ut.h"
00032 #include "permissions.h"
00033 #include "im_hash.h"
00034 #include "im_db.h"
00035 #include "im_locks.h"
00036 #include "ipmatch.h"
00037 
00038 /* initialize ipmatch table */
00039 int init_ipmatch(void)
00040 {
00041         if (db_mode != ENABLE_CACHE) {
00042                 /* not an error, but ipmatch functions will not operate */
00043                 LOG(L_WARN, "WARNING: ipmatch_init(): Database cache is disabled, thus ipmatch functions cannot be used\n");
00044                 return 0;
00045         }
00046 
00047         if (init_im_hash()) {
00048                 LOG(L_ERR, "ERROR: ipmatch_init(): cannot init ipmatch hash table\n");
00049                 return -1;
00050         }
00051 
00052         if (reload_im_cache()) {
00053                 LOG(L_ERR, "ERROR: ipmatch_init(): error occured while caching ipmatch table\n");
00054                 return -1;
00055         }
00056         return 0;
00057 }
00058 
00059 /* destroy function */
00060 void clean_ipmatch(void) {
00061         LOG(L_DBG, "DEBUG: clean_ipmatch(): free shared memory required by ipmatch table\n");
00062         destroy_im_hash();
00063 }
00064 
00065 /* process variable to filter on entry->mark */
00066 static unsigned int IM_FILTER = ~0;
00067 
00068 /* tries to find the given IP address and port number in the global hash table
00069  * return value
00070  *   1: found
00071  *   0: not found
00072  *  -1: error
00073  */
00074 static int ipmatch(struct ip_addr *ip, unsigned short port,
00075                         avp_ident_t *avp)
00076 {
00077         im_entry_t      *entry;
00078         int             ret;
00079         avp_value_t     avp_val;
00080 
00081         ret = 0;
00082 
00083         if (!IM_HASH) {
00084                 LOG(L_CRIT, "ERROR: ipmatch(): ipmatch hash table is not initialied. "
00085                         "Have you set the database url?\n");
00086                 return 0;
00087         }
00088 
00089         /* lock hash table for reading */
00090         reader_lock_imhash();
00091 
00092         LOG(L_DBG, "DEBUG: ipmatch(): start searching... (ip=%s, port=%u, filter=%u)\n",
00093                         ip_addr2a(ip), port, IM_FILTER);
00094 
00095         if (!IM_HASH->entries) {
00096                 LOG(L_DBG, "DEBUG: ipmatch(): cache is empty\n");
00097                 goto done;
00098         }
00099 
00100         entry = IM_HASH->entries[im_hash(ip)];
00101         while (entry) {
00102                 if ((entry->mark & IM_FILTER)
00103                 && ((entry->port == 0) || (port == 0) || (entry->port == port))
00104                 && (ip_addr_cmp(&entry->ip, ip))) {
00105 
00106                         LOG(L_DBG, "DEBUG: ipmatch(): entry found\n");
00107 
00108                         /* shall we set the AVP? */
00109                         if (avp) {
00110                                 /* delete AVP before inserting */
00111                                 delete_avp(avp->flags, avp->name);
00112 
00113                                 avp_val.s.s = entry->avp_val.s;
00114                                 avp_val.s.len = entry->avp_val.len;
00115                                 if (add_avp(avp->flags | AVP_VAL_STR, avp->name, avp_val)) {
00116                                         LOG(L_ERR, "ERROR: ipmatch(): failed to add AVP\n");
00117                                         ret = -1;
00118                                         break;
00119                                 }
00120                         }
00121 
00122                         ret = 1;
00123                         break;
00124                 }
00125 
00126                 entry = entry->next;
00127         }
00128 
00129         if (!entry) LOG(L_DBG, "DEBUG: ipmatch(): entry not found\n");
00130 
00131 done:
00132         /* release hash table */
00133         reader_release_imhash();
00134 
00135         /* reset filter */
00136         IM_FILTER = ~0;
00137 
00138         return ret;
00139 }
00140 
00141 /* wrapper function for ipmatch */
00142 int ipmatch_2(struct sip_msg *msg, char *str1, char *str2)
00143 {
00144         int             ret;
00145         fparam_t        *param1;
00146         str             s;
00147         struct ip_addr  *ip, ip_buf;
00148         unsigned short  port;
00149         unsigned int    iport;
00150 
00151         param1 = (fparam_t *)str1;
00152 
00153         switch(param1->type) {
00154         case FPARAM_AVP:
00155         case FPARAM_SELECT:
00156                 if (get_str_fparam(&s, msg, param1)) {
00157                         LOG(L_ERR, "ERROR: w_ipmatch_2(): could not get first parameter\n");
00158                         return -1;
00159                 }
00160                 if (parse_ip(&s, &ip_buf, &port)) {
00161                         LOG(L_ERR, "ERROR: w_ipmatch_2(): could not parse ip address\n");
00162                         return -1;
00163                 }
00164                 ip = &ip_buf;
00165                 break;
00166 
00167         case FPARAM_STR:
00168                 if (param1->v.str.s[0] == 's') {
00169                         /* "src" */
00170                         ip = &msg->rcv.src_ip;
00171                         port = msg->rcv.src_port;
00172 
00173                 } else {
00174                         /* "via2" */
00175                         if (!msg->via2 &&
00176                                 ((parse_headers(msg, HDR_VIA2_F, 0) == -1) || !msg->via2)) {
00177 
00178                                 LOG(L_ERR, "ERROR: w_ipmatch_2(): could not get 2nd VIA HF\n");
00179                                 return -1;
00180                         }
00181                         if (!msg->via2->received || !msg->via2->received->value.s) {
00182                                 LOG(L_ERR, "ERROR: w_ipmatch_2(): there is no received param in the 2nd VIA HF\n");
00183                                 return -1;
00184                         }
00185                         if (parse_ip(&msg->via2->received->value, &ip_buf, &port)) {
00186                                 LOG(L_ERR, "ERROR: w_ipmatch_2(): could not parse ip address\n");
00187                                 return -1;
00188                         }
00189                         ip = &ip_buf;
00190                         if (!msg->via2->rport || !msg->via2->rport->value.s) {
00191                                 LOG(L_WARN, "WARNING: w_ipmatch_2(): there is no rport param in the 2nd VIA HF\n");
00192                                 port = 0;
00193                         } else {
00194                                 if (str2int(&msg->via2->rport->value, &iport)) {                        
00195                                         LOG(L_ERR, "ERROR: w_ipmatch_2(): invalid port number %.*s\n",
00196                                                         msg->via2->rport->value.len, msg->via2->rport->value.s);
00197                                         return -1;
00198                                 }
00199                                 port = iport;
00200                         }
00201                 }
00202                 break;
00203 
00204         default:
00205                 LOG(L_ERR, "ERROR: w_ipmatch_2(): unknown parameter type\n");
00206                 return -1;
00207         }
00208 
00209         ret = ipmatch( 
00210                         ip,
00211                         port,
00212                         (str2) ? &((fparam_t *)str2)->v.avp : 0
00213                 );
00214                         
00215 
00216         return (ret == 0) ? -1 : 1;
00217 }
00218 
00219 /* wrapper function for ipmatch */
00220 int ipmatch_1(struct sip_msg *msg, char *str1, char *str2)
00221 {
00222         return ipmatch_2(msg, str1, 0);
00223 }
00224 
00225 /* wrapper function for ipmatch */
00226 int ipmatch_onsend(struct sip_msg *msg, char *str1, char *str2)
00227 {
00228         int             ret;
00229         struct ip_addr  ip;
00230         unsigned short  port;
00231         char            *buf, *ch1, *ch2;
00232         struct msg_start        fl;
00233         str             *uri, s;
00234 
00235         if (str1[0] == 'd') {
00236                 /* get info from destination address */
00237                 port = su_getport(get_onsend_info()->to);
00238                 su2ip_addr(&ip, get_onsend_info()->to);
00239 
00240         } else {
00241                 /* get info from Request URI 
00242                 we need to parse the first line again because the parsed uri can be
00243                 changed by another branch */
00244 
00245                 /* use another buffer pointer, because parse_first_list() modifies it */
00246                 buf = get_onsend_info()->buf;
00247                 parse_first_line(buf, get_onsend_info()->len, &fl);
00248                 if (fl.type != SIP_REQUEST) {
00249                         LOG(L_ERR, "ERROR: w_ipmatch_onsend(): message type is not request\n");
00250                         return -1;
00251                 }
00252                 uri = &(fl.u.request.uri);
00253 
00254                 /* find the host:port part in the uri */
00255                 if ((!(ch1 = memchr(uri->s, '@', uri->len))) && (!(ch1 = memchr(uri->s, ':', uri->len)))) {
00256                         LOG(L_ERR, "ERROR: w_ipmatch_onsend(): unable to get host:port part of uri: %.*s\n",
00257                                         uri->len, uri->s);
00258                         return -1;
00259                 }
00260                 /* is there a parameter in the uri? */
00261                 if ((ch2 = memchr(uri->s, ';', uri->len))) {
00262                         s.s = ch1 + 1;
00263                         s.len = ch2 - ch1 - 1;
00264                 } else {
00265                         s.s = ch1 + 1;
00266                         s.len = uri->len - (ch1 - uri->s) - 1;
00267                 }
00268                 if (parse_ip(&s, &ip, &port)) {
00269                         LOG(L_ERR, "ERROR: w_ipmatch_onsend(): could not parse ip address\n");
00270                         return -1;
00271                 }
00272         }
00273 
00274         ret = ipmatch( 
00275                         &ip,
00276                         port,
00277                         0 /* AVP operations are unsafe in onsend_route! */
00278                 );
00279 
00280         return (ret == 0) ? -1 : 1;     
00281 }
00282 
00283 /* set IM_FILTER */
00284 int ipmatch_filter(struct sip_msg *msg, char *str1, char *str2)
00285 {
00286         int     i;
00287 
00288         if (get_int_fparam(&i, msg, (fparam_t *)str1)) return -1;
00289         IM_FILTER = (unsigned int)i;
00290         return 1;
00291 }

Generated on Tue Sep 7 04:16:05 2010 for SIPExpressRouter by  doxygen 1.3.9.1