int select_msg_first_line(str* res, select_t* s, struct sip_msg* msg) { res->s=SIP_MSG_START(msg); res->len=msg->first_line.len; trim_trailing(res); return 0; }
/** initializes a net structure from a string. * @param dst - net structure that will be filled * @param s - string of the form "ip", "ip/mask_len" or "ip/ip_mak". * @return -1 on error, 0 on succes */ int mk_net_str(struct net* dst, str* s) { struct ip_addr* t; char* p; struct ip_addr ip; str addr; str mask; unsigned int bitlen; /* test for ip only */ t = str2ip(s); if (unlikely(t == 0)) t = str2ip6(s); if (likely(t)) return mk_net_bitlen(dst, t, t->len*8); /* not a simple ip, maybe an ip/netmask pair */ p = q_memchr(s->s, '/', s->len); if (likely(p)) { addr.s = s->s; addr.len = (int)(long)(p - s->s); mask.s = p + 1; mask.len = s->len - (addr.len + 1); /* allow '/' enclosed by whitespace */ trim_trailing(&addr); trim_leading(&mask); t = str2ip(&addr); if (likely(t)) { /* it can be a number */ if (str2int(&mask, &bitlen) == 0) return mk_net_bitlen(dst, t, bitlen); ip = *t; t = str2ip(&mask); if (likely(t)) return mk_net(dst, &ip, t); /* error */ return -1; } else { t = str2ip6(&addr); if (likely(t)) { /* it can be a number */ if (str2int(&mask, &bitlen) == 0) return mk_net_bitlen(dst, t, bitlen); ip = *t; t = str2ip6(&mask); if (likely(t)) return mk_net(dst, &ip, t); /* error */ return -1; } } } return -1; }
/* * Read a line, the result will be stored in line * parameter, the data is not copied, it's just * a pointer to an existing buffer */ int unixsock_read_line(str* line, str* source) { if (!line || !source) { LOG(L_ERR, "unixsock_read_line: Invalid parameter value\n"); return -1; } *line = *source; skip_line(source); line->len = source->s - line->s; trim_trailing(line); if (line->len) { return 0; } else { return 1; } }
/*! \brief * Fills the common part (for all contacts) of the info structure */ static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c, unsigned int _e, unsigned int _f, unsigned int _flags) { static ucontact_info_t ci; static str no_ua = str_init("n/a"); static str callid; static str path_received = {0,0}; static str path; static str received = {0,0}; static int received_found; static unsigned int allowed, allow_parsed; static struct sip_msg *m = 0; int_str val; if (_m!=0) { memset( &ci, 0, sizeof(ucontact_info_t)); /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); if (callid.len > CALLID_MAX_SIZE) { rerrno = R_CALLID_LEN; LM_ERR("callid too long\n"); goto error; } ci.callid = &callid; /* Get CSeq number of the message */ if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) { rerrno = R_INV_CSEQ; LM_ERR("failed to convert cseq number\n"); goto error; } /* set received socket */ if ( _flags®_SAVE_SOCKET_FLAG) { ci.sock = get_sock_hdr(_m); if (ci.sock==0) ci.sock = _m->rcv.bind_address; } else { ci.sock = _m->rcv.bind_address; } /* additional info from message */ if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent && _m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) { ci.user_agent = &_m->user_agent->body; } else { ci.user_agent = &no_ua; } /* extract Path headers */ if ( _flags®_SAVE_PATH_FLAG ) { if (build_path_vector(_m, &path, &path_received, _flags) < 0) { rerrno = R_PARSE_PATH; goto error; } if (path.len && path.s) { ci.path = &path; /* save in msg too for reply */ if (set_path_vector(_m, &path) < 0) { rerrno = R_PARSE_PATH; goto error; } } } ci.last_modified = act_time; /* set flags */ ci.flags = _f; ci.cflags = getb0flags(); /* get received */ if (path_received.len && path_received.s) { ci.cflags |= ul.nat_flag; ci.received = path_received; } allow_parsed = 0; /* not parsed yet */ received_found = 0; /* not found yet */ m = _m; /* remember the message */ } if(_c!=0) { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &ci.q) < 0) { rerrno = R_INV_Q; LM_ERR("failed to calculate q\n"); goto error; } /* set expire time */ ci.expires = _e; /* Get methods of contact */ if (_c->methods) { if (parse_methods(&(_c->methods->body), &ci.methods) < 0) { rerrno = R_PARSE; LM_ERR("failed to parse contact methods\n"); goto error; } } else { /* check on Allow hdr */ if (allow_parsed == 0) { if (m && parse_allow( m ) != -1) { allowed = get_allow_methods(m); } else { allowed = ALL_METHODS; } allow_parsed = 1; } ci.methods = allowed; } /* get received */ if (ci.received.len==0) { if (_c->received) { ci.received = _c->received->body; } else { if (received_found==0) { memset(&val, 0, sizeof(int_str)); if (rcv_avp_name>=0 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0) && val.s.len > 0) { if (val.s.len>RECEIVED_MAX_SIZE) { rerrno = R_CONTACT_LEN; LM_ERR("received too long\n"); goto error; } received = val.s; } else { received.s = 0; received.len = 0; } received_found = 1; } ci.received = received; } } } return &ci; error: return 0; }
/* * Message contained some contacts and appropriate * record was found, so we have to walk through * all contacts and do the following: * 1) If contact in usrloc doesn't exists and * expires > 0, insert new contact * 2) If contact in usrloc exists and expires * > 0, update the contact * 3) If contact in usrloc exists and expires * == 0, delete contact */ static inline int update(struct sip_msg* _m, urecord_t* _r, contact_t* _c, str* _ua) { ucontact_t* c, *c2; str callid; int cseq, e, ret; int set, reset; qvalue_t q; unsigned int nated; str* recv; int_str rcv_avp; int_str val; rcv_avp.n=rcv_avp_no; if (isflagset(_m, nat_flag) == 1) { nated = FL_NAT; } else { nated = FL_NONE; } if (max_contacts) { ret = test_max_contacts(_m, _r, _c); if (ret != 0) { build_contact(_r->contacts); return -1; } } _c = get_first_contact(_m); while(_c) { if (calc_contact_expires(_m, _c->expires, &e) < 0) { build_contact(_r->contacts); LOG(L_ERR, "update(): Error while calculating expires\n"); return -1; } if (ul.get_ucontact(_r, &_c->uri, &c) > 0) { /* Contact not found */ if (e != 0) { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -2; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*) &cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "update(): Error while converting cseq number\n"); return -3; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } if (ul.insert_ucontact(_r, &_c->uri, e, q, &callid, cseq, nated | mem_only, &c2, _ua, recv) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "update(): Error while inserting contact\n"); return -4; } } } else { if (e == 0) { if (mem_only) { c->flags |= FL_MEM; } else { c->flags &= ~FL_MEM; } if (ul.delete_ucontact(_r, c) < 0) { rerrno = R_UL_DEL_C; LOG(L_ERR, "update(): Error while deleting contact\n"); return -5; } } else { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -6; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*)&cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "update(): Error while converting cseq number\n"); return -7; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } set = nated | mem_only; reset = ~(nated | mem_only) & (FL_NAT | FL_MEM); if (ul.update_ucontact(c, e, q, &callid, cseq, set, reset, _ua, recv) < 0) { rerrno = R_UL_UPD_C; LOG(L_ERR, "update(): Error while updating contact\n"); return -8; } if (desc_time_order) { move_on_top(_r, c); } } } _c = get_next_contact(_c); } return 0; }
/* * Message contained some contacts, but record with same address * of record was not found so we have to create a new record * and insert all contacts from the message that have expires * > 0 */ static inline int insert(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _a, str *ua) { urecord_t* r = 0; ucontact_t* c; int e, cseq; qvalue_t q; str callid; unsigned int flags; str* recv; int_str rcv_avp; int_str val; int num; rcv_avp.n=rcv_avp_no; if (isflagset(_m, nat_flag) == 1) flags = FL_NAT; else flags = FL_NONE; flags |= mem_only; num = 0; while(_c) { if (calc_contact_expires(_m, _c->expires, &e) < 0) { LOG(L_ERR, "insert(): Error while calculating expires\n"); return -1; } /* Skip contacts with zero expires */ if (e == 0) goto skip; if (max_contacts && (num >= max_contacts)) { rerrno = R_TOO_MANY; ul.delete_urecord(_d, _a); return -1; } num++; if (r == 0) { if (ul.insert_urecord(_d, _a, &r) < 0) { rerrno = R_UL_NEW_R; LOG(L_ERR, "insert(): Can't insert new record structure\n"); return -2; } } /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "insert(): Error while calculating q\n"); ul.delete_urecord(_d, _a); return -3; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&get_cseq(_m)->number, (unsigned int*)&cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "insert(): Error while converting cseq number\n"); ul.delete_urecord(_d, _a); return -4; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } if (ul.insert_ucontact(r, &_c->uri, e, q, &callid, cseq, flags, &c, ua, recv) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "insert(): Error while inserting contact\n"); ul.delete_urecord(_d, _a); return -5; } skip: _c = get_next_contact(_c); } if (r) { if (!r->contacts) { ul.delete_urecord(_d, _a); } else { build_contact(r->contacts); } } return 0; }
/*! \brief * Fills the common part (for all contacts) of the info structure */ static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c, unsigned int _e, unsigned int _f, int _use_regid) { static ucontact_info_t ci; static str no_ua = str_init("n/a"); static str callid; static str path_received = {0,0}; static str path; static str received = {0,0}; static int received_found; static unsigned int allowed, allow_parsed; static struct sip_msg *m = 0; int_str val; if (_m!=0) { memset( &ci, 0, sizeof(ucontact_info_t)); /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); if (callid.len > CALLID_MAX_SIZE) { rerrno = R_CALLID_LEN; LM_ERR("callid too long\n"); goto error; } ci.callid = &callid; /* Get CSeq number of the message */ if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) { rerrno = R_INV_CSEQ; LM_ERR("failed to convert cseq number\n"); goto error; } /* set received socket */ if (_m->flags&sock_flag) { ci.sock = get_sock_val(_m); if (ci.sock==0) ci.sock = _m->rcv.bind_address; } else { ci.sock = _m->rcv.bind_address; } /* set tcp connection id */ if (_m->rcv.proto==PROTO_TCP || _m->rcv.proto==PROTO_TLS || _m->rcv.proto==PROTO_WS || _m->rcv.proto==PROTO_WSS) { ci.tcpconn_id = _m->rcv.proto_reserved1; } else { ci.tcpconn_id = -1; } /* additional info from message */ if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent && _m->user_agent->body.len>0 && _m->user_agent->body.len<MAX_UA_SIZE) { ci.user_agent = &_m->user_agent->body; } else { ci.user_agent = &no_ua; } /* extract Path headers */ if (path_enabled) { if (build_path_vector(_m, &path, &path_received) < 0) { rerrno = R_PARSE_PATH; goto error; } if (path.len && path.s) { ci.path = &path; if (path_mode != PATH_MODE_OFF) { /* save in msg too for reply */ if (set_path_vector(_m, &path) < 0) { rerrno = R_PARSE_PATH; goto error; } } } } ci.last_modified = act_time; /* set flags */ ci.flags = _f; getbflagsval(0, &ci.cflags); /* get received */ if (path_received.len && path_received.s) { ci.cflags |= ul.nat_flag; ci.received = path_received; } allow_parsed = 0; /* not parsed yet */ received_found = 0; /* not found yet */ m = _m; /* remember the message */ } else { memset( &ci.instance, 0, sizeof(str)); } if(_c!=0) { /* hook uri address - should be more than 'sip:' chars */ if(_c->uri.s!=NULL && _c->uri.len>4) ci.c = &_c->uri; /* Calculate q value of the contact */ if (m && m->id == q_override_msg_id) { ci.q = q_override_value; } else if (calc_contact_q(_c->q, &ci.q) < 0) { rerrno = R_INV_Q; LM_ERR("failed to calculate q\n"); goto error; } /* set expire time */ ci.expires = _e; /* Get methods of contact */ if (_c->methods) { if (parse_methods(&(_c->methods->body), &ci.methods) < 0) { rerrno = R_PARSE; LM_ERR("failed to parse contact methods\n"); goto error; } } else { /* check on Allow hdr */ if (allow_parsed == 0) { if (m && parse_allow( m ) != -1) { allowed = get_allow_methods(m); } else { allowed = ALL_METHODS; } allow_parsed = 1; } ci.methods = allowed; } /* get received */ if (ci.received.len==0) { if (_c->received) { ci.received = _c->received->body; } else { if (received_found==0) { memset(&val, 0, sizeof(int_str)); if (rcv_avp_name.n!=0 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0) && val.s.len > 0) { if (val.s.len>RECEIVED_MAX_SIZE) { rerrno = R_CONTACT_LEN; LM_ERR("received too long\n"); goto error; } received = val.s; } else { received.s = 0; received.len = 0; } received_found = 1; } ci.received = received; } } if(_c->instance!=NULL && _c->instance->body.len>0) ci.instance = _c->instance->body; if(_use_regid && _c->instance!=NULL && _c->reg_id!=NULL && _c->reg_id->body.len>0) { if(str2int(&_c->reg_id->body, &ci.reg_id)<0 || ci.reg_id==0) { LM_ERR("invalid reg-id value\n"); goto error; } } if(sruid_next(&_reg_sruid)<0) goto error; ci.ruid = _reg_sruid.uid; LM_DBG("generated ruid is: %.*s\n", ci.ruid.len, ci.ruid.s); } return &ci; error: return 0; }
int exec_avp(struct sip_msg *msg, char *cmd, pvname_list_p avpl) { int_str avp_val; int_str avp_name; unsigned short avp_type; FILE *pipe; int ret; char res_line[MAX_URI_SIZE+1]; str res; int exit_status; int i; pvname_list_t* crt; pid_t pid; /* pessimist: assume error by default */ ret=-1; pid = __popen3(cmd, NULL, &pipe, NULL); if (pid < 0) { LM_ERR("failed to run command: %s\n", cmd); ser_error=E_EXEC; return ret; } LM_DBG("Forked pid %d\n", pid); schedule_to_kill(pid); wait(&exit_status); /* read now line by line */ i=0; crt = avpl; while (fgets(res_line, MAX_URI_SIZE, pipe)) { res.s = res_line; res.len=strlen(res.s); trim_trailing(&res); /* skip empty line */ if (res.len==0) continue; /* ZT */ res.s[res.len]=0; avp_type = 0; if(crt==NULL) { avp_name.s.s = int2str(i + 1, &avp_name.s.len); if (!avp_name.s.s) { LM_ERR("cannot convert %d to string\n", i + 1); goto error; } avp_name.n = get_avp_id(&avp_name.s); if (avp_name.n < 0) { LM_ERR("cannot get avp id\n"); goto error; } } else { if(pv_get_avp_name(msg, &(crt->sname.pvp), &avp_name.n, &avp_type)!=0) { LM_ERR("can't get item name [%d]\n",i); goto error; } } avp_type |= AVP_VAL_STR; avp_val.s = res; if(add_avp(avp_type, avp_name.n, avp_val)!=0) { LM_ERR("unable to add avp\n"); goto error; } if(crt) crt = crt->next; i++; } if (i==0) LM_DBG("no result from %s\n", cmd); /* success */ ret=1; error: if (ferror(pipe)) { LM_ERR("pipe: %d/%s\n", errno, strerror(errno)); ser_error=E_EXEC; ret=-1; } pclose(pipe); if (WIFEXITED(exit_status)) { /* exited properly .... */ /* return false if script exited with non-zero status */ if (WEXITSTATUS(exit_status)!=0) ret=-1; } else { /* exited erroneously */ LM_ERR("cmd %s failed. exit_status=%d, errno=%d: %s\n", cmd, exit_status, errno, strerror(errno) ); ret=-1; } return ret; }
int exec_str(struct sip_msg *msg, char *cmd, char *param, int param_len) { int cmd_len; FILE *pipe; char *cmd_line; int ret; int l1; static char uri_line[MAX_URI_SIZE+1]; int uri_cnt; str uri; int exit_status; pid_t pid; /* pessimist: assume error by default */ ret=-1; l1=strlen(cmd); if(param_len>0) cmd_len=l1+param_len+4; else cmd_len=l1+1; cmd_line=pkg_malloc(cmd_len); if (cmd_line==0) { ret=ser_error=E_OUT_OF_MEM; LM_ERR("no pkg mem for command\n"); goto error00; } /* 'command parameter \0' */ memcpy(cmd_line, cmd, l1); if(param_len>0) { cmd_line[l1]=' '; cmd_line[l1+1]='\''; memcpy(cmd_line+l1+2, param, param_len); cmd_line[l1+param_len+2]='\''; cmd_line[l1+param_len+3]=0; } else { cmd_line[l1] = 0; } pid = __popen3(cmd_line, NULL, &pipe, NULL); if (pid < 0) { LM_ERR("failed to run command: %s\n", cmd_line); ser_error=E_EXEC; goto error01; } LM_DBG("Forked pid %d\n", pid); schedule_to_kill(pid); wait(&exit_status); /* read now line by line */ uri_cnt=0; while (fgets(uri_line, MAX_URI_SIZE, pipe)) { uri.s = uri_line; uri.len=strlen(uri.s); trim_trailing(&uri); /* skip empty line */ if (uri.len==0) continue; /* ZT */ uri.s[uri.len]=0; if (uri_cnt==0) { if (set_ruri(msg, &uri)==-1 ) { LM_ERR("failed to set new RURI\n"); ser_error=E_OUT_OF_MEM; goto error02; } } else { if (append_branch(msg, &uri, 0, 0, Q_UNSPECIFIED, 0, 0)==-1) { LM_ERR("append_branch failed; too many or too long URIs?\n"); goto error02; } } uri_cnt++; } if (uri_cnt==0) { LM_ERR("no uri from %s\n", cmd_line ); goto error02; } /* success */ ret=1; error02: if (ferror(pipe)) { LM_ERR("in pipe: %s\n", strerror(errno)); ser_error=E_EXEC; ret=-1; } pclose(pipe); if (WIFEXITED(exit_status)) { /* exited properly .... */ /* return false if script exited with non-zero status */ if (WEXITSTATUS(exit_status)!=0) ret=-1; } else { /* exited erroneously */ LM_ERR("cmd %s failed. exit_status=%d, errno=%d: %s\n", cmd, exit_status, errno, strerror(errno) ); ret=-1; } error01: pkg_free(cmd_line); error00: return ret; }
/* * Message contained some contacts and appropriate * record was found, so we have to walk through * all contacts and do the following: * 1) If contact in usrloc doesn't exists and * expires > 0, insert new contact * 2) If contact in usrloc exists and expires * > 0, update the contact * 3) If contact in usrloc exists and expires * == 0, delete contact */ static inline int update(struct sip_msg* _m, urecord_t* _r, str* aor, contact_t* _c, str* _ua, str* aor_filter) { ucontact_t* c, *c2; str callid; int cseq, e, ret; int set, reset; qvalue_t q; unsigned int nated; str* recv, *inst; if (isflagset(_m, save_nat_flag) == 1) { nated = FL_NAT; } else { nated = FL_NONE; } if (max_contacts) { ret = test_max_contacts(_m, _r, _c); if (ret != 0) { build_contact(_r->contacts, aor_filter); return -1; } } _c = get_first_contact(_m); while(_c) { if (calc_contact_expires(_m, _c->expires, &e) < 0) { build_contact(_r->contacts, aor_filter); LOG(L_ERR, "update(): Error while calculating expires\n"); return -1; } if(_c->instance) { inst = &_c->instance->body; } else { inst = 0; } if (ul.get_ucontact_by_instance(_r, &_c->uri, inst, &c) > 0) { /* Contact not found */ if (e != 0) { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -2; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*) &cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "update(): Error while converting cseq number\n"); return -3; } if (_c->received) { recv = &_c->received->body; } else if (nated & FL_NAT) { if (create_rcv_uri(&recv, _m) < 0) { ERR("Error while creating rcv URI\n"); rerrno = R_UL_INS_C; return -4; } } else { recv = 0; } if (ul.insert_ucontact(_r, aor, &_c->uri, e, q, &callid, cseq, nated | mem_only, &c2, _ua, recv, _m->rcv.bind_address, inst) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "update(): Error while inserting contact\n"); return -4; } } } else { if (e == 0) { if (mem_only) { c->flags |= FL_MEM; } else { c->flags &= ~FL_MEM; } if (ul.delete_ucontact(_r, c) < 0) { rerrno = R_UL_DEL_C; LOG(L_ERR, "update(): Error while deleting contact\n"); return -5; } } else { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -6; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*)&cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "update(): Error while converting cseq number\n"); return -7; } if (_c->received) { recv = &_c->received->body; } else if (nated & FL_NAT) { if (create_rcv_uri(&recv, _m) < 0) { ERR("Error while creating rcv URI\n"); rerrno = R_UL_UPD_C; return -4; } } else { recv = 0; } set = nated | mem_only; reset = ~(nated | mem_only) & (FL_NAT | FL_MEM); if (ul.update_ucontact(c, &_c->uri, aor, e, q, &callid, cseq, set, reset, _ua, recv, _m->rcv.bind_address, inst) < 0) { rerrno = R_UL_UPD_C; LOG(L_ERR, "update(): Error while updating contact\n"); return -8; } } } _c = get_next_contact(_c); } return 0; }
/* * Message contained some contacts, but record with same address * of record was not found so we have to create a new record * and insert all contacts from the message that have expires * > 0 */ static inline int insert(struct sip_msg* _m, str* aor, contact_t* _c, udomain_t* _d, str* _u, str *ua, str* aor_filter) { urecord_t* r = 0; ucontact_t* c; int e, cseq; qvalue_t q; str callid; unsigned int flags; str *recv, *inst; int num; if (isflagset(_m, save_nat_flag) == 1) flags = FL_NAT; else flags = FL_NONE; flags |= mem_only; num = 0; while(_c) { if (calc_contact_expires(_m, _c->expires, &e) < 0) { LOG(L_ERR, "insert(): Error while calculating expires\n"); return -1; } /* Skip contacts with zero expires */ if (e == 0) goto skip; if (max_contacts && (num >= max_contacts)) { rerrno = R_TOO_MANY; ul.delete_urecord(_d, _u); return -1; } num++; if (r == 0) { if (ul.insert_urecord(_d, _u, &r) < 0) { rerrno = R_UL_NEW_R; LOG(L_ERR, "insert(): Can't insert new record structure\n"); return -2; } } /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "insert(): Error while calculating q\n"); ul.delete_urecord(_d, _u); return -3; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&get_cseq(_m)->number, (unsigned int*)&cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "insert(): Error while converting cseq number\n"); ul.delete_urecord(_d, _u); return -4; } if (_c->received) { recv = &_c->received->body; } else if (flags & FL_NAT) { if (create_rcv_uri(&recv, _m) < 0) { ERR("Error while creating rcv URI\n"); ul.delete_urecord(_d, _u); return -4; } } else { recv = 0; } if(_c->instance) { inst = &_c->instance->body; } else { inst = 0; } if (ul.insert_ucontact(r, aor, &_c->uri, e, q, &callid, cseq, flags, &c, ua, recv, _m->rcv.bind_address, inst) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "insert(): Error while inserting contact\n"); ul.delete_urecord(_d, _u); return -5; } skip: _c = get_next_contact(_c); } if (r) { if (!r->contacts) { ul.delete_urecord(_d, _u); } else { build_contact(r->contacts, aor_filter); } } return 0; }
/* * Parse contacts in a Contact HF */ int parse_contacts(str* _s, contact_t** _c) { contact_t* c; contact_t* last; param_hooks_t hooks; last = NULL; while(1) { /* Allocate and clear contact structure */ c = (contact_t*)pkg_malloc(sizeof(contact_t)); if (c == 0) { LM_ERR("no pkg memory left\n"); goto error; } memset(c, 0, sizeof(contact_t)); c->name.s = _s->s; if (skip_name(_s) < 0) { LM_ERR("failed to skip name part\n"); goto error; } c->uri.s = _s->s; c->name.len = _s->s - c->name.s; trim_trailing(&c->name); /* Find the end of the URI */ if (skip_uri(_s) < 0) { LM_ERR("failed to skip URI\n"); goto error; } c->uri.len = _s->s - c->uri.s; /* Calculate URI length */ trim_trailing(&(c->uri)); /* Remove any trailing spaces from URI */ /* Remove <> if any */ if ((c->uri.len >= 2) && (c->uri.s[0] == '<') && (c->uri.s[c->uri.len - 1] == '>')) { c->uri.s++; c->uri.len -= 2; } trim(&c->uri); /* RFC3261 grammar enforces the existance of an URI */ if (c->uri.len==0) { LM_ERR("Empty URI found in contact body\n"); goto error; } if (_s->len == 0) goto ok; if (_s->s[0] == ';') { /* Contact parameter found */ _s->s++; _s->len--; trim_leading(_s); if (_s->len == 0) { LM_ERR("failed to parse params\n"); goto error; } if (parse_params(_s, CLASS_CONTACT, &hooks, &c->params) < 0) { LM_ERR("failed to parse contact parameters\n"); goto error; } c->q = hooks.contact.q; c->expires = hooks.contact.expires; c->received = hooks.contact.received; c->methods = hooks.contact.methods; c->instance = hooks.contact.instance; if (_s->len == 0) goto ok; } /* Next character is comma */ c->len = _s->s - c->name.s; _s->s++; _s->len--; trim_leading(_s); if (_s->len == 0) { LM_ERR("text after comma missing\n"); goto error; } if (last) {last->next=c;} else {*_c = c;} last = c; } error: if (c) pkg_free(c); free_contacts(_c); /* Free any contacts created so far */ return -1; ok: c->len = _s->s - c->name.s; if (last) {last->next=c;} else {*_c = c;} last = c; return 0; }
// Return a trimmed view with no leading or trailing whitespace inline const_string trim(const_string s) { return trim_initial(trim_trailing(s)); }
/* * Message contained some contacts and appropriate * record was found, so we have to walk through * all contacts and do the following: * 1) If contact in usrloc doesn't exists and * expires > 0, insert new contact * 2) If contact in usrloc exists and expires * > 0, update the contact * 3) If contact in usrloc exists and expires * == 0, delete contact */ static inline int update(struct sip_msg* _m, urecord_t* _r, contact_t* _c, str* _ua) { ucontact_t* c, *c2; str callid; int cseq, e; int set, reset; qvalue_t q; unsigned int flags; str* recv; int_str rcv_avp; int_str val; struct socket_info *sock; rcv_avp.n=rcv_avp_no; /* is nated flag */ if (nat_flag!=-1 && _m->flags&nat_flag) flags = FL_NAT; else flags = FL_NONE; /* nat type flag */ if (sip_natping_flag!=-1 && _m->flags&sip_natping_flag) flags |= FL_NAT_SIPPING; if (max_contacts) { if (test_max_contacts(_m, _r, _c) != 0 ) return -1; } _c = get_first_contact(_m); while(_c) { if (calc_contact_expires(_m, _c->expires, &e) < 0) { LOG(L_ERR, "update(): Error while calculating expires\n"); return -1; } if (ul.get_ucontact(_r, &_c->uri, &c) > 0) { /* Contact not found */ if (e != 0) { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -2; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*) &cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR, "update(): Error while converting cseq number\n"); return -3; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } if (sock_flag!=-1 && (_m->flags&sock_flag)!=0) { sock = get_sock_hdr(_m); if (sock==0) sock = _m->rcv.bind_address; } else { sock = _m->rcv.bind_address; } if (ul.insert_ucontact(_r, &_c->uri, e, q, &callid, cseq, flags | mem_only, &c2, _ua, recv, sock) < 0) { rerrno = R_UL_INS_C; LOG(L_ERR, "update(): Error while inserting contact\n"); return -4; } } } else { if (e == 0) { if (mem_only) { c->flags |= FL_MEM; } else { c->flags &= ~FL_MEM; } if (ul.delete_ucontact(_r, c) < 0) { rerrno = R_UL_DEL_C; LOG(L_ERR, "update(): Error while deleting contact\n"); return -5; } } else { /* Calculate q value of the contact */ if (calc_contact_q(_c->q, &q) < 0) { LOG(L_ERR, "update(): Error while calculating q\n"); return -6; } /* Get callid of the message */ callid = _m->callid->body; trim_trailing(&callid); /* Get CSeq number of the message */ if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), (unsigned int*)&cseq) < 0) { rerrno = R_INV_CSEQ; LOG(L_ERR,"update(): Error while converting cseq number\n"); return -7; } if (_c->received) { recv = &_c->received->body; } else if (search_first_avp(0, rcv_avp, &val)) { recv = val.s; } else { recv = 0; } if (sock_flag!=-1 && (_m->flags&sock_flag)!=0) { sock = get_sock_hdr(_m); if (sock==0) sock = _m->rcv.bind_address; } else { sock = _m->rcv.bind_address; } set = flags | mem_only; reset = ~(flags | mem_only) & (FL_NAT|FL_MEM|FL_NAT_SIPPING); if (ul.update_ucontact(c, e, q, &callid, cseq, set, reset, _ua, recv, sock) < 0) { rerrno = R_UL_UPD_C; LOG(L_ERR, "update(): Error while updating contact\n"); return -8; } if (desc_time_order) { move_on_top(_r, c); } } } _c = get_next_contact(_c); } return 0; }