/* * Do loose routing as defined in RFC3621 */ int loose_route(struct sip_msg* _m, char* _s1, char* _s2) { struct hdr_field* hdr; struct sip_uri puri; rr_t* rt; int ret; str* uri; if (find_first_route(_m) != 0) { DBG("loose_route: There is no Route HF\n"); return -1; } if (parse_sip_msg_uri(_m) == -1) { LOG(L_ERR, "loose_route: Error while parsing Request URI\n"); return -1; } hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = &rt->nameaddr.uri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "loose_route: Error while parsing the first route URI\n"); return -1; } if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no)|| _m->parsed_uri.type == TEL_URI_T || _m->parsed_uri.type == TELS_URI_T) { DBG("loose_route: RURI is myself (or tel URI)\n"); if ((ret = is_myself(&puri.host, puri.port_no)) == 1 && !(enable_double_rr && is_2rr(&puri.params))) { DBG("loose_route: found preloaded loose route\n"); return after_loose(_m, &puri, ret, 1); } else { if (has_to_tag(_m) == 1) { return after_strict(_m, &puri, ret); } else { LOG(L_WARN, "loose_route: pre-loaded strict routing?!\n"); return -1; } } } else { DBG("loose_route: RURI is NOT myself\n"); if (is_myself(&puri.host, puri.port_no)) { return after_loose(_m, &puri, 1, 0); } else { store_next_route_in_avps(uri); //LOG(L_WARN, "loose_route: no routing target is local\n"); //return -1; return after_loose(_m, &puri, 0, 0); } } }
/*! * \brief Do loose routing as per RFC3261 * \param _m SIP message * \return -1 on failure, 1 on success */ int loose_route(struct sip_msg* _m) { int ret; if (find_first_route(_m) != 0) { LM_DBG("There is no Route HF\n"); return -1; } if (parse_sip_msg_uri(_m)<0) { LM_ERR("failed to parse Request URI\n"); return -1; } ret = is_preloaded(_m); if (ret < 0) { return -1; } else if (ret == 1) { return after_loose(_m, 1); } else { if (is_myself(&_m->parsed_uri)) { return after_strict(_m); } else { return after_loose(_m, 0); } } }
void sd_notify_handler(struct sd_node *sender, void *msg, size_t msg_len) { struct event_struct *cevent; struct work_notify *w; dprintf("size: %zd, from: %s\n", msg_len, node_to_str(sender)); w = zalloc(sizeof(*w)); if (!w) return; cevent = &w->cev; cevent->ctype = EVENT_NOTIFY; vprintf(SDOG_DEBUG, "allow new deliver %p\n", cevent); w->sender = *sender; if (msg_len) { w->msg = zalloc(msg_len); if (!w->msg) return; memcpy(w->msg, msg, msg_len); } else w->msg = NULL; if (is_myself(sender->addr, sender->port)) { w->req = list_first_entry(&sys->pending_list, struct request, pending_list); list_del(&w->req->pending_list); }
static int matches_me(struct Output *out, unsigned ip, unsigned port) { unsigned i; for (i=0; i<8; i++) { if (is_myself(&out->src[i], ip, port)) return 1; } return 0; }
/* * Pass on a notification message from the cluster driver. * * Must run in the main thread as it accesses unlocked state like * sys->pending_list. */ void sd_notify_handler(struct sd_node *sender, void *data, size_t data_len) { struct vdi_op_message *msg = data; struct sd_op_template *op = get_sd_op(msg->req.opcode); int ret = msg->rsp.result; struct request *req = NULL; dprintf("op %s, size: %zd, from: %s\n", op_name(op), data_len, node_to_str(sender)); if (is_myself(sender->nid.addr, sender->nid.port)) { req = list_first_entry(&sys->pending_list, struct request, pending_list); list_del(&req->pending_list); }
static int get_vdi_bitmap_from(struct sd_node *node) { struct sd_req hdr; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; static DECLARE_BITMAP(tmp_vdi_inuse, SD_NR_VDIS); int fd, i, ret = SD_RES_SUCCESS; unsigned int rlen, wlen; char host[128]; if (is_myself(node->addr, node->port)) goto out; addr_to_str(host, sizeof(host), node->addr, 0); fd = connect_to(host, node->port); if (fd < 0) { vprintf(SDOG_ERR, "unable to get the VDI bitmap from %s: %m\n", host); ret = -SD_RES_EIO; goto out; } vprintf(SDOG_ERR, "%s:%d\n", host, node->port); memset(&hdr, 0, sizeof(hdr)); hdr.opcode = SD_OP_READ_VDIS; hdr.epoch = sys->epoch; hdr.data_length = sizeof(tmp_vdi_inuse); rlen = hdr.data_length; wlen = 0; ret = exec_req(fd, &hdr, (char *)tmp_vdi_inuse, &wlen, &rlen); close(fd); if (ret || rsp->result != SD_RES_SUCCESS) { vprintf(SDOG_ERR, "unable to get the VDI bitmap (%d, %d)\n", ret, rsp->result); goto out; } for (i = 0; i < ARRAY_SIZE(sys->vdi_inuse); i++) sys->vdi_inuse[i] |= tmp_vdi_inuse[i]; out: return ret; }
/*! * \brief Previous hop was a loose router, handle this case * \param _m SIP message * \param preloaded do we have a preloaded route set * \return -1 on failure, 1 on success */ static inline int after_loose(struct sip_msg* _m, int preloaded) { struct hdr_field* hdr; struct sip_uri puri; rr_t* rt; int res; int status = RR_DRIVEN; str uri; struct socket_info *si; int uri_is_myself, next_is_strict; int use_ob = 0; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; /* reset rr handling static vars for safety in error case */ routed_msg_id = 0; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } next_is_strict = is_strict(&puri.params); routed_params = puri.params; uri_is_myself = is_myself(&puri); /* IF the URI was added by me, remove it */ if (uri_is_myself>0) { LM_DBG("Topmost route URI: '%.*s' is me\n", uri.len, ZSW(uri.s)); /* set the hooks for the params */ routed_msg_id = _m->id; if ((use_ob = process_outbound(_m, puri.user)) < 0) { LM_INFO("failed to process outbound flow-token\n"); return FLOW_TOKEN_BROKEN; } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("No next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; if (enable_double_rr && is_2rr(&puri.params)) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) { LM_ERR("failed to parse the double route URI\n"); return RR_ERROR; } if (!use_ob) { si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { set_force_socket(_m, si); } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found for match second RR\n"); } } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("no next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; } uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } } else { #ifdef ENABLE_USER_CHECK /* check if it the ignored user */ if(uri_is_myself < 0) return NOT_RR_DRIVEN; #endif LM_DBG("Topmost URI is NOT myself\n"); routed_params.s = NULL; routed_params.len = 0; } LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s)); if (next_is_strict) { LM_DBG("Next URI is a strict router\n"); if (handle_sr(_m, hdr, rt) < 0) { LM_ERR("failed to handle strict router\n"); return RR_ERROR; } } else { /* Next hop is loose router */ LM_DBG("Next URI is a loose router\n"); if (!use_ob) { if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* dst_uri changed, so it makes sense to re-use the current uri for forking */ ruri_mark_new(); /* re-use uri for serial forking */ } /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ if (rt != hdr->parsed) { if (!del_lump(_m, hdr->body.s - _m->buf, rt->nameaddr.name.s - hdr->body.s, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } } done: if (use_ob == 1) status = RR_OB_DRIVEN; /* run RR callbacks only if we have Route URI parameters */ if(routed_params.len > 0) run_rr_callbacks( _m, &routed_params ); return status; }
/*! * \brief Previous hop was a strict router, handle this case * \param _m SIP message * \return -1 on error, 1 on success */ static inline int after_strict(struct sip_msg* _m) { int res, rem_len; struct hdr_field* hdr; struct sip_uri puri; rr_t* rt, *prev; char* rem_off; str uri; struct socket_info *si; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; /* reset rr handling static vars for safety in error case */ routed_msg_id = 0; routed_params.s = NULL; routed_params.len = 0; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { set_force_socket(_m, si); } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found for match second RR\n"); } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("searching next route failed\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("after_strict: No next URI found\n"); return NOT_RR_DRIVEN; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; /* parse the new found uri */ uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse URI\n"); return RR_ERROR; } } /* set the hooks for the param * important note: RURI is already parsed by the above function, so * we just used it without any checking */ routed_msg_id = _m->id; routed_params = _m->parsed_uri.params; if (is_strict(&puri.params)) { LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s)); /* Previous hop was a strict router and the next hop is strict * router too. There is no need to save R-URI again because it * is saved already. In fact, in this case we will behave exactly * like a strict router. */ /* Note: when there is only one Route URI left (endpoint), it will * always be a strict router because endpoints don't use ;lr parameter * In this case we will simply put the URI in R-URI and forward it, * which will work perfectly */ if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("failed to check maddr\n"); return RR_ERROR; } if (rewrite_uri(_m, &uri) < 0) { LM_ERR("failed to rewrite request URI\n"); return RR_ERROR; } if (rt->next) { rem_off = hdr->body.s; rem_len = rt->next->nameaddr.name.s - hdr->body.s; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } else { LM_DBG("Next hop: '%.*s' is loose router\n", uri.len, ZSW(uri.s)); if(get_maddr_uri(&uri, &puri)!=0) { LM_ERR("failed to check maddr\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* Next hop is a loose router - Which means that is is not endpoint yet * In This case we have to recover from previous strict routing, that * means we have to find the last Route URI and put in in R-URI and * remove the last Route URI. */ if (rt != hdr->parsed) { /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ rem_off = hdr->body.s; rem_len = rt->nameaddr.name.s - hdr->body.s; if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } res = find_rem_target(_m, &hdr, &rt, &prev); if (res < 0) { LM_ERR("searching for last Route URI failed\n"); return RR_ERROR; } else if (res > 0) { /* No remote target is an error */ return RR_ERROR; } uri = rt->nameaddr.uri; if(get_maddr_uri(&uri, 0)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (rewrite_uri(_m, &uri) < 0) { LM_ERR("failed to rewrite R-URI\n"); return RR_ERROR; } /* The first character if uri will be either '<' when it is the * only URI in a Route header field or ',' if there is more than * one URI in the header field */ LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); if (prev) { rem_off = prev->nameaddr.name.s + prev->len; rem_len = rt->nameaddr.name.s + rt->len - rem_off; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } } /* run RR callbacks only if we have Route URI parameters */ if(routed_params.len > 0) run_rr_callbacks( _m, &routed_params ); return RR_DRIVEN; }
/* * Do loose routing as defined in RFC3261 */ int loose_route(struct sip_msg* _m) { int ret; ctx_routing_set(0); if (find_first_route(_m) != 0) { LM_DBG("There is no Route HF\n"); return -1; } if (parse_sip_msg_uri(_m)<0) { LM_ERR("failed to parse Request URI\n"); return -1; } ret = is_preloaded(_m); if (ret < 0) { return -1; } else if (ret == 1) { return after_loose(_m, 1); } else { #ifdef ENABLE_USER_CHECK if (is_myself(&_m->parsed_uri.user, &_m->parsed_uri.host, _m->parsed_uri.port_no) && !(_m->parsed_uri.gr.s && _m->parsed_uri.gr.len)) { #else if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no) && !(_m->parsed_uri.gr.s && _m->parsed_uri.gr.len)) { #endif return after_strict(_m); } else { return after_loose(_m, 0); } } } int get_route_params(struct sip_msg *msg, str *val) { if(msg==NULL) return -1; /* check if params are present */ if ( (val=ctx_rrparam_get())==NULL ) return -1; return 0; } int check_route_param(struct sip_msg * msg, regex_t* re) { regmatch_t pmatch; char bk; str params; str *rparams; /* check if params are present */ if ( (rparams=ctx_rrparam_get())==NULL || rparams->len==0) return -1; /* include also the first ';' */ for( params=*rparams ; params.s[0]!=';' ; params.s--,params.len++ ); /* do the well-known trick to convert to null terminted */ bk = params.s[params.len]; params.s[params.len] = 0; LM_DBG("params are <%s>\n", params.s); if (regexec( re, params.s, 1, &pmatch, 0)!=0) { params.s[params.len] = bk; return -1; } else { params.s[params.len] = bk; return 0; } }
static inline int after_loose(struct sip_msg* _m, int preloaded) { struct hdr_field* hdr; struct sip_uri puri; struct sip_uri puri2; rr_t* rt; int res; int status; #ifdef ENABLE_USER_CHECK int ret; #endif str uri; struct socket_info *si; int force_ss = 0; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } /* IF the URI was added by me, remove it */ #ifdef ENABLE_USER_CHECK ret=is_myself(&puri.user, &puri.host, puri.port_no); if (ret>0) #else if (is_myself(&puri.host, puri.port_no)) #endif { LM_DBG("Topmost route URI: '%.*s' is me\n", uri.len, ZSW(uri.s)); /* set the hooks for the params -bogdan */ ctx_rrparam_set( &puri.params ); /* if last route in header, gonna get del_lumped now, * if not, it will be taken care of later * Mark it now as deleted */ rt->deleted = 1; if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } rt->deleted = 1; res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("No next URI found!\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); /*same case as LL , if there is no next route*/ ctx_routing_set( ROUTING_LL ); force_ss = 1; goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; if (enable_double_rr && is_2rr(&puri.params)) { force_ss = 0; /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) { LM_ERR("failed to parse the double route URI\n"); return RR_ERROR; } set_sip_defaults( puri.port_no, puri.proto); si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { _m->force_send_socket = si; } else { if (enable_socket_mismatch_warning) LM_WARN("no socket found to match 2nd RR [%d][%.*s:%d]\n", puri.proto, puri.host.len, puri.host.s, puri.port_no); } rt->deleted = 1; if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LM_ERR("failed to find next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ LM_DBG("no next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); /* same case as LL , if there is no next route */ ctx_routing_set( ROUTING_LL ); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; } else { force_ss = 1; } uri = rt->nameaddr.uri; if (parse_uri(uri.s, uri.len, &puri2) < 0) { LM_ERR("failed to parse the first route URI\n"); return RR_ERROR; } } else { #ifdef ENABLE_USER_CHECK /* check if it the ignored user */ if(ret < 0) return NOT_RR_DRIVEN; #endif LM_DBG("Topmost URI is NOT myself\n"); memcpy(&puri2, &puri, sizeof(struct sip_uri)); } LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s)); if (is_strict(&puri2.params)) { LM_DBG("Next URI is a strict router\n"); ctx_routing_set( ROUTING_LS ); if (handle_sr(_m, hdr, rt) < 0) { LM_ERR("failed to handle strict router\n"); return RR_ERROR; } } else { /* Next hop is loose router */ LM_DBG("Next URI is a loose router\n"); ctx_routing_set( ROUTING_LL ); if(get_maddr_uri(&uri, &puri2)!=0) { LM_ERR("checking maddr failed\n"); return RR_ERROR; } if (set_dst_uri(_m, &uri) < 0) { LM_ERR("failed to set dst_uri\n"); return RR_ERROR; } /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ if (rt != hdr->parsed) { if (!del_lump(_m, hdr->body.s - _m->buf, rt->nameaddr.name.s - hdr->body.s, 0)) { LM_ERR("failed to remove Route HF\n"); return RR_ERROR; } ((rr_t *)hdr->parsed)->deleted = 1; } } status = RR_DRIVEN; done: if (force_ss && !preloaded) _m->force_send_socket = _m->rcv.bind_address; /* run RR callbacks -bogdan */ run_rr_callbacks( _m, &puri.params ); return status; }
/* * Do loose routing as defined in RFC3261 */ int loose_route(struct sip_msg* _m, char* _s1, char* _s2) { int ret; removed_routes = 0; routing_type = 0; if (find_first_route(_m) != 0) { LM_DBG("There is no Route HF\n"); return -1; } if (parse_sip_msg_uri(_m)<0) { LM_ERR("failed to parse Request URI\n"); return -1; } ret = is_preloaded(_m); if (ret < 0) { return -1; } else if (ret == 1) { return after_loose(_m, 1); } else { #ifdef ENABLE_USER_CHECK if (is_myself(&_m->parsed_uri.user, &_m->parsed_uri.host, _m->parsed_uri.port_no)) { #else if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no)) { #endif return after_strict(_m); } else { return after_loose(_m, 0); } } } int get_route_params(struct sip_msg *msg, str *val) { if(msg==NULL) return -1; /* check if the hooked params belong to the same message */ if (routed_msg_id != msg->id) return -1; val->s = routed_params.s; val->len = routed_params.len; return 0; } int check_route_param(struct sip_msg * msg, regex_t* re) { regmatch_t pmatch; char bk; str params; /* check if the hooked params belong to the same message */ if (routed_msg_id != msg->id) return -1; /* check if params are present */ if ( !routed_params.s || !routed_params.len ) return -1; /* include also the first ';' */ for( params=routed_params ; params.s[0]!=';' ; params.s--,params.len++ ); /* do the well-known trick to convert to null terminted */ bk = params.s[params.len]; params.s[params.len] = 0; LM_DBG("params are <%s>\n", params.s); if (regexec( re, params.s, 1, &pmatch, 0)!=0) { params.s[params.len] = bk; return -1; } else { params.s[params.len] = bk; return 0; } }