Beispiel #1
0
/*
 * Process REGISTER request and save it's contacts
 */
static inline int save_real(struct sip_msg* _m, udomain_t* _t, char* _s, int doreply)
{
	contact_t* c;
	int st;
	str aor, ua;

	rerrno = R_FINE;

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

	if (check_contacts(_m, &st) > 0) {
		goto error;
	}
	
	get_act_time();
	c = get_first_contact(_m);

	if (extract_aor(&get_to(_m)->uri, &aor) < 0) {
		LOG(L_ERR, "save(): Error while extracting Address Of Record\n");
		goto error;
	}

	ua.len = 0;
	if (parse_headers(_m, HDR_USERAGENT, 0) != -1 && _m->user_agent &&
	    _m->user_agent->body.len > 0) {
		ua.len = _m->user_agent->body.len;
		ua.s = _m->user_agent->body.s;
	}
	if (ua.len == 0) {
		ua.len = UA_DUMMY_LEN;
		ua.s = UA_DUMMY_STR;
	}

	if (c == 0) {
		if (st) {
			if (star(_t, &aor) < 0) goto error;
		} else {
			if (no_contacts(_t, &aor) < 0) goto error;
		}
	} else {
		if (contacts(_m, c, _t, &aor, &ua) < 0) goto error;
	}

	if (doreply && (send_reply(_m) < 0)) return -1;
	else return 1;
	
 error:
	if (doreply) send_reply(_m);
	return 0;
}
Beispiel #2
0
int save(struct sip_msg* _m, char* _d, char* _f, char* _s)
{
	struct sip_msg* msg = _m;
	struct cell* t = NULL;
	contact_t* _c;
	contact_t* reply_c = NULL;
	contact_t* request_c = NULL;
	int st;
	int ret;
	int requested_exp = 0;
	int enforced_exp = 0;
	int_str val;
	struct lump* l;
	char* p;
	char forced_binding_buf[MAX_FORCED_BINDING_LEN];
	str forced_binding = {NULL, 0};
	str *binding_uri;

	if(_m->first_line.type != SIP_REPLY)
		return save_aux(_m, NULL, _d, _f, _s);

	memset(&val, 0, sizeof(int_str));
	if(!tmb.t_gett) {
		LM_ERR("TM module not loaded - can not save on reply\n");
		return -1;
	}
	t = tmb.t_gett();
	if(!t || t==T_UNDEFINED) {
		LM_ERR("Transaction not created on Register - can not save on reply\n");
		return -1;
	}
	msg = t->uas.request;
	if(!msg) {
		LM_ERR("NULL request - can not save on reply\n");
		return -1;
	}

	if (parse_message(_m) < 0) return -1;
	if (check_contacts(_m, &st) > 0) return -1;
	if (parse_message(msg) < 0) return -1;
	if (check_contacts(msg, &st) > 0) return -1;

	/* msg - request
	   _m  - reply 
	*/
	request_c = get_first_contact(msg);
	if(request_c) {
		/* For now, we deal only with the first contact
		 * FIXME: implement multiple contact handling - see check_contacts() */
		if(!request_c->expires || !request_c->expires->body.len) {
			if (((exp_body_t*)(msg->expires->parsed))->valid) {
				requested_exp = ((exp_body_t*)(msg->expires->parsed))->val;
			} else {
				LM_WARN("No expired defined\n");
			}
		} else {
			if (str2int(&(request_c->expires->body), (unsigned int*)&requested_exp)<0) {
				LM_ERR("unable to get expires from [%.*s]\n",
					request_c->expires->body.len, request_c->expires->body.s);
				return -1;
			}
		}
		LM_DBG("Binding received from client [%.*s] with requested expires [%d]\n",
				request_c->uri.len, request_c->uri.s, requested_exp);

		/* We will use the Contact from request:
		 *  - check if a modified contact was set in avp */
		if (mct_avp_name >= 0 &&
			search_first_avp(mct_avp_type,mct_avp_name,&val,0)
			&& val.s.len > 0) {
			LM_DBG("Binding sent to upper registrar [%.*s]\n",
					val.s.len, val.s.s);
			binding_uri = &val.s;
		} else {
			binding_uri = &request_c->uri;
		}

		if (requested_exp) {
			/* Let's get the contact from reply */
			_c = get_first_contact(_m);
			while (_c) {
				if (compare_uris(binding_uri, NULL, &_c->uri, NULL) == 0) {
					if(_c->expires && _c->expires->body.len) {
						if(str2int(&(_c->expires->body),
							(unsigned int*)&enforced_exp)<0) {
							LM_ERR("unable to get expires from [%.*s]\n",
								_c->expires->body.len,
								_c->expires->body.s);
							return -1;
						}
						LM_DBG("Binding received from upper registrar"
							" [%.*s] with imposed expires [%d]\n",
							_c->uri.len, _c->uri.s, enforced_exp);
						reply_c = _c;
						forced_binding.len = request_c->uri.len + 11 +
									reply_c->expires->body.len;
						if (forced_binding.len <= MAX_FORCED_BINDING_LEN) {
							forced_binding.s = forced_binding_buf;
							forced_binding_buf[0] = '<';
							memcpy(&forced_binding_buf[1],
								request_c->uri.s,
								request_c->uri.len);
							memcpy(&forced_binding_buf[request_c->uri.len + 1],
								">;expires=", 10);
							memcpy(&forced_binding_buf[request_c->uri.len + 11],
								reply_c->expires->body.s,
								reply_c->expires->body.len);
							LM_DBG("forcing binding [%.*s]\n",
								forced_binding.len,
								forced_binding.s);
							break;
						} else {
							LM_ERR("forced binding to BIG:"
								" %d > MAX_FORCED_BINDING_LEN\n",
								forced_binding.len);
							return -1;
						}
					}
				} else {
					LM_DBG("Unmatched binding [%.*s]\n",
							_c->uri.len, _c->uri.s);
				}
				_c = get_next_contact(_c);
			}
		}
		ret = save_aux(msg, forced_binding.s?&forced_binding:NULL, _d, _f, _s);
	} else {
		LM_DBG("No Contact in request => this is an interogation\n");
		ret = 1;
	}


	/* if the contact was changed in register - put the modif value */
	if(request_c && requested_exp && val.s.s) {
		if(reply_c) {
			LM_DBG("replacing contact uri [%.*s] with [%.*s]\n",
				reply_c->uri.len, reply_c->uri.s,
				request_c->uri.len, request_c->uri.s);
			/* replace with what was received in Register */
			/* reply_c->uri - now contains the initial received value */
			if((l=del_lump(_m, reply_c->uri.s - _m->buf, reply_c->uri.len, 0))==0) {
				LM_ERR("Failed to delete contact uri lump\n");
				ret = -1;
				goto done;
			}
			p = pkg_malloc( request_c->uri.len);
			if (p==0) {
				LM_ERR("no more pkg mem\n");
				ret = -1;
				goto done;
			}
			memcpy( p, request_c->uri.s, request_c->uri.len );
			if (insert_new_lump_after( l, p, request_c->uri.len, 0)==0) {
				LM_ERR("insert new lump failed\n");
				pkg_free(p);
				ret =-1;
				goto done;
			}
		}
	}

done:
	clean_msg_clone(t->uas.request, t->uas.request, t->uas.end_request);

	return ret;
}
Beispiel #3
0
int save_aux(struct sip_msg* _m, str* forced_binding, char* _d, char* _f, char* _s)
{
	struct save_ctx  sctx;
	contact_t* c;
	contact_t* forced_c;
	int st;
	str uri;
	str flags_s;
	pv_value_t val;

	rerrno = R_FINE;
	memset( &sctx, 0 , sizeof(sctx));
	sctx.max_contacts = -1;

	sctx.flags = 0;
	if (_f && _f[0]!=0) {
		if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) {
			LM_ERR("invalid flags parameter");
			return -1;
		}
		for( st=0 ; st< flags_s.len ; st++ ) {
			switch (flags_s.s[st]) {
				case 'm': sctx.flags |= REG_SAVE_MEMORY_FLAG; break;
				case 'r': sctx.flags |= REG_SAVE_NOREPLY_FLAG; break;
				case 's': sctx.flags |= REG_SAVE_SOCKET_FLAG; break;
				case 'v': sctx.flags |= REG_SAVE_PATH_RECEIVED_FLAG; break;
				case 'f': sctx.flags |= REG_SAVE_FORCE_REG_FLAG; break;
				case 'c':
					sctx.max_contacts = 0;
					while (st<flags_s.len-1 && isdigit(flags_s.s[st+1])) {
						sctx.max_contacts = sctx.max_contacts*10 + 
							flags_s.s[st+1] - '0';
						st++;
					}
					break;
				case 'p':
					if (st<flags_s.len-1) {
						st++;
						if (flags_s.s[st]=='2') {
							sctx.flags |= REG_SAVE_PATH_STRICT_FLAG; break; }
						if (flags_s.s[st]=='1') {
							sctx.flags |= REG_SAVE_PATH_LAZY_FLAG; break; }
						if (flags_s.s[st]=='0') {
							sctx.flags |= REG_SAVE_PATH_OFF_FLAG; break; }
					}
				default: LM_WARN("unsuported flag %c \n",flags_s.s[st]);
			}
		}
	}
	if(route_type == ONREPLY_ROUTE)
		sctx.flags |= REG_SAVE_NOREPLY_FLAG;

	/* if no max_contact per AOR is defined, use the global one */
	if (sctx.max_contacts == -1)
		sctx.max_contacts = max_contacts;

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

	if (forced_binding) {
		if (parse_contacts(forced_binding, &forced_c) < 0) {
			LM_ERR("Unable to parse forced binding [%.*s]\n",
				forced_binding->len, forced_binding->s);
			goto error;
		}
		/* prevent processing all the headers from the message */
		reset_first_contact();
		st = 0;
		c = forced_c;
	} else {
		if (check_contacts(_m, &st) > 0) {
			goto error;
		}
		c = get_first_contact(_m);
	}

	get_act_time();

	if (_s) {
		if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_STR)==0 ) {
			LM_ERR("PV vals is not string\n");
			return -1;
		}
		uri = val.rs;
	} else {
		uri = get_to(_m)->uri;
	}


	if (extract_aor( &uri, &sctx.aor) < 0) {
		LM_ERR("failed to extract Address Of Record\n");
		goto error;
	}

	if (c == 0) {
		if (st) {
			if (star((udomain_t*)_d, &sctx) < 0) goto error;
		} else {
			if (no_contacts((udomain_t*)_d, &sctx.aor) < 0) goto error;
		}
	} else {
		if (add_contacts(_m, c, (udomain_t*)_d, &sctx) < 0) goto error;
	}

	update_stat(accepted_registrations, 1);

	if (!is_cflag_set(REG_SAVE_NOREPLY_FLAG) && (send_reply(_m,sctx.flags)<0))
		return -1;

	return 1;
