/** * 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; }
/* * 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; }
/* 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; }
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; }
/*! \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; }
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); }
/** * 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; }