Example #1
0
static int pv_get_sruid_val(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	if(res==NULL)
		return -1;
	if(sruid_next(&_kex_sruid)<0)
		return pv_get_null(msg, param, res);
	return pv_get_strval(msg, param, res, &_kex_sruid.uid);
}
Example #2
0
/*!
 * \brief Add a new contact for an address of record
 * \param cmd mi_root containing the parameter
 * \param param not used
 * \note Expects 7 nodes: table name, AOR, contact, expires, Q,
 * useless - backward compatible, flags, cflags, methods
 * \return mi_root with the result
 */
struct mi_root* mi_usrloc_add(struct mi_root *cmd, void *param)
{
	ucontact_info_t ci;
	urecord_t* r;
	ucontact_t* c;
	struct mi_node *node;
	udomain_t *dom;
	str *aor, *contact;
	unsigned int ui_val;
	int n;

	for( n=0,node = cmd->node.kids; n<9 && node ; n++,node=node->next );
	if (n!=9 || node!=0)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);

	node = cmd->node.kids;

	/* look for table (param 1) */
	dom = mi_find_domain( &node->value );
	if (dom==NULL)
		return init_mi_tree( 404, "Table not found", 15);

	/* process the aor (param 2) */
	node = node->next;
	aor = &node->value;
	if ( mi_fix_aor(aor)!=0 )
		return init_mi_tree( 400, "Domain missing in AOR", 21);

	/* contact (param 3) */
	node = node->next;
	contact = &node->value;

	memset( &ci, 0, sizeof(ucontact_info_t));

	/* expire (param 4) */
	node = node->next;
	if (str2int( &node->value, &ui_val) < 0)
		goto bad_syntax;
	ci.expires = ui_val;

	/* q value (param 5) */
	node = node->next;
	if (str2q( &ci.q, node->value.s, node->value.len) < 0)
		goto bad_syntax;

	/* unused value (param 6) FIXME */
	node = node->next;

	/* flags value (param 7) */
	node = node->next;
	if (str2int( &node->value, (unsigned int*)&ci.flags) < 0)
		goto bad_syntax;

	/* branch flags value (param 8) */
	node = node->next;
	if (str2int( &node->value, (unsigned int*)&ci.cflags) < 0)
		goto bad_syntax;

	/* methods value (param 9) */
	node = node->next;
	if (str2int( &node->value, (unsigned int*)&ci.methods) < 0)
		goto bad_syntax;

	if(sruid_next(&_ul_sruid)<0)
		goto error;
	ci.ruid = _ul_sruid.uid;

	lock_udomain( dom, aor);

	n = get_urecord( dom, aor, &r);
	if ( n==1) {
		if (insert_urecord( dom, aor, &r) < 0)
			goto lock_error;
		c = 0;
	} else {
		if (get_ucontact( r, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &c) < 0)
			goto lock_error;
	}

	get_act_time();

	ci.callid = &mi_ul_cid;
	ci.user_agent = &mi_ul_ua;
	ci.cseq = MI_UL_CSEQ;
	/* 0 expires means permanent contact */
	if (ci.expires!=0)
		ci.expires += act_time;

	if (c) {
		if (update_ucontact( r, c, &ci) < 0)
			goto release_error;
	} else {
		if ( insert_ucontact( r, contact, &ci, &c) < 0 )
			goto release_error;
	}

	release_urecord(r);

	unlock_udomain( dom, aor);

	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
bad_syntax:
	return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
release_error:
	release_urecord(r);
lock_error:
	unlock_udomain( dom, aor);
