Example #1
0
/**
 * Check, if a user-agent follows the indicated service-routes
 */
int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
	struct sip_uri uri;
	int i;
	struct hdr_field *hdr;
	rr_t *r;
	pcontact_t * c = getContactP(_m, _d);
	/* Contact not found => not following service-routes */
	if (c == NULL) return -1;

	/* Search for the first Route-Header: */
	if (find_first_route(_m) < 0) return -1;

	LM_DBG("Got %i Route-Headers.\n", c->num_service_routes);

	/* Lock this record while working with the data: */
	ul.lock_udomain(_d, &c->aor);

	/* Check the route-set: */
	if (_m->route) {
		hdr = _m->route;
		LM_DBG("hdr is %p\n", hdr);
		/* Check, if the first host is ourself: */
		r = (rr_t*)hdr->parsed;
		if (r) {
			LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			/* Skip first headers containing myself: */
			while (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0
			  && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
				LM_DBG("Self\n");
				/* Check for more headers and fail, if it was the last one
				   Check, if service-routes are indicated.
				   If yes, request is not following service-routes */
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;

				if (!r && (c->num_service_routes > 0)) {
					LM_DBG("Not enough route-headers in Message\n");
					goto error;
				}
				LM_DBG("hdr is %p\n", hdr);
				LM_DBG("r is %p\n", r);
				if (r)
					LM_ERR("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			}
			/* Then check the following headers: */
			for (i=0; i< c->num_service_routes; i++) {
				LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s);

				/* No more Route-Headers? Not following service-routes */
				if (!r) {
					LM_ERR("No more route headers in message.\n");
					 goto error;
				}
				
				LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
 				
				/* Check length: */
				if (r->nameaddr.uri.len != c->service_routes[i].len) {
					LM_DBG("Length does not match.\n");
					 goto error;
				}
				/* Check contents: */
				if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) {
					LM_DBG("String comparison failed.\n");
					 goto error;
				}
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;
			}

			/* Check, if it was the last route-header in the message: */
			if (r) {
				LM_ERR("Too many route headers in message.\n");
				 goto error;
			}
		} else {
			LM_WARN("Strange: Route-Header is present, but not parsed?!?");
			if (c->num_service_routes > 0) goto error;
		}
	} else {
		LM_ERR("No route header in Message.\n");
		/* No route-header? Check, if service-routes are indicated.
		   If yes, request is not following service-routes */
		if (c->num_service_routes > 0) goto error;
	}
	/* Unlock domain */
	ul.unlock_udomain(_d, &c->aor);
	return 1;
error:
	/* Unlock domain */
	ul.unlock_udomain(_d, &c->aor);
	return -1;
}
Example #2
0
/*
 * Get next hop using the first Route not generated by this proxy or URI from the Request-Line
 * param msg SIP message
 * param nexthop Next hop IP
 * param bufsize Size of nexthop
 * return 0 success, -1 failure
 */
int ospGetNextHop(
    struct sip_msg* msg,
    char* nexthop,
    int bufsize)
{
    struct hdr_field* hf;
    struct sip_uri uri;
    rr_t* rt;
    int found = 0;
    int result = -1;

    if (bufsize > 0) {
        result = 0;

        for (hf = msg->headers; hf; hf = hf->next) {
            if (hf->type == HDR_ROUTE_T) {
                for (rt = (rr_t*)hf->parsed; rt; rt = rt->next) {
                    if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len, &uri) == 0) {
                        LM_DBG("host '%.*s' port '%d'\n", uri.host.len, uri.host.s, uri.port_no);

                        if (check_self(&uri.host, uri.port_no ? uri.port_no : SIP_PORT, PROTO_NONE) != 1) {
                            LM_DBG("it is NOT me, FOUND!\n");

                            if (uri.port_no != 0) {
                                snprintf(nexthop, bufsize, "%.*s:%d", uri.host.len, uri.host.s, uri.port_no);
                                nexthop[bufsize - 1] = '\0';
                            } else {
                                ospCopyStrToBuffer(&uri.host, nexthop, bufsize);
                            }
                            found = 1;
                            break;
                        } else {
                            LM_DBG("it IS me, keep looking\n");
                        }
                    } else {
                        LM_ERR("failed to parse route uri '%.*s'\n",
                            rt->nameaddr.uri.len,
                            rt->nameaddr.uri.s);
                    }
                }
                if (found == 1) {
                    break;
                }
            }
        }

        if (!found) {
            LM_DBG("using the Request-Line instead host '%.*s' port '%d'\n",
                 msg->parsed_uri.host.len,
                 msg->parsed_uri.host.s,
                 msg->parsed_uri.port_no);

            if (msg->parsed_uri.port_no != 0) {
                snprintf(nexthop, bufsize, "%.*s:%d", msg->parsed_uri.host.len, msg->parsed_uri.host.s, msg->parsed_uri.port_no);
                nexthop[bufsize - 1] = '\0';
            } else {
                ospCopyStrToBuffer(&msg->parsed_uri.host, nexthop, bufsize);
            }
            found = 1;
        }
    }

    return result;
}
Example #3
0
/* removes first via & sends msg to the second
 * - mode param controls if modules sip response callbacks are executed */
