예제 #1
0
int w_is_supported(sip_msg_t *msg, char *_option, char *p2)
{
	unsigned long option;

	option = (unsigned long)_option;

	if (parse_supported(msg) < 0)
		return -1;

	if ((((struct option_tag_body*)msg->supported->parsed)->option_tags_all &
				option) == 0)
		return -1;
	else
		return 1;
}
예제 #2
0
/**
 * Gether the message information about SST from the current message
 * being processed.
 *
 * @param msg The current message to parse.
 * @param minfo The SST information found in the message.
 *
 * @return 0 on success, -1 on a parsing error.
 */
static int parse_msg_for_sst_info(struct sip_msg *msg, sst_msg_info_t *minfo)
{
	int rtn = 0;
	struct session_expires se = {0,0};

	if (!msg || !minfo) {
		return (-1);
	}
	
	/* 
	 * parse the supported infor
	 */
	minfo->supported = 0; /*Clear it */
	minfo->se = 0;
	minfo->refresher = sst_refresher_unspecified;
	minfo->min_se = 0;

	/*
	 * The parse_supported() will return 0 if found and parsed OK, -1
	 * if not found or an error parsing the one it did find! So assume
	 * it is not found if unsuccessfull.
	 */
	if ((rtn = parse_supported(msg)) == 0) {
		if ((((struct option_tag_body*)msg->supported->parsed)->option_tags_all
						& F_OPTION_TAG_TIMER)) {
			minfo->supported = 1;
		}
	}
	/*
	 * Parse the Min-SE: header next.
	 */
	minfo->min_se = 0;
	if ((rtn = parse_min_se(msg, &minfo->min_se)) != parse_sst_success) {
		minfo->min_se = 0; /* Make sure it statys clean */
	}
	minfo->se = 0;
	if ((rtn = parse_session_expires(msg, &se)) == parse_sst_success) {
		minfo->se = se.interval;
		minfo->refresher = se.refresher;
	}
	return(0);
}
예제 #3
0
/*! \brief
 * Allocate a memory buffer and print Contact
 * header fields into it
 */
int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
{
	char *p, *cp;
	char *a;
	int fl, len;
	str user;
	str inst;
	unsigned int ahash;
	unsigned short digit;
	int mode;
	sr_xavp_t *xavp=NULL;
	sr_xavp_t *list=NULL;
	str xname = {"ruid", 4};
	sr_xval_t xval;



	if(msg!=NULL && parse_supported(msg)==0
			&& (get_supported(msg) & F_OPTION_TAG_GRUU))
		mode = 1;
	else
		mode = 0;

	contact.data_len = calc_buf_len(c, host, mode);

	if (!contact.data_len) return 0;

	if (!contact.buf || (contact.buf_len < contact.data_len)) {
		if (contact.buf) pkg_free(contact.buf);
		contact.buf = (char*)pkg_malloc(contact.data_len);
		if (!contact.buf) {
			contact.data_len = 0;
			contact.buf_len = 0;
			LM_ERR("no pkg memory left\n");
			return -1;
		} else {
			contact.buf_len = contact.data_len;
		}
	}

	p = contact.buf;
	
	memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN);
	p += CONTACT_BEGIN_LEN;

	/* add xavp with details of the record (ruid, ...) */
	if(reg_xavp_rcd.s!=NULL)
	{
		list = xavp_get(&reg_xavp_rcd, NULL);
		xavp = list;
	}

	fl = 0;
	while(c) {
		if (VALID_CONTACT(c, act_time)) {
			if (fl) {
				memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN);
				p += CONTACT_SEP_LEN;
			} else {
				fl = 1;
			}

			*p++ = '<';
			memcpy(p, c->c.s, c->c.len);
			p += c->c.len;
			*p++ = '>';

			len = len_q(c->q);
			if (len) {
				memcpy(p, Q_PARAM, Q_PARAM_LEN);
				p += Q_PARAM_LEN;
				memcpy(p, q2str(c->q, 0), len);
				p += len;
			}

			memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN);
			p += EXPIRES_PARAM_LEN;
			cp = int2str((int)(c->expires - act_time), &len);
			memcpy(p, cp, len);
			p += len;

			if (rcv_param.len>0 && c->received.s) {
				*p++ = ';';
				memcpy(p, rcv_param.s, rcv_param.len);
				p += rcv_param.len;
				*p++ = '=';
				*p++ = '\"';
				memcpy(p, c->received.s, c->received.len);
				p += c->received.len;
				*p++ = '\"';
			}
			if (reg_gruu_enabled==1 && c->instance.len>0 && mode==1) {
				user.s = c->aor->s;
				a = memchr(c->aor->s, '@', c->aor->len);
				if(a!=NULL) {
					user.len = a - user.s;
				} else {
					user.len = c->aor->len;
				}
				/* pub-gruu */
				memcpy(p, PUB_GRUU_PARAM, PUB_GRUU_PARAM_LEN);
				p += PUB_GRUU_PARAM_LEN;
				*p++ = '\"';
				memcpy(p, "sip:", 4);
				p += 4;
				if(a!=NULL) {
					memcpy(p, c->aor->s, c->aor->len);
					p += c->aor->len;
				} else {
					memcpy(p, user.s, user.len);
					p += user.len;
					*p++ = '@';
					memcpy(p, host->s, host->len);
					p += host->len;
				}
				memcpy(p, GR_PARAM, GR_PARAM_LEN);
				p += GR_PARAM_LEN;
				inst = c->instance;
				if(inst.s[0]=='<' && inst.s[inst.len-1]=='>') {
					inst.s++;
					inst.len -= 2;
				}
				memcpy(p, inst.s, inst.len);
				p += inst.len;
				*p++ = '\"';
				/* temp-gruu */
				memcpy(p, TMP_GRUU_PARAM, TMP_GRUU_PARAM_LEN);
				p += TMP_GRUU_PARAM_LEN;
				*p++ = '\"';
				memcpy(p, "sip:", 4);
				p += 4;
				memcpy(p, c->ruid.s, c->ruid.len);
				p += c->ruid.len;
				*p++ = '-';
				ahash = ul.get_aorhash(c->aor);
				while(ahash!=0)
				{
					digit =  ahash & 0x0f;
					*p++ = (digit >= 10) ? digit + 'a' - 10 : digit + '0';
					ahash >>= 4;
				}
				*p++ = '@';
				memcpy(p, host->s, host->len);
				p += host->len;
				memcpy(p, GR_PARAM, GR_PARAM_LEN);
				p += GR_PARAM_LEN - 1;
				*p++ = '\"';
			}

			if (c->instance.len>0) {
				/* +sip-instance */
				memcpy(p, SIP_INSTANCE_PARAM, SIP_INSTANCE_PARAM_LEN);
				p += SIP_INSTANCE_PARAM_LEN;
				*p++ = '\"';
				memcpy(p, c->instance.s, c->instance.len);
				p += c->instance.len;
				*p++ = '\"';
			}
			if (c->reg_id>0) {
				/* reg-id */
				memcpy(p, REG_ID_PARAM, REG_ID_PARAM_LEN);
				p += REG_ID_PARAM_LEN;
				cp = int2str(c->reg_id, &len);
				memcpy(p, cp, len);
				p += len;
			}
			if(reg_xavp_rcd.s!=NULL)
			{
				memset(&xval, 0, sizeof(sr_xval_t));
				xval.type = SR_XTYPE_STR;
				xval.v.s = c->ruid;
				if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
					LM_ERR("cannot add ruid value to xavp\n");
				}
			}
		}

		c = c->next;
	}