error:
	return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
}
Example #3
0
int process_contact(udomain_t * domain, urecord_t ** ul_record, str aor, str callid,
		int cseq, int expires, int event, str contact_uri) {
	str no_str = {0, 0};
	static str no_ua = str_init("n/a");
	static ucontact_info_t ci;
	ucontact_t * ul_contact;

	if (*ul_record == NULL) {
		switch(event) {
			case EVENT_REGISTERED:
			case EVENT_CREATED:
			case EVENT_REFRESHED:
				/* In case, no record exists and new one should be created,
				   create a new entry for this user in the usrloc-DB */
				if (ul.insert_urecord(domain, &aor, ul_record) < 0) {
					LM_ERR("failed to insert new user-record\n");
					return RESULT_ERROR;
				}
				break;
			default:
				/* No entry in usrloc and the contact is expired, deleted, unregistered, whatever:
                                   We do not need to do anything. */
				return RESULT_NO_CONTACTS;
				break;
		}
	}
	
	/* Make sure, no crap is in the structure: */
	memset( &ci, 0, sizeof(ucontact_info_t));	
	/* Get callid of the message */
	ci.callid = &callid;
	/* Get CSeq number of the message */
	ci.cseq = cseq;
	ci.sock = NULL;
	/* additional info from message */
	ci.user_agent = &no_ua;
	ci.last_modified = time(0);

	/* set expire time */
	ci.expires = time(0) + expires;

	/* set ruid */
	if(sruid_next(&_reginfo_sruid) < 0) {
		LM_ERR("failed to generate ruid");
	} else {
		ci.ruid = _reginfo_sruid.uid;
	}

	/* Now we start looking for the contact: */
	if (((*ul_record)->contacts == 0)
		|| (ul.get_ucontact(*ul_record, &contact_uri, &callid, &no_str, cseq+1, &ul_contact) != 0)) {
		if (ul.insert_ucontact(*ul_record, &contact_uri, &ci, &ul_contact) < 0) {
			LM_ERR("failed to insert new contact\n");
			return RESULT_ERROR;
		}
	} else {
		if (ul.update_ucontact(*ul_record, ul_contact, &ci) < 0) {
			LM_ERR("failed to update contact\n");
			return RESULT_ERROR;
		}
	}
	ul_contact = (*ul_record)->contacts;
	while (ul_contact) {
		if (VALID_CONTACT(ul_contact, time(0))) return RESULT_CONTACTS_FOUND;
		ul_contact = ul_contact->next;
	}

	return RESULT_NO_CONTACTS;
}
Example #4
0
int msrp_cmap_save(msrp_frame_t *mf)
{
    unsigned int idx;
    unsigned int hid;
    str fpeer;
#define MSRP_SBUF_SIZE	256
    char sbuf[MSRP_SBUF_SIZE];
    str srcaddr;
    str srcsock;
    int msize;
    int expires;
    msrp_citem_t *it;
    msrp_citem_t *itb;

    if(_msrp_cmap_head==NULL || mf==NULL)
        return -1;
    if(mf->fline.rtypeid!=MSRP_REQ_AUTH)
    {
        LM_DBG("save can be used only for AUTH\n");
        return -2;
    }

    if(msrp_frame_get_expires(mf, &expires)<0)
        expires = msrp_auth_max_expires;
    if(expires<msrp_auth_min_expires)
    {
        LM_DBG("expires is lower than min value\n");
        srcaddr.len = snprintf(sbuf, MSRP_SBUF_SIZE, "Min-Expires: %d\r\n",
                               msrp_auth_min_expires);
        msrp_reply(mf, &msrp_reply_423_code, &msrp_reply_423_text,
                   &srcaddr);
        return -3;
    }
    if(expires>msrp_auth_max_expires)
    {
        LM_DBG("expires is greater than max value\n");
        srcaddr.len = snprintf(sbuf, MSRP_SBUF_SIZE, "Max-Expires: %d\r\n",
                               msrp_auth_max_expires);
        msrp_reply(mf, &msrp_reply_423_code, &msrp_reply_423_text,
                   &srcaddr);
        return -4;
    }
    if(msrp_frame_get_first_from_path(mf, &fpeer)<0)
    {
        LM_ERR("cannot get first path uri\n");
        return -1;
    }

    if(sruid_next(&_msrp_sruid)<0)
    {
        LM_ERR("cannot get next msrp uid\n");
        return -1;
    }
    hid = msrp_get_hashid(&_msrp_sruid.uid);
    idx = msrp_get_slot(hid, _msrp_cmap_head->mapsize);

    srcaddr.s = sbuf;
    if (msrp_tls_module_loaded)
    {
        memcpy(srcaddr.s, "msrps://", 8);
        srcaddr.s+=8;
    } else {
        memcpy(srcaddr.s, "msrp://", 7);
        srcaddr.s+=7;
    }
    strcpy(srcaddr.s, ip_addr2a(&mf->tcpinfo->rcv->src_ip));
    strcat(srcaddr.s, ":");
    strcat(srcaddr.s, int2str(mf->tcpinfo->rcv->src_port, NULL));
    srcaddr.s = sbuf;
    srcaddr.len = strlen(srcaddr.s);
    srcsock = mf->tcpinfo->rcv->bind_address->sock_str;
    LM_DBG("saving connection info for [%.*s] [%.*s] (%u/%u)\n",
           fpeer.len, fpeer.s, _msrp_sruid.uid.len, _msrp_sruid.uid.s,
           idx, hid);
    LM_DBG("frame received from [%.*s] via [%.*s]\n",
           srcaddr.len, srcaddr.s, srcsock.len, srcsock.s);

    msize = sizeof(msrp_citem_t) + (_msrp_sruid.uid.len
                                    + fpeer.len + srcaddr.len + srcsock.len + 4)*sizeof(char);

    /* build the item */
    it = (msrp_citem_t*)shm_malloc(msize);
    if(it==NULL)
    {
        LM_ERR("no more shm\n");
        return -1;
    }
    memset(it, 0, msize);
    it->citemid = hid;

    it->sessionid.s = (char*)it +  + sizeof(msrp_citem_t);
    it->sessionid.len = _msrp_sruid.uid.len;
    memcpy(it->sessionid.s, _msrp_sruid.uid.s, _msrp_sruid.uid.len);
    it->sessionid.s[it->sessionid.len] = '\0';

    it->peer.s = it->sessionid.s + it->sessionid.len + 1;
    it->peer.len = fpeer.len;
    memcpy(it->peer.s, fpeer.s, fpeer.len);
    it->peer.s[it->peer.len] = '\0';

    it->addr.s = it->peer.s + it->peer.len + 1;
    it->addr.len = srcaddr.len;
    memcpy(it->addr.s, srcaddr.s, srcaddr.len);
    it->addr.s[it->addr.len] = '\0';

    it->sock.s = it->addr.s + it->addr.len + 1;
    it->sock.len = srcsock.len;
    memcpy(it->sock.s, srcsock.s, srcsock.len);
    it->sock.s[it->sock.len] = '\0';

    it->expires = time(NULL) + expires;
    it->conid = mf->tcpinfo->con->id;

    /* insert item in cmap */
    lock_get(&_msrp_cmap_head->cslots[idx].lock);
    if(_msrp_cmap_head->cslots[idx].first==NULL) {
        _msrp_cmap_head->cslots[idx].first = it;
    } else {
        for(itb=_msrp_cmap_head->cslots[idx].first; itb; itb=itb->next)
        {
            if(itb->citemid>it->citemid || itb->next==NULL) {
                if(itb->next==NULL) {
                    itb->next=it;
                    it->prev = itb;
                } else {
                    it->next = itb;
                    if(itb->prev==NULL) {
                        _msrp_cmap_head->cslots[idx].first = it;
                    } else {
                        itb->prev->next = it;
                    }
                    it->prev = itb->prev;
                    itb->prev = it;
                }
                break;
            }
        }
    }
    _msrp_cmap_head->cslots[idx].lsize++;
    lock_release(&_msrp_cmap_head->cslots[idx].lock);

    if(mf->tcpinfo->rcv->proto==PROTO_TLS || mf->tcpinfo->rcv->proto==PROTO_WSS)
    {
        srcaddr.len = snprintf(sbuf, MSRP_SBUF_SIZE,
                               "Use-Path: msrps://%.*s/%.*s;tcp\r\nExpires: %d\r\n",
                               (msrp_use_path_addr.s)?msrp_use_path_addr.len:(srcsock.len-4),
                               (msrp_use_path_addr.s)?msrp_use_path_addr.s:(srcsock.s+4),
                               _msrp_sruid.uid.len, _msrp_sruid.uid.s,
                               expires);
    } else {
        srcaddr.len = snprintf(sbuf, MSRP_SBUF_SIZE,
                               "Use-Path: msrp://%.*s/%.*s;tcp\r\nExpires: %d\r\n",
                               (msrp_use_path_addr.s)?msrp_use_path_addr.len:(srcsock.len-4),
                               (msrp_use_path_addr.s)?msrp_use_path_addr.s:(srcsock.s+4),
                               _msrp_sruid.uid.len, _msrp_sruid.uid.s,
                               expires);
    }
    srcaddr.s = sbuf;

    if(msrp_reply(mf, &msrp_reply_200_code, &msrp_reply_200_text,
                  &srcaddr)<0)
        return -5;
    return 0;
}
Example #5
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;
}
Example #6
0
/* returns : -1 - error
 *            0 - ok, but no contact added
 *            n - ok and n contacts added
 */