static int do_forward_reply(struct sip_msg* msg, int mode)
{
	char* new_buf;
	struct dest_info dst;
	unsigned int new_len;
	int r;
#ifdef USE_TCP
	char* s;
	int len;
#endif
	init_dest_info(&dst);
	new_buf=0;
	/*check if first via host = us */
	if (check_via){
		if (check_self(&msg->via1->host,
					msg->via1->port?msg->via1->port:SIP_PORT,
					msg->via1->proto)!=1){
			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
					" %.*s:%d\n", msg->via1->host.len, msg->via1->host.s,
									msg->via1->port);
			/* send error msg back? */
			goto error;
		}
	}
	
	/* check modules response_f functions */
	if(likely(mode==0)) {
		for (r=0; r<mod_response_cbk_no; r++)
			if (mod_response_cbks[r](msg)==0) goto skip;
	}
	/* we have to forward the reply stateless, so we need second via -bogdan*/
	if (parse_headers( msg, HDR_VIA2_F, 0 )==-1 
		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
	{
		/* no second via => error */
		LOG(L_DBG, "reply cannot be forwarded - no 2nd via\n");
		goto error;
	}

	new_buf = build_res_buf_from_sip_res( msg, &new_len);
	if (!new_buf){
		LOG(L_ERR, "ERROR: forward_reply: building failed\n");
		goto error;
	}

	dst.proto=msg->via2->proto;
	SND_FLAGS_OR(&dst.send_flags, &msg->fwd_send_flags, &msg->rpl_send_flags);
	if (update_sock_struct_from_via( &dst.to, msg, msg->via2 )==-1) goto error;
#ifdef USE_COMP
	dst.comp=msg->via2->comp_no;
#endif

#if defined USE_TCP || defined USE_SCTP
	if (
#ifdef USE_TCP
			dst.proto==PROTO_TCP
			|| dst.proto==PROTO_WS
#ifdef USE_TLS
			|| dst.proto==PROTO_TLS
			|| dst.proto==PROTO_WSS
#endif
#ifdef USE_SCTP
			||
#endif /* USE_SCTP */
#endif /* USE_TCP */
#ifdef USE_SCTP
			dst.proto==PROTO_SCTP
#endif /* USE_SCTP */
			){
		/* find id in i param if it exists */
		if (msg->via1->i && msg->via1->i->value.s){
			s=msg->via1->i->value.s;
			len=msg->via1->i->value.len;
			DBG("forward_reply: i=%.*s\n",len, ZSW(s));
			if (reverse_hex2int(s, len, (unsigned int*)&dst.id)<0){
				LOG(L_ERR, "ERROR: forward_reply: bad via i param \"%.*s\"\n",
						len, ZSW(s));
					dst.id=0;
			}
		}		
				
	} 
#endif

	apply_force_send_socket(&dst, msg);

	if (msg_send(&dst, new_buf, new_len)<0)
	{
		STATS_RPL_FWD_DROP();
		goto error;
	}
#ifdef STATS
	STATS_TX_RESPONSE(  (msg->first_line.u.reply.statuscode/100) );
#endif

	DBG(" reply forwarded to %.*s:%d\n", 
			msg->via2->host.len, msg->via2->host.s,
			(unsigned short) msg->via2->port);

	STATS_RPL_FWD_OK();
	pkg_free(new_buf);
skip:
	return 0;
error:
	if (new_buf) pkg_free(new_buf);
	return -1;
}
Example #4
0
static int l_siplua_getRoute(lua_State *L)
{
  struct sipapi_object *o;
  rr_t *rt;
  str uri;
  struct sip_uri puri;
  int n = 1;

  o = luaL_checkudata(L, 1, "siplua.api");
  if (parse_headers(o->msg, HDR_ROUTE_F, 0) == -1)
    return luaL_error(L, "failed to parse headers");
  if (!o->msg->route)
    {
      lua_pushnil(L);
      return 1;
    }
  if (parse_rr(o->msg->route) < 0)
    return luaL_error(L, "failed to parse route HF");
  lua_newtable(L);
  for (rt = (rr_t *)o->msg->route->parsed; rt; rt = rt->next )
    {
      uri = rt->nameaddr.uri;
      lua_pushinteger(L, n++);
      lua_newtable(L);
      lua_pushliteral(L, "uri");
      lua_pushlstring(L, uri.s, uri.len);
      lua_rawset(L, -3);
      if (parse_uri(uri.s, uri.len, &puri) < 0)
	{
	  if (n == 1)
	    return luaL_error(L, "failed to parse the first route URI");
	  continue;
	}
      lua_pushliteral(L, "user");
      lua_pushlstring(L, puri.user.s, puri.user.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "host");
      lua_pushlstring(L, puri.host.s, puri.host.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "port");
      lua_pushinteger(L, puri.port_no);
      lua_rawset(L, -3);
      lua_pushliteral(L, "params");
      lua_pushlstring(L, puri.params.s, puri.params.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "lr");
      lua_pushlstring(L, puri.lr.s, puri.lr.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "lr_val");
      lua_pushlstring(L, puri.lr_val.s, puri.lr_val.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "r2");
      lua_pushlstring(L, puri.r2.s, puri.r2.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "r2_val");
      lua_pushlstring(L, puri.r2_val.s, puri.r2_val.len);
      lua_rawset(L, -3);
      lua_pushliteral(L, "is_myself");
      if (check_self(&puri.host, puri.port_no ? puri.port_no : SIP_PORT, 0) >= 0)
	lua_pushboolean(L, 1);
      else
	lua_pushboolean(L, 0);
      lua_rawset(L, -3);
      lua_rawset(L, -3);
    }
  return 1;
}
Example #5
0
/*! \brief removes first via & sends msg to the second */
int forward_reply(struct sip_msg* msg)
{
	char* new_buf;
	union sockaddr_union* to;
	unsigned int new_len;
	struct sr_module *mod;
	int proto;
	int id; /* used only by tcp*/
	struct socket_info *send_sock;
	char* s;
	int len;

	to=0;
	id=0;
	new_buf=0;
	/*check if first via host = us */
	if (check_via){
		if (check_self(&msg->via1->host,
					msg->via1->port?msg->via1->port:SIP_PORT,
					msg->via1->proto)!=1){
			LM_ERR("host in first via!=me : %.*s:%d\n",
				msg->via1->host.len, msg->via1->host.s,	msg->via1->port);
			/* send error msg back? */
			goto error;
		}
	}
	/* quick hack, slower for multiple modules*/
	for (mod=modules;mod;mod=mod->next){
		if ((mod->exports) && (mod->exports->response_f)){
			LM_DBG("found module %s, passing reply to it\n",
					mod->exports->name);
			if (mod->exports->response_f(msg)==0) goto skip;
		}
	}

	/* if stateless fwd was disabled, we cannot have stateless replies here*/
	if (sl_fwd_disabled)
		goto skip;

	/* we have to forward the reply stateless, so we need second via -bogdan*/
	if (parse_headers( msg, HDR_VIA2_F, 0 )==-1
		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
	{
		/* no second via => error */
		LM_ERR("no 2nd via found in reply\n");
		goto error;
	}

	to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
	if (to==0){
		LM_ERR("out of pkg memory\n");
		goto error;
	}

	proto=msg->via2->proto;
	if (update_sock_struct_from_via( to, msg, msg->via2 )==-1) goto error;

	if (is_tcp_based_proto(proto)){
		/* find id in i param if it exists */
		if (msg->via1->i&&msg->via1->i->value.s){
			s=msg->via1->i->value.s;
			len=msg->via1->i->value.len;
			id=reverse_hex2int(s, len);
		}
	}

	send_sock = get_send_socket(msg, to, proto);

	new_buf = build_res_buf_from_sip_res( msg, &new_len, send_sock,0);
	if (!new_buf){
		LM_ERR("failed to build rpl from req failed\n");
		goto error;
	}

	if (msg_send(send_sock, proto, to, id, new_buf, new_len, msg)<0) {
		update_stat( drp_rpls, 1);
		goto error0;
	}
	update_stat( fwd_rpls, 1);
	/*
	 * If no port is specified in the second via, then this
	 * message output a wrong port number - zero. Despite that
	 * the correct port is choosen in update_sock_struct_from_via,
	 * as its visible with su_getport(to); .
	 */
	LM_DBG("reply forwarded to %.*s:%d\n", msg->via2->host.len,
		msg->via2->host.s, (unsigned short) msg->via2->port);

	pkg_free(new_buf);
	pkg_free(to);
skip:
	return 0;
error:
	update_stat( err_rpls, 1);
error0:
	if (new_buf) pkg_free(new_buf);
	if (to) pkg_free(to);
	return -1;
}
Example #6
0
int send_resource_subs(char* uri, void* param)
{
	str pres_uri, *tmp_str;
	struct sip_uri parsed_pres_uri;
	int duplicate = 0;
	str *normalized_uri;

	subs_info_t *s = (subs_info_t *) ((void**)param)[0];
	list_entry_t **rls_contact_list = (list_entry_t **) ((void**)param)[1];

	pres_uri.s = uri;
	pres_uri.len = strlen(uri);

	normalized_uri = normalize_sip_uri(&pres_uri);
	if (normalized_uri->s == NULL || normalized_uri->len == 0) {
		LM_ERR("failed to normalize RLS entry URI %.*s\n",
				pres_uri.len, pres_uri.s);
		return -1;
	}

	if (parse_uri(normalized_uri->s, normalized_uri->len, &parsed_pres_uri)
			< 0) {
		LM_ERR("bad uri: %.*s\n", normalized_uri->len, normalized_uri->s);
		return -1;
	}

	if (check_self(&parsed_pres_uri.host, 0, PROTO_NONE) != 1
			&& rls_disable_remote_presence != 0)
	{
		LM_WARN("Unable to subscribe to remote contact %.*s for watcher %.*s\n",
				normalized_uri->len, normalized_uri->s,
				s->watcher_uri->len,
				s->watcher_uri->s);
		return 1;
	}

	/* Silently drop subscribes over the limit - will print a single warning
	 * later */
	if (rls_max_backend_subs > 0 && ++counter > rls_max_backend_subs)
		return 1;

	s->pres_uri = normalized_uri;
	s->remote_target = normalized_uri;

	/* Build list of contacts... checking each contact exists only once */
	if ((tmp_str = (str *)pkg_malloc(sizeof(str))) == NULL)
	{
		LM_ERR("out of private memory\n");
		return -1;
	}
	if ((tmp_str->s = (char *)pkg_malloc(sizeof(char) * pres_uri.len)) == NULL)
	{
		pkg_free(tmp_str);
		LM_ERR("out of private memory\n");
		return -1;
	}
	memcpy(tmp_str->s, normalized_uri->s, normalized_uri->len);
	tmp_str->len = normalized_uri->len;
	*rls_contact_list = list_insert(tmp_str, *rls_contact_list, &duplicate);
	if (duplicate != 0)
	{
		LM_WARN("%.*s has %.*s multiple times in the same resource list\n",
				s->watcher_uri->len, s->watcher_uri->s,
				s->pres_uri->len, s->pres_uri->s);
		pkg_free(tmp_str->s);
		pkg_free(tmp_str);
		return 1;
	}

	return pua_send_subscribe(s);
}
Example #7
0
/**
 * Check, if a user-agent follows the indicated service-routes
 */
int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
	struct sip_uri uri;
	int i;
	struct hdr_field *hdr;
	rr_t *r;
	char routes[MAXROUTES][MAXROUTESIZE];
	unsigned int num_routes = 0;
	
	struct via_body * vb;
	unsigned short port;
	unsigned short proto;
	/* Contact not found => not following service-routes */
//	if (c == NULL) return -1;

	/* Search for the first Route-Header: */
	if (find_first_route(_m) < 0) return -1;

//	LM_DBG("Got %i Route-Headers.\n", c->num_service_routes);

	vb = cscf_get_ue_via(_m);
	port = vb->port?vb->port:5060;
	proto = vb->proto;
	
	/* Lock this record while working with the data: */
	ul.lock_udomain(_d, &vb->host, port, proto);
    
	if (_m->route) {
		hdr = _m->route;
		r = (rr_t*)hdr->parsed;
		//get rid of ourselves from route header
		if (r) {
			LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0)
			  && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
				LM_DBG("Self\n");
				/* Check for more headers and fail, if it was the last one
				   Check, if service-routes are indicated.
				   If yes, request is not following service-routes */
				if (find_next_route(_m, &hdr) != 0) 
					r = NULL;
				else 
					r = (rr_t*)hdr->parsed;
				
				LM_DBG("hdr is %p\n", hdr);
				LM_DBG("r is %p\n", r);
				if (r)
					LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			}
			
			int i = 0;
			while (r) {
				memset(routes[i],0,MAXROUTESIZE);
				memcpy(routes[i], r->nameaddr.uri.s, r->nameaddr.uri.len);
				
				if (find_next_route(_m, &hdr) != 0) 
					r = NULL;
				else 
					r = (rr_t*)hdr->parsed;
				
				i += 1;
				num_routes += 1;
			}
			
			LM_DBG("num_routes is %d\n", num_routes);
			for (i=0; i<num_routes; i++) {
				LM_DBG("route %d for checking is %s\n", i, routes[i]);
			}
			pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, routes, num_routes);
			if (!c) {
				LM_DBG("no contact found in usrloc when checking for service route\n");
				goto error;
			}
			
			LM_DBG("we have a contact which satisifes the routes...\n");
			ul.unlock_udomain(_d, &vb->host, port, proto);
			return 1;
		}
	} else {
		LM_DBG("Request doesn't have any route headers to check service-route...ignoring\n");
		goto error;
	}
	
	pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, 0, 0);
	if (!c) {
		LM_DBG("no contact found in usrloc when checking for service route\n");
		goto error;
	}

	/* Check the route-set: */
	if (_m->route) {
		hdr = _m->route;
		LM_DBG("hdr is %p\n", hdr);
		/* Check, if the first host is ourself: */
		r = (rr_t*)hdr->parsed;
		if (r) {
			LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			/* Skip first headers containing myself: */
			while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0)
			  && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
				LM_DBG("Self\n");
				/* Check for more headers and fail, if it was the last one
				   Check, if service-routes are indicated.
				   If yes, request is not following service-routes */
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;

				if (!r && (c->num_service_routes > 0)) {
					LM_DBG("Not enough route-headers in Message\n");
					goto error;
				}
				LM_DBG("hdr is %p\n", hdr);
				LM_DBG("r is %p\n", r);
				if (r)
					LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			}
			LM_DBG("We have %d service-routes\n", c->num_service_routes);
			/* Then check the following headers: */
			for (i=0; i< c->num_service_routes; i++) {
				LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s);

				/* No more Route-Headers? Not following service-routes */
				if (!r) {
					LM_DBG("No more route headers in message.\n");
					 goto error;
				}
				
				LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
 				
				/* Check length: */
				if (r->nameaddr.uri.len != c->service_routes[i].len) {
					LM_DBG("Length does not match.\n");
					 goto error;
				}
				/* Check contents: */
				if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) {
					LM_DBG("String comparison failed.\n");
					 goto error;
				}
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;
			}

			/* Check, if it was the last route-header in the message: */
			if (r) {
				LM_DBG("Too many route headers in message.\n");
				 goto error;
			}
		} else {
			LM_WARN("Strange: Route-Header is present, but not parsed?!?");
			if (c->num_service_routes > 0) goto error;
		}
	} else {
		LM_DBG("No route header in Message.\n");
		/* No route-header? Check, if service-routes are indicated.
		   If yes, request is not following service-routes */
		if (c->num_service_routes > 0) goto error;
	}
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return 1;
error:
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return -1;
}