예제 #4
0
파일: reply.c 프로젝트: mtulio/mtulio
/*! \brief
 * Send a reply
 */
int send_reply(struct sip_msg* _m, unsigned int _flags)
{
	str unsup = str_init(SUPPORTED_PATH_STR);
	long code;
	str msg = str_init(MSG_200); /* makes gcc shut up */
	char* buf;

	if (contact.data_len > 0) {
		add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
		contact.data_len = 0;
	}
			
	if (rerrno == R_FINE && (_flags&REG_SAVE_PATH_FLAG) && _m->path_vec.s) {
		if ( (_flags&REG_SAVE_PATH_OFF_FLAG)==0 ) {
			if (parse_supported(_m)<0 && (_flags&REG_SAVE_PATH_STRICT_FLAG)) {
				rerrno = R_PATH_UNSUP;
				if (add_unsupported(_m, &unsup) < 0)
					return -1;
				if (add_path(_m, &_m->path_vec) < 0)
					return -1;
			}
			else if (get_supported(_m) & F_SUPPORTED_PATH) {
				if (add_path(_m, &_m->path_vec) < 0)
					return -1;
			} else if ((_flags&REG_SAVE_PATH_STRICT_FLAG)) {
				rerrno = R_PATH_UNSUP;
				if (add_unsupported(_m, &unsup) < 0)
					return -1;
				if (add_path(_m, &_m->path_vec) < 0)
					return -1;
			}
		}
	}

	code = codes[rerrno];
	switch(code) {
	case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1; break;
	case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
	case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
	case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
	case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
	}
	
	if (code != 200) {
		buf = (char*)pkg_malloc(E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1);
		if (!buf) {
			LM_ERR("no pkg memory left\n");
			return -1;
		}
		memcpy(buf, E_INFO, E_INFO_LEN);
		memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len);
		memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN);
		add_lump_rpl( _m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN,
			LUMP_RPL_HDR|LUMP_RPL_NODUP);

		if (code >= 500 && code < 600 && retry_after) {
			if (add_retry_after(_m) < 0) {
				return -1;
			}
		} 
	}
	
	if (sigb.reply(_m, code, &msg, NULL) == -1) {
		LM_ERR("failed to send %ld %.*s\n", code, msg.len,msg.s);
		return -1;
	} else return 0;
}
예제 #5
0
파일: save.c 프로젝트: Jared-Prime/kamailio
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri)
{
	contact_t* c;
	int st, mode;
	str aor;
	int ret;
	sip_uri_t *u;
	rr_t *route;
	struct sip_uri puri;
	param_hooks_t hooks;
	param_t *params;
	contact_t *contact;
	int use_ob = 1, use_regid = 1;

	u = parse_to_uri(_m);
	if(u==NULL)
		goto error;

	rerrno = R_FINE;
	ret = 1;

	if (parse_message(_m) < 0) {
		goto error;
	}

	if (check_contacts(_m, &st) > 0) {
		goto error;
	}

	if (parse_supported(_m) == 0) {
		if (!(get_supported(_m)	& F_OPTION_TAG_OUTBOUND)
				&& reg_outbound_mode == REG_OUTBOUND_REQUIRE) {
			LM_WARN("Outbound required by server and not supported by UAC\n");
			rerrno = R_OB_UNSUP;
			goto error;
		}
	}

	if (parse_require(_m) == 0) {
		if ((get_require(_m) & F_OPTION_TAG_OUTBOUND)
				&& reg_outbound_mode == REG_OUTBOUND_NONE) {
			LM_WARN("Outbound required by UAC and not supported by server\n");
			rerrno = R_OB_REQD;
			goto error;
		}
	}

	if (reg_outbound_mode != REG_OUTBOUND_NONE
			&& _m->contact && _m->contact->parsed
			&& !(parse_headers(_m, HDR_VIA2_F, 0) == -1 || _m->via2 == 0
				|| _m->via2->error != PARSE_OK)) {
		/* Outbound supported on server, and more than one Via: - not the first hop */

		if (!(parse_headers(_m, HDR_PATH_F, 0) == -1 || _m->path == 0)) {
			route = (rr_t *)0;
			if (parse_rr_body(_m->path->body.s, _m->path->body.len, &route) < 0) {
				LM_ERR("Failed to parse Path: header body\n");
				goto error;
			}
			if (parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) < 0) {
				LM_ERR("Failed to parse Path: URI\n");
				goto error;
			}
			if (parse_params(&puri.params, CLASS_URI, &hooks, &params) != 0) {
				LM_ERR("Failed to parse Path: URI parameters\n");
				goto error;
			}
			if (!hooks.uri.ob) {
				/* No ;ob parameter to top Path: URI - no outbound */
				use_ob = 0;
			}

		} else {
			/* No Path: header - no outbound */
			use_ob = 0;

		}

		contact = ((contact_body_t *) _m->contact->parsed)->contacts;
		if (!contact) {
			LM_ERR("empty Contact:\n");
			goto error;
		}

		if ((use_ob == 0) && (reg_regid_mode == REG_REGID_OUTBOUND)) {
			if ((get_supported(_m) & F_OPTION_TAG_OUTBOUND)
					&& contact->reg_id) {
				LM_WARN("Outbound used by UAC but not supported by edge proxy\n");
				rerrno = R_OB_UNSUP_EDGE;
				goto error;
			} else {
				/* ignore ;reg-id parameter */
				use_regid = 0;
			}
		}
	}

	get_act_time();
	c = get_first_contact(_m);

	if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract Address Of Record\n");
		goto error;
	}

	mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE;

	if (c == 0) {
		if (st) {
			if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=3;
		} else {
			if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=4;
		}
	} else {
		mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
		if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode, use_regid)) < 0)
			goto error;
		ret = (ret==0)?1:ret;
	}

	update_stat(accepted_registrations, 1);

	/* Only send reply upon request, not upon reply */
	if ((is_route_type(REQUEST_ROUTE) || is_route_type(FAILURE_ROUTE))
			&& !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0))
		return -1;

	return ret;
