orig_transaction.c

Go to the documentation of this file.
00001 /*
00002  * openser osp module. 
00003  *
00004  * This module enables openser to communicate with an Open Settlement 
00005  * Protocol (OSP) server.  The Open Settlement Protocol is an ETSI 
00006  * defined standard for Inter-Domain VoIP pricing, authorization
00007  * and usage exchange.  The technical specifications for OSP 
00008  * (ETSI TS 101 321 V4.1.1) are available at www.etsi.org.
00009  *
00010  * Uli Abend was the original contributor to this module.
00011  * 
00012  * Copyright (C) 2001-2005 Fhg Fokus
00013  *
00014  * This file is part of Kamailio, a free SIP server.
00015  *
00016  * Kamailio is free software; you can redistribute it and/or modify
00017  * it under the terms of the GNU General Public License as published by
00018  * the Free Software Foundation; either version 2 of the License, or
00019  * (at your option) any later version
00020  *
00021  * Kamailio is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  * GNU General Public License for more details.
00025  *
00026  * You should have received a copy of the GNU General Public License
00027  * along with this program; if not, write to the Free Software
00028  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00029  */
00030 
00031 #include <string.h>
00032 #include <osp/osp.h>
00033 #include "../../dset.h"
00034 #include "../../usr_avp.h"
00035 #include "../../mem/mem.h"
00036 #include "../auth/api.h"
00037 #include "orig_transaction.h"
00038 #include "destination.h"
00039 #include "osptoolkit.h"
00040 #include "sipheader.h"
00041 #include "usage.h"
00042 
00043 extern char* _osp_device_ip;
00044 extern char* _osp_device_port;
00045 extern int _osp_max_dests;
00046 extern int _osp_redir_uri;
00047 extern int_str _osp_snid_avpname;
00048 extern unsigned short _osp_snid_avptype;
00049 extern OSPTPROVHANDLE _osp_provider;
00050 extern auth_api_t osp_auth;
00051 
00052 const int OSP_FIRST_ROUTE = 1;
00053 const int OSP_NEXT_ROUTE = 0;
00054 const int OSP_MAIN_ROUTE = 1;
00055 const int OSP_BRANCH_ROUTE = 0;
00056 const str OSP_CALLING_NAME = {"_osp_calling_translated_", 24};
00057 
00058 static int ospLoadRoutes(OSPTTRANHANDLE transaction, int destcount, char* source, char* sourcedev, char* origcalled, time_t authtime);
00059 static int ospPrepareDestination(struct sip_msg* msg, int isfirst, int type, int format);
00060 static int ospSetRpid(struct sip_msg* msg, osp_dest* dest);
00061 
00062 /*
00063  * Get routes from AuthRsp
00064  * param transaction Transaction handle
00065  * param destcount Expected destination count
00066  * param source Source IP
00067  * param sourcedev Source device IP
00068  * param origcalled Original called number
00069  * param authtime Request authorization time
00070  * return 0 success, -1 failure
00071  */
00072 static int ospLoadRoutes(
00073     OSPTTRANHANDLE transaction, 
00074     int destcount, 
00075     char* source, 
00076     char* sourcedev, 
00077     char* origcalled, 
00078     time_t authtime)
00079 {
00080     int count;
00081     int errorcode;
00082     osp_dest* dest;
00083     osp_dest dests[OSP_DEF_DESTS];
00084     OSPE_DEST_PROT protocol;
00085     OSPE_DEST_OSP_ENABLED enabled;
00086     int result = 0;
00087     
00088     for (count = 0; count < destcount; count++) {
00089         /* This is necessary because we will save destinations in reverse order */
00090         dest = ospInitDestination(&dests[count]);
00091 
00092         if (dest == NULL) {
00093             result = -1;
00094             break;
00095         }
00096 
00097         dest->destinationCount = count + 1;
00098         strncpy(dest->origcalled, origcalled, sizeof(dest->origcalled) - 1);
00099 
00100         if (count == 0) {
00101             errorcode = OSPPTransactionGetFirstDestination(
00102                 transaction,
00103                 sizeof(dest->validafter),
00104                 dest->validafter,
00105                 dest->validuntil,
00106                 &dest->timelimit,
00107                 &dest->callidsize,
00108                 (void*)dest->callid,
00109                 sizeof(dest->called),
00110                 dest->called,
00111                 sizeof(dest->calling),
00112                 dest->calling,
00113                 sizeof(dest->host),
00114                 dest->host,
00115                 sizeof(dest->destdev),
00116                 dest->destdev,
00117                 &dest->tokensize,
00118                 dest->token);
00119         } else {
00120             errorcode = OSPPTransactionGetNextDestination(
00121                 transaction,
00122                 0,
00123                 sizeof(dest->validafter),
00124                 dest->validafter,
00125                 dest->validuntil,
00126                 &dest->timelimit,
00127                 &dest->callidsize,
00128                 (void*)dest->callid,
00129                 sizeof(dest->called),
00130                 dest->called,
00131                 sizeof(dest->calling),
00132                 dest->calling,
00133                 sizeof(dest->host),
00134                 dest->host,
00135                 sizeof(dest->destdev),
00136                 dest->destdev,
00137                 &dest->tokensize,
00138                 dest->token);
00139         }
00140         
00141         if (errorcode != OSPC_ERR_NO_ERROR) {
00142             LM_ERR("failed to load routes (%d) expected '%d' current '%d'\n", 
00143                 errorcode, 
00144                 destcount, 
00145                 count);
00146             result = -1;
00147             break;
00148         }
00149 
00150         errorcode = OSPPTransactionGetDestProtocol(transaction, &protocol);
00151         if (errorcode != OSPC_ERR_NO_ERROR) {
00152             /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
00153             LM_DBG("cannot get dest protocol (%d)\n", errorcode);
00154             protocol = OSPE_DEST_PROT_SIP;
00155         }
00156         switch (protocol) {
00157             case OSPE_DEST_PROT_H323_LRQ:
00158             case OSPE_DEST_PROT_H323_SETUP:
00159             case OSPE_DEST_PROT_IAX:
00160                 dest->supported = 0;
00161                 break;
00162             case OSPE_DEST_PROT_SIP:
00163             case OSPE_DEST_PROT_UNDEFINED:
00164             case OSPE_DEST_PROT_UNKNOWN:
00165             default:
00166                 dest->supported = 1;
00167                 break;
00168         }
00169 
00170         errorcode = OSPPTransactionIsDestOSPEnabled(transaction, &enabled);
00171         if (errorcode != OSPC_ERR_NO_ERROR) {
00172             /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
00173             LM_DBG("cannot get dest OSP version (%d)\n", errorcode);
00174         } else if (enabled == OSPE_OSP_FALSE) {
00175             /* Destination device does not support OSP. Do not send token to it */
00176             dest->token[0] = '\0';
00177             dest->tokensize = 0;
00178         }
00179 
00180         errorcode = OSPPTransactionGetDestNetworkId(transaction, dest->networkid);
00181         if (errorcode != OSPC_ERR_NO_ERROR) {
00182             /* This does not mean an ERROR. The OSP server may not support OSP 2.1.1 */
00183             LM_DBG("cannot get dest network ID (%d)\n", errorcode);
00184             dest->networkid[0] = '\0';
00185         }
00186 
00187         strncpy(dest->source, source, sizeof(dest->source) - 1);
00188         strncpy(dest->srcdev, sourcedev, sizeof(dest->srcdev) - 1);
00189         dest->type = OSPC_SOURCE;
00190         dest->transid = ospGetTransactionId(transaction);
00191         dest->authtime = authtime;
00192 
00193         LM_INFO("get destination '%d': "
00194             "valid after '%s' "
00195             "valid until '%s' "
00196             "time limit '%d' seconds "
00197             "call id '%.*s' "
00198             "calling '%s' "
00199             "called '%s' "
00200             "host '%s' "
00201             "supported '%d' "
00202             "network id '%s' "
00203             "token size '%d'\n",
00204             count, 
00205             dest->validafter, 
00206             dest->validuntil, 
00207             dest->timelimit, 
00208             dest->callidsize, 
00209             dest->callid, 
00210             dest->calling, 
00211             dest->called, 
00212             dest->host, 
00213             dest->supported,
00214             dest->networkid, 
00215             dest->tokensize);
00216     }
00217 
00218     /* 
00219      * Save destination in reverse order,
00220      * when we start searching avps the destinations
00221      * will be in order 
00222      */
00223     if (result == 0) {
00224         for(count = destcount -1; count >= 0; count--) {
00225             if (ospSaveOrigDestination(&dests[count]) == -1) {
00226                 LM_ERR("failed to save originate destination\n");
00227                 /* Report terminate CDR */
00228                 ospRecordEvent(0, 500);
00229                 result = -1;
00230                 break;
00231             }
00232         }
00233     }
00234 
00235     return result;
00236 }
00237 
00238 /*
00239  * Request OSP authorization and routeing
00240  * param msg SIP message
00241  * param ignore1
00242  * param ignore2
00243  * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure, MODULE_RETURNCODE_ERROR error
00244  */
00245 int ospRequestRouting(
00246     struct sip_msg* msg, 
00247     char* ignore1, 
00248     char* ignore2)
00249 {
00250     int errorcode;
00251     time_t authtime;
00252     char called[OSP_E164BUF_SIZE];
00253     char calling[OSP_E164BUF_SIZE];
00254     char sourcedev[OSP_STRBUF_SIZE];
00255     char deviceinfo[OSP_STRBUF_SIZE];
00256     struct usr_avp* snidavp = NULL;
00257     int_str snidval;
00258     char snid[OSP_STRBUF_SIZE];
00259     unsigned int callidnumber = 1;
00260     OSPTCALLID* callids[callidnumber];
00261     unsigned int logsize = 0;
00262     char* detaillog = NULL;
00263     const char** preferred = NULL;
00264     unsigned int destcount;
00265     OSPTTRANHANDLE transaction = -1;
00266     int result = MODULE_RETURNCODE_FALSE;
00267 
00268     authtime = time(NULL);
00269 
00270     destcount = _osp_max_dests;
00271 
00272     if ((errorcode = OSPPTransactionNew(_osp_provider, &transaction)) != OSPC_ERR_NO_ERROR) {
00273         LM_ERR("failed to create new OSP transaction (%d)\n", errorcode);
00274     } else if ((ospGetRpidUserpart(msg, calling, sizeof(calling)) != 0) &&
00275         (ospGetFromUserpart(msg, calling, sizeof(calling)) != 0)) 
00276     {
00277         LM_ERR("failed to extract calling number\n");
00278     } else if ((ospGetUriUserpart(msg, called, sizeof(called)) != 0) &&
00279         (ospGetToUserpart(msg, called, sizeof(called)) != 0)) 
00280     {
00281         LM_ERR("failed to extract called number\n");
00282     } else if (ospGetCallId(msg, &(callids[0])) != 0) {
00283         LM_ERR("failed to extract call id\n");
00284     } else if (ospGetSourceAddress(msg, sourcedev, sizeof(sourcedev)) != 0) {
00285         LM_ERR("failed to extract source deivce address\n");
00286     } else {
00287         ospConvertAddress(sourcedev, deviceinfo, sizeof(deviceinfo));
00288 
00289         if ((_osp_snid_avpname.n != 0) &&
00290             ((snidavp = search_first_avp(_osp_snid_avptype, _osp_snid_avpname, &snidval, 0)) != NULL) &&
00291             (snidavp->flags & AVP_VAL_STR) && (snidval.s.s && snidval.s.len)) 
00292         {
00293             snprintf(snid, sizeof(snid), "%.*s", snidval.s.len, snidval.s.s);
00294             OSPPTransactionSetNetworkIds(transaction, snid, "");
00295         } else {
00296             snid[0] = '\0';
00297         }
00298 
00299         LM_INFO("request auth and routing for: "
00300             "source_ip '%s' "
00301             "source_port '%s' "
00302             "source_dev '%s' "
00303             "source_networkid '%s' "
00304             "calling '%s' "
00305             "called '%s' "
00306             "call_id '%.*s' "
00307             "dest_count '%d'\n",
00308             _osp_device_ip,
00309             _osp_device_port,
00310             deviceinfo,         /* in "[x.x.x.x]" or host.domain format */
00311             snid,
00312             calling,
00313             called,
00314             callids[0]->ospmCallIdLen,
00315             callids[0]->ospmCallIdVal,
00316             destcount
00317         );    
00318 
00319         /* try to request authorization */
00320         errorcode = OSPPTransactionRequestAuthorisation(
00321             transaction,       /* transaction handle */
00322             _osp_device_ip,    /* from the configuration file */
00323             deviceinfo,        /* source device of call, protocol specific, in OSP format */
00324             calling,           /* calling number in nodotted e164 notation */
00325             OSPC_E164,         /* calling number format */
00326             called,            /* called number */
00327             OSPC_E164,         /* called number format */
00328             "",                /* optional username string, used if no number */
00329             callidnumber,      /* number of call ids, here always 1 */
00330             callids,           /* sized-1 array of call ids */
00331             preferred,         /* preferred destinations, here always NULL */
00332             &destcount,        /* max destinations, after call dest_count */
00333             &logsize,          /* size allocated for detaillog (next param) 0=no log */
00334             detaillog);        /* memory location for detaillog to be stored */
00335 
00336         if ((errorcode == OSPC_ERR_NO_ERROR) &&
00337             (ospLoadRoutes(transaction, destcount, _osp_device_ip, sourcedev, called, authtime) == 0))
00338         {
00339             LM_INFO("there are '%d' OSP routes, call_id '%.*s'\n",
00340                 destcount,
00341                 callids[0]->ospmCallIdLen,
00342                 callids[0]->ospmCallIdVal);
00343             result = MODULE_RETURNCODE_TRUE;
00344         } else {
00345             LM_ERR("failed to request auth and routing (%d), call_id '%.*s'\n",
00346                 errorcode,
00347                 callids[0]->ospmCallIdLen,
00348                 callids[0]->ospmCallIdVal);
00349             switch (errorcode) {
00350                 case OSPC_ERR_TRAN_ROUTE_BLOCKED:
00351                     result = -403;
00352                     break;
00353                 case OSPC_ERR_TRAN_ROUTE_NOT_FOUND:
00354                     result = -404;
00355                     break;
00356                 case OSPC_ERR_NO_ERROR:
00357                     /* AuthRsp ok but ospLoadRoutes fails */
00358                     result = MODULE_RETURNCODE_ERROR;
00359                     break;
00360                 default:
00361                     result = MODULE_RETURNCODE_FALSE;
00362                     break;
00363             }
00364         }
00365     }
00366 
00367     if (callids[0] != NULL) {
00368         OSPPCallIdDelete(&(callids[0]));
00369     }
00370 
00371     if (transaction != -1) {
00372         OSPPTransactionDelete(transaction);
00373     }
00374     
00375     return result;
00376 }
00377 
00378 /*
00379  * Check if there is a route
00380  * param msg SIP message
00381  * param ignore1
00382  * param ignore2
00383  * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
00384  */
00385 int ospCheckRoute(
00386     struct sip_msg* msg, 
00387     char* ignore1, 
00388     char* ignore2)
00389 {
00390     if (ospCheckOrigDestination() == 0) {
00391         return MODULE_RETURNCODE_TRUE;
00392     } else {
00393         return MODULE_RETURNCODE_FALSE;
00394     }
00395 }
00396 
00397 /*
00398  * Create RPID AVP
00399  * param msg SIP message
00400  * param dest Destination structure
00401  * return 0 success, 1 calling number same, -1 failure
00402  */
00403 static int ospSetRpid(
00404     struct sip_msg* msg, 
00405     osp_dest* dest)
00406 {
00407     str rpid;
00408     char calling[OSP_STRBUF_SIZE];
00409     char source[OSP_STRBUF_SIZE];
00410     char buffer[OSP_STRBUF_SIZE];
00411     int result = -1;
00412 
00413     if ((ospGetRpidUserpart(msg, calling, sizeof(calling)) != 0) &&
00414         (ospGetFromUserpart(msg, calling, sizeof(calling)) !=0))
00415     {
00416         LM_ERR("failed to extract calling number\n");
00417         return result;
00418     } 
00419 
00420     if (strcmp(calling, dest->calling) == 0) {
00421         /* Do nothing for this case */ 
00422         result = 1;
00423     } else if ((osp_auth.rpid_avp.s.s == NULL) || (osp_auth.rpid_avp.s.len == 0)) {
00424         LM_WARN("rpid_avp is not foune, cannot set rpid avp\n");
00425         result = -1;
00426     } else {
00427         if (dest->source[0] == '[') {
00428             /* Strip "[]" */
00429             memset(source, 0, sizeof(source));
00430             strncpy(source, &dest->source[1], sizeof(source) - 1);
00431             source[strlen(source) - 1] = '\0';
00432         }
00433     
00434         snprintf(
00435             buffer, 
00436             sizeof(buffer), 
00437             "\"%s\" <sip:%s@%s>", 
00438             dest->calling, 
00439             dest->calling, 
00440             source);
00441 
00442         rpid.s = buffer;
00443         rpid.len = strlen(buffer);
00444         add_avp(osp_auth.rpid_avp_type | AVP_VAL_STR, (int_str)osp_auth.rpid_avp, (int_str)rpid);
00445 
00446         result = 0;
00447     }
00448 
00449     return result;
00450 }
00451 
00452 /*
00453  * Check if the calling number is translated.
00454  *     This function checks the avp set by ospPrepareDestination.
00455  * param msg SIP message
00456  * param ignore1
00457  * param ignore2
00458  * return MODULE_RETURNCODE_TRUE calling number translated MODULE_RETURNCODE_FALSE without transaltion
00459  */
00460 int ospCheckTranslation(
00461     struct sip_msg* msg, 
00462     char* ignore1, 
00463     char* ignore2)
00464 {
00465     int_str callingval;
00466     int result = MODULE_RETURNCODE_FALSE;
00467 
00468     if (search_first_avp(AVP_NAME_STR, (int_str)OSP_CALLING_NAME, &callingval, 0) != NULL) {
00469         if (callingval.n == 0) {
00470             LM_DBG("the calling number does not been translated\n");
00471         } else {
00472             LM_DBG("the calling number is translated\n");
00473             result = MODULE_RETURNCODE_TRUE;
00474         }
00475     } else {
00476         LM_ERR("there is not calling translation avp\n");
00477     }
00478 
00479     return result;
00480 }
00481 
00482 /*
00483  * Build SIP message for destination
00484  * param msg SIP message
00485  * param isfirst Is first destination
00486  * param type Main or branch route block
00487  * param format URI format
00488  * return MODULE_RETURNCODE_TRUE success MODULE_RETURNCODE_FALSE failure
00489  */
00490 static int ospPrepareDestination(
00491     struct sip_msg* msg, 
00492     int isfirst,
00493     int type,
00494     int format)
00495 {
00496     int_str val;
00497     int res;
00498     str newuri = {NULL, 0};
00499     int result = MODULE_RETURNCODE_FALSE;
00500 
00501     osp_dest* dest = ospGetNextOrigDestination();
00502 
00503     if (dest != NULL) {
00504         ospRebuildDestionationUri(&newuri, dest->called, dest->host, "", format);
00505 
00506         LM_INFO("prepare route to URI '%.*s' for call_id '%.*s' transaction_id '%llu'\n",
00507             newuri.len,
00508             newuri.s,
00509             dest->callidsize,
00510             dest->callid,
00511             dest->transid);
00512 
00513         if (type == OSP_MAIN_ROUTE) {
00514             if (isfirst == OSP_FIRST_ROUTE) {
00515                 rewrite_uri(msg, &newuri);
00516             } else {
00517                 append_branch(msg, &newuri, NULL, NULL, Q_UNSPECIFIED, 0, NULL);
00518             }
00519             /* Do not add route specific OSP information */
00520             result = MODULE_RETURNCODE_TRUE;
00521         } else if (type == OSP_BRANCH_ROUTE) {
00522             /* For branch route, add route specific OSP information */
00523 
00524             /* Update the Request-Line */
00525             rewrite_uri(msg, &newuri);
00526 
00527             /* Add OSP token header */
00528             ospAddOspHeader(msg, dest->token, dest->tokensize);
00529 
00530             /* Add branch-specific OSP Cookie */
00531             ospRecordOrigTransaction(msg, dest->transid, dest->srcdev, dest->calling, dest->called, dest->authtime, dest->destinationCount);
00532 
00533             /* Add rpid avp for calling number translation */
00534             res = ospSetRpid(msg, dest);
00535             switch (res) {
00536                 case 0:
00537                     /* Calling number is translated */
00538                     val.n = 1;
00539                     add_avp(AVP_NAME_STR, (int_str)OSP_CALLING_NAME, val);
00540                     break;
00541                 default:
00542                     LM_DBG("cannot set rpid avp\n");
00543                     /* Just like without calling translation */
00544                 case 1:
00545                     /* Calling number does not been translated */
00546                     val.n = 0;
00547                     add_avp(AVP_NAME_STR, (int_str)OSP_CALLING_NAME, val);
00548                     break;
00549             }
00550 
00551             result = MODULE_RETURNCODE_TRUE;
00552         } else {
00553             LM_ERR("unsupported route block type\n");
00554         }
00555     } else {
00556         LM_DBG("there is no more routes\n");
00557         ospReportOrigSetupUsage();
00558     }
00559 
00560     if (newuri.len > 0) {
00561         pkg_free(newuri.s);
00562     }
00563     
00564     return result;
00565 }
00566 
00567 /*
00568  * Prepare OSP route
00569  *     This function only works in branch route block.
00570  *     This function is only for Kamailio.
00571  * param msg SIP message
00572  * param ignore1
00573  * param ignore2
00574  * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
00575  */
00576 int ospPrepareRoute(
00577     struct sip_msg* msg, 
00578     char* ignore1, 
00579     char* ignore2)
00580 {
00581     int result = MODULE_RETURNCODE_TRUE;
00582 
00583     /* The first parameter will be ignored */
00584     result = ospPrepareDestination(msg, OSP_FIRST_ROUTE, OSP_BRANCH_ROUTE, 0);
00585 
00586     return result;
00587 }
00588 
00589 /*
00590  * Prepare all OSP routes
00591  *     This function does not work in branch route block.
00592  * param msg SIP message
00593  * param ignore1
00594  * param ignore2
00595  * return MODULE_RETURNCODE_TRUE success, MODULE_RETURNCODE_FALSE failure
00596  */
00597 int ospPrepareAllRoutes(
00598     struct sip_msg* msg, 
00599     char* ignore1, 
00600     char* ignore2)
00601 {
00602     int result = MODULE_RETURNCODE_TRUE;
00603 
00604     for(result = ospPrepareDestination(msg, OSP_FIRST_ROUTE, OSP_MAIN_ROUTE, _osp_redir_uri);
00605         result == MODULE_RETURNCODE_TRUE;
00606         result = ospPrepareDestination(msg, OSP_NEXT_ROUTE, OSP_MAIN_ROUTE, _osp_redir_uri))
00607     {
00608     }
00609 
00610     return MODULE_RETURNCODE_TRUE;
00611 }
00612 

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