error:
	update_stat(rejected_registrations, 1);

	if ( !is_cflag_set(REG_SAVE_NOREPLY_FLAG) )
		send_reply(_m,sctx.flags);

	return 0;
}
Beispiel #4
0
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;
}
Beispiel #5
0
/*
 * Process REGISTER request and save it's contacts
 */
static inline int save_real(struct sip_msg* _m, udomain_t* _t, char* aor_filt, int doreply)
{
	contact_t* c;
	int st;
	str uid, ua, aor_filter;

	rerrno = R_FINE;

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

	if (check_contacts(_m, &st) > 0) {
		goto error;
	}
	
	if (aor_filt) {
	    if (get_str_fparam(&aor_filter, _m, (fparam_t*)aor_filt) != 0) {
		ERR("registrar:save: Unable to get the AOR value\n");
		return -1;
	    }
	} else {
	    aor_filter.s = 0;
	    aor_filter.len = 0;
	}

	get_act_time();
	c = get_first_contact(_m);

	if (get_to_uid(&uid, _m) < 0) goto error;

	ua.len = 0;
	if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent &&
	    _m->user_agent->body.len > 0) {
		ua.len = _m->user_agent->body.len;
		ua.s = _m->user_agent->body.s;
	}
	if (ua.len == 0) {
		ua.len = UA_DUMMY_LEN;
		ua.s = UA_DUMMY_STR;
	}

	if (c == 0) {
		if (st) {
			if (star(_t, &uid, &aor_filter) < 0) goto error;
		} else {
			if (no_contacts(_t, &uid, &aor_filter) < 0) goto error;
		}
	} else {
		if (contacts(_m, c, _t, &uid, &ua, &aor_filter) < 0) goto error;
	}

	if (doreply) {
		if (send_reply(_m) < 0) return -1;
	} else {
		     /* No reply sent, create attributes with values
		      * of reply code, reason text, and contacts
		      */
		if (setup_attrs(_m) < 0) return -1;
	}
	return 1;

 error:
	if (doreply) {
		send_reply(_m);
		return 0;
	}
	return -2;
}
Beispiel #6
0
int save_aux(struct sip_msg* _m, str* forced_binding, void* _d, str* flags_s,
				str* uri, str* _owtag)
{
	struct save_ctx  sctx;
	contact_t* c;
	contact_t* forced_c = NULL;
	int st;

	rerrno = R_FINE;
	memset( &sctx, 0 , sizeof(sctx));
	sctx.max_contacts = -1;

	sctx.flags = 0;
	sctx.min_expires = min_expires;
	sctx.max_expires = max_expires;
	if ( flags_s ) {
		for( st=0 ; st< flags_s->len ; st++ ) {
			switch (flags_s->s[st]) {
				case 'm': sctx.flags |= REG_SAVE_MEMORY_FLAG; break;
				case 'r': sctx.flags |= REG_SAVE_NOREPLY_FLAG; break;
				case 's': sctx.flags |= REG_SAVE_SOCKET_FLAG; break;
				case 'v': sctx.flags |= REG_SAVE_PATH_RECEIVED_FLAG; break;
				case 'f': sctx.flags |= REG_SAVE_FORCE_REG_FLAG; break;
				case 'c':
					sctx.max_contacts = 0;
					while (st<flags_s->len-1 && isdigit(flags_s->s[st+1])) {
						sctx.max_contacts = sctx.max_contacts*10 +
							flags_s->s[st+1] - '0';
						st++;
					}
					break;
				case 'e':
					sctx.min_expires = 0;
					while (st<flags_s->len-1 && isdigit(flags_s->s[st+1])) {
						sctx.min_expires = sctx.min_expires*10 +
							flags_s->s[st+1] - '0';
						st++;
					}
					break;
				case 'E':
					sctx.max_expires = 0;
					while (st<flags_s->len-1 && isdigit(flags_s->s[st+1])) {
						sctx.max_expires = sctx.max_expires*10 +
							flags_s->s[st+1] - '0';
						st++;
					}
					break;
				case 'p':
					if (st<flags_s->len-1) {
						st++;
						if (flags_s->s[st]=='2') {
							sctx.flags |= REG_SAVE_PATH_STRICT_FLAG; break; }
						if (flags_s->s[st]=='1') {
							sctx.flags |= REG_SAVE_PATH_LAZY_FLAG; break; }
						if (flags_s->s[st]=='0') {
							sctx.flags |= REG_SAVE_PATH_OFF_FLAG; break; }
					}
				default: LM_WARN("unsupported flag %c \n",flags_s->s[st]);
			}
		}
	}
	if(route_type == ONREPLY_ROUTE)
		sctx.flags |= REG_SAVE_NOREPLY_FLAG;

	/* if no max_contact per AOR is defined, use the global one */
	if (sctx.max_contacts == -1)
		sctx.max_contacts = max_contacts;

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

	if (forced_binding) {
		if (parse_contacts(forced_binding, &forced_c) < 0) {
			LM_ERR("Unable to parse forced binding [%.*s]\n",
				forced_binding->len, forced_binding->s);
			goto error;
		}
		/* prevent processing all the headers from the message */
		reset_first_contact();
		st = 0;
		c = forced_c;
	} else {
		if (check_contacts(_m, &st) > 0) {
			goto error;
		}
		c = get_first_contact(_m);
	}

	update_act_time();

	if (!uri)
		uri = &(get_to(_m)->uri);

	if (_owtag)
		sctx.ownership_tag = *_owtag;

	if (extract_aor(uri, &sctx.aor,0,0) < 0) {
		LM_ERR("failed to extract Address Of Record\n");
		goto error;
	}

	if (c == 0) {
		if (st) {
			if (star((udomain_t*)_d, &sctx,_m) < 0) goto error;
		} else {
			if (no_contacts((udomain_t*)_d, &sctx.aor,_m) < 0) goto error;
		}
	} else {
		if (add_contacts(_m, c, (udomain_t*)_d, &sctx) < 0) goto error;
	}

	update_stat(accepted_registrations, 1);

	if (!is_cflag_set(REG_SAVE_NOREPLY_FLAG) && (send_reply(_m,sctx.flags)<0))
		goto return_minus_one;

	if (forced_c) free_contacts(&forced_c);

	return 1;
error:
	update_stat(rejected_registrations, 1);

	if ( !is_cflag_set(REG_SAVE_NOREPLY_FLAG) )
		send_reply(_m,sctx.flags);

	if (forced_c) free_contacts(&forced_c);

	return -2;

return_minus_one:
	if (forced_c) free_contacts(&forced_c);

	return -1;
}
Beispiel #7
0
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;
}