error:
	update_stat(rejected_registrations, 1);
	if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) )
		reg_send_reply(_m);

	return 0;
}
예제 #6
0
파일: reply.c 프로젝트: aallamaa/kamailio
/*! \brief
 * Send a reply
 */
int reg_send_reply(struct sip_msg* _m, contact_for_header_t* contact_header) {
    str unsup = str_init(OPTION_TAG_PATH_STR);
    long code;
    str msg = str_init(MSG_200); /* makes gcc shut up */
    char* buf;

    if (contact_header && contact_header->buf && contact_header->data_len > 0) {
    	LM_DBG("Contacts: %.*s\n", contact_header->data_len, contact_header->buf);
        add_lump_rpl(_m, contact_header->buf, contact_header->data_len, LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE);
        contact_header->data_len = 0;
    }

    if (rerrno == R_FINE && path_enabled && _m->path_vec.s) {
        if (path_mode != PATH_MODE_OFF) {
            if (parse_supported(_m) < 0 && path_mode == PATH_MODE_STRICT) {
                rerrno = R_PATH_UNSUP;
                if (add_unsupported(_m, &unsup) < 0)
                    return -1;
                if (add_path(_m, &_m->path_vec) < 0)
                    return -1;
            } else if (get_supported(_m) & F_OPTION_TAG_PATH) {
                if (add_path(_m, &_m->path_vec) < 0)
                    return -1;
            } else if (path_mode == PATH_MODE_STRICT) {
                rerrno = R_PATH_UNSUP;
                if (add_unsupported(_m, &unsup) < 0)
                    return -1;
                if (add_path(_m, &_m->path_vec) < 0)
                    return -1;
            }
        }
    }

    code = codes[rerrno];
    switch (code) {
        case 200: msg.s = MSG_200;
            msg.len = sizeof (MSG_200) - 1;
            break;
        case 400: msg.s = MSG_400;
            msg.len = sizeof (MSG_400) - 1;
            break;
        case 420: msg.s = MSG_420;
            msg.len = sizeof (MSG_420) - 1;
            break;
        case 500: msg.s = MSG_500;
            msg.len = sizeof (MSG_500) - 1;
            break;
        case 503: msg.s = MSG_503;
            msg.len = sizeof (MSG_503) - 1;
            break;
    }

    if (code != 200) {
        buf = (char*) pkg_malloc(E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1);
        if (!buf) {
            LM_ERR("no pkg memory left\n");
            return -1;
        }
        memcpy(buf, E_INFO, E_INFO_LEN);
        memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len);
        memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN);
        add_lump_rpl(_m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN,
                LUMP_RPL_HDR | LUMP_RPL_NODUP);

        if (code >= 500 && code < 600 && cfg_get(registrar, registrar_cfg, retry_after)) {
            if (add_retry_after(_m) < 0) {
                return -1;
            }
        }
    }

    if ((code > 199) && (code < 299)) {
        if (p_associated_uri.data_len > 0) {
            add_lump_rpl(_m, p_associated_uri.buf, p_associated_uri.data_len,
                    LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE);
            p_associated_uri.data_len = 0;
        }
        if (add_service_route(_m, &scscf_serviceroute_uri_str) < 0) { //TODO - need to insert orig into this scscf_name
            return -1;
        }
    }

    if (slb.freply(_m, code, &msg) < 0) {
        LM_ERR("failed to send %ld %.*s\n", code, msg.len, msg.s);
        return -1;
    } else return 0;
}
예제 #7
0
int rls_handle_subscribe(struct sip_msg* msg, char* s1, char* s2)
{
	struct to_body *pto, *pfrom = NULL; 
	subs_t subs;
	pres_ev_t* event= NULL;
	str* contact= NULL;
	xmlDocPtr doc= NULL;
	xmlNodePtr service_node= NULL;
	unsigned int hash_code= 0;
	event_t* parsed_event;
	param_t* ev_param= NULL;
	int init_req;
	int reply_code;
	str reply_str;

	/*** filter: 'For me or for presence server?' */

	reply_code = 400;
	reply_str = pu_400_rpl;

	memset(&subs, 0, sizeof(subs_t));

	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("parsing headers\n");
		goto error;
	}

	/* check for Support: eventlist header */
	if(!msg->supported)
	{
		LM_DBG("no supported header found\n");
		return to_presence_code;
	}
	
	if(parse_supported(msg) < 0)
	{
		LM_ERR("failed to parse supported headers\n");
		reply_code = 500;
		reply_str = pu_500_rpl;
		goto error;
	}

	if(!(get_supported(msg) & F_SUPPORTED_EVENTLIST))
	{
		LM_DBG("No 'Support: eventlist' header found\n");
		return to_presence_code;
	}

	/* inspecting the Event header field */
	if(msg->event && msg->event->body.len > 0)
	{
		if (!msg->event->parsed && (parse_event(msg->event) < 0))
		{
			LM_ERR("cannot parse Event header\n");
			reply_code = 500;
			reply_str = pu_500_rpl;
			goto error;
		}
		if(! ( ((event_t*)msg->event->parsed)->parsed & rls_events) )
		{
			return to_presence_code;
		}
	}
	else
	{
		goto bad_event;
	}

	/* search event in the list */
	parsed_event= (event_t*)msg->event->parsed;
	event= pres_search_event(parsed_event);
	if(event== NULL)
	{
		goto bad_event;
	}
	subs.event= event;
	
	/* extract the id if any*/
	ev_param= parsed_event->params;
	while(ev_param)
	{
		if(ev_param->name.len== 2 && strncasecmp(ev_param->name.s, "id", 2)== 0)
		{
			subs.event_id= ev_param->body;
			break;
		}
		ev_param= ev_param->next;
	}

	pto = get_to(msg);
	if (pto == NULL || pto->error != PARSE_OK)
	{
		LM_ERR("parsing 'To' header failed\n");
		goto error;
	}

	if(parse_from_uri(msg)<0)
	{
		LM_ERR("failed to parse From header\n");
		goto error;
	}

	pfrom = (struct to_body*)msg->from->parsed;
	if(pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		goto error;
	}

	/* verify if the presentity URI is a resource list */
	if(pto->tag_value.s== NULL || pto->tag_value.len==0)
		/* if an initial Subscribe */
	{
		struct sip_uri fu = ((struct to_body*)msg->from->parsed)->parsed_uri;
		if( parse_sip_msg_uri(msg)< 0)
		{
			LM_ERR("parsing Request URI failed\n");
			goto error;
		}

		/*verify if Request URI represents a list by asking xcap server*/	
		if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host,
					&subs.pres_uri)< 0)
		{
			LM_ERR("while constructing uri from user and domain\n");
			reply_code = 500;
			reply_str = pu_500_rpl;
			goto error;
		}
		
		if( get_resource_list(&subs.pres_uri, fu.user, fu.host,
					&service_node, &doc) < 0)
		{
			LM_ERR("failed to get resource list document\n");
			reply_code = 500;
			reply_str = pu_500_rpl;
			goto error;
		}
		
		if(doc== NULL|| service_node==NULL)
		{
			LM_DBG("list not found - search for uri = %.*s\n",subs.pres_uri.len,
				subs.pres_uri.s);
			pkg_free(subs.pres_uri.s);
			return to_presence_code;
		}
	}
	else  /* if request inside a dialog */
	{
		if( msg->callid==NULL || msg->callid->body.s==NULL)
		{
			LM_ERR("cannot parse callid header\n");
			goto error;
		}

		/* search if a stored dialog */
		hash_code= core_hash(&msg->callid->body, &pto->tag_value, hash_size);
		lock_get(&rls_table[hash_code].lock);

		if(pres_search_shtable(rls_table,msg->callid->body,
					pto->tag_value,	pfrom->tag_value, hash_code)== NULL)
		{
			lock_release(&rls_table[hash_code].lock);
			/* reply with Call/Transaction Does Not Exist */
			LM_DBG("No dialog match found\n");
			return to_presence_code;
		}
		lock_release(&rls_table[hash_code].lock);
	}

	/* extract dialog information from message headers */
	if(pres_extract_sdialog_info(&subs, msg, rls_max_expires, &init_req,
				server_address)< 0)
	{
		LM_ERR("bad Subscribe request\n");
		goto error;
	}

	reply_code = 500;
	reply_str = pu_500_rpl;


	if(init_req) /* if an initial subscribe */
	{
		/** reply with 200 OK*/
		if(reply_200(msg, &subs.local_contact, subs.expires, &subs.to_tag)< 0)
			goto error_free;
		hash_code= core_hash(&subs.callid, &subs.to_tag, hash_size);

		subs.local_cseq= 0;

		if(subs.expires!= 0)
		{
			subs.version= 1;
			if(pres_insert_shtable(rls_table, hash_code, &subs)< 0)
			{
				LM_ERR("while adding new subscription\n");
				goto error_free;
			}
		}
	}
	else
	{
		if(update_rlsubs(&subs, hash_code, &reply_code, &reply_str) < 0)
		{
			LM_ERR("while updating resource list subscription\n");
			goto error;
		}

		if(get_resource_list(&subs.pres_uri, subs.from_user,
					subs.from_domain, &service_node, &doc)< 0)
		{
			LM_ERR("when getting resource list\n");
			goto error;
		}
		if(doc== NULL || service_node== NULL)
		{
			LM_DBG("list not found( in-dialog request)- search for uri = %.*s\n",
					subs.pres_uri.len, subs.pres_uri.s);
			reply_code = 404;
			reply_str = pu_404_rpl;
			goto error;
		}

		/** reply with 200 OK*/
		if(reply_200(msg, &subs.local_contact, subs.expires, 0)< 0)
			goto error_free;
	}
