bool Basic_block::is_delayed_slot(Instruction *i){ if (get_branch()== NULL) return false; int j = (getInst(get_branch()))->get_index(); return (j < i-> get_index()); }
static gboolean builder_source_git_download (BuilderSource *source, gboolean update_vcs, BuilderContext *context, GError **error) { BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); g_autofree char *location = NULL; location = get_url_or_path (self, context, error); if (location == NULL) return FALSE; if (!builder_git_mirror_repo (location, NULL, update_vcs, TRUE, self->disable_fsckobjects, get_branch (self), context, error)) return FALSE; if (self->commit != NULL && self->branch != NULL) { g_autofree char *current_commit = builder_git_get_current_commit (location,get_branch (self), context, error); if (current_commit == NULL) return FALSE; if (strcmp (current_commit, self->commit) != 0) return flatpak_fail (error, "Git commit for branch %s is %s, but expected %s\n", self->branch, current_commit, self->commit); } return TRUE; }
static gboolean builder_source_git_bundle (BuilderSource *source, BuilderContext *context, GError **error) { BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); g_autofree char *location = NULL; g_autoptr(GFile) mirror_dir = NULL; location = get_url_or_path (self, context, error); g_print ("builder_source_git_bundle %s\n", location); if (location == NULL) return FALSE; mirror_dir = flatpak_build_file (builder_context_get_app_dir (context), "sources/git", NULL); if (!flatpak_mkdir_p (mirror_dir, NULL, error)) return FALSE; if (!builder_git_mirror_repo (location, flatpak_file_get_path_cached (mirror_dir), FALSE, TRUE, FALSE, get_branch (self), context, error)) return FALSE; return TRUE; }
void print(struct tree *str) { int i = 0; int len; if (str == NULL) return; len = str->width; switch(str->type) { case CHAR: putchar(str->data.c); break; case INT: printf("%d", str->data.i); break; case DOUBLE: printf("%f", str->data.d); break; case TREE: print(str->data.t); break; default: break; } while (i < len) { print(get_branch(str, i++)); } }
struct node *find_link (int index, struct node *parent, struct node *child, int firsti, int lasti) // Find and establish the suffix link for the given child node, // working downward from its parent's suffix link. { int e, betalen, r, depth; struct node *vp, *branch, *leaf; // Capture beta for later consumption betalen = lasti - firsti; // traverse parent's suffix link. vp = parent -> sfxlink; branch = get_branch (firsti, vp); if (branch && betalen) { // Beta not empty // Consume Beta and Establish child -> sfxlink leaf = consume_beta (index, firsti, betalen, branch, child); } else { // Beta was empty or no branch exists for the letter at input[index] child -> sfxlink = vp; leaf = find_path (index, index, vp); } return leaf; }
/* * Check if host in Request URI is local */ int is_uri_host_local(struct sip_msg* _msg, char* _s1, char* _s2) { str branch; qvalue_t q; struct sip_uri puri; struct attr_list *attrs; str did; if ( is_route_type(REQUEST_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE) ) { if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("error while parsing R-URI\n"); return -1; } return hash_table_lookup(&(_msg->parsed_uri.host), &did, &attrs); } else if (is_route_type(FAILURE_ROUTE)) { branch.s = get_branch(0, &branch.len, &q, 0, 0, 0, 0, 0, 0, 0); if (branch.s) { if (parse_uri(branch.s, branch.len, &puri) < 0) { LM_ERR("error while parsing branch URI\n"); return -1; } return hash_table_lookup(&(puri.host), &did, &attrs); } else { LM_ERR("branch is missing, error in script\n"); return -1; } } else { LM_ERR("unsupported route type\n"); return -1; } }
static gboolean builder_source_git_update (BuilderSource *source, BuilderContext *context, GError **error) { BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); g_autoptr(GFile) mirror_dir = NULL; char *current_commit; g_autofree char *location = NULL; location = get_url_or_path (self, context, error); if (location == NULL) return FALSE; mirror_dir = git_get_mirror_dir (location, context); current_commit = git_get_current_commit (mirror_dir, get_branch (self), context, NULL); if (current_commit) { g_free (self->branch); self->branch = current_commit; } return TRUE; }
/* * Check if host in Request URI is local */ int is_uri_host_local(struct sip_msg* _msg, char* _s1, char* _s2) { str branch; qvalue_t q; struct sip_uri puri; if ((route_type == REQUEST_ROUTE) || (route_type == BRANCH_ROUTE)) { if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("Error while parsing R-URI\n"); return -1; } return is_domain_local(&(_msg->parsed_uri.host)); } else if (route_type == FAILURE_ROUTE) { branch.s = get_branch(0, &branch.len, &q, 0, 0, 0, 0); if (branch.s) { if (parse_uri(branch.s, branch.len, &puri) < 0) { LM_ERR("Error while parsing branch URI\n"); return -1; } return is_domain_local(&(puri.host)); } else { LM_ERR("Branch is missing, error in script\n"); return -1; } } else { LM_ERR("Unsupported route type\n"); return -1; } }
struct tree *get_branch_t(struct tree *root, struct tree *branch) { struct tree *child; inc_refcount(branch); child = (struct tree *)get_branch(root, branch->data.i); dec_refcount(branch); return child; }
int main(int argc, char *argv[]){ if(argc != 2){ fprintf(stderr, "Wrong number of arguments! Usage: %s [get-branch|get-pending|get-dir]\n", argv[0]); exit(EXIT_FAILURE); } if(strcmp(argv[1], "get-branch") == 0){ get_branch(); } else if(strcmp(argv[1], "get-pending") == 0){ int pending = get_pending(); if(pending > 0){ printf("%%B(%d)%%b\n", pending); } } else if(strcmp(argv[1], "get-dir") == 0){ int files; int dirs; if(get_dirlisting(&files, &dirs)){ printf("%d/%d\n", files, dirs); } } else { fprintf(stderr, "Unknown argument: '%s'. Usage: %s [get-branch|get-pending|get-dir]\n", argv[1], argv[0]); exit(EXIT_FAILURE); } return 0; }
static void builder_source_git_checksum (BuilderSource *source, BuilderCache *cache, BuilderContext *context) { BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); g_autoptr(GFile) mirror_dir = NULL; g_autofree char *current_commit = NULL; g_autoptr(GError) error = NULL; g_autofree char *location = NULL; builder_cache_checksum_str (cache, self->url); builder_cache_checksum_str (cache, self->path); builder_cache_checksum_str (cache, self->branch); location = get_url_or_path (self, context, &error); if (location != NULL) { mirror_dir = git_get_mirror_dir (location, context); current_commit = git_get_current_commit (mirror_dir, get_branch (self), context, &error); if (current_commit) builder_cache_checksum_str (cache, current_commit); else if (error) g_warning ("Failed to get current git checksum: %s", error->message); } else { g_warning ("No url or path"); } }
struct node *consume_beta (int index, int firsti, int betalen, struct node *startnode, struct node *u) // Consume Beta (slice of input string); // Establish suffix link of u to point to the spot at which Beta was consumed; // Find leaf insertion location and return a pointer to it. { int e, r, depth; struct node *branch, *leaf; r = 0; branch = startnode; while (r < betalen) { e = (branch -> endi) - (branch -> starti); if (r + e > betalen) { // Beta is consumed mid-edge. // Break edge. Assign the suffix link to the breakpoint and append leaf. u -> sfxlink = break_edge (branch -> starti + (betalen - r), branch); allocate_node (&leaf, index, index + u -> sfxlink -> strdepth, slen, u -> sfxlink); push_branch (&(u -> sfxlink), leaf); break; } else if (r + e == betalen) { // Beta is consumed at an existing node // Establish link and place the leaf by matching characters. u -> sfxlink = branch; depth = index - 1 + u -> strdepth; leaf = find_path (index, depth, branch); break; } else { // Hop to next node by adding its edge length to r. r += e; branch = get_branch (firsti + r, branch); } } return leaf; }
static inline int get_block(struct inode * inode, sector_t block, struct buffer_head *bh, int create) { int err = -EIO; int offsets[DEPTH]; Indirect chain[DEPTH]; Indirect *partial; int left; int depth = block_to_path(inode, block, offsets); if (depth == 0) goto out; reread: partial = get_branch(inode, depth, offsets, chain, &err); if (!partial) { got_it: map_bh(bh, inode->i_sb, block_to_cpu(chain[depth-1].key)); partial = chain+depth-1; goto cleanup; } if (!create || err == -EIO) { cleanup: while (partial > chain) { brelse(partial->bh); partial--; } out: return err; } if (err == -EAGAIN) goto changed; left = (chain + depth) - partial; err = alloc_branch(inode, left, offsets+(partial-chain), partial); if (err) goto cleanup; if (splice_branch(inode, chain, partial, left) < 0) goto changed; set_buffer_new(bh); goto got_it; changed: while (partial > chain) { brelse(partial->bh); partial--; } goto reread; }
struct node *find_path (int index, int sufdepth, struct node *v) // Find path to the insertion point for the suffix beginning at input_string[index]. // Allocate and insert the node. { int i, j, e; struct node *branch, *parent, *newint, *leaf, *tmp; // find child starting with input_string[sufdepth] i = sufdepth; parent = v; branch = get_branch (i, v); if (branch) { j = branch -> starti; e = branch -> endi - branch -> starti; // Look for the first mismatch in the current suffix and the path below v while (input_string[i] == input_string[j]) { if (!(--e)) { parent = branch; if ((branch = get_branch (++i, branch)) == NULL) break; j = branch -> starti; e = branch -> endi - branch -> starti; } else { ++i; ++j; } } } // Allocate and insert a leaf at the branch point. if (branch) { // Fork branch by making new internal node if (branch -> endi - branch -> starti > 1) { newint = break_edge (j, branch); allocate_node (&leaf, index, i, slen, newint); push_branch (&newint, leaf); } else { allocate_node (&leaf, index, i, slen, branch); push_branch (&branch, leaf); } } else { allocate_node (&leaf, index, i, slen, parent); push_branch (&parent, leaf); } return leaf; }
/** Return the next branch from the dset array. * 0 is returned if there are no more branches */ char* next_branch(int* len, qvalue_t* q, str* dst_uri, str* path, unsigned int* flags, struct socket_info** force_socket) { char* ret; ret=get_branch(branch_iterator, len, q, dst_uri, path, flags, force_socket); if (likely(ret)) branch_iterator++; return ret; }
t_lst *block_branch_get( t_block *block, int dir) { t_lst *branch = lst_new( "branch"); t_lst *bricks = block->bricks; t_link *l; t_block *target; t_brick *brick; for( l = bricks->first; l; l = l->next) { brick = l->data; target = get_block_connected( brick, dir); if( target) get_branch( target, branch, dir); } return branch; }
void get_branch( t_block *block, t_lst *lst, int dir) { if( !block_in_list( block, lst)) { lst_add( lst, block, block->id.name); t_lst *bricks = block->bricks; t_brick *brick; t_block *target; t_link *l; for( l = bricks->first; l; l = l->next) { brick = l->data; target = get_block_connected( brick, dir); if( target) get_branch( target, lst, dir); } } }
static gboolean builder_source_git_extract (BuilderSource *source, GFile *dest, BuilderOptions *build_options, BuilderContext *context, GError **error) { BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); g_autofree char *location = NULL; location = get_url_or_path (self, context, error); if (location == NULL) return FALSE; if (!builder_git_checkout (location, get_branch (self), dest, context, error)) return FALSE; return TRUE; }
static gboolean builder_source_git_extract (BuilderSource *source, GFile *dest, BuilderContext *context, GError **error) { BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); g_autoptr(GFile) mirror_dir = NULL; g_autofree char *mirror_dir_path = NULL; g_autofree char *dest_path = NULL; g_autofree char *location = NULL; location = get_url_or_path (self, context, error); if (location == NULL) return FALSE; mirror_dir = git_get_mirror_dir (location, context); mirror_dir_path = g_file_get_path (mirror_dir); dest_path = g_file_get_path (dest); if (!git (NULL, NULL, error, "clone", mirror_dir_path, dest_path, NULL)) return FALSE; if (!git (dest, NULL, error, "checkout", get_branch (self), NULL)) return FALSE; if (!git_extract_submodule (location, dest, context, error)) return FALSE; if (!git (dest, NULL, error, "config", "--local", "remote.origin.url", location, NULL)) return FALSE; return TRUE; }
static Indirect *find_shared(struct inode *inode, int depth, int offsets[DEPTH], Indirect chain[DEPTH], block_t *top) { Indirect *partial, *p; int k, err; *top = 0; for (k = depth; k > 1 && !offsets[k-1]; k--) ; partial = get_branch(inode, k, offsets, chain, &err); write_lock(&pointers_lock); if (!partial) partial = chain + k-1; if (!partial->key && *partial->p) { write_unlock(&pointers_lock); goto no_top; } for (p=partial;p>chain && all_zeroes((block_t*)p->bh->b_data,p->p);p--) ; if (p == chain + k - 1 && p > chain) { p->p--; } else { *top = *p->p; *p->p = 0; } write_unlock(&pointers_lock); while(partial > p) { brelse(partial->bh); partial--; } no_top: return partial; }
static gboolean builder_source_git_download (BuilderSource *source, gboolean update_vcs, BuilderContext *context, GError **error) { BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); g_autofree char *url = NULL; url = get_url (self, context, error); if (url == NULL) return FALSE; if (!git_mirror_repo (url, update_vcs, get_branch (self), context, error)) return FALSE; return TRUE; }
/*! \brief * Lookup contact in the database and rewrite Request-URI * \return: -1 : not found * -2 : found but method not allowed * -3 : error */ int lookup(struct sip_msg* _m, char* _t, char* _f, char* _s) { unsigned int flags; urecord_t* r; str aor, uri; ucontact_t* ptr,*it; int res; int ret; str path_dst; str flags_s; char* ua = NULL; char* re_end = NULL; int re_len = 0; char tmp; regex_t ua_re; int regexp_flags = 0; regmatch_t ua_match; pv_value_t val; int_str istr; str sip_instance = {0,0},call_id = {0,0}; /* branch index */ int idx; /* temporary branch values*/ int tlen; char *turi; qvalue_t tq; flags = 0; if (_f && _f[0]!=0) { if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) { LM_ERR("invalid owner uri parameter"); return -1; } for( res=0 ; res< flags_s.len ; res++ ) { switch (flags_s.s[res]) { case 'm': flags |= REG_LOOKUP_METHODFILTER_FLAG; break; case 'b': flags |= REG_LOOKUP_NOBRANCH_FLAG; break; case 'r': flags |= REG_BRANCH_AOR_LOOKUP_FLAG; break; case 'u': if (flags_s.s[res+1] != '/') { LM_ERR("no regexp after 'u' flag"); break; } res++; if ((re_end = strrchr(flags_s.s+res+1, '/')) == NULL) { LM_ERR("no regexp after 'u' flag"); break; } res++; re_len = re_end-flags_s.s-res; if (re_len == 0) { LM_ERR("empty regexp"); break; } ua = flags_s.s+res; flags |= REG_LOOKUP_UAFILTER_FLAG; LM_DBG("found regexp /%.*s/", re_len, ua); res += re_len; break; case 'i': regexp_flags |= REG_ICASE; break; case 'e': regexp_flags |= REG_EXTENDED; break; default: LM_WARN("unsuported flag %c \n",flags_s.s[res]); } } } if (flags®_BRANCH_AOR_LOOKUP_FLAG) { /* extract all the branches for further usage */ nbranches = 0; while ( (turi=get_branch(nbranches, &tlen, &tq, NULL, NULL, NULL, NULL)) ) { /* copy uri */ branch_uris[nbranches].s = urimem[nbranches]; if (tlen) { memcpy(branch_uris[nbranches].s, turi, tlen); branch_uris[nbranches].len = tlen; } else { *branch_uris[nbranches].s = '\0'; branch_uris[nbranches].len = 0; } nbranches++; } clear_branches(); idx=0; } 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 { if (_m->new_uri.s) uri = _m->new_uri; else uri = _m->first_line.u.request.uri; } if (extract_aor(&uri, &aor,&sip_instance,&call_id) < 0) { LM_ERR("failed to extract address of record\n"); return -3; } get_act_time(); ul.lock_udomain((udomain_t*)_t, &aor); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); ul.unlock_udomain((udomain_t*)_t, &aor); return -1; } if (flags & REG_LOOKUP_UAFILTER_FLAG) { tmp = *(ua+re_len); *(ua+re_len) = '\0'; if (regcomp(&ua_re, ua, regexp_flags) != 0) { LM_ERR("bad regexp '%s'\n", ua); *(ua+re_len) = tmp; return -1; } *(ua+re_len) = tmp; } ptr = r->contacts; ret = -1; /* look first for an un-expired and suported contact */ search_valid_contact: while ( (ptr) && !(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr,flags))) ptr = ptr->next; if (ptr==0) { /* nothing found */ LM_DBG("nothing found !\n"); goto done; } ua_re_check( ret = -1; ptr = ptr->next; goto search_valid_contact ); if (sip_instance.len && sip_instance.s) { LM_DBG("ruri has gruu in lookup\n"); /* uri has GRUU */ if (ptr->instance.len-2 != sip_instance.len || memcmp(ptr->instance.s+1,sip_instance.s,sip_instance.len)) { LM_DBG("no match to sip instace - [%.*s] - [%.*s]\n",ptr->instance.len-2,ptr->instance.s+1, sip_instance.len,sip_instance.s); /* not the targeted instance, search some more */ ptr = ptr->next; goto search_valid_contact; } LM_DBG("matched sip instace\n"); } if (call_id.len && call_id.s) { /* decide whether GRUU is expired or not * * first - match call-id */ if (ptr->callid.len != call_id.len || memcmp(ptr->callid.s,call_id.s,call_id.len)) { LM_DBG("no match to call id - [%.*s] - [%.*s]\n",ptr->callid.len,ptr->callid.s, call_id.len,call_id.s); ptr = ptr->next; goto search_valid_contact; } /* matched call-id, check if there are newer contacts with * same sip instace bup newer last_modified */ it = ptr->next; while ( it ) { if (VALID_CONTACT(it,act_time)) { if (it->instance.len-2 == sip_instance.len && sip_instance.s && memcmp(it->instance.s+1,sip_instance.s,sip_instance.len) == 0) if (it->last_modified > ptr->last_modified) { /* same instance id, but newer modified -> expired GRUU, no match at all */ break; } } it=it->next; } if (it != NULL) { ret = -1; goto done; } } LM_DBG("found a complete match\n"); ret = 1; if (ptr) { LM_DBG("setting as ruri <%.*s>\n",ptr->c.len,ptr->c.s); if (set_ruri(_m, &ptr->c) < 0) { LM_ERR("unable to rewrite Request-URI\n"); ret = -3; goto done; } /* If a Path is present, use first path-uri in favour of * received-uri because in that case the last hop towards the uac * has to handle NAT. - agranig */ if (ptr->path.s && ptr->path.len) { if (get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); ret = -3; goto done; } if (set_path_vector(_m, &ptr->path) < 0) { LM_ERR("failed to set path vector\n"); ret = -3; goto done; } if (set_dst_uri(_m, &path_dst) < 0) { LM_ERR("failed to set dst_uri of Path\n"); ret = -3; goto done; } } else if (ptr->received.s && ptr->received.len) { if (set_dst_uri(_m, &ptr->received) < 0) { ret = -3; goto done; } } set_ruri_q( _m, ptr->q); setbflag( _m, 0, ptr->cflags); if (ptr->sock) _m->force_send_socket = ptr->sock; /* populate the 'attributes' avp */ if (attr_avp_name != -1) { istr.s = ptr->attr; if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) { LM_ERR("Failed to populate attr avp!\n"); } } ptr = ptr->next; } /* Append branches if enabled */ /* If we got to this point and the URI had a ;gr parameter and it was matched * to a contact. No point in branching */ if ( flags®_LOOKUP_NOBRANCH_FLAG || (sip_instance.len && sip_instance.s) ) goto done; LM_DBG("looking for branches\n"); do { for( ; ptr ; ptr = ptr->next ) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m,ptr,flags)) { path_dst.len = 0; if(ptr->path.s && ptr->path.len && get_path_dst_uri(&ptr->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); continue; } ua_re_check(continue); /* The same as for the first contact applies for branches * regarding path vs. received. */ LM_DBG("setting branch <%.*s>\n",ptr->c.len,ptr->c.s); if (append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received, &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) { LM_ERR("failed to append a branch\n"); /* Also give a chance to the next branches*/ continue; } /* populate the 'attributes' avp */ if (attr_avp_name != -1) { istr.s = ptr->attr; if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) { LM_ERR("Failed to populate attr avp!\n"); } } } } /* 0 branches condition also filled; idx initially -1*/ if (!(flags®_BRANCH_AOR_LOOKUP_FLAG) || idx == nbranches) goto done; /* relsease old aor lock */ ul.unlock_udomain((udomain_t*)_t, &aor); ul.release_urecord(r, 0); /* idx starts from -1 */ uri = branch_uris[idx]; if (extract_aor(&uri, &aor, NULL, &call_id) < 0) { LM_ERR("failed to extract address of record for branch uri\n"); return -3; } /* release old urecord */ /* get lock on new aor */ LM_DBG("getting contacts from aor [%.*s]" "in branch %d\n", aor.len, aor.s, idx); ul.lock_udomain((udomain_t*)_t, &aor); res = ul.get_urecord((udomain_t*)_t, &aor, &r); if (res > 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); goto done; } idx++; ptr = r->contacts; } while (1);
static inline int get_block(struct inode * inode, sector_t block, struct buffer_head *bh, int create) { int err = -EIO; int offsets[DEPTH]; Indirect chain[DEPTH]; Indirect *partial; int left; int depth = block_to_path(inode, block, offsets); if (depth == 0) goto out; reread: partial = get_branch(inode, depth, offsets, chain, &err); /* Simplest case - block found, no allocation needed */ if (!partial) { got_it: map_bh(bh, inode->i_sb, block_to_cpu(chain[depth-1].key)); /* Clean up and exit */ partial = chain+depth-1; /* the whole chain */ goto cleanup; } /* Next simple case - plain lookup or failed read of indirect block */ if (!create || err == -EIO) { cleanup: while (partial > chain) { brelse(partial->bh); partial--; } out: return err; } /* * Indirect block might be removed by truncate while we were * reading it. Handling of that case (forget what we've got and * reread) is taken out of the main path. */ if (err == -EAGAIN) goto changed; left = (chain + depth) - partial; err = alloc_branch(inode, left, offsets+(partial-chain), partial); if (err) goto cleanup; if (splice_branch(inode, chain, partial, left) < 0) goto changed; set_buffer_new(bh); goto got_it; changed: while (partial > chain) { brelse(partial->bh); partial--; } goto reread; }
/* function returns: * 1 - forward successful * -1 - error during forward */ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , struct proxy_l * proxy, int reset_bcounter, int locked) { str reply_reason_487 = str_init("Request Terminated"); str backup_uri; str backup_dst; int branch_ret, lowest_ret; str current_uri; branch_bm_t added_branches; int i, q; struct cell *t_invite; int success_branch; str dst_uri; struct socket_info *bk_sock; unsigned int br_flags, bk_bflags; int idx; str path; str bk_path; /* make -Wall happy */ current_uri.s=0; /* before doing enything, update the t flags from msg */ t->uas.request->flags = p_msg->flags; if (p_msg->REQ_METHOD==METHOD_CANCEL) { t_invite=t_lookupOriginalT( p_msg ); if (t_invite!=T_NULL_CELL) { t_invite->flags |= T_WAS_CANCELLED_FLAG; cancel_invite( p_msg, t, t_invite, locked ); return 1; } } /* do not forward requests which were already cancelled*/ if (no_new_branches(t)) { LM_INFO("discarding fwd for a 6xx transaction\n"); ser_error = E_NO_DESTINATION; return -1; } if (was_cancelled(t)) { /* is this the first attempt of sending a branch out ? */ if (t->nr_of_outgoings==0) { /* if no other signalling was performed on the transaction * and the transaction was already canceled, better * internally generate the 487 reply here */ if (locked) t_reply_unsafe( t, p_msg , 487 , &reply_reason_487); else t_reply( t, p_msg , 487 , &reply_reason_487); } LM_INFO("discarding fwd for a cancelled transaction\n"); ser_error = E_NO_DESTINATION; return -1; } /* backup current uri, sock and flags... add_uac changes it */ backup_uri = p_msg->new_uri; backup_dst = p_msg->dst_uri; bk_sock = p_msg->force_send_socket; bk_path = p_msg->path_vec; bk_bflags = p_msg->ruri_bflags; /* advertised address/port are not changed */ /* check if the UAS retranmission port needs to be updated */ if ( (p_msg->msg_flags ^ t->uas.request->msg_flags) & FL_FORCE_RPORT ) su_setport( &t->uas.response.dst.to, p_msg->rcv.src_port ); /* if no more specific error code is known, use this */ lowest_ret=E_BUG; /* branches added */ added_branches=0; /* branch to begin with */ if (reset_bcounter) { t->first_branch=t->nr_of_outgoings; /* check if the previous branch is a PHONY one and if yes * keep it in the set of active branches; that means the * transaction had a t_wait_for_new_branches() call prior to relay() */ if ( t->first_branch>0 && (t->uac[t->first_branch-1].flags & T_UAC_IS_PHONY) ) t->first_branch--; } /* as first branch, use current uri */ current_uri = *GET_RURI(p_msg); branch_ret = add_uac( t, p_msg, ¤t_uri, &backup_dst, getb0flags(p_msg), &p_msg->path_vec, proxy); if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; /* ....and now add the remaining additional branches */ for( idx=0; (current_uri.s=get_branch( idx, ¤t_uri.len, &q, &dst_uri, &path, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) { branch_ret = add_uac( t, p_msg, ¤t_uri, &dst_uri, br_flags, &path, proxy); /* pick some of the errors in case things go wrong; note that picking lowest error is just as good as any other algorithm which picks any other negative branch result */ if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } /* consume processed branches */ clear_branches(); /* restore original stuff */ p_msg->new_uri=backup_uri; p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/ p_msg->dst_uri = backup_dst; p_msg->force_send_socket = bk_sock; p_msg->path_vec = bk_path; p_msg->ruri_bflags = bk_bflags; /* update on_branch, _only_ if modified, otherwise it overwrites * whatever it is already in the transaction */ if (get_on_branch()) t->on_branch = get_on_branch(); /* update flags, if changed in branch route */ t->uas.request->flags = p_msg->flags; /* things went wrong ... no new branch has been fwd-ed at all */ if (added_branches==0) { LM_ERR("failure to add branches\n"); ser_error = lowest_ret; return lowest_ret; } /* send them out now */ success_branch=0; for (i=t->first_branch; i<t->nr_of_outgoings; i++) { if (added_branches & (1<<i)) { if (t->uac[i].br_flags & tcp_no_new_conn_bflag) tcp_no_new_conn = 1; do { if (check_blacklists( t->uac[i].request.dst.proto, &t->uac[i].request.dst.to, t->uac[i].request.buffer.s, t->uac[i].request.buffer.len)) { LM_DBG("blocked by blacklists\n"); ser_error=E_IP_BLOCKED; } else { run_trans_callbacks(TMCB_PRE_SEND_BUFFER, t, p_msg, 0, i); if (SEND_BUFFER( &t->uac[i].request)==0) { ser_error = 0; break; } LM_ERR("sending request failed\n"); ser_error=E_SEND; } /* get next dns entry */ if ( t->uac[i].proxy==0 || get_next_su( t->uac[i].proxy, &t->uac[i].request.dst.to, (ser_error==E_IP_BLOCKED)?0:1)!=0 ) break; t->uac[i].request.dst.proto = t->uac[i].proxy->proto; /* update branch */ if ( update_uac_dst( p_msg, &t->uac[i] )!=0) break; }while(1); tcp_no_new_conn = 0; if (ser_error) { shm_free(t->uac[i].request.buffer.s); t->uac[i].request.buffer.s = NULL; t->uac[i].request.buffer.len = 0; continue; } success_branch++; start_retr( &t->uac[i].request ); set_kr(REQ_FWDED); /* successfully sent out -> run callbacks */ if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT|TMCB_MSG_SENT_OUT) ) { set_extra_tmcb_params( &t->uac[i].request.buffer, &t->uac[i].request.dst); run_trans_callbacks( TMCB_REQUEST_BUILT|TMCB_MSG_SENT_OUT, t, p_msg, 0, 0); } } } return (success_branch>0)?1:-1; }
/* * determines the permission of the call * return values: * -1: deny * 1: allow */ static int check_routing(struct sip_msg* msg, int idx) { struct hdr_field *from; int len, q; static char from_str[EXPRESSION_LENGTH+1]; static char ruri_str[EXPRESSION_LENGTH+1]; char* uri_str; str branch; int br_idx; /* turn off control, allow any routing */ if ((!allow[idx].rules) && (!deny[idx].rules)) { LM_DBG("no rules => allow any routing\n"); return 1; } /* looking for FROM HF */ if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) { LM_ERR("failed to parse message\n"); return -1; } if (!msg->from) { LM_ERR("FROM header field not found\n"); return -1; } /* we must call parse_from_header explicitly */ if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) { LM_ERR("failed to parse From body\n"); return -1; } from = msg->from; len = ((struct to_body*)from->parsed)->uri.len; if (len > EXPRESSION_LENGTH) { LM_ERR("From header field is too long: %d chars\n", len); return -1; } strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len); from_str[len] = '\0'; /* looking for request URI */ if (parse_sip_msg_uri(msg) < 0) { LM_ERR("uri parsing failed\n"); return -1; } len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5; if (len > EXPRESSION_LENGTH) { LM_ERR("Request URI is too long: %d chars\n", len); return -1; } strcpy(ruri_str, "sip:"); memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len); ruri_str[msg->parsed_uri.user.len + 4] = '@'; memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, msg->parsed_uri.host.len); ruri_str[len] = '\0'; LM_DBG("looking for From: %s Request-URI: %s\n", from_str, ruri_str); /* rule exists in allow file */ if (search_rule(allow[idx].rules, from_str, ruri_str)) { if (check_all_branches) goto check_branches; LM_DBG("allow rule found => routing is allowed\n"); return 1; } /* rule exists in deny file */ if (search_rule(deny[idx].rules, from_str, ruri_str)) { LM_DBG("deny rule found => routing is denied\n"); return -1; } if (!check_all_branches) { LM_DBG("neither allow nor deny rule found => routing is allowed\n"); return 1; } check_branches: for( br_idx=0 ; (branch.s=get_branch(br_idx,&branch.len,&q,0,0,0,0,0,0,0))!=0 ; br_idx++ ) { uri_str = get_plain_uri(&branch); if (!uri_str) { LM_ERR("failed to extract plain URI\n"); return -1; } LM_DBG("looking for From: %s Branch: %s\n", from_str, uri_str); if (search_rule(allow[idx].rules, from_str, uri_str)) { continue; } if (search_rule(deny[idx].rules, from_str, uri_str)) { LM_DBG("deny rule found for one of branches => routing" "is denied\n"); return -1; } } LM_DBG("check of branches passed => routing is allowed\n"); return 1; }
/* function returns: * 1 - forward successful * -1 - error during forward */ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , struct proxy_l * proxy) { str backup_uri; str backup_dst; int branch_ret, lowest_ret; str current_uri; branch_bm_t added_branches; int i, q; struct cell *t_invite; int success_branch; str dst_uri; struct socket_info *bk_sock; unsigned int br_flags; unsigned int bk_br_flags; int idx; str path; str bk_path; /* make -Wall happy */ current_uri.s=0; /* before doing enything, update the t falgs from msg */ t->uas.request->flags = p_msg->flags; if (p_msg->REQ_METHOD==METHOD_CANCEL) { t_invite=t_lookupOriginalT( p_msg ); if (t_invite!=T_NULL_CELL) { t_invite->flags |= T_WAS_CANCELLED_FLAG; cancel_invite( p_msg, t, t_invite ); return 1; } } /* do not forward requests which were already cancelled*/ if (was_cancelled(t) || no_new_branches(t)) { LM_ERR("discarding fwd for a cancelled/6xx transaction\n"); ser_error = E_NO_DESTINATION; return -1; } /* backup current uri, sock and flags... add_uac changes it */ backup_uri = p_msg->new_uri; backup_dst = p_msg->dst_uri; bk_sock = p_msg->force_send_socket; bk_br_flags = getb0flags(); bk_path = p_msg->path_vec; /* check if the UAS retranmission port needs to be updated */ if ( (p_msg->msg_flags ^ t->uas.request->msg_flags) & FL_FORCE_RPORT ) su_setport( &t->uas.response.dst.to, p_msg->rcv.src_port ); /* if no more specific error code is known, use this */ lowest_ret=E_BUG; /* branches added */ added_branches=0; /* branch to begin with */ t->first_branch=t->nr_of_outgoings; /* as first branch, use current uri */ current_uri = *GET_RURI(p_msg); branch_ret = add_uac( t, p_msg, ¤t_uri, &backup_dst, &p_msg->path_vec, proxy); if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; /* ....and now add the remaining additional branches */ for( idx=0; (current_uri.s=get_branch( idx, ¤t_uri.len, &q, &dst_uri, &path, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) { setb0flags(br_flags); branch_ret = add_uac( t, p_msg, ¤t_uri, &dst_uri, &path, proxy); /* pick some of the errors in case things go wrong; note that picking lowest error is just as good as any other algorithm which picks any other negative branch result */ if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } /* consume processed branches */ clear_branches(); /* restore original stuff */ p_msg->new_uri=backup_uri; p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/ p_msg->dst_uri = backup_dst; p_msg->force_send_socket = bk_sock; p_msg->path_vec = bk_path; setb0flags(bk_br_flags); /* update on_branch, if modified */ t->on_branch = get_on_branch(); /* update flags, if changed in branch route */ t->uas.request->flags = p_msg->flags; /* things went wrong ... no new branch has been fwd-ed at all */ if (added_branches==0) { LM_ERR("failure to add branches\n"); ser_error = lowest_ret; return lowest_ret; } /* send them out now */ success_branch=0; for (i=t->first_branch; i<t->nr_of_outgoings; i++) { if (added_branches & (1<<i)) { #ifdef USE_TCP if (t->uac[i].br_flags & tcp_no_new_conn_bflag) tcp_no_new_conn = 1; #endif do { if (check_blacklists( t->uac[i].request.dst.proto, &t->uac[i].request.dst.to, t->uac[i].request.buffer.s, t->uac[i].request.buffer.len)) { LM_DBG("blocked by blacklists\n"); ser_error=E_IP_BLOCKED; } else { if (SEND_BUFFER( &t->uac[i].request)==0) { ser_error = 0; break; } LM_ERR("sending request failed\n"); ser_error=E_SEND; } /* get next dns entry */ if ( t->uac[i].proxy==0 || get_next_su( t->uac[i].proxy, &t->uac[i].request.dst.to, (ser_error==E_IP_BLOCKED)?0:1)!=0 ) break; t->uac[i].request.dst.proto = t->uac[i].proxy->proto; /* update branch */ if ( update_uac_dst( p_msg, &t->uac[i] )!=0) break; }while(1); #ifdef USE_TCP tcp_no_new_conn = 0; #endif if (ser_error) { shm_free(t->uac[i].request.buffer.s); t->uac[i].request.buffer.s = NULL; t->uac[i].request.buffer.len = 0; continue; } success_branch++; start_retr( &t->uac[i].request ); set_kr(REQ_FWDED); /* successfully sent out -> run callbacks */ if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT) ) { set_extra_tmcb_params( &t->uac[i].request.buffer, &t->uac[i].request.dst); run_trans_callbacks( TMCB_REQUEST_BUILT, t, p_msg,0, -p_msg->REQ_METHOD); } } } return (success_branch>0)?1:-1; }
int main(int argc, char *argv[]) { struct unionfs_addbranch_args addargs; struct unionfs_rdwrbranch_args rdwrargs; unsigned long remountdata[3]; fd_set branchlist; struct stat st; int fd = -1; int ret, i; char *path, resolv_path[PATH_MAX], resolv_bp[PATH_MAX]; char *options = NULL, *actual_path = NULL; int action; char *branchpath; int branchnum; int unionpos = 1; int modepos = 2; progname = argv[0]; /* check that minimum number of args were specified */ if (argc < 3) usage(); if (argv[1][0] == '-' && argv[1][1] == '-') { modepos = 1; unionpos = 2; } else { modepos = 2; unionpos = 1; } if (realpath(argv[unionpos], resolv_path) == NULL) { perror("realpath()"); exit(EXIT_FAILURE); } path = resolv_path; if (strcmp(path, "/") && (path[strlen(path) - 1] == '/')) { path[strlen(path) - 1] = '\0'; } if (!strcmp(argv[modepos], "--add")) { action = ADD; } else if (!strcmp(argv[modepos], "--remove")) { action = REMOVE; } else if (!strcmp(argv[modepos], "--mode")) { action = MODE; } else if (!strcmp(argv[modepos], "--list")) { action = LIST; } else if (!strcmp(argv[modepos], "--query")) { action = QUERY; } else { usage(); } if (stat(path, &st) == -1) { fprintf(stderr, "stat(%s): %s\n", path, strerror(errno)); exit(EXIT_FAILURE); } if (find_union(path, &options, &actual_path, 1) < 0) { fprintf(stderr, "%s is not a valid union.\n", path); exit(EXIT_FAILURE); } branches = parse_options(options); if (!branches) { fprintf(stderr, "Could not parse options from /proc/mounts!\n"); exit(EXIT_FAILURE); } /* open file on which ioctl will operate (that is actually any file in the union) */ if (action != REMOVE) { fd = open(path, O_RDONLY); if (fd < 0) { fprintf(stderr, "open(%s): %s\n", path, strerror(errno)); exit(EXIT_FAILURE); } } /* Parse the action's options into something usable, and do it. */ switch (action) { case ADD: if (argc < 4) usage(); /* Default values if the user leaves them unspecified. */ branchnum = 0; addargs.ab_perms = MAY_READ | MAY_WRITE; branchpath = NULL; for (i = 3; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == '-') { if (!strcmp(argv[i], "--before")) { i++; if (i == argc) { fprintf(stderr, "%s requires an argument!\n", argv[i - 1]); usage(); } branchnum = get_branch(argv[i]); if (branchnum == -1) { fprintf(stderr, "%s is not a valid branch.\nThe current branch configuration is:\n", argv[i]); dump_branches("\t"); } } else if (!strcmp(argv[i], "--after")) { i++; if (i == argc) { fprintf(stderr, "%s requires an argument!\n", argv[i - 1]); usage(); } branchnum = get_branch(argv[i]); if (branchnum == -1) { fprintf(stderr, "%s is not a valid branch.\nThe current branch configuration is:\n", argv[i]); dump_branches("\t"); } branchnum++; } else if (!strcmp(argv[i], "--mode")) { i++; if (i == argc) { fprintf(stderr, "%s requires an argument!\n", argv[i - 1]); usage(); } if (!strcmp(argv[i], "ro")) { addargs.ab_perms = MAY_READ; } else if (!strcmp(argv[i], "rw")) { addargs.ab_perms = MAY_READ | MAY_WRITE; } else { fprintf(stderr, "Valid modes are ro and rw you specified: \"%s\"\n", argv[i]); usage(); } } else { fprintf(stderr, "Unknown option: %s\n", argv[i]); usage(); } } else { /* The options must go before the path */ if ((i + 1) != argc) { fprintf(stderr, "The path of the branch to add must go after all options.\n"); usage(); } if (branchnum != -1) { fprintf(stderr, "%s already exists in the Union\n", argv[i]); usage(); } branchpath = argv[i]; } } if (!branchpath) { fprintf(stderr, "You must specify the path to add into the union!\n"); usage(); } if (realpath(branchpath, resolv_bp) == NULL) { perror("realpath()"); exit(EXIT_FAILURE); } addargs.ab_branch = branchnum; addargs.ab_path = resolv_bp; errno = 0; ret = ioctl(fd, UNIONFS_IOCTL_ADDBRANCH, &addargs); if (ret < 0) { switch (errno) { case E2BIG: fprintf(stderr, "Unionfs supports only %d branches.\n", FD_SETSIZE); break; } fprintf(stderr, "Failed to add %s into %s: %s", branchpath, path, strerror(errno)); exit(EXIT_FAILURE); } break; case MODE: if (argc != 5) { usage(); } if (!strcmp(argv[4], "ro")) { rdwrargs.rwb_perms = MAY_READ; branchnum = 3; } else if (!strcmp(argv[4], "rw")) { rdwrargs.rwb_perms = MAY_READ | MAY_WRITE; branchnum = 3; } else if (!strcmp(argv[3], "ro")) { rdwrargs.rwb_perms = MAY_READ; branchnum = 4; } else if (!strcmp(argv[3], "rw")) { rdwrargs.rwb_perms = MAY_READ | MAY_WRITE; branchnum = 4; } else { usage(); } if (realpath(argv[branchnum], resolv_bp) == NULL) { perror("realpath()"); exit(EXIT_FAILURE); } branchpath = resolv_bp; /* Set a branches writeable status. */ rdwrargs.rwb_branch = get_branch(branchpath); if (rdwrargs.rwb_branch == -1) { fprintf(stderr, "%s is not a valid branch.\nThe current branch configuration is:\n", branchpath); dump_branches("\t"); exit(EXIT_FAILURE); } ret = ioctl(fd, UNIONFS_IOCTL_RDWRBRANCH, &rdwrargs); if (ret < 0) { fprintf(stderr, "Failed to set permissions for %s in %s: %s", branchpath, path, strerror(errno)); exit(EXIT_FAILURE); } goto out; break; case REMOVE: if (argc != 4) usage(); if (realpath(argv[3], resolv_bp) == NULL) { perror("realpath()"); exit(EXIT_FAILURE); } branchpath = resolv_bp; branchnum = get_branch(branchpath); if (branchnum == -1) { fprintf(stderr, "%s is not a valid branch.\nThe current branch configuration is:\n", branchpath); dump_branches("\t"); exit(EXIT_FAILURE); } errno = 0; remountdata[0] = UNIONFS_REMOUNT_MAGIC; remountdata[1] = UNIONFS_IOCTL_DELBRANCH; remountdata[2] = branchnum; ret = mount("unionfs", actual_path, "unionfs", MS_REMOUNT | MS_MGC_VAL, remountdata); if (ret < 0) { fprintf(stderr, "Failed to remove %s from %s: %s", branchpath, path, strerror(errno)); exit(EXIT_FAILURE); } break; case LIST: dump_branches("\t"); break; case QUERY: if (argc != 3) { usage(); } if ((fd = open(argv[unionpos], O_RDONLY)) < 0) { fprintf(stderr, "Unable to open file %s : %s", argv[unionpos], strerror(errno)); exit(EXIT_FAILURE); } ret = ioctl(fd, UNIONFS_IOCTL_QUERYFILE, &branchlist); if (ret < 0) { fprintf(stderr, "Unable to retrieve list of branches for file %s : %s\n", argv[unionpos], strerror(errno)); exit(EXIT_FAILURE); } for (i = 0; i <= ret; i++) { char r, w; r = (branchperms[i] & MAY_READ) ? 'r' : '-'; w = (branchperms[i] & MAY_WRITE) ? 'w' : '-'; if (FD_ISSET(i, &branchlist)) printf("%s\t%s (%c%c)\n", argv[unionpos], branches[i], r, w); } break; } out: if (fd != -1) close(fd); exit(EXIT_SUCCESS); }
/* * Loads contacts in destination set into contacts_avp in reverse * priority order and associated each contact with Q_FLAG telling if * contact is the last one in its priority class. Finally, removes * all branches from destination set. */ int t_load_contacts(struct sip_msg* msg, char* key, char* value) { str uri, tmp, dst_uri, path, branch_info, *ruri; qvalue_t first_q, q; struct contact *contacts, *next, *prev, *curr; int_str val; int first_idx, idx; struct socket_info* sock; unsigned int flags; /* Check if contacts_avp has been defined */ if (contacts_avp.n == 0) { LM_ERR("feature has been disabled - " "to enable define contacts_avp module parameter"); return -1; } /* Check if anything needs to be done */ if (nr_branches == 0) { LM_DBG("t_load_contacts(): nothing to do - no branches!\n"); return 1; } ruri = (str *)0; /* Take first q from Request-URI */ ruri = GET_RURI(msg); if (!ruri) { LM_ERR("no Request-URI found\n"); return -1; } first_q = get_ruri_q(); first_idx = 0; /* Check if all q values are equal */ for(idx = first_idx; (tmp.s = get_branch(idx, &tmp.len, &q, 0, 0, 0, 0)) != 0; idx++) { if (q != first_q) { goto rest; } } LM_DBG("t_load_contacts(): nothing to do - all contacts have same q!\n"); return 1; rest: /* Allocate memory for first contact */ contacts = (struct contact *)pkg_malloc(sizeof(struct contact)); if (!contacts) { LM_ERR("no memory for contact info\n"); return -1; } /* Insert Request-URI branch to first contact */ contacts->uri.s = ruri->s; contacts->uri.len = ruri->len; contacts->dst_uri = msg->dst_uri; contacts->sock = msg->force_send_socket; getbflagsval(0, &contacts->flags); contacts->path = msg->path_vec; contacts->q = first_q; contacts->next = (struct contact *)0; /* Insert (remaining) branches to contact list in increasing q order */ for(idx = first_idx; (uri.s = get_branch(idx,&uri.len,&q,&dst_uri,&path,&flags,&sock)) != 0; idx++ ) { next = (struct contact *)pkg_malloc(sizeof(struct contact)); if (!next) { LM_ERR("no memory for contact info\n"); free_contact_list(contacts); return -1; } next->uri = uri; next->q = q; next->dst_uri = dst_uri; next->path = path; next->flags = flags; next->sock = sock; next->next = (struct contact *)0; prev = (struct contact *)0; curr = contacts; while (curr && (curr->q < q)) { prev = curr; curr = curr->next; } if (!curr) { next->next = (struct contact *)0; prev->next = next; } else { next->next = curr; if (prev) { prev->next = next; } else { contacts = next; } } } /* Assign values for q_flags */ curr = contacts; curr->q_flag = 0; while (curr->next) { if (curr->q < curr->next->q) { curr->next->q_flag = Q_FLAG; } else { curr->next->q_flag = 0; } curr = curr->next; } /* Add contacts to contacts_avp */ curr = contacts; while (curr) { if (encode_branch_info(&branch_info, curr) == 0) { LM_ERR("encoding of branch info failed\n"); free_contact_list(contacts); if (branch_info.s) pkg_free(branch_info.s); return -1; } val.s = branch_info; add_avp(contacts_avp_type|AVP_VAL_STR|(curr->q_flag), contacts_avp, val); pkg_free(branch_info.s); LM_DBG("loaded contact <%.*s> with q_flag <%d>\n", STR_FMT(&val.s), curr->q_flag); curr = curr->next; } /* Clear all branches */ clear_branches(); /* Free contact list */ free_contact_list(contacts); return 1; }
/*! \brief * Loads contacts in destination set into "serial_fork" AVP in reverse * priority order and associated each contact with Q_FLAG telling if * contact is the last one in its priority class. Finally, removes * all branches from destination set. */ int serialize_branches(struct sip_msg *msg, int clean_before ) { static struct serial_contact contacts[MAX_BRANCHES]; int n, last, first, i, prev; str branch, *ruri; qvalue_t q, ruri_q; char *p; str dst_uri, path, enc_info; unsigned int flags; struct socket_info *sock_info; int_str val; int idx; /* Check if anything needs to be done */ if (nr_branches == 0) { LM_DBG("nothing to do - no branches!\n"); return 0; } ruri = GET_RURI(msg); ruri_q = get_ruri_q(); flags = getb0flags(); for (idx = 0; (branch.s = get_branch(idx,&branch.len,&q,0,0,0,0)); idx++) { if (q != ruri_q) break; } if (branch.s == 0) { LM_DBG("nothing to do - all same q!\n"); return 0; } /* reset contact array */ n = 0; /* Insert Request-URI to contact list */ enc_info.len = 3 * sizeof(long) + ruri->len + msg->dst_uri.len + msg->path_vec.len + 3; enc_info.s = (char*) pkg_malloc (enc_info.len); if (!enc_info.s) { LM_ERR("no pkg memory left\n"); goto error; /* nothing to free here */ } memset(enc_info.s, 0, enc_info.len); p = enc_info.s; LM_DBG("Msg information <%.*s,%.*s,%.*s,%d,%u>\n", ruri->len, ruri->s, msg->dst_uri.len, msg->dst_uri.s, msg->path_vec.len, msg->path_vec.s, ruri_q, flags); *((long*) p) = (long)msg->force_send_socket; p += sizeof(long); *((long*) p) = (long)flags; p += sizeof(long); *((long*) p) = (long)ruri_q; p += sizeof(long); memcpy(p , ruri->s, ruri->len); p += ruri->len + 1; memcpy(p, msg->dst_uri.s, msg->dst_uri.len); p += msg->dst_uri.len + 1; memcpy(p, msg->path_vec.s, msg->path_vec.len); contacts[n].enc_info = enc_info; contacts[n].q = ruri_q; contacts[n].next = -1; last = n; first = n; n++; /* Insert branch URIs to contact list in increasing q order */ for (idx = 0;(branch.s = get_branch(idx, &branch.len, &q, &dst_uri, &path, &flags, &sock_info)); idx++){ enc_info.len = 3 * sizeof(long) + branch.len + dst_uri.len + path.len + 3; enc_info.s = (char*) pkg_malloc (enc_info.len); if (!enc_info.s) { LM_ERR("no pkg memory left\n"); goto error_free; } memset(enc_info.s, 0, enc_info.len); p = enc_info.s; LM_DBG("Branch information <%.*s,%.*s,%.*s,%d,%u>\n", branch.len, branch.s, dst_uri.len, dst_uri.s, path.len, path.s, q, flags); *((long*) p) = (long)sock_info; p += sizeof(long); *((long*) p) = (long)flags; p += sizeof(long); *((long*) p) = (long)q; p += sizeof(long); memcpy(p , branch.s, branch.len); p += branch.len + 1; memcpy(p, dst_uri.s, dst_uri.len); p += dst_uri.len + 1; memcpy(p, path.s, path.len); contacts[n].enc_info = enc_info; contacts[n].q = q; /* insert based on q */ for (i = first, prev=-1; i != -1 && contacts[i].q < q; prev=i,i = contacts[i].next); if (i == -1) { /* append */ last = contacts[last].next = n; contacts[n].next = -1; } else { if (i == first) { /* first element */ contacts[n].next = first; first = n; } else { /* before pos i */ contacts[n].next = contacts[prev].next; contacts[prev].next = n; } } n++; } /* Assign values for q_flags */ for (i = first; contacts[i].next != -1; i = contacts[i].next) { if (contacts[i].q < contacts[contacts[i].next].q) contacts[contacts[i].next].q_flag = Q_FLAG; else contacts[contacts[i].next].q_flag = 0; } if (clean_before) destroy_avps( 0/*type*/, serial_avp, 1/*all*/); /* Add contacts to "contacts" AVP */ for (i = first; i != -1; i = contacts[i].next) { val.s = contacts[i].enc_info; if (add_avp( AVP_VAL_STR|contacts[i].q_flag, serial_avp, val)) { LM_ERR("failed to add avp\n"); goto error_free; } pkg_free(contacts[i].enc_info.s); contacts[i].enc_info.s = NULL; } /* Clear all branches */ clear_branches(); return 0; error_free: for( i=0 ; i<n ; i++) { if (contacts[i].enc_info.s) pkg_free(contacts[i].enc_info.s); } error: return -1; }
/* function returns: * 1 - forward successful * -1 - error during forward */ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , struct proxy_l * proxy, int proto) { str backup_uri; str backup_dst; int branch_ret, lowest_ret; str current_uri; branch_bm_t added_branches; int i, q; struct cell *t_invite; int success_branch; int try_new; str dst_uri; struct socket_info *bk_sock; int rurib_flags; int br_flags; int idx; /* make -Wall happy */ current_uri.s=0; set_kr(REQ_FWDED); if (p_msg->REQ_METHOD==METHOD_CANCEL) { t_invite=t_lookupOriginalT( p_msg ); if (t_invite!=T_NULL_CELL) { t_invite->flags |= T_WAS_CANCELLED_FLAG; e2e_cancel( p_msg, t, t_invite ); UNREF(t_invite); return 1; } } /* do not forward requests which were already cancelled*/ if (was_cancelled(t)) { LOG(L_ERR,"ERROR:tm:t_forward_nonack: discarding fwd for " "a cancelled transaction\n"); return -1; } /* backup current uri, sock and flags ... add_uac changes it */ backup_uri = p_msg->new_uri; backup_dst = p_msg->dst_uri; bk_sock = p_msg->force_send_socket; rurib_flags = p_msg->flags&(~gflags_mask); /* if no more specific error code is known, use this */ lowest_ret=E_BUG; /* branches added */ added_branches=0; /* branch to begin with */ t->first_branch=t->nr_of_outgoings; /* on first-time forwarding, use current uri, later only what is in additional branches (which may be continuously refilled) */ if (t->first_branch==0) { try_new=1; current_uri = *GET_RURI(p_msg); branch_ret = add_uac( t, p_msg, ¤t_uri, &backup_dst, proxy, proto ); if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } else try_new=0; for( idx=0; (current_uri.s=get_branch( idx, ¤t_uri.len, &q, &dst_uri, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) { try_new++; p_msg->flags = (p_msg->flags&gflags_mask) | br_flags; branch_ret=add_uac( t, p_msg, ¤t_uri, &dst_uri, proxy, proto); /* pick some of the errors in case things go wrong; note that picking lowest error is just as good as any other algorithm which picks any other negative branch result */ if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } /* consume processed branches */ clear_branches(); /* restore original stuff */ p_msg->new_uri=backup_uri; p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/ p_msg->dst_uri = backup_dst; p_msg->force_send_socket = bk_sock; /* update on_branch, if modified */ t->on_branch = get_on_branch(); /* set flags */ p_msg->flags = (p_msg->flags&gflags_mask)|rurib_flags; t->uas.request->flags = p_msg->flags&gflags_mask; /* don't forget to clear all branches processed so far */ /* things went wrong ... no new branch has been fwd-ed at all */ if (added_branches==0) { if (try_new==0) { LOG(L_ERR, "ERROR:tm:t_forward_nonack: no branch for " "forwarding\n"); return -1; } LOG(L_ERR, "ERROR:tm:t_forward_nonack: failure to add branches\n"); return lowest_ret; } /* send them out now */ success_branch=0; for (i=t->first_branch; i<t->nr_of_outgoings; i++) { if (added_branches & (1<<i)) { if (SEND_BUFFER( &t->uac[i].request)==-1) { LOG(L_ERR, "ERROR:tm:t_forward_nonack: sending request " "failed\n"); if (proxy) { proxy->errors++; proxy->ok=0; } } else { success_branch++; } start_retr( &t->uac[i].request ); } } if (success_branch<=0) { ser_error=E_SEND; return -1; } return 1; }