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
00038 #include <stdio.h>
00039 #include "../../ut.h"
00040 #include "../../xavp.h"
00041 #include "../../parser/msg_parser.h"
00042 #include "../../lib/kcore/parse_supported.h"
00043 #include "../../data_lump_rpl.h"
00044 #include "../usrloc/usrloc.h"
00045 #include "rerrno.h"
00046 #include "reg_mod.h"
00047 #include "regtime.h"
00048 #include "reply.h"
00049 #include "config.h"
00050
00051 #define MAX_CONTACT_BUFFER 1024
00052
00053 #define E_INFO "P-Registrar-Error: "
00054 #define E_INFO_LEN (sizeof(E_INFO) - 1)
00055
00056 #define CONTACT_BEGIN "Contact: "
00057 #define CONTACT_BEGIN_LEN (sizeof(CONTACT_BEGIN) - 1)
00058
00059 #define Q_PARAM ";q="
00060 #define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
00061
00062 #define EXPIRES_PARAM ";expires="
00063 #define EXPIRES_PARAM_LEN (sizeof(EXPIRES_PARAM) - 1)
00064
00065 #define CONTACT_SEP ", "
00066 #define CONTACT_SEP_LEN (sizeof(CONTACT_SEP) - 1)
00067
00068 #define GR_PARAM ";gr="
00069 #define GR_PARAM_LEN (sizeof(GR_PARAM) - 1)
00070
00071 #define SIP_INSTANCE_PARAM ";+sip.instance="
00072 #define SIP_INSTANCE_PARAM_LEN (sizeof(SIP_INSTANCE_PARAM) - 1)
00073
00074 #define PUB_GRUU_PARAM ";pub-gruu="
00075 #define PUB_GRUU_PARAM_LEN (sizeof(PUB_GRUU_PARAM) - 1)
00076
00077 #define TMP_GRUU_PARAM ";temp-gruu="
00078 #define TMP_GRUU_PARAM_LEN (sizeof(TMP_GRUU_PARAM) - 1)
00079
00080 #define REG_ID_PARAM ";reg-id="
00081 #define REG_ID_PARAM_LEN (sizeof(REG_ID_PARAM) - 1)
00082
00083 extern int reg_gruu_enabled;
00084
00088 static struct {
00089 char* buf;
00090 int buf_len;
00091 int data_len;
00092 } contact = {0, 0, 0};
00093
00094
00100 static inline unsigned int calc_buf_len(ucontact_t* c, str *host, int mode)
00101 {
00102 unsigned int len;
00103 int qlen;
00104
00105 len = 0;
00106 while(c) {
00107 if (VALID_CONTACT(c, act_time)) {
00108 if (len) len += CONTACT_SEP_LEN;
00109 len += 2 + c->c.len;
00110 qlen = len_q(c->q);
00111 if (qlen) len += Q_PARAM_LEN + qlen;
00112 len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN;
00113 if (c->received.s) {
00114 len += 1
00115 + rcv_param.len
00116 + 1
00117 + 1
00118 + c->received.len
00119 + 1
00120 ;
00121 }
00122 if (reg_gruu_enabled==1 && c->instance.len>0 && mode==1) {
00123
00124 len += PUB_GRUU_PARAM_LEN
00125 + 1
00126 + 4
00127 + c->aor->len
00128 + 1
00129 + host->len
00130 + GR_PARAM_LEN
00131 + c->instance.len
00132 + 1
00133 ;
00134
00135 len += TMP_GRUU_PARAM_LEN
00136 + 1
00137 + 4
00138 + c->ruid.len
00139 + 1
00140 + 8
00141 + 1
00142 + host->len
00143 + GR_PARAM_LEN
00144 - 1
00145 + 1
00146 ;
00147 }
00148 if (c->instance.len>0) {
00149
00150 len += SIP_INSTANCE_PARAM_LEN
00151 + 1
00152 + c->instance.len
00153 + 1
00154 ;
00155 }
00156 if (c->reg_id>0) {
00157
00158 len += REG_ID_PARAM_LEN + INT2STR_MAX_LEN;
00159 }
00160 }
00161 c = c->next;
00162 }
00163
00164 if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN;
00165 return len;
00166 }
00167
00168
00173 int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
00174 {
00175 char *p, *cp;
00176 char *a;
00177 int fl, len;
00178 str user;
00179 str inst;
00180 unsigned int ahash;
00181 unsigned short digit;
00182 int mode;
00183 sr_xavp_t *xavp=NULL;
00184 sr_xavp_t *list=NULL;
00185 str xname = {"ruid", 4};
00186 sr_xval_t xval;
00187
00188
00189
00190 if(msg!=NULL && parse_supported(msg)==0
00191 && (get_supported(msg) & F_SUPPORTED_GRUU))
00192 mode = 1;
00193 else
00194 mode = 0;
00195
00196 contact.data_len = calc_buf_len(c, host, mode);
00197
00198 if (!contact.data_len) return 0;
00199
00200 if (!contact.buf || (contact.buf_len < contact.data_len)) {
00201 if (contact.buf) pkg_free(contact.buf);
00202 contact.buf = (char*)pkg_malloc(contact.data_len);
00203 if (!contact.buf) {
00204 contact.data_len = 0;
00205 contact.buf_len = 0;
00206 LM_ERR("no pkg memory left\n");
00207 return -1;
00208 } else {
00209 contact.buf_len = contact.data_len;
00210 }
00211 }
00212
00213 p = contact.buf;
00214
00215 memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN);
00216 p += CONTACT_BEGIN_LEN;
00217
00218
00219 if(reg_xavp_rcd.s!=NULL)
00220 {
00221 list = xavp_get(®_xavp_rcd, NULL);
00222 xavp = list;
00223 }
00224
00225 fl = 0;
00226 while(c) {
00227 if (VALID_CONTACT(c, act_time)) {
00228 if (fl) {
00229 memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN);
00230 p += CONTACT_SEP_LEN;
00231 } else {
00232 fl = 1;
00233 }
00234
00235 *p++ = '<';
00236 memcpy(p, c->c.s, c->c.len);
00237 p += c->c.len;
00238 *p++ = '>';
00239
00240 len = len_q(c->q);
00241 if (len) {
00242 memcpy(p, Q_PARAM, Q_PARAM_LEN);
00243 p += Q_PARAM_LEN;
00244 memcpy(p, q2str(c->q, 0), len);
00245 p += len;
00246 }
00247
00248 memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN);
00249 p += EXPIRES_PARAM_LEN;
00250 cp = int2str((int)(c->expires - act_time), &len);
00251 memcpy(p, cp, len);
00252 p += len;
00253
00254 if (c->received.s) {
00255 *p++ = ';';
00256 memcpy(p, rcv_param.s, rcv_param.len);
00257 p += rcv_param.len;
00258 *p++ = '=';
00259 *p++ = '\"';
00260 memcpy(p, c->received.s, c->received.len);
00261 p += c->received.len;
00262 *p++ = '\"';
00263 }
00264 if (reg_gruu_enabled==1 && c->instance.len>0 && mode==1) {
00265 user.s = c->aor->s;
00266 a = memchr(c->aor->s, '@', c->aor->len);
00267 if(a!=NULL) {
00268 user.len = a - user.s;
00269 } else {
00270 user.len = c->aor->len;
00271 }
00272
00273 memcpy(p, PUB_GRUU_PARAM, PUB_GRUU_PARAM_LEN);
00274 p += PUB_GRUU_PARAM_LEN;
00275 *p++ = '\"';
00276 memcpy(p, "sip:", 4);
00277 p += 4;
00278 if(a!=NULL) {
00279 memcpy(p, c->aor->s, c->aor->len);
00280 p += c->aor->len;
00281 } else {
00282 memcpy(p, user.s, user.len);
00283 p += user.len;
00284 *p++ = '@';
00285 memcpy(p, host->s, host->len);
00286 p += host->len;
00287 }
00288 memcpy(p, GR_PARAM, GR_PARAM_LEN);
00289 p += GR_PARAM_LEN;
00290 inst = c->instance;
00291 if(inst.s[0]=='<' && inst.s[inst.len-1]=='>') {
00292 inst.s++;
00293 inst.len -= 2;
00294 }
00295 memcpy(p, inst.s, inst.len);
00296 p += inst.len;
00297 *p++ = '\"';
00298
00299 memcpy(p, TMP_GRUU_PARAM, TMP_GRUU_PARAM_LEN);
00300 p += TMP_GRUU_PARAM_LEN;
00301 *p++ = '\"';
00302 memcpy(p, "sip:", 4);
00303 p += 4;
00304 memcpy(p, c->ruid.s, c->ruid.len);
00305 p += c->ruid.len;
00306 *p++ = '-';
00307 ahash = ul.get_aorhash(c->aor);
00308 while(ahash!=0)
00309 {
00310 digit = ahash & 0x0f;
00311 *p++ = (digit >= 10) ? digit + 'a' - 10 : digit + '0';
00312 ahash >>= 4;
00313 }
00314 *p++ = '@';
00315 memcpy(p, host->s, host->len);
00316 p += host->len;
00317 memcpy(p, GR_PARAM, GR_PARAM_LEN);
00318 p += GR_PARAM_LEN - 1;
00319 *p++ = '\"';
00320 }
00321
00322 if (c->instance.len>0) {
00323
00324 memcpy(p, SIP_INSTANCE_PARAM, SIP_INSTANCE_PARAM_LEN);
00325 p += SIP_INSTANCE_PARAM_LEN;
00326 *p++ = '\"';
00327 memcpy(p, c->instance.s, c->instance.len);
00328 p += c->instance.len;
00329 *p++ = '\"';
00330 }
00331 if (c->reg_id>0) {
00332
00333 memcpy(p, REG_ID_PARAM, REG_ID_PARAM_LEN);
00334 p += REG_ID_PARAM_LEN;
00335 cp = int2str(c->reg_id, &len);
00336 memcpy(p, cp, len);
00337 p += len;
00338 }
00339 if(reg_xavp_rcd.s!=NULL)
00340 {
00341 memset(&xval, 0, sizeof(sr_xval_t));
00342 xval.type = SR_XTYPE_STR;
00343 xval.v.s = c->ruid;
00344 xavp_add_value(&xname, &xval, &xavp);
00345 }
00346 }
00347
00348 c = c->next;
00349 }
00350
00351
00352 if(reg_xavp_rcd.s!=NULL)
00353 {
00354 if(list==NULL)
00355 {
00356
00357 xval.type = SR_XTYPE_XAVP;
00358 xval.v.xavp = xavp;
00359 xavp_add_value(®_xavp_rcd, &xval, NULL);
00360 }
00361 }
00362
00363 memcpy(p, CRLF, CRLF_LEN);
00364 p += CRLF_LEN;
00365
00366 contact.data_len = p - contact.buf;
00367
00368 LM_DBG("created Contact HF: %.*s\n", contact.data_len, contact.buf);
00369 return 0;
00370 }
00371
00372
00373 #define MSG_200 "OK"
00374 #define MSG_400 "Bad Request"
00375 #define MSG_420 "Bad Extension"
00376 #define MSG_500 "Server Internal Error"
00377 #define MSG_503 "Service Unavailable"
00378
00379 #define EI_R_FINE "No problem"
00380 #define EI_R_UL_DEL_R "usrloc_record_delete failed"
00381 #define EI_R_UL_GET_R "usrloc_record_get failed"
00382 #define EI_R_UL_NEW_R "usrloc_record_new failed"
00383 #define EI_R_INV_CSEQ "Invalid CSeq number"
00384 #define EI_R_UL_INS_C "usrloc_contact_insert failed"
00385 #define EI_R_UL_INS_R "usrloc_record_insert failed"
00386 #define EI_R_UL_DEL_C "usrloc_contact_delete failed"
00387 #define EI_R_UL_UPD_C "usrloc_contact_update failed"
00388 #define EI_R_TO_USER "No username in To URI"
00389 #define EI_R_AOR_LEN "Address Of Record too long"
00390 #define EI_R_AOR_PARSE "Error while parsing AOR"
00391 #define EI_R_INV_EXP "Invalid expires param in contact"
00392 #define EI_R_INV_Q "Invalid q param in contact"
00393 #define EI_R_PARSE "Message parse error"
00394 #define EI_R_TO_MISS "To header not found"
00395 #define EI_R_CID_MISS "Call-ID header not found"
00396 #define EI_R_CS_MISS "CSeq header not found"
00397 #define EI_R_PARSE_EXP "Expires parse error"
00398 #define EI_R_PARSE_CONT "Contact parse error"
00399 #define EI_R_STAR_EXP "* used in contact and expires is not zero"
00400 #define EI_R_STAR_CONT "* used in contact and more than 1 contact"
00401 #define EI_R_OOO "Out of order request"
00402 #define EI_R_RETRANS "Retransmission"
00403 #define EI_R_UNESCAPE "Error while unescaping username"
00404 #define EI_R_TOO_MANY "Too many registered contacts"
00405 #define EI_R_CONTACT_LEN "Contact/received too long"
00406 #define EI_R_CALLID_LEN "Callid too long"
00407 #define EI_R_PARSE_PATH "Path parse error"
00408 #define EI_R_PATH_UNSUP "No support for found Path indicated"
00409
00410 str error_info[] = {
00411 {EI_R_FINE, sizeof(EI_R_FINE) - 1},
00412 {EI_R_UL_DEL_R, sizeof(EI_R_UL_DEL_R) - 1},
00413 {EI_R_UL_GET_R, sizeof(EI_R_UL_GET_R) - 1},
00414 {EI_R_UL_NEW_R, sizeof(EI_R_UL_NEW_R) - 1},
00415 {EI_R_INV_CSEQ, sizeof(EI_R_INV_CSEQ) - 1},
00416 {EI_R_UL_INS_C, sizeof(EI_R_UL_INS_C) - 1},
00417 {EI_R_UL_INS_R, sizeof(EI_R_UL_INS_R) - 1},
00418 {EI_R_UL_DEL_C, sizeof(EI_R_UL_DEL_C) - 1},
00419 {EI_R_UL_UPD_C, sizeof(EI_R_UL_UPD_C) - 1},
00420 {EI_R_TO_USER, sizeof(EI_R_TO_USER) - 1},
00421 {EI_R_AOR_LEN, sizeof(EI_R_AOR_LEN) - 1},
00422 {EI_R_AOR_PARSE, sizeof(EI_R_AOR_PARSE) - 1},
00423 {EI_R_INV_EXP, sizeof(EI_R_INV_EXP) - 1},
00424 {EI_R_INV_Q, sizeof(EI_R_INV_Q) - 1},
00425 {EI_R_PARSE, sizeof(EI_R_PARSE) - 1},
00426 {EI_R_TO_MISS, sizeof(EI_R_TO_MISS) - 1},
00427 {EI_R_CID_MISS, sizeof(EI_R_CID_MISS) - 1},
00428 {EI_R_CS_MISS, sizeof(EI_R_CS_MISS) - 1},
00429 {EI_R_PARSE_EXP, sizeof(EI_R_PARSE_EXP) - 1},
00430 {EI_R_PARSE_CONT, sizeof(EI_R_PARSE_CONT) - 1},
00431 {EI_R_STAR_EXP, sizeof(EI_R_STAR_EXP) - 1},
00432 {EI_R_STAR_CONT, sizeof(EI_R_STAR_CONT) - 1},
00433 {EI_R_OOO, sizeof(EI_R_OOO) - 1},
00434 {EI_R_RETRANS, sizeof(EI_R_RETRANS) - 1},
00435 {EI_R_UNESCAPE, sizeof(EI_R_UNESCAPE) - 1},
00436 {EI_R_TOO_MANY, sizeof(EI_R_TOO_MANY) - 1},
00437 {EI_R_CONTACT_LEN,sizeof(EI_R_CONTACT_LEN) - 1},
00438 {EI_R_CALLID_LEN, sizeof(EI_R_CALLID_LEN) - 1},
00439 {EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1},
00440 {EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1}
00441
00442 };
00443
00444 int codes[] = {
00445 200,
00446 500,
00447 500,
00448 500,
00449 400,
00450 500,
00451 500,
00452 500,
00453 500,
00454 400,
00455 500,
00456 400,
00457 400,
00458 400,
00459 400,
00460 400,
00461 400,
00462 400,
00463 400,
00464 400,
00465 400,
00466 400,
00467 200,
00468 200,
00469 400,
00470 503,
00471 400,
00472 400,
00473 400,
00474 420
00475
00476 };
00477
00478
00479 #define RETRY_AFTER "Retry-After: "
00480 #define RETRY_AFTER_LEN (sizeof(RETRY_AFTER) - 1)
00481
00482 static int add_retry_after(struct sip_msg* _m)
00483 {
00484 char* buf, *ra_s;
00485 int ra_len;
00486
00487 ra_s = int2str(cfg_get(registrar, registrar_cfg, retry_after), &ra_len);
00488 buf = (char*)pkg_malloc(RETRY_AFTER_LEN + ra_len + CRLF_LEN);
00489 if (!buf) {
00490 LM_ERR("no pkg memory left\n");
00491 return -1;
00492 }
00493 memcpy(buf, RETRY_AFTER, RETRY_AFTER_LEN);
00494 memcpy(buf + RETRY_AFTER_LEN, ra_s, ra_len);
00495 memcpy(buf + RETRY_AFTER_LEN + ra_len, CRLF, CRLF_LEN);
00496 add_lump_rpl(_m, buf, RETRY_AFTER_LEN + ra_len + CRLF_LEN,
00497 LUMP_RPL_HDR | LUMP_RPL_NODUP);
00498 return 0;
00499 }
00500
00501 #define PATH "Path: "
00502 #define PATH_LEN (sizeof(PATH) - 1)
00503
00504 static int add_path(struct sip_msg* _m, str* _p)
00505 {
00506 char* buf;
00507
00508 buf = (char*)pkg_malloc(PATH_LEN + _p->len + CRLF_LEN);
00509 if (!buf) {
00510 LM_ERR("no pkg memory left\n");
00511 return -1;
00512 }
00513 memcpy(buf, PATH, PATH_LEN);
00514 memcpy(buf + PATH_LEN, _p->s, _p->len);
00515 memcpy(buf + PATH_LEN + _p->len, CRLF, CRLF_LEN);
00516 add_lump_rpl(_m, buf, PATH_LEN + _p->len + CRLF_LEN,
00517 LUMP_RPL_HDR | LUMP_RPL_NODUP);
00518 return 0;
00519 }
00520
00521 #define UNSUPPORTED "Unsupported: "
00522 #define UNSUPPORTED_LEN (sizeof(UNSUPPORTED) - 1)
00523
00524 static int add_unsupported(struct sip_msg* _m, str* _p)
00525 {
00526 char* buf;
00527
00528 buf = (char*)pkg_malloc(UNSUPPORTED_LEN + _p->len + CRLF_LEN);
00529 if (!buf) {
00530 LM_ERR("no pkg memory left\n");
00531 return -1;
00532 }
00533 memcpy(buf, UNSUPPORTED, UNSUPPORTED_LEN);
00534 memcpy(buf + UNSUPPORTED_LEN, _p->s, _p->len);
00535 memcpy(buf + UNSUPPORTED_LEN + _p->len, CRLF, CRLF_LEN);
00536 add_lump_rpl(_m, buf, UNSUPPORTED_LEN + _p->len + CRLF_LEN,
00537 LUMP_RPL_HDR | LUMP_RPL_NODUP);
00538 return 0;
00539 }
00540
00544 int reg_send_reply(struct sip_msg* _m)
00545 {
00546 str unsup = str_init(SUPPORTED_PATH_STR);
00547 long code;
00548 str msg = str_init(MSG_200);
00549 char* buf;
00550
00551 if (contact.data_len > 0) {
00552 add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
00553 contact.data_len = 0;
00554 }
00555
00556 if (rerrno == R_FINE && path_enabled && _m->path_vec.s) {
00557 if (path_mode != PATH_MODE_OFF) {
00558 if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) {
00559 rerrno = R_PATH_UNSUP;
00560 if (add_unsupported(_m, &unsup) < 0)
00561 return -1;
00562 if (add_path(_m, &_m->path_vec) < 0)
00563 return -1;
00564 }
00565 else if (get_supported(_m) & F_SUPPORTED_PATH) {
00566 if (add_path(_m, &_m->path_vec) < 0)
00567 return -1;
00568 } else if (path_mode == PATH_MODE_STRICT) {
00569 rerrno = R_PATH_UNSUP;
00570 if (add_unsupported(_m, &unsup) < 0)
00571 return -1;
00572 if (add_path(_m, &_m->path_vec) < 0)
00573 return -1;
00574 }
00575 }
00576 }
00577
00578 code = codes[rerrno];
00579 switch(code) {
00580 case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1; break;
00581 case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
00582 case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
00583 case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
00584 case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
00585 }
00586
00587 if (code != 200) {
00588 buf = (char*)pkg_malloc(E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1);
00589 if (!buf) {
00590 LM_ERR("no pkg memory left\n");
00591 return -1;
00592 }
00593 memcpy(buf, E_INFO, E_INFO_LEN);
00594 memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len);
00595 memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN);
00596 add_lump_rpl( _m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN,
00597 LUMP_RPL_HDR|LUMP_RPL_NODUP);
00598
00599 if (code >= 500 && code < 600 && cfg_get(registrar, registrar_cfg, retry_after)) {
00600 if (add_retry_after(_m) < 0) {
00601 return -1;
00602 }
00603 }
00604 }
00605
00606 if (slb.freply(_m, code, &msg) < 0) {
00607 LM_ERR("failed to send %ld %.*s\n", code, msg.len,msg.s);
00608 return -1;
00609 } else return 0;
00610 }
00611
00612
00616 void free_contact_buf(void)
00617 {
00618 if (contact.buf) {
00619 pkg_free(contact.buf);
00620 contact.buf = 0;
00621 contact.buf_len = 0;
00622 contact.data_len = 0;
00623 }
00624 }