/*** send Subscribe requests for all in the list */

	/* call sending Notify with full state */
	if(send_full_notify(&subs, service_node, subs.version,
				&subs.pres_uri,hash_code)< 0)
	{
		LM_ERR("while sending full state Notify\n");
		goto error_free;
	}

	if(resource_subscriptions(&subs, service_node)< 0)
	{
		LM_ERR("while sending Subscribe requests to resources in a list\n");
		goto error_free;
	}

	if(contact)
	{	
		if(contact->s)
			pkg_free(contact->s);
		pkg_free(contact);
	}
		
	pkg_free(subs.pres_uri.s);
	if(subs.record_route.s)
		pkg_free(subs.record_route.s);
	xmlFreeDoc(doc);
	return 1;


bad_event:
	if(reply_489(msg)< 0)
		LM_ERR("failed to send 489 reply\n");
	goto error_free;

error:
	if (rls_sigb.reply(msg, reply_code, &reply_str, 0) == -1)
	{
		LM_ERR("failed to send 400 reply\n");
		return -1;
	}


error_free:
	if(contact)
	{	
		if(contact->s)
			pkg_free(contact->s);
		pkg_free(contact);
	}
	if(subs.pres_uri.s)
		pkg_free(subs.pres_uri.s);
		
	if(subs.record_route.s)
			pkg_free(subs.record_route.s);	
	if(doc)
		xmlFreeDoc(doc);
	return -1;
}
예제 #8
0
int rls_handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain)
{
	subs_t subs;
	pres_ev_t* event = NULL;
	int err_ret = -1;
	int ret = to_presence_code;
	str* contact = NULL;
	xmlDocPtr doc = NULL;
	xmlNodePtr service_node = NULL;
	unsigned int hash_code=0;
	int to_tag_gen = 0;
	event_t* parsed_event;
	param_t* ev_param = NULL;
	str reason;
	int rt;
	str rlsubs_did = {0, 0};

	memset(&subs, 0, sizeof(subs_t));

	/** sanity checks - parse all headers */
	if (parse_headers(msg, HDR_EOH_F, 0)<-1)
	{
		LM_ERR("failed parsing all headers\n");
		if (slb.freply(msg, 400, &pu_400_rpl) < 0)
		{
			LM_ERR("while sending 400 reply\n");
			return -1;
		}
		return 0;
	}
	/* check for To and From headesr */
	if(parse_to_uri(msg)<0 || parse_from_uri(msg)<0)
	{
		LM_ERR("failed to find To or From headers\n");
		if (slb.freply(msg, 400, &pu_400_rpl) < 0)
		{
			LM_ERR("while sending 400 reply\n");
			return -1;
		}
		return 0;
	}
	if(get_from(msg)->tag_value.s ==NULL || get_from(msg)->tag_value.len==0)
	{
		LM_ERR("no from tag value present\n");
		return -1;
	}
	if(msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot find callid header\n");
		return -1;
	}
	if(parse_sip_msg_uri(msg)<0)
	{
		LM_ERR("failed parsing Request URI\n");
		return -1;
	}

	/* check for header 'Support: eventlist' */
	if(msg->supported==NULL)
	{
		LM_DBG("supported header not found - not for rls\n");
		goto forpresence;
	}

	if(parse_supported(msg)<0)
	{
		LM_ERR("failed to parse supported headers\n");
		return -1;
	}

	if(!(get_supported(msg) & F_SUPPORTED_EVENTLIST))
	{
		LM_DBG("No support for 'eventlist' - not for rls\n");
		goto forpresence;
	}

	/* inspecting the Event header field */
	if(msg->event && msg->event->body.len > 0)
	{
		if (!msg->event->parsed && (parse_event(msg->event) < 0))
		{
			LM_ERR("cannot parse Event header\n");
			goto error;
		}
		if(! ( ((event_t*)msg->event->parsed)->type & rls_events) )
		{	
			goto forpresence;
		}
	} else {
		goto bad_event;
	}

	/* search event in the list */
	parsed_event = (event_t*)msg->event->parsed;
	event = pres_search_event(parsed_event);
	if(event==NULL)
	{
		goto bad_event;
	}
	subs.event= event;

	/* extract the id if any*/
	ev_param= parsed_event->params.list;
	while(ev_param)
	{
		if(ev_param->name.len==2 && strncmp(ev_param->name.s, "id", 2)==0)
		{
			subs.event_id = ev_param->body;
			break;
		}
		ev_param= ev_param->next;
	}

	/* extract dialog information from message headers */
	if(pres_extract_sdialog_info(&subs, msg, rls_max_expires,
				&to_tag_gen, rls_server_address,
				watcher_user, watcher_domain)<0)
	{
		LM_ERR("bad subscribe request\n");
		goto error;
	}

	hash_code = core_hash(&subs.callid, &subs.to_tag, hash_size);
	if (CONSTR_RLSUBS_DID(&subs, &rlsubs_did) < 0)
	{
		LM_ERR("cannot build rls subs did\n");
		goto error;
	}
	subs.updated = core_hash(&rlsubs_did, NULL, 0) %
		(waitn_time * rls_notifier_poll_rate * rls_notifier_processes);
	
	if(get_to(msg)->tag_value.s==NULL || get_to(msg)->tag_value.len==0)
	{ /* initial Subscribe */
		/*verify if Request URI represents a list by asking xcap server*/	
		if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host,
					&subs.pres_uri)<0)
		{
			LM_ERR("while constructing uri from user and domain\n");
			goto error;
		}
		if(rls_get_service_list(&subs.pres_uri, &subs.watcher_user,
					&subs.watcher_domain, &service_node, &doc)<0)
		{
			LM_ERR("while attepmting to get a resource list\n");
			goto error;
		}
		if(doc==NULL)
		{
			/* if not for RLS, pass it to presence serivce */
			LM_DBG("list not found - searched for uri <%.*s>\n",
					subs.pres_uri.len, subs.pres_uri.s);
			goto forpresence;
		}

		/* if correct reply with 200 OK */
		if(reply_200(msg, &subs.local_contact, subs.expires)<0)
			goto error;

		subs.local_cseq = 0;

		if(subs.expires != 0)
		{
			subs.version = 1;
			if (dbmode==RLS_DB_ONLY)
			{
				rt=insert_rlsdb( &subs );
			}
			else
			{
				rt=pres_insert_shtable(rls_table, hash_code, &subs);
			}
			if (rt<0)
			{
				LM_ERR("while adding new subscription\n");
				goto error;
			}
		}
	} else {
		/* search if a stored dialog */
		if ( dbmode == RLS_DB_ONLY )
		{
			if (rls_dbf.start_transaction)
			{
				if (rls_dbf.start_transaction(rls_db, DB_LOCKING_WRITE) < 0)
				{
					LM_ERR("in start_transaction\n");
					goto error;
				}
			}

			rt = get_dialog_subscribe_rlsdb(&subs);

			if (rt <= 0)
			{
				LM_DBG("subscription dialog not found for <%.*s@%.*s>\n",
						subs.watcher_user.len, subs.watcher_user.s,
						subs.watcher_domain.len, subs.watcher_domain.s);

				if (rls_dbf.end_transaction)
				{
					if (rls_dbf.end_transaction(rls_db) < 0)
					{
						LM_ERR("in end_transaction\n");
						goto error;
					}
				}

				goto forpresence;
			}
			else if(rt>=400)
			{
				reason = (rt==400)?pu_400_rpl:stale_cseq_rpl;
		
				if (slb.freply(msg, 400, &reason) < 0)
				{
					LM_ERR("while sending reply\n");
					goto error;
				}

				if (rls_dbf.end_transaction)
				{
					if (rls_dbf.end_transaction(rls_db) < 0)
					{
						LM_ERR("in end_transaction\n");
						goto error;
					}
				}

				ret = 0;
				goto stop;
			}

			/* if correct reply with 200 OK */
			if(reply_200(msg, &subs.local_contact, subs.expires)<0)
				goto error;

			if (update_dialog_subscribe_rlsdb(&subs) < 0)
			{
				LM_ERR("while updating resource list subscription\n");
				goto error;
			}

			if (rls_dbf.end_transaction)
			{
				if (rls_dbf.end_transaction(rls_db) < 0)
				{
					LM_ERR("in end_transaction\n");
					goto error;
				}
			}
		}
		else
		{
			lock_get(&rls_table[hash_code].lock);
			if(pres_search_shtable(rls_table, subs.callid,
					subs.to_tag, subs.from_tag, hash_code)==NULL)
			{
				lock_release(&rls_table[hash_code].lock);
				LM_DBG("subscription dialog not found for <%.*s@%.*s>\n",
						subs.watcher_user.len, subs.watcher_user.s,
						subs.watcher_domain.len, subs.watcher_domain.s);
				goto forpresence;
			}
			lock_release(&rls_table[hash_code].lock);

			/* if correct reply with 200 OK */
			if(reply_200(msg, &subs.local_contact, subs.expires)<0)
				goto error;

			rt = update_rlsubs(&subs, hash_code);

			if(rt<0)
			{
				LM_ERR("while updating resource list subscription\n");
				goto error;
			}
	
			if(rt>=400)
			{
				reason = (rt==400)?pu_400_rpl:stale_cseq_rpl;
		
				if (slb.freply(msg, 400, &reason) < 0)
				{
					LM_ERR("while sending reply\n");
					goto error;
				}
				ret = 0;
				goto stop;
			}
		}	
		if(rls_get_service_list(&subs.pres_uri, &subs.watcher_user,
					&subs.watcher_domain, &service_node, &doc)<0)
		{
			LM_ERR("failed getting resource list\n");
			goto error;
		}
		if(doc==NULL)
		{
			/* warning: no document returned?!?! */
			LM_WARN("no document returned for uri <%.*s>\n",
					subs.pres_uri.len, subs.pres_uri.s);
			goto done;
		}
	}

	if (dbmode != RLS_DB_ONLY)
	{
		/* sending notify with full state */
		if(send_full_notify(&subs, service_node, &subs.pres_uri, hash_code)<0)
		{
			LM_ERR("failed sending full state notify\n");
			goto error;
		}
	}

	/* send subscribe requests for all in the list */
	if(resource_subscriptions(&subs, service_node)< 0)
	{
		LM_ERR("failed sending subscribe requests to resources in list\n");
		goto error;
	}

	if (dbmode !=RLS_DB_ONLY)
		remove_expired_rlsubs(&subs, hash_code);

