reply.c

Go to the documentation of this file.
00001 /*
00002  * $Id: reply.c 5599 2009-02-12 19:18:14Z miconda $
00003  *
00004  * Send a reply
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * --------
00026  * 2003-01-18: buffer overflow patch committed (Jan on behalf of Maxim)
00027  * 2003-01-21: Errors reported via Error-Info header field - janakj
00028  * 2003-09-11: updated to new build_lump_rpl() interface (bogdan)
00029  * 2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
00030  */
00031 
00032 /*!
00033  * \file
00034  * \brief SIP registrar module - Send a reply
00035  * \ingroup registrar   
00036  */  
00037 
00038 #include <stdio.h>
00039 #include "../../ut.h"
00040 #include "../../parser/msg_parser.h"
00041 #include "../../parser/parse_supported.h"
00042 #include "../../data_lump_rpl.h"
00043 #include "../usrloc/usrloc.h"
00044 #include "rerrno.h"
00045 #include "reg_mod.h"
00046 #include "regtime.h"
00047 #include "reply.h"
00048 
00049 
00050 #define MAX_CONTACT_BUFFER 1024
00051 
00052 #define E_INFO "P-Registrar-Error: "
00053 #define E_INFO_LEN (sizeof(E_INFO) - 1)
00054 
00055 #define CONTACT_BEGIN "Contact: "
00056 #define CONTACT_BEGIN_LEN (sizeof(CONTACT_BEGIN) - 1)
00057 
00058 #define Q_PARAM ";q="
00059 #define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
00060 
00061 #define EXPIRES_PARAM ";expires="
00062 #define EXPIRES_PARAM_LEN (sizeof(EXPIRES_PARAM) - 1)
00063 
00064 #define CONTACT_SEP ", "
00065 #define CONTACT_SEP_LEN (sizeof(CONTACT_SEP) - 1)
00066 
00067 
00068 /*! \brief
00069  * Buffer for Contact header field
00070  */
00071 static struct {
00072    char* buf;
00073    int buf_len;
00074    int data_len;
00075 } contact = {0, 0, 0};
00076 
00077 
00078 /*! \brief
00079  * Calculate the length of buffer needed to
00080  * print contacts
00081  */
00082 static inline unsigned int calc_buf_len(ucontact_t* c)
00083 {
00084    unsigned int len;
00085    int qlen;
00086 
00087    len = 0;
00088    while(c) {
00089       if (VALID_CONTACT(c, act_time)) {
00090          if (len) len += CONTACT_SEP_LEN;
00091          len += 2 /* < > */ + c->c.len;
00092          qlen = len_q(c->q);
00093          if (qlen) len += Q_PARAM_LEN + qlen;
00094          len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN;
00095          if (c->received.s) {
00096             len += 1 /* ; */ 
00097                + rcv_param.len 
00098                + 1 /* = */ 
00099                + 1 /* dquote */ 
00100                + c->received.len
00101                + 1 /* dquote */
00102                ;
00103          }
00104       }
00105       c = c->next;
00106    }
00107 
00108    if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN;
00109    return len;
00110 }
00111 
00112 
00113 /*! \brief
00114  * Allocate a memory buffer and print Contact
00115  * header fields into it
00116  */
00117 int build_contact(ucontact_t* c)
00118 {
00119    char *p, *cp;
00120    int fl, len;
00121 
00122    contact.data_len = calc_buf_len(c);
00123    if (!contact.data_len) return 0;
00124 
00125    if (!contact.buf || (contact.buf_len < contact.data_len)) {
00126       if (contact.buf) pkg_free(contact.buf);
00127       contact.buf = (char*)pkg_malloc(contact.data_len);
00128       if (!contact.buf) {
00129          contact.data_len = 0;
00130          contact.buf_len = 0;
00131          LM_ERR("no pkg memory left\n");
00132          return -1;
00133       } else {
00134          contact.buf_len = contact.data_len;
00135       }
00136    }
00137 
00138    p = contact.buf;
00139    
00140    memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN);
00141    p += CONTACT_BEGIN_LEN;
00142 
00143    fl = 0;
00144    while(c) {
00145       if (VALID_CONTACT(c, act_time)) {
00146          if (fl) {
00147             memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN);
00148             p += CONTACT_SEP_LEN;
00149          } else {
00150             fl = 1;
00151          }
00152 
00153          *p++ = '<';
00154          memcpy(p, c->c.s, c->c.len);
00155          p += c->c.len;
00156          *p++ = '>';
00157 
00158          len = len_q(c->q);
00159          if (len) {
00160             memcpy(p, Q_PARAM, Q_PARAM_LEN);
00161             p += Q_PARAM_LEN;
00162             memcpy(p, q2str(c->q, 0), len);
00163             p += len;
00164          }
00165 
00166          memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN);
00167          p += EXPIRES_PARAM_LEN;
00168          cp = int2str((int)(c->expires - act_time), &len);
00169          memcpy(p, cp, len);
00170          p += len;
00171 
00172          if (c->received.s) {
00173             *p++ = ';';
00174             memcpy(p, rcv_param.s, rcv_param.len);
00175             p += rcv_param.len;
00176             *p++ = '=';
00177             *p++ = '\"';
00178             memcpy(p, c->received.s, c->received.len);
00179             p += c->received.len;
00180             *p++ = '\"';
00181          }
00182       }
00183 
00184       c = c->next;
00185    }
00186 
00187    memcpy(p, CRLF, CRLF_LEN);
00188    p += CRLF_LEN;
00189 
00190    contact.data_len = p - contact.buf;
00191 
00192    LM_DBG("created Contact HF: %.*s\n", contact.data_len, contact.buf);
00193    return 0;
00194 }
00195 
00196 
00197 #define MSG_200 "OK"
00198 #define MSG_400 "Bad Request"
00199 #define MSG_420 "Bad Extension"
00200 #define MSG_500 "Server Internal Error"
00201 #define MSG_503 "Service Unavailable"
00202 
00203 #define EI_R_FINE       "No problem"                                /* R_FINE */
00204 #define EI_R_UL_DEL_R   "usrloc_record_delete failed"               /* R_UL_DEL_R */
00205 #define  EI_R_UL_GET_R   "usrloc_record_get failed"                  /* R_UL_GET */
00206 #define  EI_R_UL_NEW_R   "usrloc_record_new failed"                  /* R_UL_NEW_R */
00207 #define  EI_R_INV_CSEQ   "Invalid CSeq number"                       /* R_INV_CSEQ */
00208 #define  EI_R_UL_INS_C   "usrloc_contact_insert failed"              /* R_UL_INS_C */
00209 #define  EI_R_UL_INS_R   "usrloc_record_insert failed"               /* R_UL_INS_R */
00210 #define  EI_R_UL_DEL_C   "usrloc_contact_delete failed"              /* R_UL_DEL_C */
00211 #define  EI_R_UL_UPD_C   "usrloc_contact_update failed"              /* R_UL_UPD_C */
00212 #define  EI_R_TO_USER    "No username in To URI"                     /* R_TO_USER */
00213 #define  EI_R_AOR_LEN    "Address Of Record too long"                /* R_AOR_LEN */
00214 #define  EI_R_AOR_PARSE  "Error while parsing AOR"                   /* R_AOR_PARSE */
00215 #define  EI_R_INV_EXP    "Invalid expires param in contact"          /* R_INV_EXP */
00216 #define  EI_R_INV_Q      "Invalid q param in contact"                /* R_INV_Q */
00217 #define  EI_R_PARSE      "Message parse error"                       /* R_PARSE */
00218 #define  EI_R_TO_MISS    "To header not found"                       /* R_TO_MISS */
00219 #define  EI_R_CID_MISS   "Call-ID header not found"                  /* R_CID_MISS */
00220 #define  EI_R_CS_MISS    "CSeq header not found"                     /* R_CS_MISS */ 
00221 #define  EI_R_PARSE_EXP "Expires parse error"                       /* R_PARSE_EXP */
00222 #define  EI_R_PARSE_CONT   "Contact parse error"                       /* R_PARSE_CONT */
00223 #define  EI_R_STAR_EXP  "* used in contact and expires is not zero" /* R_STAR__EXP */
00224 #define  EI_R_STAR_CONT "* used in contact and more than 1 contact" /* R_STAR_CONT */
00225 #define  EI_R_OOO "Out of order request"                      /* R_OOO */
00226 #define  EI_R_RETRANS   "Retransmission"                            /* R_RETRANS */
00227 #define EI_R_UNESCAPE   "Error while unescaping username"           /* R_UNESCAPE */
00228 #define EI_R_TOO_MANY   "Too many registered contacts"              /* R_TOO_MANY */
00229 #define EI_R_CONTACT_LEN  "Contact/received too long"               /* R_CONTACT_LEN */
00230 #define EI_R_CALLID_LEN  "Callid too long"                          /* R_CALLID_LEN */
00231 #define EI_R_PARSE_PATH  "Path parse error"                         /* R_PARSE_PATH */
00232 #define EI_R_PATH_UNSUP  "No support for found Path indicated"      /* R_PATH_UNSUP */
00233 
00234 str error_info[] = {
00235    {EI_R_FINE,       sizeof(EI_R_FINE) - 1},
00236    {EI_R_UL_DEL_R,   sizeof(EI_R_UL_DEL_R) - 1},
00237    {EI_R_UL_GET_R,   sizeof(EI_R_UL_GET_R) - 1},
00238    {EI_R_UL_NEW_R,   sizeof(EI_R_UL_NEW_R) - 1},
00239    {EI_R_INV_CSEQ,   sizeof(EI_R_INV_CSEQ) - 1},
00240    {EI_R_UL_INS_C,   sizeof(EI_R_UL_INS_C) - 1},
00241    {EI_R_UL_INS_R,   sizeof(EI_R_UL_INS_R) - 1},
00242    {EI_R_UL_DEL_C,   sizeof(EI_R_UL_DEL_C) - 1},
00243    {EI_R_UL_UPD_C,   sizeof(EI_R_UL_UPD_C) - 1},
00244    {EI_R_TO_USER,    sizeof(EI_R_TO_USER) - 1},
00245    {EI_R_AOR_LEN,    sizeof(EI_R_AOR_LEN) - 1},
00246    {EI_R_AOR_PARSE,  sizeof(EI_R_AOR_PARSE) - 1},
00247    {EI_R_INV_EXP,    sizeof(EI_R_INV_EXP) - 1},
00248    {EI_R_INV_Q,      sizeof(EI_R_INV_Q) - 1},
00249    {EI_R_PARSE,      sizeof(EI_R_PARSE) - 1},
00250    {EI_R_TO_MISS,    sizeof(EI_R_TO_MISS) - 1},
00251    {EI_R_CID_MISS,   sizeof(EI_R_CID_MISS) - 1},
00252    {EI_R_CS_MISS,    sizeof(EI_R_CS_MISS) - 1},
00253    {EI_R_PARSE_EXP,  sizeof(EI_R_PARSE_EXP) - 1},
00254    {EI_R_PARSE_CONT, sizeof(EI_R_PARSE_CONT) - 1},
00255    {EI_R_STAR_EXP,   sizeof(EI_R_STAR_EXP) - 1},
00256    {EI_R_STAR_CONT,  sizeof(EI_R_STAR_CONT) - 1},
00257    {EI_R_OOO,        sizeof(EI_R_OOO) - 1},
00258    {EI_R_RETRANS,    sizeof(EI_R_RETRANS) - 1},
00259    {EI_R_UNESCAPE,   sizeof(EI_R_UNESCAPE) - 1},
00260    {EI_R_TOO_MANY,   sizeof(EI_R_TOO_MANY) - 1},
00261    {EI_R_CONTACT_LEN,sizeof(EI_R_CONTACT_LEN) - 1},
00262    {EI_R_CALLID_LEN, sizeof(EI_R_CALLID_LEN) - 1},
00263    {EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1},
00264    {EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1}
00265 
00266 };
00267 
00268 int codes[] = {
00269    200, /* R_FINE */
00270    500, /* R_UL_DEL_R */
00271    500, /* R_UL_GET */
00272    500, /* R_UL_NEW_R */
00273    400, /* R_INV_CSEQ */
00274    500, /* R_UL_INS_C */
00275    500, /* R_UL_INS_R */
00276    500, /* R_UL_DEL_C */
00277    500, /* R_UL_UPD_C */
00278    400, /* R_TO_USER */
00279    500, /* R_AOR_LEN */
00280    400, /* R_AOR_PARSE */
00281    400, /* R_INV_EXP */
00282    400, /* R_INV_Q */
00283    400, /* R_PARSE */
00284    400, /* R_TO_MISS */
00285    400, /* R_CID_MISS */
00286    400, /* R_CS_MISS */
00287    400, /* R_PARSE_EXP */
00288    400, /* R_PARSE_CONT */
00289    400, /* R_STAR_EXP */
00290    400, /* R_STAR_CONT */
00291    200, /* R_OOO */
00292    200, /* R_RETRANS */
00293    400, /* R_UNESCAPE */
00294    503, /* R_TOO_MANY */
00295    400, /* R_CONTACT_LEN */
00296    400, /* R_CALLID_LEN */
00297    400, /* R_PARSE_PATH */
00298    420  /* R_PATH_UNSUP */
00299 
00300 };
00301 
00302 
00303 #define RETRY_AFTER "Retry-After: "
00304 #define RETRY_AFTER_LEN (sizeof(RETRY_AFTER) - 1)
00305 
00306 static int add_retry_after(struct sip_msg* _m)
00307 {
00308    char* buf, *ra_s;
00309    int ra_len;
00310    
00311    ra_s = int2str(retry_after, &ra_len);
00312    buf = (char*)pkg_malloc(RETRY_AFTER_LEN + ra_len + CRLF_LEN);
00313    if (!buf) {
00314       LM_ERR("no pkg memory left\n");
00315       return -1;
00316    }
00317    memcpy(buf, RETRY_AFTER, RETRY_AFTER_LEN);
00318    memcpy(buf + RETRY_AFTER_LEN, ra_s, ra_len);
00319    memcpy(buf + RETRY_AFTER_LEN + ra_len, CRLF, CRLF_LEN);
00320    add_lump_rpl(_m, buf, RETRY_AFTER_LEN + ra_len + CRLF_LEN,
00321            LUMP_RPL_HDR | LUMP_RPL_NODUP);
00322    return 0;
00323 }
00324 
00325 #define PATH "Path: "
00326 #define PATH_LEN (sizeof(PATH) - 1)
00327 
00328 static int add_path(struct sip_msg* _m, str* _p)
00329 {
00330    char* buf;
00331 
00332    buf = (char*)pkg_malloc(PATH_LEN + _p->len + CRLF_LEN);
00333    if (!buf) {
00334       LM_ERR("no pkg memory left\n");
00335       return -1;
00336    }
00337    memcpy(buf, PATH, PATH_LEN);
00338    memcpy(buf + PATH_LEN, _p->s, _p->len);
00339    memcpy(buf + PATH_LEN + _p->len, CRLF, CRLF_LEN);
00340    add_lump_rpl(_m, buf, PATH_LEN + _p->len + CRLF_LEN,
00341            LUMP_RPL_HDR | LUMP_RPL_NODUP);
00342    return 0;
00343 }
00344 
00345 #define UNSUPPORTED "Unsupported: "
00346 #define UNSUPPORTED_LEN (sizeof(UNSUPPORTED) - 1)
00347 
00348 static int add_unsupported(struct sip_msg* _m, str* _p)
00349 {
00350    char* buf;
00351 
00352    buf = (char*)pkg_malloc(UNSUPPORTED_LEN + _p->len + CRLF_LEN);
00353    if (!buf) {
00354       LM_ERR("no pkg memory left\n");
00355       return -1;
00356    }
00357    memcpy(buf, UNSUPPORTED, UNSUPPORTED_LEN);
00358    memcpy(buf + UNSUPPORTED_LEN, _p->s, _p->len);
00359    memcpy(buf + UNSUPPORTED_LEN + _p->len, CRLF, CRLF_LEN);
00360    add_lump_rpl(_m, buf, UNSUPPORTED_LEN + _p->len + CRLF_LEN,
00361            LUMP_RPL_HDR | LUMP_RPL_NODUP);
00362    return 0;
00363 }
00364  
00365 /*! \brief
00366  * Send a reply
00367  */
00368 int send_reply(struct sip_msg* _m)
00369 {
00370    str unsup = str_init(SUPPORTED_PATH_STR);
00371    long code;
00372    str msg = str_init(MSG_200); /* makes gcc shut up */
00373    char* buf;
00374 
00375    if (contact.data_len > 0) {
00376       add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
00377       contact.data_len = 0;
00378    }
00379          
00380    if (rerrno == R_FINE && path_enabled && _m->path_vec.s) {
00381       if (path_mode != PATH_MODE_OFF) {
00382          if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) {
00383             rerrno = R_PATH_UNSUP;
00384             if (add_unsupported(_m, &unsup) < 0)
00385                return -1;
00386             if (add_path(_m, &_m->path_vec) < 0)
00387                return -1;
00388          }
00389          else if (get_supported(_m) & F_SUPPORTED_PATH) {
00390             if (add_path(_m, &_m->path_vec) < 0)
00391                return -1;
00392          } else if (path_mode == PATH_MODE_STRICT) {
00393             rerrno = R_PATH_UNSUP;
00394             if (add_unsupported(_m, &unsup) < 0)
00395                return -1;
00396             if (add_path(_m, &_m->path_vec) < 0)
00397                return -1;
00398          }
00399       }
00400    }
00401 
00402    code = codes[rerrno];
00403    switch(code) {
00404    case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1; break;
00405    case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
00406    case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
00407    case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
00408    case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
00409    }
00410    
00411    if (code != 200) {
00412       buf = (char*)pkg_malloc(E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1);
00413       if (!buf) {
00414          LM_ERR("no pkg memory left\n");
00415          return -1;
00416       }
00417       memcpy(buf, E_INFO, E_INFO_LEN);
00418       memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len);
00419       memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN);
00420       add_lump_rpl( _m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN,
00421          LUMP_RPL_HDR|LUMP_RPL_NODUP);
00422 
00423       if (code >= 500 && code < 600 && retry_after) {
00424          if (add_retry_after(_m) < 0) {
00425             return -1;
00426          }
00427       } 
00428    }
00429    
00430    if (slb.send_reply(_m, code, &msg) == -1) {
00431       LM_ERR("failed to send %ld %.*s\n", code, msg.len,msg.s);
00432       return -1;
00433    } else return 0;
00434 }
00435 
00436 
00437 /*! \brief
00438  * Release contact buffer if any
00439  */
00440 void free_contact_buf(void)
00441 {
00442    if (contact.buf) {
00443       pkg_free(contact.buf);
00444       contact.buf = 0;
00445       contact.buf_len = 0;
00446       contact.data_len = 0;
00447    }
00448 }

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