sipheader.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 <osp/osp.h>
00032 #include <osp/ospb64.h>
00033 #include "../../forward.h"
00034 #include "../../parser/parse_from.h"
00035 #include "../../parser/parse_rpid.h"
00036 #include "../../parser/parse_rr.h"
00037 #include "../../parser/parse_uri.h"
00038 #include "../../data_lump.h"
00039 #include "../../mem/mem.h"
00040 #include "osp_mod.h"
00041 #include "sipheader.h"
00042 
00043 extern int _osp_use_rpid;
00044 
00045 static void ospSkipPlus(char* e164);
00046 static int ospAppendHeader(struct sip_msg* msg, str* header); 
00047 
00048 /* 
00049  * Copy str to buffer and check overflow 
00050  * param source Str
00051  * param buffer Buffer
00052  * param buffersize Size of buffer
00053  */
00054 void ospCopyStrToBuffer(
00055     str* source, 
00056     char* buffer, 
00057     int buffersize)
00058 {
00059     int copybytes;
00060 
00061     if (source->len > buffersize - 1) {
00062         LM_ERR("buffer for copying '%.*s' is too small, will copy the first '%d' bytes\n",
00063             source->len,
00064             source->s, 
00065             buffersize);
00066         copybytes = buffersize - 1;
00067     } else {
00068         copybytes = source->len;
00069     }
00070 
00071     strncpy(buffer, source->s, copybytes);
00072     buffer[copybytes] = '\0';
00073 }
00074 
00075 /* 
00076  * Remove '+' in E164 string
00077  * param e164 E164 string
00078  */
00079 static void ospSkipPlus(
00080     char* e164)
00081 {
00082     if (*e164 == '+') {
00083         strncpy(e164, e164 + 1, strlen(e164) - 1);
00084         e164[strlen(e164) - 1] = '\0';
00085     }
00086 }
00087 
00088 /* 
00089  * Get calling number from From header
00090  * param msg SIP message
00091  * param fromuser User part of From header
00092  * param buffersize Size of fromuser buffer
00093  * return 0 success, -1 failure
00094  */
00095 int ospGetFromUserpart(
00096     struct sip_msg* msg, 
00097     char* fromuser, 
00098     int buffersize)
00099 {
00100     struct to_body* from;
00101     struct sip_uri uri;
00102     int result = -1;
00103 
00104     fromuser[0] = '\0';
00105 
00106     if (msg->from != NULL) {
00107         if (parse_from_header(msg) == 0) {
00108             from = get_from(msg);
00109             if (parse_uri(from->uri.s, from->uri.len, &uri) == 0) {
00110                 ospCopyStrToBuffer(&uri.user, fromuser, buffersize);
00111                 ospSkipPlus(fromuser);
00112                 result = 0;
00113             } else {
00114                 LM_ERR("failed to parse From uri\n");
00115             }
00116         } else {
00117             LM_ERR("failed to parse From header\n");
00118         }
00119     } else {
00120         LM_ERR("failed to find From header\n");
00121     }
00122 
00123     return result;
00124 }
00125 
00126 /* 
00127  * Get calling number from Remote-Party-ID header
00128  * param msg SIP message
00129  * param rpiduser User part of Remote-Party-ID header
00130  * param buffersize Size of fromuser buffer
00131  * return 0 success, -1 failure
00132  */
00133 int ospGetRpidUserpart(
00134     struct sip_msg* msg, 
00135     char* rpiduser, 
00136     int buffersize)
00137 {
00138     struct to_body* rpid;
00139     struct sip_uri uri;
00140     int result = -1;
00141 
00142     rpiduser[0] = '\0';
00143 
00144     if (_osp_use_rpid != 0) {
00145         if (msg->rpid != NULL) {
00146             if (parse_rpid_header(msg) == 0) {
00147                 rpid = get_rpid(msg);
00148                 if (parse_uri(rpid->uri.s, rpid->uri.len, &uri) == 0) {
00149                     ospCopyStrToBuffer(&uri.user, rpiduser, buffersize);
00150                     ospSkipPlus(rpiduser);
00151                     result = 0;
00152                 } else {
00153                     LM_ERR("failed to parse RPID uri\n");
00154                 }
00155             } else {
00156                 LM_ERR("failed to parse RPID header\n");
00157             }
00158         } else {
00159             LM_DBG("without RPID header\n");
00160         }
00161     } else {
00162         LM_DBG("do not use RPID header\n");
00163     }
00164 
00165     return result;
00166 }
00167 
00168 /* 
00169  * Get called number from To header
00170  * param msg SIP message
00171  * param touser User part of To header
00172  * param buffersize Size of touser buffer
00173  * return 0 success, -1 failure
00174  */
00175 int ospGetToUserpart(
00176     struct sip_msg* msg, 
00177     char* touser, 
00178     int buffersize)
00179 {
00180     struct to_body* to;
00181     struct sip_uri uri;
00182     int result = -1;
00183 
00184     touser[0] = '\0';
00185 
00186     if (msg->to != NULL) {
00187         if (parse_headers(msg, HDR_TO_F, 0) == 0) {
00188             to = get_to(msg);
00189             if (parse_uri(to->uri.s, to->uri.len, &uri) == 0) {
00190                 ospCopyStrToBuffer(&uri.user, touser, buffersize);
00191                 ospSkipPlus(touser);
00192                 result = 0;
00193             } else {
00194                 LM_ERR("failed to parse To uri\n");
00195             }
00196         } else {
00197             LM_ERR("failed to parse To header\n");
00198         }
00199     } else {
00200         LM_ERR("failed to find To header\n");
00201     }
00202 
00203     return result;
00204 }
00205 
00206 /* 
00207  * Get called number from Request-Line header
00208  * param msg SIP message
00209  * param touser User part of To header
00210  * param buffersize Size of touser buffer
00211  * return 0 success, -1 failure
00212  */
00213 int ospGetUriUserpart(
00214     struct sip_msg* msg, 
00215     char* uriuser, 
00216     int buffersize)
00217 {
00218     int result = -1;
00219 
00220     uriuser[0] = '\0';
00221 
00222     if (parse_sip_msg_uri(msg) >= 0) {
00223         ospCopyStrToBuffer(&msg->parsed_uri.user, uriuser, buffersize);
00224         ospSkipPlus(uriuser);
00225         result = 0;
00226     } else {
00227         LM_ERR("failed to parse Request-Line URI\n");
00228     }
00229 
00230     return result;
00231 }
00232 
00233 /* 
00234  * Append header to SIP message
00235  * param msg SIP message
00236  * param header Header to be appended
00237  * return 0 success, -1 failure
00238  */
00239 static int ospAppendHeader(
00240     struct sip_msg* msg, 
00241     str* header)
00242 {
00243     char* s;
00244     struct lump* anchor;
00245     
00246     if((msg == 0) || (header == 0) || (header->s == 0) || (header->len <= 0)) {
00247         LM_ERR("bad parameters for appending header\n");
00248         return -1;
00249     }
00250 
00251     if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
00252         LM_ERR("failed to parse message\n");
00253         return -1;
00254     }
00255 
00256     anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
00257     if (anchor == 0) {
00258         LM_ERR("failed to get anchor\n");
00259         return -1;
00260     }
00261 
00262     s = (char*)pkg_malloc(header->len);
00263     if (s == 0) {
00264         LM_ERR("no pkg memory\n");
00265         return -1;
00266     }
00267 
00268     memcpy(s, header->s, header->len);
00269 
00270     if (insert_new_lump_before(anchor, s, header->len, 0) == 0) {
00271         LM_ERR("failed to insert lump\n");
00272         pkg_free(s);
00273         return -1;
00274     }
00275     
00276     return 0;
00277 }
00278 
00279 /* 
00280  * Add OSP token header to SIP message
00281  * param msg SIP message
00282  * param token OSP authorization token
00283  * param tokensize Size of OSP authorization token
00284  * return 0 success, -1 failure
00285  */
00286 int ospAddOspHeader(
00287     struct sip_msg* msg, 
00288     unsigned char* token, 
00289     unsigned int tokensize)
00290 {
00291     str headerval;
00292     char buffer[OSP_HEADERBUF_SIZE];
00293     unsigned char encodedtoken[OSP_TOKENBUF_SIZE];
00294     unsigned int encodedtokensize = sizeof(encodedtoken);
00295     int  result = -1;
00296 
00297     if (tokensize == 0) {
00298         LM_DBG("destination is not OSP device\n");
00299         result = 0;
00300     } else {
00301         if (OSPPBase64Encode(token, tokensize, encodedtoken, &encodedtokensize) == 0) {
00302             snprintf(buffer,
00303                 sizeof(buffer),
00304                 "%s%.*s\r\n", 
00305                 OSP_TOKEN_HEADER,
00306                 encodedtokensize,
00307                 encodedtoken);
00308     
00309             headerval.s = buffer;
00310             headerval.len = strlen(buffer);
00311     
00312             LM_DBG("setting osp token header field '%s'\n", buffer);
00313     
00314             if (ospAppendHeader(msg, &headerval) == 0) {
00315                 result = 0;
00316             } else {
00317                 LM_ERR("failed to append osp header\n");
00318             }
00319         } else {
00320             LM_ERR("failed to base64 encode token\n");
00321         }
00322     }
00323 
00324     return result;
00325 }
00326 
00327 /* 
00328  * Get OSP token from SIP message
00329  * param msg SIP message
00330  * param token OSP authorization token
00331  * param tokensize Size of OSP authorization token
00332  * return 0 success, -1 failure
00333  */
00334 int ospGetOspHeader(
00335     struct sip_msg* msg, 
00336     unsigned char* token, 
00337     unsigned int* tokensize)
00338 {
00339     struct hdr_field* hf;
00340     int errorcode;
00341     int result = -1;
00342 
00343     parse_headers(msg, HDR_EOH_F, 0);
00344 
00345     for (hf = msg->headers; hf; hf = hf->next) {
00346         if ((hf->type == HDR_OTHER_T) && (hf->name.len == OSP_HEADER_SIZE - 2)) {
00347             // possible hit
00348             if (strncasecmp(hf->name.s, OSP_TOKEN_HEADER, OSP_HEADER_SIZE) == 0) {
00349                 if ((errorcode = OSPPBase64Decode(hf->body.s, hf->body.len, token, tokensize)) == OSPC_ERR_NO_ERROR) {
00350                     result = 0;
00351                 } else {
00352                     LM_ERR("failed to base64 decode token (%d)\n", errorcode);
00353                     LM_ERR("header '%.*s' length %d\n", hf->body.len, hf->body.s, hf->body.len);
00354                 }
00355                 break;
00356             }        
00357         } 
00358     }
00359 
00360     return result;
00361 }
00362 
00363 /* 
00364  * Get first VIA header and use the IP or host name
00365  * param msg SIP message
00366  * param sourceaddress Source address
00367  * param buffersize Size of sourceaddress
00368  * return 0 success, -1 failure
00369  */
00370 int ospGetSourceAddress(
00371     struct sip_msg* msg, 
00372     char* sourceaddress, 
00373     int buffersize)
00374 {
00375     struct hdr_field* hf;
00376     struct via_body* via;
00377     int result = -1;
00378 
00379     /* 
00380      * No need to call parse_headers, called already and VIA is parsed
00381      * anyway by default 
00382      */
00383     for (hf = msg->headers; hf; hf = hf->next) {
00384         if (hf->type == HDR_VIA_T) {
00385             // found first VIA
00386             via = (struct via_body*)hf->parsed;    
00387             ospCopyStrToBuffer(&via->host, sourceaddress, buffersize);
00388 
00389             LM_DBG("source address '%s'\n", sourceaddress);
00390 
00391             result = 0;
00392             break;
00393         } 
00394     }
00395 
00396     return result;
00397 }
00398 
00399 /* 
00400  * Get Call-ID header from SIP message
00401  * param msg SIP message
00402  * param callid Call ID
00403  * return 0 success, -1 failure
00404  */
00405 int ospGetCallId(
00406     struct sip_msg* msg, 
00407     OSPTCALLID** callid)
00408 {
00409     struct hdr_field* hf;
00410     int result = -1;
00411 
00412     hf = (struct hdr_field*)msg->callid;
00413     if (hf != NULL) {
00414         *callid = OSPPCallIdNew(hf->body.len, (unsigned char*)hf->body.s);
00415         if (*callid) {
00416             result = 0;
00417         } else {
00418             LM_ERR("failed to allocate OSPCALLID object for '%.*s'\n", hf->body.len, hf->body.s);
00419         }
00420     } else {
00421         LM_ERR("failed to find Call-ID header\n");
00422     }    
00423 
00424     return result;
00425 }
00426 
00427 /* 
00428  * Get route parameters from the 1st Route or Request-Line
00429  * param msg SIP message
00430  * param routeparameters Route parameters
00431  * param buffersize Size of routeparameters
00432  * return 0 success, -1 failure
00433  */
00434 int ospGetRouteParameters(
00435     struct sip_msg* msg, 
00436     char* routeparameters, 
00437     int buffersize)
00438 {
00439     struct hdr_field* hf;
00440     rr_t* rt;
00441     struct sip_uri uri;
00442     int result = -1;
00443 
00444     LM_DBG("parsed uri host '%.*s' port '%d' vars '%.*s'\n",
00445         msg->parsed_uri.host.len,
00446         msg->parsed_uri.host.s,
00447         msg->parsed_uri.port_no,
00448         msg->parsed_uri.params.len,
00449         msg->parsed_uri.params.s);
00450 
00451     if (!(hf = msg->route)) {
00452         LM_DBG("there is no Route headers\n");
00453     } else if (!(rt = (rr_t*)hf->parsed)) {
00454         LM_ERR("route headers are not parsed\n");
00455     } else if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len, &uri) != 0) {
00456         LM_ERR("failed to parse the Route uri '%.*s'\n", rt->nameaddr.uri.len, rt->nameaddr.uri.s);
00457     } else if (check_self(&uri.host, uri.port_no ? uri.port_no : SIP_PORT, PROTO_NONE) != 1) {
00458         LM_DBG("the Route uri is NOT mine\n");
00459         LM_DBG("host '%.*s' port '%d'\n", uri.host.len, uri.host.s, uri.port_no);
00460         LM_DBG("params '%.*s'\n", uri.params.len, uri.params.s);
00461     } else {
00462         LM_DBG("the Route uri IS mine - '%.*s'\n", uri.params.len, uri.params.s);
00463         LM_DBG("host '%.*s' port '%d'\n", uri.host.len, uri.host.s, uri.port_no);
00464         ospCopyStrToBuffer(&uri.params, routeparameters, buffersize);
00465         result = 0;
00466     }
00467 
00468     if ((result == -1) && (msg->parsed_uri.params.len > 0)) {
00469         LM_DBG("using route parameters from Request-Line uri\n");
00470         ospCopyStrToBuffer(&msg->parsed_uri.params, routeparameters, buffersize);
00471         routeparameters[msg->parsed_uri.params.len] = '\0';
00472         result = 0;
00473     }
00474 
00475     return result;
00476 }
00477 
00478 /* 
00479  * Rebuild URI using called number, destination IP, and port
00480  * param newuri URI to be built
00481  * param called Called number
00482  * param dest Destination IP
00483  * param port Destination port
00484  * param format URI format
00485  * return 0 success, -1 failure
00486  */
00487 int ospRebuildDestionationUri(
00488     str* newuri, 
00489     char* called,
00490     char* dest, 
00491     char* port,
00492     int format) 
00493 {
00494     static const str TRANS = {";transport=tcp", 14};
00495     char* buffer;
00496     int calledsize;
00497     int destsize;
00498     int portsize;
00499 
00500     calledsize = strlen(called);
00501     destsize = strlen(dest);
00502     portsize = strlen(port);
00503 
00504     LM_DBG("'%s'(%d) '%s'(%d) '%s'(%d) '%d'\n",
00505         called, 
00506         calledsize,
00507         dest, 
00508         destsize, 
00509         port, 
00510         portsize,
00511         format); 
00512 
00513     /* "sip:" + called + "@" + dest + : + port + " SIP/2.0" for URI format 0 */
00514     /* "<sip:" + called + "@" + dest + : + port> + " SIP/2.0" for URI format 1 */
00515     newuri->s = (char*)pkg_malloc(1 + 4 + calledsize + 1 + destsize + 1 + portsize + 1 + 1 + 16 + TRANS.len);
00516     if (newuri == NULL) {
00517         LM_ERR("no pkg memory\n");
00518         return -1;
00519     }    
00520     buffer = newuri->s;
00521 
00522     if (format == 1) {
00523       *buffer++ = '<';
00524     }
00525     *buffer++ = 's';
00526     *buffer++ = 'i';
00527     *buffer++ = 'p';
00528     *buffer++ = ':';
00529 
00530     memcpy(buffer, called, calledsize);
00531     buffer += calledsize;
00532     *buffer++ = '@';
00533     
00534     if (*dest == '[') {
00535         /* leave out annoying [] */
00536         memcpy(buffer, dest + 1, destsize - 2);
00537         buffer += destsize - 2;
00538     } else {
00539         memcpy(buffer, dest, destsize);
00540         buffer += destsize;
00541     }
00542     
00543     if (portsize > 0) {
00544         *buffer++ = ':';
00545         memcpy(buffer, port, portsize);
00546         buffer += portsize;
00547     }
00548 
00549     if (format == 1) {
00550       *buffer++ = '>';
00551     }
00552 
00553 /*    
00554     *buffer++ = ' ';
00555     *buffer++ = 'S';
00556     *buffer++ = 'I';
00557     *buffer++ = 'P';
00558     *buffer++ = '/';
00559     *buffer++ = '2';
00560     *buffer++ = '.';
00561     *buffer++ = '0';
00562 
00563     memcpy(buffer, TRANS.s, TRANS.len);
00564     buffer += TRANS.len;
00565     *buffer = '\0';
00566 */
00567 
00568     newuri->len = buffer - newuri->s;
00569 
00570     LM_DBG("new uri '%.*s'\n", newuri->len, newuri->s);
00571 
00572     return 0;
00573 }
00574 
00575 /* 
00576  * Get next hop using the first Route not generated by this proxy or URI from the Request-Line
00577  * param msg SIP message
00578  * param nexthop Next hop IP
00579  * param buffersize Size of nexthop
00580  */
00581 void ospGetNextHop(
00582     struct sip_msg* msg, 
00583     char* nexthop, 
00584     int buffersize)
00585 {
00586     struct hdr_field* hf;
00587     struct sip_uri uri;
00588     rr_t* rt;
00589     int found = 0;
00590 
00591     for (hf = msg->headers; hf; hf = hf->next) {
00592         if (hf->type == HDR_ROUTE_T) {
00593             for (rt = (rr_t*)hf->parsed; rt; rt = rt->next) {
00594                 if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len, &uri) == 0) {
00595                     LM_DBG("host '%.*s' port '%d'\n", uri.host.len, uri.host.s, uri.port_no);
00596 
00597                     if (check_self(&uri.host, uri.port_no ? uri.port_no : SIP_PORT, PROTO_NONE) != 1) {
00598                         LM_DBG("it is NOT me, FOUND!\n");
00599 
00600                         ospCopyStrToBuffer(&uri.host, nexthop, buffersize);
00601                         found = 1;
00602                         break;
00603                     } else {
00604                         LM_DBG("it IS me, keep looking\n");
00605                     }
00606                 } else {
00607                     LM_ERR("failed to parse route uri '%.*s'\n",  
00608                         rt->nameaddr.uri.len, 
00609                         rt->nameaddr.uri.s);
00610                 }
00611             }
00612             if (found == 1) {
00613                 break;
00614             }
00615         }
00616     }
00617 
00618     if (!found) {
00619         LM_DBG("using the Request-Line instead host '%.*s' port '%d'\n",
00620              msg->parsed_uri.host.len,
00621              msg->parsed_uri.host.s,
00622              msg->parsed_uri.port_no);
00623 
00624         ospCopyStrToBuffer(&msg->parsed_uri.host, nexthop, buffersize);
00625         found = 1;
00626     }
00627 }

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