done:
	ret = 1;
stop:
forpresence:
	if(contact!=NULL)
	{	
		if(contact->s!=NULL)
			pkg_free(contact->s);
		pkg_free(contact);
	}

	if(subs.pres_uri.s!=NULL)
		pkg_free(subs.pres_uri.s);
	if(subs.record_route.s!=NULL)
		pkg_free(subs.record_route.s);
	if(doc!=NULL)
		xmlFreeDoc(doc);
	if (rlsubs_did.s != NULL)
		pkg_free(rlsubs_did.s);
	return ret;

bad_event:
	err_ret = 0;
	if(reply_489(msg)<0)
	{
		LM_ERR("failed sending 489 reply\n");
		err_ret = -1;
	}

error:
	LM_ERR("occured in rls_handle_subscribe\n");

	if(contact!=NULL)
	{	
		if(contact->s!=NULL)
			pkg_free(contact->s);
		pkg_free(contact);
	}
	if(subs.pres_uri.s!=NULL)
		pkg_free(subs.pres_uri.s);

	if(subs.record_route.s!=NULL)
		pkg_free(subs.record_route.s);

	if(doc!=NULL)
		xmlFreeDoc(doc);

	if (rlsubs_did.s != NULL)
		pkg_free(rlsubs_did.s);

	if (rls_dbf.abort_transaction)
	{
		if (rls_dbf.abort_transaction(rls_db) < 0)
			LM_ERR("in abort_transaction\n");
	}
	
	return err_ret;
}
예제 #9
0
파일: save.c 프로젝트: halan/kamailio
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri)
{
	contact_t* c;
	int st, mode;
	str aor;
	int ret;
	sip_uri_t *u;

	u = parse_to_uri(_m);
	if(u==NULL)
		goto error;

	rerrno = R_FINE;
	ret = 1;

	if (parse_message(_m) < 0) {
		goto error;
	}

	if (check_contacts(_m, &st) > 0) {
		goto error;
	}

	if (parse_supported(_m) == 0) {
		if (!(((struct supported_body *)_m->supported->parsed)->supported_all
				& F_SUPPORTED_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) {
			LM_WARN("Outbound required by server and not supported by UAC\n");
			rerrno = R_OB_UNSUP;
			goto error;
		}
	}
	
	get_act_time();
	c = get_first_contact(_m);

	if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract Address Of Record\n");
		goto error;
	}

	mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE;

	if (c == 0) {
		if (st) {
			if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=3;
		} else {
			if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
			else ret=4;
		}
	} else {
		mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
		if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode)) < 0)
			goto error;
		ret = (ret==0)?1:ret;
	}

	update_stat(accepted_registrations, 1);

	/* Only send reply upon request, not upon reply */
	if ((is_route_type(REQUEST_ROUTE)) && !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0))
		return -1;

	return ret;
