00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00069
00070
00071 static struct {
00072 char* buf;
00073 int buf_len;
00074 int data_len;
00075 } contact = {0, 0, 0};
00076
00077
00078
00079
00080
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
00100 + c->received.len
00101 + 1
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
00114
00115
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"
00204 #define EI_R_UL_DEL_R "usrloc_record_delete failed"
00205 #define EI_R_UL_GET_R "usrloc_record_get failed"
00206 #define EI_R_UL_NEW_R "usrloc_record_new failed"
00207 #define EI_R_INV_CSEQ "Invalid CSeq number"
00208 #define EI_R_UL_INS_C "usrloc_contact_insert failed"
00209 #define EI_R_UL_INS_R "usrloc_record_insert failed"
00210 #define EI_R_UL_DEL_C "usrloc_contact_delete failed"
00211 #define EI_R_UL_UPD_C "usrloc_contact_update failed"
00212 #define EI_R_TO_USER "No username in To URI"
00213 #define EI_R_AOR_LEN "Address Of Record too long"
00214 #define EI_R_AOR_PARSE "Error while parsing AOR"
00215 #define EI_R_INV_EXP "Invalid expires param in contact"
00216 #define EI_R_INV_Q "Invalid q param in contact"
00217 #define EI_R_PARSE "Message parse error"
00218 #define EI_R_TO_MISS "To header not found"
00219 #define EI_R_CID_MISS "Call-ID header not found"
00220 #define EI_R_CS_MISS "CSeq header not found"
00221 #define EI_R_PARSE_EXP "Expires parse error"
00222 #define EI_R_PARSE_CONT "Contact parse error"
00223 #define EI_R_STAR_EXP "* used in contact and expires is not zero"
00224 #define EI_R_STAR_CONT "* used in contact and more than 1 contact"
00225 #define EI_R_OOO "Out of order request"
00226 #define EI_R_RETRANS "Retransmission"
00227 #define EI_R_UNESCAPE "Error while unescaping username"
00228 #define EI_R_TOO_MANY "Too many registered contacts"
00229 #define EI_R_CONTACT_LEN "Contact/received too long"
00230 #define EI_R_CALLID_LEN "Callid too long"
00231 #define EI_R_PARSE_PATH "Path parse error"
00232 #define EI_R_PATH_UNSUP "No support for found Path indicated"
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,
00270 500,
00271 500,
00272 500,
00273 400,
00274 500,
00275 500,
00276 500,
00277 500,
00278 400,
00279 500,
00280 400,
00281 400,
00282 400,
00283 400,
00284 400,
00285 400,
00286 400,
00287 400,
00288 400,
00289 400,
00290 400,
00291 200,
00292 200,
00293 400,
00294 503,
00295 400,
00296 400,
00297 400,
00298 420
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
00366
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);
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
00438
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 }