static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
								long max, struct acc_param *reason, unsigned int bflags)
{
	static struct sip_msg  dup_rpl;
	static contact_t *scontacts[MAX_CONTACTS_PER_REPLY];
	static qvalue_t  sqvalues[MAX_CONTACTS_PER_REPLY];
	struct hdr_field *hdr;
	struct hdr_field *contact_hdr;
	contact_t        *contacts;
	int n,i;
	int added;
	int dup;
	int ret;

	/* dup can be:
	 *    0 - sh reply but nothing duplicated 
	 *    1 - sh reply but only contact body parsed
	 *    2 - sh reply and contact header and body parsed
	 *    3 - private reply
	 */
	dup = 0; /* sh_rpl not duplicated */
	ret = 0; /* success and no contact added */
	contact_hdr = 0;

	if (sh_rpl==0 || sh_rpl==FAKED_REPLY)
		return 0;

	if (sh_rpl->contact==0) {
		/* contact header is not parsed */
		if ( sh_rpl->msg_flags&FL_SHM_CLONE ) {
			/* duplicate the reply into private memory to be able 
			 * to parse it and afterwards to free the parsed mems */
			memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) );
			dup = 2;
			/* ok -> force the parsing of contact header */
			if ( parse_headers( &dup_rpl, HDR_EOH_F, 0)<0 ) {
				LM_ERR("dup_rpl parse failed\n");
				ret = -1;
				goto restore;
			}
			if (dup_rpl.contact==0) {
				LM_DBG("contact hdr not found in dup_rpl\n");
				goto restore;
			}
			contact_hdr = dup_rpl.contact;
		} else {
			dup = 3;
			/* force the parsing of contact header */
			if ( parse_headers( sh_rpl, HDR_EOH_F, 0)<0 ) {
				LM_ERR("sh_rpl parse failed\n");
				ret = -1;
				goto restore;
			}
			if (sh_rpl->contact==0) {
				LM_DBG("contact hdr not found in sh_rpl\n");
				goto restore;
			}
			contact_hdr = sh_rpl->contact;
		}
	} else {
		contact_hdr = sh_rpl->contact;
	}

	/* parse the body of contact headers */
	hdr = contact_hdr;
	while(hdr) {
		if (hdr->type == HDR_CONTACT_T) {
			if (hdr->parsed==0) {
				if(parse_contact(hdr) < 0) {
					LM_ERR("failed to parse Contact body\n");
					ret = -1;
					goto restore;
				}
				if (dup==0)
					dup = 1;
				}
		}
		hdr = hdr->next;
	}

	/* we have the contact header and its body parsed -> sort the contacts
	 * based on the q value */
	contacts = ((contact_body_t*)contact_hdr->parsed)->contacts;
	if (contacts==0) {
		LM_DBG("contact hdr has no contacts\n");
		goto restore;
	}
	n = sort_contacts(contact_hdr, scontacts, sqvalues);
	if (n==0) {
		LM_DBG("no contacts left after filtering\n");
		goto restore;
	}

	i=0;

	/* more branches than requested in the parameter
	 * - add only the last ones from sorted array,
	 *   because the order is by increasing q */
	if (max!=-1 && n>max)
		i = n - max;

	added = 0;

	/* add the sortet contacts as branches in dset and log this! */
	for (  ; i<n ; i++ ) {
		LM_DBG("adding contact <%.*s>\n", scontacts[i]->uri.len,
				scontacts[i]->uri.s);
		if(sruid_next(&_redirect_sruid)==0) {
			if(append_branch( 0, &scontacts[i]->uri, 0, 0, sqvalues[i],
						bflags, 0, &_redirect_sruid.uid, 0,
						&_redirect_sruid.uid, &_redirect_sruid.uid)<0) {
				LM_ERR("failed to add contact to dset\n");
			} else {
				added++;
				if (rd_acc_fct!=0 && reason) {
					/* log the redirect */
					req->new_uri =  scontacts[i]->uri;
					//FIXME
					rd_acc_fct( req, (char*)reason, acc_db_table);
				}
			}
		} else {
			LM_ERR("failed to generate ruid for a new branch\n");
		}
	}

	ret = (added==0)?-1:added;
restore:
	if (dup==1) {
		free_contact( (contact_body_t**)(void*)(&contact_hdr->parsed) );
	} else if (dup==2) {
		/* are any new headers found? */
		if (dup_rpl.last_header!=sh_rpl->last_header) {
			/* identify in the new headere list (from dup_rpl) 
			 * the sh_rpl->last_header and start remove everything after */
			hdr = sh_rpl->last_header;
			free_hdr_field_lst(hdr->next);
			hdr->next=0;
		}
	}
	return ret;

}