error:
	update_stat(rejected_registrations, 1);
	if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) )
		reg_send_reply(_m);

	return 0;
}
예제 #10
0
파일: reply.c 프로젝트: NormB/opensips
/*! \brief
 * Allocate a memory buffer and print Contact
 * header fields into it
 */
int build_contact(ucontact_t* c,struct sip_msg *_m)
{
	char *p, *cp, *tmpgr;
	int fl, len,grlen;
	int build_gruu = 0;
	struct socket_info *sock;

	if (!disable_gruu && _m->supported && parse_supported(_m) == 0 &&
		(get_supported(_m) & F_SUPPORTED_GRUU))
		build_gruu=1;

	contact.data_len = calc_buf_len(c,build_gruu,_m);
	if (!contact.data_len) return 0;

	if (!contact.buf || (contact.buf_len < contact.data_len)) {
		if (contact.buf) pkg_free(contact.buf);
		contact.buf = (char*)pkg_malloc(contact.data_len);
		if (!contact.buf) {
			contact.data_len = 0;
			contact.buf_len = 0;
			LM_ERR("no pkg memory left\n");
			return -1;
		} else {
			contact.buf_len = contact.data_len;
		}
	}

	p = contact.buf;

	memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN);
	p += CONTACT_BEGIN_LEN;

	fl = 0;
	while(c) {
		if (VALID_CONTACT(c, get_act_time())) {
			if (fl) {
				memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN);
				p += CONTACT_SEP_LEN;
			} else {
				fl = 1;
			}

			*p++ = '<';
			memcpy(p, c->c.s, c->c.len);
			p += c->c.len;
			*p++ = '>';

			len = len_q(c->q);
			if (len) {
				memcpy(p, Q_PARAM, Q_PARAM_LEN);
				p += Q_PARAM_LEN;
				memcpy(p, q2str(c->q, 0), len);
				p += len;
			}

			memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN);
			p += EXPIRES_PARAM_LEN;
			cp = int2str((int)(c->expires - get_act_time()), &len);
			memcpy(p, cp, len);
			p += len;

			if (c->received.s) {
				*p++ = ';';
				memcpy(p, rcv_param.s, rcv_param.len);
				p += rcv_param.len;
				*p++ = '=';
				*p++ = '\"';
				memcpy(p, c->received.s, c->received.len);
				p += c->received.len;
				*p++ = '\"';
			}

			if (build_gruu && c->instance.s) {
				sock = (c->sock)?(c->sock):(_m->rcv.bind_address);
				/* build pub GRUU */
				memcpy(p,PUB_GRUU,PUB_GRUU_SIZE);
				p += PUB_GRUU_SIZE;
				*p++ = '\"';
				memcpy(p,SIP_PROTO,SIP_PROTO_SIZE);
				p += SIP_PROTO_SIZE;
				memcpy(p,c->aor->s,c->aor->len);
				p += c->aor->len;
				if (!reg_use_domain) {
					*p++ = '@';
					memcpy(p,sock->name.s,sock->name.len);
					p += sock->name.len;
					*p++ = ':';
					memcpy(p,sock->port_no_str.s,sock->port_no_str.len);
					p += sock->port_no_str.len;
				}
				memcpy(p,GR_PARAM,GR_PARAM_SIZE);
				p += GR_PARAM_SIZE;
				memcpy(p,c->instance.s+1,c->instance.len-2);
				p += c->instance.len-2;
				*p++ = '\"';

				/* build temp GRUU */
				memcpy(p,TEMP_GRUU,TEMP_GRUU_SIZE);
				p += TEMP_GRUU_SIZE;
				*p++ = '\"';
				memcpy(p,SIP_PROTO,SIP_PROTO_SIZE);
				p += SIP_PROTO_SIZE;
				memcpy(p,TEMP_GRUU_HEADER,TEMP_GRUU_HEADER_SIZE);
				p += TEMP_GRUU_HEADER_SIZE;

				tmpgr = build_temp_gruu(c->aor,&c->instance,&c->callid,&grlen);
				base64encode((unsigned char *)p,
						(unsigned char *)tmpgr,grlen);
				p += calc_temp_gruu_len(c->aor,&c->instance,&c->callid);
				*p++ = '@';
				memcpy(p,sock->name.s,sock->name.len);
				p += sock->name.len;
				*p++ = ':';
				memcpy(p,sock->port_no_str.s,sock->port_no_str.len);
				p += sock->port_no_str.len;
				memcpy(p,GR_NO_VAL,GR_NO_VAL_SIZE);
				p += GR_NO_VAL_SIZE;
				*p++ = '\"';

				/* build +sip.instance */
				memcpy(p,SIP_INSTANCE,SIP_INSTANCE_SIZE);
				p += SIP_INSTANCE_SIZE;
				*p++ = '\"';
				memcpy(p,c->instance.s+1,c->instance.len-2);
				p += c->instance.len-2;
				*p++ = '\"';
			}
		}

		c = c->next;
	}

	memcpy(p, CRLF, CRLF_LEN);
	p += CRLF_LEN;

	contact.data_len = p - contact.buf;

	LM_DBG("created Contact HF: %.*s\n", contact.data_len, contact.buf);
	return 0;
}