int pres_refresh_watchers(str *pres, str *event, int type, str *file_uri, str *filename) { pres_ev_t *ev; struct sip_uri uri; str *rules_doc= NULL; int result; ev= contains_event(event, NULL); if(ev==NULL) { LM_ERR("wrong event parameter\n"); return -1; } if(type==0) { /* if a request to refresh watchers authorization */ if(ev->get_rules_doc==NULL) { LM_ERR("wrong request for a refresh watchers authorization status" "for an event that does not require authorization\n"); goto error; } if(parse_uri(pres->s, pres->len, &uri)<0) { LM_ERR("parsing uri [%.*s]\n", pres->len, pres->s); goto error; } result= ev->get_rules_doc(&uri.user, &uri.host, &rules_doc); if(result<0 || rules_doc==NULL || rules_doc->s==NULL) { LM_ERR("no rules doc found for the user\n"); goto error; } if(update_watchers_status(*pres, ev, rules_doc)<0) { LM_ERR("failed to update watchers\n"); goto error; } pkg_free(rules_doc->s); pkg_free(rules_doc); rules_doc = NULL; } else { if (type == 2) { if (update_hard_presentity(pres, ev, file_uri, filename) < 0) { LM_ERR("updating hard presentity\n"); goto error; } } /* if a request to refresh notified info */ if(query_db_notify(pres, ev, NULL)< 0) { LM_ERR("sending Notify requests\n"); goto error; } } return 0; error: if(rules_doc) { if(rules_doc->s) pkg_free(rules_doc->s); pkg_free(rules_doc); } return -1; }
/* ret= 0! if action -> end of list(e.g DROP), > 0 to continue processing next actions and <0 on error */ int do_action(struct action* a, struct sip_msg* msg) { int ret; int v; union sockaddr_union* to; struct socket_info* send_sock; struct proxy_l* p; char* tmp; char *new_uri, *end, *crt; int len; int user; struct sip_uri uri, next_hop; struct sip_uri* u; unsigned short port; int proto; /* reset the value of error to E_UNSPEC so avoid unknowledgable functions to return with errror (status<0) and not setting it leaving there previous error; cache the previous value though for functions which want to process it */ prev_ser_error=ser_error; ser_error=E_UNSPEC; ret=E_BUG; switch ((unsigned char)a->type){ case DROP_T: ret=0; break; case FORWARD_T: #ifdef USE_TCP case FORWARD_TCP_T: #endif #ifdef USE_TLS case FORWARD_TLS_T: #endif case FORWARD_UDP_T: if (a->type==FORWARD_UDP_T) proto=PROTO_UDP; #ifdef USE_TCP else if (a->type==FORWARD_TCP_T) proto= PROTO_TCP; #endif #ifdef USE_TLS else if (a->type==FORWARD_TLS_T) proto= PROTO_TLS; #endif else proto=msg->rcv.proto; if (a->p1_type==URIHOST_ST){ /*parse uri*/ if (msg->dst_uri.len) { ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop); u = &next_hop; } else { ret = parse_sip_msg_uri(msg); u = &msg->parsed_uri; } if (ret<0) { LOG(L_ERR, "ERROR: do_action: forward: bad_uri " " dropping packet\n"); break; } switch (a->p2_type){ case URIPORT_ST: port=u->port_no; break; case NUMBER_ST: port=a->p2.number; break; default: LOG(L_CRIT, "BUG: do_action bad forward 2nd" " param type (%d)\n", a->p2_type); ret=E_UNSPEC; goto error_fwd_uri; } switch(u->proto){ case PROTO_NONE: proto=PROTO_UDP; break; case PROTO_UDP: #ifdef USE_TCP case PROTO_TCP: #endif #ifdef USE_TLS case PROTO_TLS: #endif proto=u->proto; break; default: LOG(L_ERR,"ERROR: do action: forward: bad uri" " transport %d\n", u->proto); ret=E_BAD_PROTO; goto error_fwd_uri; } #ifdef USE_TLS if (u->secure){ if (u->proto==PROTO_UDP){ LOG(L_ERR, "ERROR: do_action: forward: secure uri" " incompatible with transport %d\n", u->proto); ret=E_BAD_PROTO; goto error_fwd_uri; } proto=PROTO_TLS; } #endif /* create a temporary proxy*/ p=mk_proxy(&u->host, port, proto); if (p==0){ LOG(L_ERR, "ERROR: bad host name in uri," " dropping packet\n"); ret=E_BAD_ADDRESS; goto error_fwd_uri; } ret=forward_request(msg, p, proto); /*free_uri(&uri); -- no longer needed, in sip_msg*/ free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); if (ret>=0) ret=1; }else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){ ret=forward_request(msg,(struct proxy_l*)a->p1.data, proto); if (ret>=0) ret=1; }else{ LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; } break; case SEND_T: case SEND_TCP_T: if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){ LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; break; } to=(union sockaddr_union*) pkg_malloc(sizeof(union sockaddr_union)); if (to==0){ LOG(L_ERR, "ERROR: do_action: " "memory allocation failure\n"); ret=E_OUT_OF_MEM; break; } p=(struct proxy_l*)a->p1.data; if (p->ok==0){ if (p->host.h_addr_list[p->addr_idx+1]) p->addr_idx++; else p->addr_idx=0; p->ok=1; } ret=hostent2su( to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT ); if (ret==0){ p->tx++; p->tx_bytes+=msg->len; if (a->type==SEND_T){ /*udp*/ send_sock=get_send_socket(to, PROTO_UDP); if (send_sock!=0){ ret=udp_send(send_sock, msg->buf, msg->len, to); }else{ ret=-1; } } #ifdef USE_TCP else{ /*tcp*/ ret=tcp_send(PROTO_TCP, msg->buf, msg->len, to, 0); } #endif } pkg_free(to); if (ret<0){ p->errors++; p->ok=0; }else ret=1; break; case LOG_T: if ((a->p1_type!=NUMBER_ST)|(a->p2_type!=STRING_ST)){ LOG(L_CRIT, "BUG: do_action: bad log() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; break; } LOG(a->p1.number, a->p2.string); ret=1; break; /* jku -- introduce a new branch */ case APPEND_BRANCH_T: if ((a->p1_type!=STRING_ST)) { LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n", a->p1_type ); ret=E_BUG; break; } ret=append_branch( msg, a->p1.string, a->p1.string ? strlen(a->p1.string):0 ); break; /* jku begin: is_length_greater_than */ case LEN_GT_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n", a->p1_type ); ret=E_BUG; break; } /* DBG("XXX: message length %d, max %d\n", msg->len, a->p1.number ); */ ret = msg->len >= a->p1.number ? 1 : -1; break; /* jku end: is_length_greater_than */ /* jku - begin : flag processing */ case SETFLAG_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad setflag() type %d\n", a->p1_type ); ret=E_BUG; break; } if (!flag_in_range( a->p1.number )) { ret=E_CFG; break; } setflag( msg, a->p1.number ); ret=1; break; case RESETFLAG_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad resetflag() type %d\n", a->p1_type ); ret=E_BUG; break; } if (!flag_in_range( a->p1.number )) { ret=E_CFG; break; } resetflag( msg, a->p1.number ); ret=1; break; case ISFLAGSET_T: if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad isflagset() type %d\n", a->p1_type ); ret=E_BUG; break; } if (!flag_in_range( a->p1.number )) { ret=E_CFG; break; } ret=isflagset( msg, a->p1.number ); break; /* jku - end : flag processing */ case ERROR_T: if ((a->p1_type!=STRING_ST)|(a->p2_type!=STRING_ST)){ LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n", a->p1_type, a->p2_type); ret=E_BUG; break; } LOG(L_NOTICE, "WARNING: do_action: error(\"%s\", \"%s\") " "not implemented yet\n", a->p1.string, a->p2.string); ret=1; break; case ROUTE_T: if (a->p1_type!=NUMBER_ST){ LOG(L_CRIT, "BUG: do_action: bad route() type %d\n", a->p1_type); ret=E_BUG; break; } if ((a->p1.number>RT_NO)||(a->p1.number<0)){ LOG(L_ERR, "ERROR: invalid routing table number in" "route(%lu)\n", a->p1.number); ret=E_CFG; break; } ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1; break; case EXEC_T: if (a->p1_type!=STRING_ST){ LOG(L_CRIT, "BUG: do_action: bad exec() type %d\n", a->p1_type); ret=E_BUG; break; } LOG(L_NOTICE, "WARNING: exec(\"%s\") not fully implemented," " using dumb version...\n", a->p1.string); ret=system(a->p1.string); if (ret!=0){ LOG(L_NOTICE, "WARNING: exec() returned %d\n", ret); } ret=1; break; case REVERT_URI_T: if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; msg->new_uri.s=0; msg->parsed_uri_ok=0; /* invalidate current parsed uri*/ }; ret=1; break; case SET_HOST_T: case SET_HOSTPORT_T: case SET_USER_T: case SET_USERPASS_T: case SET_PORT_T: case SET_URI_T: case PREFIX_T: case STRIP_T: case STRIP_TAIL_T: user=0; if (a->type==STRIP_T || a->type==STRIP_TAIL_T) { if (a->p1_type!=NUMBER_ST) { LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n", a->p1_type); break; } } else if (a->p1_type!=STRING_ST){ LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n", a->p1_type); ret=E_BUG; break; } if (a->type==SET_URI_T){ if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; } msg->parsed_uri_ok=0; len=strlen(a->p1.string); msg->new_uri.s=pkg_malloc(len+1); if (msg->new_uri.s==0){ LOG(L_ERR, "ERROR: do_action: memory allocation" " failure\n"); ret=E_OUT_OF_MEM; break; } memcpy(msg->new_uri.s, a->p1.string, len); msg->new_uri.s[len]=0; msg->new_uri.len=len; ret=1; break; } if (msg->new_uri.s) { tmp=msg->new_uri.s; len=msg->new_uri.len; }else{ tmp=msg->first_line.u.request.uri.s; len=msg->first_line.u.request.uri.len; } if (parse_uri(tmp, len, &uri)<0){ LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping" " packet\n", tmp); ret=E_UNSPEC; break; } new_uri=pkg_malloc(MAX_URI_SIZE); if (new_uri==0){ LOG(L_ERR, "ERROR: do_action: memory allocation " " failure\n"); ret=E_OUT_OF_MEM; break; } end=new_uri+MAX_URI_SIZE; crt=new_uri; /* begin copying */ len=strlen("sip:"); if(crt+len>end) goto error_uri; memcpy(crt,"sip:",len);crt+=len; /* user */ /* prefix (-jiri) */ if (a->type==PREFIX_T) { tmp=a->p1.string; len=strlen(tmp); if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; /* whatever we had before, with prefix we have username now */ user=1; } if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) { tmp=a->p1.string; len=strlen(tmp); } else if (a->type==STRIP_T) { if (a->p1.number>uri.user.len) { LOG(L_WARN, "Error: too long strip asked; " " deleting username: %lu of <%.*s>\n", a->p1.number, uri.user.len, uri.user.s ); len=0; } else if (a->p1.number==uri.user.len) { len=0; } else { tmp=uri.user.s + a->p1.number; len=uri.user.len - a->p1.number; } } else if (a->type==STRIP_TAIL_T) { if (a->p1.number>uri.user.len) { LOG(L_WARN, "WARNING: too long strip_tail asked; " " deleting username: %lu of <%.*s>\n", a->p1.number, uri.user.len, uri.user.s ); len=0; } else if (a->p1.number==uri.user.len) { len=0; } else { tmp=uri.user.s; len=uri.user.len - a->p1.number; } } else { tmp=uri.user.s; len=uri.user.len; } if (len){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; user=1; /* we have an user field so mark it */ } if (a->type==SET_USERPASS_T) tmp=0; else tmp=uri.passwd.s; /* passwd */ if (tmp){ len=uri.passwd.len; if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* host */ if (user || tmp){ /* add @ */ if(crt+1>end) goto error_uri; *crt='@'; crt++; } if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) { tmp=a->p1.string; if (tmp) len = strlen(tmp); else len=0; } else { tmp=uri.host.s; len = uri.host.len; } if (tmp){ if(crt+len>end) goto error_uri; memcpy(crt,tmp,len);crt+=len; } /* port */ if (a->type==SET_HOSTPORT_T) tmp=0; else if (a->type==SET_PORT_T) { tmp=a->p1.string; if (tmp) len = strlen(tmp); else len = 0; } else { tmp=uri.port.s; len = uri.port.len; } if (tmp){ if(crt+len+1>end) goto error_uri; *crt=':'; crt++; memcpy(crt,tmp,len);crt+=len; } /* params */ tmp=uri.params.s; if (tmp){ len=uri.params.len; if(crt+len+1>end) goto error_uri; *crt=';'; crt++; memcpy(crt,tmp,len);crt+=len; } /* headers */ tmp=uri.headers.s; if (tmp){ len=uri.headers.len; if(crt+len+1>end) goto error_uri; *crt='?'; crt++; memcpy(crt,tmp,len);crt+=len; } *crt=0; /* null terminate the thing */ /* copy it to the msg */ if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri.s=new_uri; msg->new_uri.len=crt-new_uri; msg->parsed_uri_ok=0; ret=1; break; case IF_T: /* if null expr => ignore if? */ if ((a->p1_type==EXPR_ST)&&a->p1.data){ v=eval_expr((struct expr*)a->p1.data, msg); if (v<0){ if (v==EXPR_DROP){ /* hack to quit on DROP*/ ret=0; break; }else{ LOG(L_WARN,"WARNING: do_action:" "error in expression\n"); } } ret=1; /*default is continue */ if (v>0) { if ((a->p2_type==ACTIONS_ST)&&a->p2.data){ ret=run_actions((struct action*)a->p2.data, msg); } }else if ((a->p3_type==ACTIONS_ST)&&a->p3.data){ ret=run_actions((struct action*)a->p3.data, msg); } } break; case MODULE_T: if ( ((a->p1_type==CMDF_ST)&&a->p1.data)/*&& ((a->p2_type==STRING_ST)&&a->p2.data)*/ ){ ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data, (char*)a->p3.data); }else{ LOG(L_CRIT,"BUG: do_action: bad module call\n"); } break; case FORCE_RPORT_T: msg->msg_flags|=FL_FORCE_RPORT; ret=1; /* continue processing */ break; case SET_ADV_ADDR_T: if (a->p1_type!=STR_ST){ LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() " "type %d\n", a->p1_type); ret=E_BUG; break; } msg->set_global_address=*((str*)a->p1.data); ret=1; /* continue processing */ break; case SET_ADV_PORT_T: if (a->p1_type!=STR_ST){ LOG(L_CRIT, "BUG: do_action: bad set_advertised_port() " "type %d\n", a->p1_type); ret=E_BUG; break; } msg->set_global_port=*((str*)a->p1.data); ret=1; /* continue processing */ break; default: LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type); } /*skip:*/ return ret; error_uri: LOG(L_ERR, "ERROR: do_action: set*: uri too long\n"); if (new_uri) pkg_free(new_uri); return E_UNSPEC; error_fwd_uri: /*free_uri(&uri); -- not needed anymore, using msg->parsed_uri*/ return ret; }
/* ** parse_vararg: read & check a attribute value */ STRPTR parse_vararg( HSCVAR *var, INFILE *inpf ) { STRPTR str_vararg = NULL; /* return value */ int ch; /* char read from input */ /* TODO: handle "<>" (reset var->text to NULL) */ infskip_ws( inpf ); /* disable log */ inflog_disable( inpf ); /* read var->quote char */ ch = infgetc( inpf ); if ( !strchr( VQ_STR_QUOTE, ch ) ) if ( ch != EOF ) var->quote = VQ_NO_QUOTE; else err_eof( inpf, "reading attribute" ); else var->quote = ch; /* warning if no quote */ if ( ( var->quote == VQ_NO_QUOTE ) && !( var->varflag & VF_NOQUOTE ) ) { message( MSG_ARG_NO_QUOTE, inpf ); errstr( "Argument without quote\n" ); } /* read arg string */ if ( var->quote == '<' ) { /* ** get arg from other var */ STRPTR nw = infgetw( inpf ); if ( nw ) { HSCVAR *refvar = find_varname( vars, nw ); if ( refvar ) { /* TODO: type checking */ var->quote = refvar->quote; str_vararg = refvar->text; /* check empty/circular reference */ if ( !str_vararg ) { message( MSG_EMPTY_SYMB_REF, inpf ); errstr( "Empty reference to" ); errsym( var->name ); errlf(); } /* debugging message */ DDA( fprintf( stderr, "** %s refers to <%s>\n", var->name, refvar->name ) ); } else { /* reference to unknown var */ message( MSG_UNKN_SYMB_REF, inpf ); errstr( "reference to unknown" ); errsym( nw ); errlf(); } if ( (!refvar) || (!str_vararg ) ) { /* return empty var */ var->quote = '"'; str_vararg = ""; } parse_gt( inpf ); } else err_eof( inpf, "reading attribute" ); } else if ( var->quote != EOF ) { /* ** get arg from input file */ BOOL end = FALSE; /* clear vararg or set with first char read */ if ( var->quote == VQ_NO_QUOTE ) end = !set_estr( vararg, ch2str( ch ) ); else end = !clr_estr( vararg ); if ( end ) err_mem( inpf ); /* ** read next char from input file until a ** closing quote if found. ** if the arg had no quote, a white space ** or a '>' is used to detect end of arg. ** if a LF is found, view error message */ while ( !end ) { ch = infgetc( inpf ); end = TRUE; if ( ch == EOF ) err_eof( inpf, "reading attribute" ); else if ( (ch==var->quote) || ( ch==CH_LF ) || ( (var->quote==VQ_NO_QUOTE) && ( inf_isws(ch,inpf) || ( ch=='>' ) ) ) ) { /* end of arg reached */ str_vararg = estr2str( vararg ); if ( var->quote == VQ_NO_QUOTE ) { if ( ch==CH_LF ) err_streol( inpf ); inungetc( ch, inpf ); } } else { /* append next char to vararg */ if ( !app_estrch( vararg, ch ) ) err_mem( inpf ); else end = FALSE; /* continue loop */ } } } if ( str_vararg && var ) /* ** check enum type */ if (var->vartype == VT_ENUM) check_enumstr( var, str_vararg, inpf ); /* ** parse uri (only if no macro-attr) ** (convert abs.uris, check existence) */ else if (var->vartype == VT_URI ) if ( !(var->varflag & VF_MACRO) ) str_vararg = parse_uri( str_vararg, inpf ); else { DDA( fprintf( stderr, "** didn't parse uri \"%s\"\n", str_vararg ) ); } /* update and enable log */ if ( !fatal_error ) { BOOL ok = TRUE; if ( var->quote != VQ_NO_QUOTE ) ok &= inflog_app( inpf, ch2str( var->quote ) );/* append quote */ inflog_app( inpf, str_vararg ); /* append arg */ if ( var->quote != VQ_NO_QUOTE ) ok &= inflog_app( inpf, ch2str( var->quote ) );/* append quote */ inflog_enable( inpf ); /* enable log */ if ( !ok ) err_mem( NULL ); } return ( str_vararg ); }
int zmq::socket_base_t::term_endpoint (const char *addr_) { ENTER_MUTEX (); // Check whether the library haven't been shut down yet. if (unlikely (ctx_terminated)) { errno = ETERM; EXIT_MUTEX (); return -1; } // Check whether endpoint address passed to the function is valid. if (unlikely (!addr_)) { errno = EINVAL; EXIT_MUTEX (); return -1; } // Process pending commands, if any, since there could be pending unprocessed process_own()'s // (from launch_child() for example) we're asked to terminate now. int rc = process_commands (0, false); if (unlikely(rc != 0)) { EXIT_MUTEX (); return -1; } // Parse addr_ string. std::string protocol; std::string address; if (parse_uri(addr_, protocol, address) || check_protocol(protocol)) { EXIT_MUTEX (); return -1; } // Disconnect an inproc socket if (protocol == "inproc") { if (unregister_endpoint (std::string(addr_), this) == 0) { EXIT_MUTEX (); return 0; } std::pair <inprocs_t::iterator, inprocs_t::iterator> range = inprocs.equal_range (std::string (addr_)); if (range.first == range.second) { errno = ENOENT; EXIT_MUTEX (); return -1; } for (inprocs_t::iterator it = range.first; it != range.second; ++it) it->second->terminate (true); inprocs.erase (range.first, range.second); EXIT_MUTEX (); return 0; } std::string resolved_addr = std::string (addr_); std::pair <endpoints_t::iterator, endpoints_t::iterator> range; // The resolved last_endpoint is used as a key in the endpoints map. // The address passed by the user might not match in the TCP case due to // IPv4-in-IPv6 mapping (EG: tcp://[::ffff:127.0.0.1]:9999), so try to // resolve before giving up. Given at this stage we don't know whether a // socket is connected or bound, try with both. if (protocol == "tcp") { range = endpoints.equal_range (resolved_addr); if (range.first == range.second) { tcp_address_t *tcp_addr = new (std::nothrow) tcp_address_t (); alloc_assert (tcp_addr); rc = tcp_addr->resolve (address.c_str (), false, options.ipv6); if (rc == 0) { tcp_addr->to_string (resolved_addr); range = endpoints.equal_range (resolved_addr); if (range.first == range.second) { rc = tcp_addr->resolve (address.c_str (), true, options.ipv6); if (rc == 0) { tcp_addr->to_string (resolved_addr); } } } LIBZMQ_DELETE(tcp_addr); } } // Find the endpoints range (if any) corresponding to the addr_ string. range = endpoints.equal_range (resolved_addr); if (range.first == range.second) { errno = ENOENT; EXIT_MUTEX (); return -1; } for (endpoints_t::iterator it = range.first; it != range.second; ++it) { // If we have an associated pipe, terminate it. if (it->second.second != NULL) it->second.second->terminate (false); term_child (it->second.first); } endpoints.erase (range.first, range.second); EXIT_MUTEX (); return 0; }
/* Params: * str1 - as unsigned int - can be CPL_RUN_INCOMING or CPL_RUN_OUTGOING * str2 - as unsigned int - flags regarding state(less)|(ful) * str3 - URI in SPVE structure */ static int cpl_invoke_script3(struct sip_msg* msg, char* str1, char* str2, char *str3) { struct cpl_interpreter *cpl_intr; str username = {0,0}; str domain = {0,0}; str uri = {0,0}; sip_uri_t puri; str loc; str script; /* get the user_name */ if(str3==NULL) { if ( ((unsigned long)str1)&CPL_RUN_INCOMING ) { /* if it's incoming -> get the destination user name */ if (get_dest_user( msg, &username, &domain)==-1) goto error0; } else { /* if it's outgoing -> get the origin user name */ if (get_orig_user( msg, &username, &domain)==-1) goto error0; } } else { if(fixup_get_svalue(msg, (gparam_p)str3, &uri)!=0) { LM_ERR("invalid uri parameter"); goto error0; } if (parse_uri(uri.s, uri.len, &puri) || !puri.user.len) { LM_ERR("unable to extract user name from URI param\n"); return -1; } username = puri.user; domain = puri.host; } /* get the script for this user */ if (get_user_script(&username, cpl_env.use_domain?&domain:0, &script, &cpl_bin_col)==-1) goto error0; /* has the user a non-empty script? if not, return normally, allowing the * script execution to continue */ if ( !script.s || !script.len ) return 1; /* build a new script interpreter */ if ( (cpl_intr=new_cpl_interpreter(msg,&script))==0 ) goto error1; /* set the flags */ cpl_intr->flags =(unsigned int)((unsigned long)str1)|((unsigned long)str2); /* build user AOR */ if (build_user_AOR( &username, &domain, &(cpl_intr->user), 0)!=0 ) goto error2; /* for OUTGOING we need also the destination user for init. with him * the location set */ if ( ((unsigned long)str1)&CPL_RUN_OUTGOING ) { /* build user initial location -> get the destination user name */ if (get_dest_user( msg, &username, &domain)==-1) goto error2; if (build_user_AOR( &username, &domain, &loc, 1)!=0 ) goto error2; if (add_location( &(cpl_intr->loc_set), &loc, 0, 10, 0/*no dup*/)==-1) goto error2; } /* run the script */ switch (cpl_run_script( cpl_intr )) { case SCRIPT_DEFAULT: free_cpl_interpreter( cpl_intr ); return 1; /* execution of ser's script will continue */ case SCRIPT_END: free_cpl_interpreter( cpl_intr ); case SCRIPT_TO_BE_CONTINUED: return 0; /* break the SER script */ case SCRIPT_RUN_ERROR: case SCRIPT_FORMAT_ERROR: goto error2; } return 1; error2: free_cpl_interpreter( cpl_intr ); return -1; error1: shm_free(script.s); error0: return -1; }
void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps) { char *uuid; str suuid; reg_uac_t *ri = NULL; contact_t* c; int expires; struct sip_uri puri; struct hdr_field *hdr; HASHHEX response; str *new_auth_hdr = NULL; static struct authenticate_body auth; struct uac_credential cred; char b_ruri[MAX_URI_SIZE]; str s_ruri; #ifdef UAC_OLD_AUTH char b_turi[MAX_URI_SIZE]; str s_turi; #endif char b_hdrs[MAX_UACH_SIZE]; str s_hdrs; uac_req_t uac_r; str method = {"REGISTER", 8}; int ret; dlg_t tmdlg; if(ps->param==NULL || *ps->param==0) { LM_DBG("uuid not received\n"); return; } uuid = *((char**)ps->param); LM_DBG("completed with status %d [uuid: %s]\n", ps->code, uuid); suuid.s = uuid; suuid.len = strlen(suuid.s); ri = reg_ht_get_byuuid(&suuid); if(ri==NULL) { LM_DBG("no user with uuid %s\n", uuid); goto done; } if(ps->code == 200) { if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse headers\n"); goto error; } if (ps->rpl->contact==NULL) { LM_ERR("no Contact found\n"); goto error; } if (parse_contact(ps->rpl->contact) < 0) { LM_ERR("failed to parse Contact HF\n"); goto error; } if (((contact_body_t*)ps->rpl->contact->parsed)->star) { LM_DBG("* Contact found\n"); goto done; } if (contact_iterator(&c, ps->rpl, 0) < 0) goto done; while(c) { if(parse_uri(c->uri.s, c->uri.len, &puri)!=0) { LM_ERR("failed to parse c-uri\n"); goto error; } if(suuid.len==puri.user.len && (strncmp(puri.user.s, suuid.s, suuid.len)==0)) { /* calculate expires */ expires=0; if(c->expires==NULL || c->expires->body.len<=0) { if(ps->rpl->expires!=NULL && ps->rpl->expires->body.len>0) expires = atoi(ps->rpl->expires->body.s); } else { str2int(&c->expires->body, (unsigned int*)(&expires)); } ri->timer_expires = ri->timer_expires + expires; ri->flags |= UAC_REG_ONLINE; goto done; } if (contact_iterator(&c, ps->rpl, c) < 0) { LM_DBG("local contact not found\n"); goto done; } } } if(ps->code == 401 || ps->code == 407) { if(ri->flags & UAC_REG_AUTHSENT) { LM_ERR("authentication failed for <%.*s>\n", ri->l_uuid.len, ri->l_uuid.s); goto error; } hdr = get_autenticate_hdr(ps->rpl, ps->code); if (hdr==0) { LM_ERR("failed to extract authenticate hdr\n"); goto error; } LM_DBG("auth header body [%.*s]\n", hdr->body.len, hdr->body.s); if (parse_authenticate_body(&hdr->body, &auth)<0) { LM_ERR("failed to parse auth hdr body\n"); goto error; } if (ri->realm.len>0) { /* only check if realms match if it is non-empty */ if(auth.realm.len!=ri->realm.len || strncmp(auth.realm.s, ri->realm.s, ri->realm.len)!=0) { LM_ERR("realms do not match. requested realm: [%.*s]\n", auth.realm.len, auth.realm.s); goto error; } } cred.realm = auth.realm; cred.user = ri->auth_username; cred.passwd = ri->auth_password; cred.next = NULL; snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s", ri->r_domain.len, ri->r_domain.s); s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s); do_uac_auth(&method, &s_ruri, &cred, &auth, response); new_auth_hdr=build_authorization_hdr(ps->code, &s_ruri, &cred, &auth, response); if (new_auth_hdr==0) { LM_ERR("failed to build authorization hdr\n"); goto error; } #ifdef UAC_OLD_AUTH snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s", ri->r_username.len, ri->r_username.s, ri->r_domain.len, ri->r_domain.s); s_turi.s = b_turi; s_turi.len = strlen(s_turi.s); #endif snprintf(b_hdrs, MAX_UACH_SIZE, "Contact: <sip:%.*s@%.*s>\r\n" "Expires: %d\r\n" "%.*s", ri->l_uuid.len, ri->l_uuid.s, reg_contact_addr.len, reg_contact_addr.s, ri->expires, new_auth_hdr->len, new_auth_hdr->s); s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s); pkg_free(new_auth_hdr->s); memset(&uac_r, 0, sizeof(uac_r)); if(uac_reg_tmdlg(&tmdlg, ps->rpl)<0) { LM_ERR("failed to build tm dialog\n"); goto error; } tmdlg.rem_target = s_ruri; if(ri->auth_proxy.len) tmdlg.dst_uri = ri->auth_proxy; uac_r.method = &method; uac_r.headers = &s_hdrs; uac_r.dialog = &tmdlg; uac_r.cb_flags = TMCB_LOCAL_COMPLETED; /* Callback function */ uac_r.cb = uac_reg_tm_callback; /* Callback parameter */ uac_r.cbp = (void*)uuid; #ifdef UAC_OLD_AUTH ret = uac_tmb.t_request(&uac_r, /* UAC Req */ &s_ruri, /* Request-URI */ &s_turi, /* To */ &s_turi, /* From */ (ri->auth_proxy.len)?&ri->auth_proxy:NULL /* outbound uri */ ); #endif ret = uac_tmb.t_request_within(&uac_r); if(ret<0) { LM_ERR("failed to send request with authentication for [%.*s]", ri->l_uuid.len, ri->l_uuid.s); goto error; } ri->flags |= UAC_REG_AUTHSENT; return; } else { LM_ERR("got sip response %d while registering [%.*s]\n", ps->code, ri->l_uuid.len, ri->l_uuid.s); goto error; } error: if(reg_retry_interval) { ri->timer_expires = time(NULL) + reg_retry_interval; } else { ri->flags |= UAC_REG_DISABLED; counter_inc(regdisabled); } done: if(ri) ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT); shm_free(uuid); counter_inc(regactive); }
int zmq::socket_base_t::bind (const char *addr_) { ENTER_MUTEX (); if (unlikely (ctx_terminated)) { errno = ETERM; EXIT_MUTEX (); return -1; } // Process pending commands, if any. int rc = process_commands (0, false); if (unlikely (rc != 0)) { EXIT_MUTEX (); return -1; } // Parse addr_ string. std::string protocol; std::string address; if (parse_uri (addr_, protocol, address) || check_protocol (protocol)) { EXIT_MUTEX (); return -1; } if (protocol == "inproc") { const endpoint_t endpoint = { this, options }; rc = register_endpoint (addr_, endpoint); if (rc == 0) { connect_pending (addr_, this); last_endpoint.assign (addr_); options.connected = true; } EXIT_MUTEX (); return rc; } if (protocol == "pgm" || protocol == "epgm" || protocol == "norm" || protocol == "udp") { // For convenience's sake, bind can be used interchangeable with // connect for PGM, EPGM, NORM and UDP transports. EXIT_MUTEX (); rc = connect (addr_); if (rc != -1) options.connected = true; return rc; } // Remaining transports require to be run in an I/O thread, so at this // point we'll choose one. io_thread_t *io_thread = choose_io_thread (options.affinity); if (!io_thread) { errno = EMTHREAD; EXIT_MUTEX (); return -1; } if (protocol == "tcp") { tcp_listener_t *listener = new (std::nothrow) tcp_listener_t ( io_thread, this, options); alloc_assert (listener); rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno()); EXIT_MUTEX (); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (last_endpoint.c_str (), (own_t *) listener, NULL); options.connected = true; EXIT_MUTEX (); return 0; } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS if (protocol == "ipc") { ipc_listener_t *listener = new (std::nothrow) ipc_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno()); EXIT_MUTEX (); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (last_endpoint.c_str (), (own_t *) listener, NULL); options.connected = true; EXIT_MUTEX (); return 0; } #endif #if defined ZMQ_HAVE_TIPC if (protocol == "tipc") { tipc_listener_t *listener = new (std::nothrow) tipc_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno()); EXIT_MUTEX (); return -1; } // Save last endpoint URI listener->get_address (last_endpoint); add_endpoint (addr_, (own_t *) listener, NULL); options.connected = true; EXIT_MUTEX (); return 0; } #endif #if defined ZMQ_HAVE_VMCI if (protocol == "vmci") { vmci_listener_t *listener = new (std::nothrow) vmci_listener_t ( io_thread, this, options); alloc_assert (listener); int rc = listener->set_address (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(listener); event_bind_failed (address, zmq_errno ()); EXIT_MUTEX (); return -1; } listener->get_address (last_endpoint); add_endpoint (last_endpoint.c_str(), (own_t *) listener, NULL); options.connected = true; EXIT_MUTEX (); return 0; } #endif EXIT_MUTEX (); zmq_assert (false); return -1; }
/** * _remove - Delete an entire AOR entry or just one or more of its Contacts * Parameter format: _remove(domain, AOR[, Contact URI or plain hostname]) * * @udomain: (udomain_t *) * @aor_gp: address-of-record as a SIP URI (plain string or pvar) * @contact_gp: contact to be deleted or domain in front of multiple contacts * * @return: 1 on success, negative on failure */ int _remove(struct sip_msg *msg, char *udomain, char *aor_gp, char *contact_gp) { static struct sip_uri puri; struct hostent delete_he, *he; urecord_t *record; ucontact_t *contact, *it; str uri, aor_user, delete_user = { NULL, 0 }; int err, count = 0; int delete_by_hostname = 0; unsigned short delete_port; memset(&delete_he, 0, sizeof delete_he); if (fixup_get_svalue(msg, (gparam_p)aor_gp, &uri) != 0) { LM_ERR("failed to get gparam_t value\n"); return E_UNSPEC; } if (parse_uri(uri.s, uri.len, &puri) != 0) { LM_ERR("failed to parse aor: '%.*s'\n", uri.len, uri.s); return E_BAD_URI; } aor_user = puri.user; ul.lock_udomain((udomain_t *)udomain, &aor_user); if (ul.get_urecord((udomain_t *)udomain, &aor_user, &record) != 0) { LM_DBG("no record '%.*s' found!\n", aor_user.len, aor_user.s); err = 1; goto out_unlock; } /* if no contact uri param is given, delete the whole urecord entry */ if (!contact_gp) { if (ul.delete_urecord((udomain_t *)udomain, &aor_user, record, 0) != 0) { LM_ERR("failed to delete urecord for aor '%.*s'\n", aor_user.len, aor_user.s); err = E_UNSPEC; goto out_unlock; } err = 1; goto out_unlock; } if (fixup_get_svalue(msg, (gparam_p)contact_gp, &uri) != 0) { LM_ERR("failed to retrieve value of contact pv\n"); err = E_UNSPEC; goto out_unlock; } /* minimum two-letters for the domain name */ if (uri.len < 5) { LM_ERR("Invalid domain given: '%.*s'\n", uri.len, uri.s); err = E_INVALID_PARAMS; goto out_unlock; } /* a domain/IP address was given instead of a SIP contact URI */ if (uri.s[0] != 's' || uri.s[1] != 'i' || uri.s[2] != 'p' || (uri.s[3] != ':' && (uri.s[3] != 's' || uri.s[4] != ':'))) { delete_by_hostname = 1; he = sip_resolvehost(&uri, &delete_port, &puri.proto, 0, NULL); if (!he) { LM_ERR("cannot resolve given host: '%.*s'\n", uri.len, uri.s); err = E_UNSPEC; goto out_unlock; } LM_DBG("Delete by host: '%s'\n", inet_ntoa(*(struct in_addr *)(he->h_addr_list[0]))); } else { LM_DBG("parsing uri: %.*s\n", uri.len, uri.s); if (parse_uri(uri.s, uri.len, &puri) != 0) { LM_ERR("failed to parse contact uri: '%.*s'\n", uri.len, uri.s); err = E_BAD_URI; goto out_unlock; } delete_user = puri.user; he = sip_resolvehost(&puri.host, &delete_port, &puri.proto, 0, NULL); if (!he) { LM_ERR("cannot resolve given uri: '%.*s'\n", uri.len, uri.s); err = E_UNSPEC; goto out_unlock; } if (puri.port_no > 0) delete_port = puri.port_no; LM_DBG("Delete by contact: [ User %.*s | Host %s | Port %d ]\n", delete_user.len, delete_user.s, inet_ntoa(*(struct in_addr *)(he->h_addr_list[0])), delete_port); } if (hostent_cpy(&delete_he, he) != 0) { LM_ERR("no more pkg mem\n"); err = E_OUT_OF_MEM; goto out_unlock; } for (it = record->contacts; it; ) { contact = it; it = it->next; count++; LM_DBG("parsing contact uri '%.*s'\n", contact->c.len, contact->c.s); if (parse_uri(contact->c.s, contact->c.len, &puri) != 0) { LM_ERR("failed to parse contact uri: '%.*s'\n", contact->c.len, contact->c.s); err = E_BAD_URI; goto out_unlock; } /* if necessary, solve the next_hop towards the contact */ he = sip_resolvehost(&contact->next_hop.name, &contact->next_hop.port, &contact->next_hop.proto, 0, NULL); if (!he) { LM_ERR("failed to resolve next hop of contact '%.*s'\n", contact->c.len, contact->c.s); continue; } LM_DBG("Contact: [ User %.*s | Host %s | Port %d ]\n", puri.user.len, puri.user.s, inet_ntoa(*(struct in_addr *)(he->h_addr_list[0])), puri.port_no); if (delete_by_hostname) { if (!memcmp(delete_he.h_addr_list[0], he->h_addr_list[0], he->h_length)) { ul.delete_ucontact(record, contact, 0); count--; } } else { if (delete_user.len == puri.user.len && delete_port == puri.port_no && !memcmp(delete_he.h_addr_list[0], he->h_addr_list[0], he->h_length) && !memcmp(delete_user.s, puri.user.s, puri.user.len)) { ul.delete_ucontact(record, contact, 0); count--; } } } err = 1; /* remove the AOR if no more contacts are attached */ if (count == 0) { if (ul.delete_urecord((udomain_t *)udomain, &aor_user, record, 0) != 0) { LM_ERR("failed to delete urecord for aor '%.*s'\n", aor_user.len, aor_user.s); err = 1; } } out_unlock: ul.unlock_udomain((udomain_t *)udomain, &aor_user); free_hostent(&delete_he); return err; }
/*! \brief * Message contained some contacts, but record with same address * of record was not found so we have to create a new record * and insert all contacts from the message that have expires * > 0 */ static inline int insert_contacts(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _a, struct save_ctx *_sctx) { ucontact_info_t* ci; urecord_t* r; ucontact_t* c; unsigned int cflags; int num; int e; int e_max; int tcp_check; struct sip_uri uri; cflags = (_sctx->flags®_SAVE_MEMORY_FLAG)?FL_MEM:FL_NONE; if (is_tcp_based_proto(_m->rcv.proto) && (_m->flags&tcp_persistent_flag)) { e_max = 0; tcp_check = 1; } else { e_max = tcp_check = 0; } for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) { /* calculate expires */ calc_contact_expires(_m, _c->expires, &e, _sctx); /* Skip contacts with zero expires */ if (e == 0) continue; if (_sctx->max_contacts && (num >= _sctx->max_contacts)) { if (_sctx->flags®_SAVE_FORCE_REG_FLAG) { /* we are overflowing the number of maximum contacts, so remove the first (oldest) one to prevent this */ if (r==NULL || r->contacts==NULL) { LM_CRIT("BUG - overflow detected with r=%p and " "contacts=%p\n",r,r->contacts); goto error; } if (ul.delete_ucontact( r, r->contacts, 0)!=0) { LM_ERR("failed to remove contact\n"); goto error; } } else { LM_INFO("too many contacts (%d) for AOR <%.*s>, max=%d\n", num, _a->len, _a->s, _sctx->max_contacts); rerrno = R_TOO_MANY; goto error; } } else { num++; } if (r==0) { if (ul.insert_urecord(_d, _a, &r, 0) < 0) { rerrno = R_UL_NEW_R; LM_ERR("failed to insert new record structure\n"); goto error; } } /* pack the contact_info */ if ( (ci=pack_ci( (ci==0)?_m:0, _c, e, cflags, _sctx->flags))==0 ) { LM_ERR("failed to extract contact info\n"); goto error; } if ( r->contacts==0 || ul.get_ucontact(r, &_c->uri, ci->callid, ci->cseq+1, &c)!=0 ) { if (ul.insert_ucontact( r, &_c->uri, ci, &c, 0) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); goto error; } } else { if (ul.update_ucontact( r, c, ci, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto error; } } if (tcp_check) { /* parse contact uri to see if transport is TCP */ if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) { LM_ERR("failed to parse contact <%.*s>\n", _c->uri.len, _c->uri.s); } else if ( is_tcp_based_proto(uri.proto) ) { if (e_max) { LM_WARN("multiple TCP contacts on single REGISTER\n"); if (e>e_max) e_max = e; } else { e_max = e; } } } } if (r) { if (r->contacts) { build_contact(r->contacts,_m); } ul.release_urecord(r, 0); } if ( tcp_check && e_max>0 ) { e_max -= act_time; trans_set_dst_attr( &_m->rcv, DST_FCNTL_SET_LIFETIME, (void*)(long)(e_max + 10) ); } return 0; error: if (r) ul.delete_urecord(_d, _a, r, 0); return -1; }
int zmq::socket_base_t::term_endpoint (const char *addr_) { ENTER_MUTEX(); // Check whether the library haven't been shut down yet. if (unlikely (ctx_terminated)) { errno = ETERM; EXIT_MUTEX(); return -1; } // Check whether endpoint address passed to the function is valid. if (unlikely (!addr_)) { errno = EINVAL; EXIT_MUTEX(); return -1; } // Process pending commands, if any, since there could be pending unprocessed process_own()'s // (from launch_child() for example) we're asked to terminate now. int rc = process_commands (0, false); if (unlikely(rc != 0)) { EXIT_MUTEX(); return -1; } // Parse addr_ string. std::string protocol; std::string address; if (parse_uri(addr_, protocol, address) || check_protocol(protocol)) { EXIT_MUTEX(); return -1; } // Disconnect an inproc socket if (protocol == "inproc") { if (unregister_endpoint (std::string(addr_), this) == 0) { EXIT_MUTEX(); return 0; } std::pair <inprocs_t::iterator, inprocs_t::iterator> range = inprocs.equal_range (std::string (addr_)); if (range.first == range.second) { errno = ENOENT; EXIT_MUTEX(); return -1; } for (inprocs_t::iterator it = range.first; it != range.second; ++it) it->second->terminate (true); inprocs.erase (range.first, range.second); EXIT_MUTEX(); return 0; } // Find the endpoints range (if any) corresponding to the addr_ string. std::pair <endpoints_t::iterator, endpoints_t::iterator> range = endpoints.equal_range (std::string (addr_)); if (range.first == range.second) { errno = ENOENT; EXIT_MUTEX(); return -1; } for (endpoints_t::iterator it = range.first; it != range.second; ++it) { // If we have an associated pipe, terminate it. if (it->second.second != NULL) it->second.second->terminate (false); term_child (it->second.first); } endpoints.erase (range.first, range.second); EXIT_MUTEX(); return 0; }
/* * Calculate dialog hooks * @return: * negative : error * 0 : no routes present * F_RB_NH_LOOSE : routes present, next hop is loose router * F_RB_NH_STRICT: next hop is strict. */ static inline int calculate_hooks(dlg_t* _d) { str* uri; struct sip_uri puri; int nhop; /* we might re-calc. some existing hooks => * reset all the hooks to 0 */ memset(&_d->hooks, 0, sizeof(_d->hooks)); if (_d->route_set) { uri = &_d->route_set->nameaddr.uri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "calculate_hooks(): Error while parsing URI\n"); return -1; } if (puri.lr.s) { if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target; else _d->hooks.request_uri = &_d->rem_uri; _d->hooks.next_hop = &_d->route_set->nameaddr.uri; _d->hooks.first_route = _d->route_set; nhop = F_RB_NH_LOOSE; } else { _d->hooks.request_uri = &_d->route_set->nameaddr.uri; _d->hooks.next_hop = _d->hooks.request_uri; _d->hooks.first_route = _d->route_set->next; if (_d->rem_target.len > 0) _d->hooks.last_route = &_d->rem_target; else _d->hooks.last_route = NULL; /* ? */ nhop = F_RB_NH_STRICT; } } else { if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target; else _d->hooks.request_uri = &_d->rem_uri; if (_d->dst_uri.s) _d->hooks.next_hop = &_d->dst_uri; else _d->hooks.next_hop = _d->hooks.request_uri; nhop = 0; /* * the routes in the hooks need to be reset because if the route_set * was dropped somewhere else then these will remain set without the * actual routes existing any more */ _d->hooks.first_route = 0; _d->hooks.last_route = 0; } if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) { _d->hooks.ru.s = _d->hooks.request_uri->s; _d->hooks.ru.len = _d->hooks.request_uri->len; _d->hooks.request_uri = &_d->hooks.ru; get_raw_uri(_d->hooks.request_uri); } if ((_d->hooks.next_hop) && (_d->hooks.next_hop->s) && (_d->hooks.next_hop->len)) { _d->hooks.nh.s = _d->hooks.next_hop->s; _d->hooks.nh.len = _d->hooks.next_hop->len; _d->hooks.next_hop = &_d->hooks.nh; get_raw_uri(_d->hooks.next_hop); } return nhop; }
static void standard_request_handler(void *cls, struct SPDY_Request * request, uint8_t priority, const char *method, const char *path, const char *version, const char *host, const char *scheme, struct SPDY_NameValue * headers) { (void)cls; (void)priority; (void)host; (void)scheme; struct Proxy *proxy; int ret; struct URI *uri; struct SPDY_Session *session; PRINT_VERBOSE2("received request for '%s %s %s'\n", method, path, version); if(NULL == (proxy = malloc(sizeof(struct Proxy)))) DIE("No memory"); memset(proxy, 0, sizeof(struct Proxy)); session = SPDY_get_session_for_request(request); assert(NULL != session); proxy->session_alive = SPDY_get_cls_from_session(session); assert(NULL != proxy->session_alive); proxy->request = request; if(NULL == (proxy->headers = SPDY_name_value_create())) DIE("No memory"); if(glob_opt.transparent) { if(NULL != glob_opt.http_backend) //use always same host ret = asprintf(&(proxy->url),"%s://%s%s", scheme, glob_opt.http_backend, path); else //use host header ret = asprintf(&(proxy->url),"%s://%s%s", scheme, host, path); if(-1 == ret) DIE("No memory"); ret = parse_uri(&uri_preg, proxy->url, &uri); if(ret != 0) DIE("parsing built uri failed"); } else { ret = parse_uri(&uri_preg, path, &uri); PRINT_INFO2("path %s '%s' '%s'", path, uri->scheme, uri->host); if(ret != 0 || !strlen(uri->scheme) || !strlen(uri->host)) DIE("parsing received uri failed"); if(NULL != glob_opt.http_backend) //use backend host { ret = asprintf(&(proxy->url),"%s://%s%s", uri->scheme, glob_opt.http_backend, uri->path_and_more); if(-1 == ret) DIE("No memory"); } else //use request path if(NULL == (proxy->url = strdup(path))) DIE("No memory"); } free_uri(uri); PRINT_VERBOSE2("curl will request '%s'", proxy->url); SPDY_name_value_iterate(headers, &iterate_cb, proxy); if(NULL == (proxy->curl_handle = curl_easy_init())) { PRINT_INFO("curl_easy_init failed"); abort(); } if(glob_opt.curl_verbose) CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1); CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url); if(glob_opt.http10) CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEFUNCTION, curl_write_cb); CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEDATA, proxy); CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERFUNCTION, curl_header_cb); CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERDATA, proxy); CURL_SETOPT(proxy->curl_handle, CURLOPT_PRIVATE, proxy); CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTPHEADER, proxy->curl_headers); CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYHOST, 0L); if(glob_opt.ipv4 && !glob_opt.ipv6) CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); else if(glob_opt.ipv6 && !glob_opt.ipv4) CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle))) { PRINT_INFO2("curl_multi_add_handle failed (%i)", ret); abort(); } //~5ms additional latency for calling this if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running)) && CURLM_CALL_MULTI_PERFORM != ret) { PRINT_INFO2("curl_multi_perform failed (%i)", ret); abort(); } call_curl_run = true; }
/* This function extracts meta-info from the sip_msg structure and * formats it so that it can be used to rapidly access the message structured * parts. * * RETURNS: LENGTH of structure on success, <0 if failure * if there was failure, you don't need to pkg_free the payload (it is done inside). * if there was success, you __NEED_TO_PKG_FREE_THE_PAYLOAD__ from the calling function. * * The encoded meta-info is composed by 3 sections: * * MSG_META_INFO: * 2: short int in network-byte-order, if <100, the msg is a REQUEST and the int * is the code of the METHOD. if >100, it is a RESPONSE and the int is the code * of the response. * 2: short int in NBO: payload-start based pointer (index) to where the SIP MSG starts. * 2: short int in NBO: the sip-message length * 2: METHOD or CODE string SIP-START-based pointer and length * 2: R-URI or REASON PHRASE string SIP-START-based pointer and length * 2: VERSION string SIP-START-based pointer and length * 2: short int in NBO: start of the content of the SIP message * [1+N]: in case this is a request, the length of the encoded-uri and the encoded-uri * 1: how many present headers have been found. * * MSG_HEADERS_INDEX: * N*3: groups of 3 bytes, each one describing a header struct: the first byte * is a letter that corresponds to a header type, the second and third bytes are a NBO * inidex to where this struct begins within the HEADERS_META_INFO section. * * HEADERS_META_INFO: * M: all the codified headers meta info structs one after another * * SIP_MSG: * the SIP message as it has been received. * * The length of the structure, will be ((short*)payload)[1] + ((short*)payload)[2] * * TODO: msg->parsed_uri msg->parsed_orig_uri_ok, msg->first_line->u.request.uri * buggy and little bit fuzzy */ int encode_msg(struct sip_msg *msg,char *payload,int len) { int i,j,k,u,request; unsigned short int h; struct hdr_field* hf; struct msg_start* ms; struct sip_uri miuri; char *myerror=NULL; ptrdiff_t diff; str body = {NULL,0}; if(len < MAX_ENCODED_MSG + MAX_MESSAGE_LEN) return -1; if(parse_headers(msg,HDR_EOH_F,0)<0){ myerror="in parse_headers"; goto error; } memset(payload,0,len); ms=&msg->first_line; if(ms->type == SIP_REQUEST) request=1; else if(ms->type == SIP_REPLY) request=0; else{ myerror="message is neither request nor response"; goto error; } if(request) { for(h=0,j=1;h<32;j=(0x01<<h),h++) if(j & ms->u.request.method_value) break; } else { h=(unsigned short)(ms->u.reply.statuscode); } if(h==32){/*statuscode wont be 32...*/ myerror="unknown message type\n"; goto error; } h=htons(h); /*first goes the message code type*/ memcpy(payload,&h,2); h=htons((unsigned short int)msg->len); /*then goes the message start idx, but we'll put it later*/ /*then goes the message length (we hope it to be less than 65535 bytes...)*/ memcpy(&payload[MSG_LEN_IDX],&h,2); /*then goes the content start index (starting from SIP MSG START)*/ if (get_body(msg,&body) < 0) { myerror="body parsing failed"; goto error; } if(0>(diff=(body.s-msg->buf))){ myerror="body starts before the message (uh ?)"; goto error; }else h=htons((unsigned short int)diff); memcpy(payload+CONTENT_IDX,&h,2); payload[METHOD_CODE_IDX]=(unsigned char)(request? (ms->u.request.method.s-msg->buf): (ms->u.reply.status.s-msg->buf)); payload[METHOD_CODE_IDX+1]=(unsigned char)(request? (ms->u.request.method.len): (ms->u.reply.status.len)); payload[URI_REASON_IDX]=(unsigned char)(request? (ms->u.request.uri.s-msg->buf): (ms->u.reply.reason.s-msg->buf)); payload[URI_REASON_IDX+1]=(unsigned char)(request? (ms->u.request.uri.len): (ms->u.reply.reason.len)); payload[VERSION_IDX]=(unsigned char)(request? (ms->u.request.version.s-msg->buf): (ms->u.reply.version.s-msg->buf)); if(request){ if (parse_uri(ms->u.request.uri.s,ms->u.request.uri.len, &miuri)<0){ LM_ERR("<%.*s>\n",ms->u.request.uri.len,ms->u.request.uri.s); myerror="while parsing the R-URI"; goto error; } if(0>(j=encode_uri2(msg->buf, ms->u.request.method.s-msg->buf+ms->len, ms->u.request.uri,&miuri, (unsigned char*)&payload[REQUEST_URI_IDX+1]))) { myerror="ENCODE_MSG: ERROR while encoding the R-URI"; goto error; } payload[REQUEST_URI_IDX]=(unsigned char)j; k=REQUEST_URI_IDX+1+j; }else k=REQUEST_URI_IDX; u=k; k++; for(i=0,hf=msg->headers;hf;hf=hf->next,i++); i++;/*we do as if there was an extra header, that marks the end of the previous header in the headers hashtable(read below)*/ j=k+3*i; for(i=0,hf=msg->headers;hf;hf=hf->next,k+=3){ payload[k]=(unsigned char)(hf->type & 0xFF); h=htons(j); /*now goes a payload-based-ptr to where the header-code starts*/ memcpy(&payload[k+1],&h,2); /*TODO fix this... fixed with k-=3?*/ if(0>(i=encode_header(msg,hf,(unsigned char*)(payload+j),MAX_ENCODED_MSG+MAX_MESSAGE_LEN-j))){ LM_ERR("encoding header %.*s\n",hf->name.len,hf->name.s); goto error; /* XXX: not sure if this should be considered or not, but the code is * not executed anyway; commenting it for now. k-=3; continue; */ } j+=(unsigned short int)i; } /*now goes the number of headers that have been found, right after the meta-msg-section*/ payload[u]=(unsigned char)((k-u-1)/3); j=htons(j); /*now copy the number of bytes that the headers-meta-section has occupied,right afther * headers-meta-section(the array with ['v',[2:where],'r',[2:where],'R',[2:where],...] * this is to know where the LAST header ends, since the length of each header-struct * is calculated substracting the nextHeaderStart - presentHeaderStart * the k+1 is because payload[k] is usually the letter*/ memcpy(&payload[k+1],&j,2); k+=3; j=ntohs(j); /*now we copy the headers-meta-section after the msg-headers-meta-section*/ /*memcpy(&payload[k],payload2,j);*/ /*j+=k;*/ /*pkg_free(payload2);*/ /*now we copy the actual message after the headers-meta-section*/ memcpy(&payload[j],msg->buf,msg->len); LM_DBG("msglen = %d,msg starts at %d\n",msg->len,j); j=htons(j); /*now we copy at the beginning, the index to where the actual message starts*/ memcpy(&payload[MSG_START_IDX],&j,2); return GET_PAY_SIZE( payload ); error: LM_ERR("%s\n",myerror); return -1; }
int ds_load_list(char *lfile) { char line[256], *p; FILE *f = NULL; int id, i, j, setn; str uri; struct sip_uri puri; ds_dest_p dp = NULL, dp0 = NULL; ds_set_p sp = NULL, sp0 = NULL; ds_setidx_p si = NULL, si0 = NULL; if(lfile==NULL || strlen(lfile)<=0) { LOG(L_ERR, "DISPATCHER:ds_load_list: bad list file\n"); return -1; } f = fopen(lfile, "r"); if(f==NULL) { LOG(L_ERR, "DISPATCHER:ds_load_list: can't open list file [%s]\n", lfile); return -1; } id = setn = 0; p = fgets(line, 256, f); while(p) { /* eat all white spaces */ while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n')) p++; if(*p=='\0' || *p=='#') goto next_line; /* get set id */ id = 0; while(*p>='0' && *p<='9') { id = id*10+ (*p-'0'); p++; } /* eat all white spaces */ while(*p && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n')) p++; if(*p=='\0' || *p=='#') { LOG(L_ERR, "DISPATCHER:ds_load_list: bad line [%s]\n", line); goto error; } /* get uri */ uri.s = p; while(*p && *p!=' ' && *p!='\t' && *p!='\r' && *p!='\n' && *p!='#') p++; uri.len = p-uri.s; /* check uri */ if(parse_uri(uri.s, uri.len, &puri)!=0) { LOG(L_ERR, "DISPATCHER:ds_load_list: bad uri [%.*s]\n", uri.len, uri.s); goto error; } /* check index */ si = _ds_index; while(si) { if(si->id == id) break; si = si->next; } if(si==NULL) { si = (ds_setidx_p)pkg_malloc(sizeof(ds_setidx_t)); if(si==NULL) { LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory\n"); goto error; } memset(si, 0, sizeof(ds_setidx_t)); si->id = id; si->next = _ds_index; if(_ds_index!=NULL) si->index = _ds_index->index + 1; _ds_index = si; } /* get dest set */ sp = _ds_list; while(sp) { if(sp->id == id) break; sp = sp->next; } if(sp==NULL) { sp = (ds_set_p)pkg_malloc(sizeof(ds_set_t)); if(sp==NULL) { LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory.\n"); goto error; } memset(sp, 0, sizeof(ds_set_t)); sp->next = _ds_list; _ds_list = sp; setn++; } sp->id = id; sp->nr++; sp->index = si->index; /* store uri */ dp = (ds_dest_p)pkg_malloc(sizeof(ds_dest_t)); if(dp==NULL) { LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n"); goto error; } memset(dp, 0, sizeof(ds_dest_t)); dp->uri.s = (char*)pkg_malloc(uri.len+1); if(dp->uri.s==NULL) { LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n"); pkg_free(dp); goto error; } strncpy(dp->uri.s, uri.s, uri.len); dp->uri.s[uri.len]='\0'; dp->uri.len = uri.len; dp->next = sp->dlist; sp->dlist = dp; DBG("DISPATCHER:ds_load_list: dest [%d/%d/%d] <%.*s>\n", sp->index, sp->id, sp->nr, dp->uri.len, dp->uri.s); next_line: p = fgets(line, 256, f); } fclose(f); f = NULL; DBG("DISPATCHER:ds_load_list: found [%d] dest sets\n", setn); /* re-index destination sets for fast access */ sp0 = (ds_set_p)pkg_malloc(setn*sizeof(ds_set_t)); if(sp0==NULL) { LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n"); goto error; } memset(sp0, 0, setn*sizeof(ds_set_t)); sp = _ds_list; for(i=setn-1; i>=0; i--) { memcpy(&sp0[i], sp, sizeof(ds_set_t)); if(i==setn-1) sp0[i].next = NULL; else sp0[i].next = &sp0[i+1]; dp0 = (ds_dest_p)pkg_malloc(sp0[i].nr*sizeof(ds_dest_t)); if(dp0==NULL) { LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n"); ds_destroy_list(); goto error; } memset(dp0, 0, sp0[i].nr*sizeof(ds_dest_t)); dp = sp0[i].dlist; for(j=sp0[i].nr-1; j>=0; j--) { memcpy(&dp0[j], dp, sizeof(ds_dest_t)); if(j==sp0[j].nr-1) dp0[j].next = NULL; else dp0[j].next = &dp0[j+1]; dp = dp->next; } sp0[i].dlist = dp0; sp = sp->next; } sp = _ds_list; _ds_list = sp0; while(sp) { dp = sp->dlist; while(dp) { dp0 = dp; dp = dp->next; pkg_free(dp0); } sp0 = sp; sp = sp->next; pkg_free(sp0); } return 0; error: if(f!=NULL) fclose(f); si = _ds_index; while(si) { si0 = si; si = si->next; pkg_free(si0); } _ds_index = NULL; sp = _ds_list; while(sp) { dp = sp->dlist; while(dp) { if(dp->uri.s!=NULL) pkg_free(dp->uri.s); dp->uri.s=NULL; dp0 = dp; dp = dp->next; pkg_free(dp0); } sp0 = sp; sp = sp->next; pkg_free(sp0); } return -1; }
static int ki_xcaps_put(sip_msg_t* msg, str* uri, str* path, str* pbody) { struct sip_uri turi; str body = {0, 0}; str etag = {0, 0}; str etag_hdr = {0, 0}; str tbuf; str nbuf = {0, 0}; str allow = {0, 0}; xcap_uri_t xuri; if(uri->s==NULL || uri->len == 0) { LM_ERR("invalid uri parameter\n"); goto error; } if(path->s==NULL || path->len == 0) { LM_ERR("invalid path parameter\n"); return -1; } if(parse_uri(uri->s, uri->len, &turi)!=0) { LM_ERR("parsing uri parameter [%.*s]\n", uri->len, uri->s); goto error; } if(xcap_parse_uri(path, &xcaps_root, &xuri)<0) { LM_ERR("cannot parse xcap uri [%.*s]\n", path->len, path->s); goto error; } switch(xuri.type) { case DIRECTORY: case XCAP_CAPS: allow.s = xcaps_hdr_buf; allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: GET\r\n"); xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL); break; case SEARCH: allow.s = xcaps_hdr_buf; allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: POST\r\n"); xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL); break; default: if(pbody->len <= 0) { LM_ERR("invalid body parameter\n"); goto error; } body.s = (char*)pkg_malloc(pbody->len+1); if(body.s==NULL) { LM_ERR("no more pkg\n"); goto error; } memcpy(body.s, pbody->s, pbody->len); body.len = pbody->len; body.s[body.len] = '\0'; xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag); if(check_preconditions(msg, etag)!=1) { xcaps_send_reply(msg, 412, &xcaps_str_precon, NULL, NULL, NULL); pkg_free(body.s); return -2; } if(xuri.nss!=NULL && xuri.node.len>0) { /* partial document upload * - fetch, update, delete and store */ if(xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &tbuf) != 0) { LM_ERR("could not fetch xcap document\n"); goto error; } if(xcaps_xpath_hack(&tbuf, 0)<0) { LM_ERR("could not hack xcap document\n"); goto error; } if(xcaps_xpath_set(&tbuf, &xuri.node, &body, &nbuf)<0) { LM_ERR("could not update xcap document\n"); goto error; } if(nbuf.len<=0) { LM_ERR("no new content\n"); goto error; } pkg_free(body.s); body = nbuf; if(xcaps_xpath_hack(&body, 1)<0) { LM_ERR("could not hack xcap document\n"); goto error; } } if(xcaps_generate_etag_hdr(&etag_hdr)<0) { LM_ERR("could not generate etag\n"); goto error; } etag.s = etag_hdr.s + 7; /* 'ETag: "' */ etag.len = etag_hdr.len - 10; /* 'ETag: " "\r\n' */ if(xcaps_put_db(&turi.user, &turi.host, &xuri, &etag, &body)<0) { LM_ERR("could not store document\n"); goto error; } xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag_hdr, NULL, NULL); if(body.s!=NULL) pkg_free(body.s); break; } return 1; error: xcaps_send_reply(msg, 500, &xcaps_str_srverr, NULL, NULL, NULL); if(body.s!=NULL) pkg_free(body.s); return -1; }
/*! \brief * Message contained some contacts and appropriate * record was found, so we have to walk through * all contacts and do the following: * 1) If contact in usrloc doesn't exists and * expires > 0, insert new contact * 2) If contact in usrloc exists and expires * > 0, update the contact * 3) If contact in usrloc exists and expires * == 0, delete contact */ static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c, struct save_ctx *_sctx) { ucontact_info_t *ci; ucontact_t *c, *c_last, *c_it; int e; unsigned int cflags; int ret; int num; int e_max; int tcp_check; struct sip_uri uri; /* mem flag */ cflags = (_sctx->flags®_SAVE_MEMORY_FLAG)?FL_MEM:FL_NONE; /* pack the contact_info */ if ( (ci=pack_ci( _m, 0, 0, cflags, _sctx->flags))==0 ) { LM_ERR("failed to initial pack contact info\n"); goto error; } /* count how many contacts we have right now */ num = 0; if (_sctx->max_contacts) { c = _r->contacts; while(c) { if (VALID_CONTACT(c, act_time)) num++; c = c->next; } } if (is_tcp_based_proto(_m->rcv.proto) && (_m->flags&tcp_persistent_flag)) { e_max = -1; tcp_check = 1; } else { e_max = tcp_check = 0; } for( ; _c ; _c = get_next_contact(_c) ) { /* calculate expires */ calc_contact_expires(_m, _c->expires, &e, _sctx); /* search for the contact*/ ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &c); if (ret==-1) { LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s); rerrno = R_INV_CSEQ; goto error; } else if (ret==-2) { continue; } if ( ret > 0 ) { /* Contact not found -> expired? */ if (e==0) continue; /* we need to add a new contact -> too many ?? */ while (_sctx->max_contacts && num>=_sctx->max_contacts) { if (_sctx->flags®_SAVE_FORCE_REG_FLAG) { /* we are overflowing the number of maximum contacts, so remove the oldest valid one to prevent this */ for( c_it=_r->contacts,c_last=NULL ; c_it ; c_it=c_it->next ) if (VALID_CONTACT(c_it, act_time)) c_last=c_it; if (c_last==NULL) { LM_CRIT("BUG - overflow detected but no valid " "contacts found :( \n"); goto error; } LM_DBG("overflow on inserting new contact -> removing " "<%.*s>\n", c_last->c.len, c_last->c.s); if (ul.delete_ucontact( _r, c_last, 0)!=0) { LM_ERR("failed to remove contact\n"); goto error; } num--; } else { LM_INFO("too many contacts for AOR <%.*s>, max=%d\n", _r->aor.len, _r->aor.s, _sctx->max_contacts); rerrno = R_TOO_MANY; return -1; } } /* pack the contact_info */ if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) { LM_ERR("failed to extract contact info\n"); goto error; } if (ul.insert_ucontact( _r, &_c->uri, ci, &c, 0) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); goto error; } } else { /* Contact found */ if (e == 0) { /* it's expired */ if (_sctx->flags®_SAVE_MEMORY_FLAG) { c->flags |= FL_MEM; } else { c->flags &= ~FL_MEM; } if (ul.delete_ucontact(_r, c, 0) < 0) { rerrno = R_UL_DEL_C; LM_ERR("failed to delete contact\n"); goto error; } } else { /* do update */ /* if the contact to be updated is not valid, it will be after * update, so need to compensate the total number of contact */ if ( !VALID_CONTACT(c,act_time) ) num++; while ( _sctx->max_contacts && num>_sctx->max_contacts ) { if (_sctx->flags®_SAVE_FORCE_REG_FLAG) { /* we are overflowing the number of maximum contacts, so remove the first (oldest) one to prevent this (but not the one to be updated !) */ for( c_it=_r->contacts,c_last=NULL ; c_it ; c_it=c_it->next ) if (VALID_CONTACT(c_it, act_time) && c_it!=c) c_last=c_it; if (c_last==NULL) { LM_CRIT("BUG - overflow detected but no " "valid contacts found :( \n"); goto error; } LM_DBG("overflow on update -> removing contact " "<%.*s>\n", c_last->c.len, c_last->c.s); if (ul.delete_ucontact( _r, c_last, 0)!=0) { LM_ERR("failed to remove contact\n"); goto error; } num--; } else { LM_INFO("too many contacts for AOR <%.*s>, max=%d\n", _r->aor.len, _r->aor.s, _sctx->max_contacts); rerrno = R_TOO_MANY; return -1; } } /* pack the contact specific info */ if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) { LM_ERR("failed to pack contact specific info\n"); goto error; } if (ul.update_ucontact(_r, c, ci, 0) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto error; } } } if (tcp_check) { /* parse contact uri to see if transport is TCP */ if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) { LM_ERR("failed to parse contact <%.*s>\n", _c->uri.len, _c->uri.s); } else if (is_tcp_based_proto(uri.proto)) { if (e_max>0) { LM_WARN("multiple TCP contacts on single REGISTER\n"); } if (e>e_max) e_max = e; } } } if ( tcp_check && e_max>-1 ) { if (e_max) e_max -= act_time; trans_set_dst_attr( &_m->rcv, DST_FCNTL_SET_LIFETIME, (void*)(long)(e_max + 10) ); } return 0; error: return -1; }
int uac_reg_request_to(struct sip_msg *msg, str *src, unsigned int mode) { char ruri[MAX_URI_SIZE]; struct sip_uri puri; reg_uac_t *reg = NULL; pv_value_t val; struct action act; struct run_act_ctx ra_ctx; switch(mode) { case 0: reg = reg_ht_get_byuuid(src); break; case 1: if(reg_use_domain) { if (parse_uri(src->s, src->len, &puri)!=0) { LM_ERR("failed to parse uri\n"); return -2; } reg = reg_ht_get_byuser(&puri.user, &puri.host); } else { reg = reg_ht_get_byuser(src, NULL); } break; default: LM_ERR("unknown mode: %d\n", mode); return -1; } if(reg==NULL) { LM_DBG("no user: %.*s\n", src->len, src->s); return -1; } // Set uri ($ru) snprintf(ruri, MAX_URI_SIZE, "sip:%.*s@%.*s", reg->r_username.len, reg->r_username.s, reg->r_domain.len, reg->r_domain.s); memset(&act, 0, sizeof(act)); act.type = SET_URI_T; act.val[0].type = STRING_ST; act.val[0].u.string = ruri; init_run_actions_ctx(&ra_ctx); if (do_action(&ra_ctx, &act, msg) < 0) { LM_ERR("error while setting request uri\n"); return -1; } // Set auth_proxy ($du) if (set_dst_uri(msg, ®->auth_proxy) < 0) { LM_ERR("error while setting outbound proxy\n"); return -1; } memset(&val, 0, sizeof(pv_value_t)); val.flags |= PV_VAL_STR; // Set auth_realm val.rs = reg->realm; if(pv_set_spec_value(msg, &auth_realm_spec, 0, &val)!=0) { LM_ERR("error while setting auth_realm\n"); return -1; } // Set auth_username val.rs = reg->auth_username; if(pv_set_spec_value(msg, &auth_username_spec, 0, &val)!=0) { LM_ERR("error while setting auth_username\n"); return -1; } // Set auth_password val.rs = reg->auth_password; if(pv_set_spec_value(msg, &auth_password_spec, 0, &val)!=0) { LM_ERR("error while setting auth_password\n"); return -1; } return 1; }
/* Authorize digest credentials */ int authorize(struct sip_msg* msg, pv_elem_t* realm, int hftype) { auth_diam_result_t ret; struct hdr_field* h; auth_body_t* cred = NULL; str* uri; struct sip_uri puri; str domain; if (realm) { if (pv_printf_s(msg, realm, &domain)!=0) { LM_ERR("pv_printf_s failed\n"); return AUTH_ERROR; } } else { domain.len = 0; domain.s = 0; } /* see what is to do after a first look at the message */ ret = diam_pre_auth(msg, &domain, hftype, &h); switch(ret) { case NO_CREDENTIALS: cred = NULL; break; case DO_AUTHORIZATION: cred = (auth_body_t*)h->parsed; break; default: return ret; } if (get_uri(msg, &uri) < 0) { LM_ERR("From/To URI not found\n"); return AUTH_ERROR; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_ERR("failed to parse From/To URI\n"); return AUTH_ERROR; } // user.s = (char *)pkg_malloc(puri.user.len); // un_escape(&(puri.user), &user); /* parse the ruri, if not yet */ if(msg->parsed_uri_ok==0 && parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse the Request-URI\n"); return AUTH_ERROR; } /* preliminary check */ if(cred) { if (puri.host.len != cred->digest.realm.len) { LM_DBG("credentials realm and URI host do not match\n"); return AUTH_ERROR; } if (strncasecmp(puri.host.s, cred->digest.realm.s, puri.host.len) != 0) { LM_DBG("credentials realm and URI host do not match\n"); return AUTH_ERROR; } } if( diameter_authorize(cred?h:NULL, &msg->first_line.u.request.method, puri, msg->parsed_uri, msg->id, rb) != 1) { send_resp(msg, 500, &dia_500_err, NULL, 0); return AUTH_ERROR; } if( srv_response(msg, rb, hftype) != 1 ) return AUTH_ERROR; mark_authorized_cred(msg, h); return AUTHORIZED; }
int main(int argc, char *argv[]) { FILE *pf; char buff[BUFSIZE]; int c, i, port; unsigned int tsp; char *scheme, *user, *host, *backup; pid_t pid; struct timespec ts; int upp; #ifdef HAVE_GETOPT_LONG int option_index = 0; static struct option l_opts[] = { {"help", 0, 0, 'X'}, {"version", 0, 0, 'V'}, {"filename", 1, 0, 'f'}, {"sip-uri", 1, 0, 's'}, {"traceroute-mode", 0, 0, 'T'}, {"usrloc-mode", 0, 0, 'U'}, {"invite-mode", 0, 0, 'I'}, {"message-mode", 0, 0, 'M'}, {"contact", 1, 0, 'C'}, {"appendix-begin", 1, 0, 'b'}, {"appendix-end", 1, 0, 'e'}, {"sleep", 1, 0, 'o'}, {"expires", 1, 0, 'x'}, {"remove-bindings", 1, 0, 'z'}, {"flood-mode", 0, 0, 'F'}, {"random-mode", 0, 0, 'R'}, {"trash-chars", 1, 0, 't'}, {"local-port", 1, 0, 'l'}, {"remote-port", 1, 0, 'r'}, {"outbound-proxy", 1, 0, 'p'}, {"hostname", 1, 0, 'H'}, {"max-fowards", 1, 0, 'm'}, {"numeric", 0, 0, 'n'}, {"no-via", 0, 0, 'i'}, {"password", 1, 0, 'a'}, {"ignore-redirects", 0, 0, 'd'}, {"verbose", 0, 0, 'v'}, {"extract-ip", 0, 0, 'w'}, {"replace-string", 0, 0, 'g'}, {"replace", 0, 0, 'G'}, {"nagios-code", 0, 0, 'N'}, {"nagios-warn", 1, 0, 'W'}, {"search", 1, 0, 'q'}, {"message-body", 1, 0, 'B'}, {"disposition", 1, 0, 'O'}, {"processes", 1, 0, 'P'}, {"auth-username", 1, 0, 'u'}, {"no-crlf", 0, 0, 'L'}, {"timing", 0, 0, 'A'}, {"symmetric", 0, 0, 'S'}, {"from", 1, 0, 'c'}, {"timeout-factor", 1, 0, 'D'}, {"transport", 1, 0, 'E'}, {0, 0, 0, 0} }; #endif /* some initialisation to be shure */ file_b=uri_b=trace=lport=usrloc=flood=verbose=randtrash=trashchar = 0; warning_ext=rand_rem=nonce_count=replace_b=invite=message = 0; sleep_ms=empty_contact=nagios_warn=timing=outbound_proxy=symmetric = 0; namebeg=nameend=maxforw= -1; numeric=via_ins=redirects=fix_crlf=processes = 1; username=password=replace_str=hostname=contact_uri=mes_body = NULL; con_dis=auth_username=from_uri = NULL; scheme = user = host = backup = req = rep = rec = NULL; re = NULL; address= 0; transport=tsp = 0; rport = port = 0; expires_t = USRLOC_EXP_DEF; inv_final = 64 * SIP_T1; memset(buff, 0, BUFSIZE); memset(fqdn, 0, FQDN_SIZE); if (argc==1) { print_help(); } /* lots of command line switches to handle*/ #ifdef HAVE_GETOPT_LONG while ((c=getopt_long(argc, argv, "a:Ab:B:c:C:dD:e:E:f:Fg:GhH:iIl:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:Xz:", l_opts, &option_index)) != EOF){ #else while ((c=getopt(argc, argv, "a:Ab:B:c:C:dD:e:E:f:Fg:GhH:iIl:Lm:MnNo:O:p:P:q:r:Rs:St:Tu:UvVwW:x:z:")) != EOF){ #endif switch(c){ case 'a': password=str_alloc(strlen(optarg) + 1); strncpy(password, optarg, strlen(optarg)); break; case 'A': timing=1; break; case 'b': namebeg=str_to_int(optarg); break; case 'B': mes_body=str_alloc(strlen(optarg) + 1); strncpy(mes_body, optarg, strlen(optarg)); break; case 'c': backup=str_alloc(strlen(optarg)+1); strncpy(backup, optarg, strlen(optarg)); parse_uri(backup, &scheme, &user, &host, &port); if (scheme == NULL) { fprintf(stderr, "error: missing scheme in From URI\n"); exit_code(2); } else if (user == NULL) { fprintf(stderr, "error: missing username in From URI\n"); exit_code(2); } else if (host == NULL) { fprintf(stderr, "error: missing host in From URI\n"); exit_code(2); } else { from_uri=str_alloc(strlen(optarg)+1); strncpy(from_uri, optarg, strlen(optarg)); } free(backup); break; case 'C': if ((strlen(optarg) == 5 && STRNCASECMP(optarg, "empty", 5) == 0) || (strlen(optarg) == 4 && STRNCASECMP(optarg, "none", 4) == 0)) { empty_contact = 1; } else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "*", 1) == 0) { contact_uri=str_alloc(strlen(optarg)+1); strncpy(contact_uri, optarg, strlen(optarg)); } else { backup=str_alloc(strlen(optarg)+1); strncpy(backup, optarg, strlen(optarg)); parse_uri(backup, &scheme, &user, &host, &port); if (scheme == NULL) { fprintf(stderr, "error: REGISTER Contact uri doesn't not contain " "sip:, sips:, *, or is not empty\n"); exit_code(2); } else if (user == NULL) { fprintf(stderr, "error: missing username in Contact uri\n"); exit_code(2); } else if (host == NULL) { fprintf(stderr, "error: missing host in Contact uri\n"); exit_code(2); } else { contact_uri=str_alloc(strlen(optarg)+1); strncpy(contact_uri, optarg, strlen(optarg)); } free(backup); } break; case 'd': redirects=0; break; case 'D': inv_final = str_to_int(optarg) * SIP_T1; break; case 'e': nameend=str_to_int(optarg); break; case 'E': if (strlen(optarg) == 3 && STRNCASECMP(optarg, "udp", 3) == 0) { transport = SIP_UDP_TRANSPORT; } else if (strlen(optarg) == 3 && STRNCASECMP(optarg, "tcp", 3) == 0) { transport = SIP_TCP_TRANSPORT; } else if (strlen(optarg) == 3 && STRNCASECMP(optarg, "tls", 3) == 0) { fprintf(stderr, "error: TLS is not supported yet, supported values: udp, tcp\n"); exit_code(2); transport = SIP_TLS_TRANSPORT; } else { fprintf(stderr, "error: unsupported transport '%s', supported values: udp, tcp\n", optarg); exit_code(2); } break; case 'F': flood=1; break; case 'f': if (strlen(optarg) != 1 && STRNCASECMP(optarg, "-", 1) != 0) { /* file is opened in binary mode so that the cr-lf is preserved */ pf = fopen(optarg, "rb"); if (!pf){ fprintf(stderr, "error: unable to open the file '%s'.\n", optarg); exit_code(2); } if (fread(buff, 1, sizeof(buff), pf) >= sizeof(buff)){ fprintf(stderr, "error:the file is too big. try files of less " "than %i bytes.\n", BUFSIZE); fprintf(stderr, " or recompile the program with bigger " "BUFSIZE defined.\n"); exit_code(2); } fclose(pf); } else if (strlen(optarg) == 1 && STRNCASECMP(optarg, "-", 1) == 0) { if (read_stdin(&buff[0], sizeof(buff)) == 0) { exit_code(0); } } else { fprintf(stderr, "error: unable to handle input file name: %s\n", optarg); exit_code(2); } file_b=1; break; case 'g': replace_str=optarg; break; case 'G': replace_b=1; break; case 'h': print_help(); break; case 'H': hostname=optarg; break; case 'i': via_ins=0; break; case 'I': invite=1; break; case 'l': lport=str_to_int(optarg); break; case 'L': fix_crlf=0; break; case 'm': maxforw=str_to_int(optarg); break; case 'M': message=1; break; case 'n': numeric = 0; break; case 'N': exit_mode=EM_NAGIOS; break; case 'o': sleep_ms = 0; if (strlen(optarg) == 4 && STRNCASECMP(optarg, "rand", 4) == 0) { sleep_ms = -2; } else { sleep_ms = str_to_int(optarg); } break; case 'O': con_dis=str_alloc(strlen(optarg) + 1); strncpy(con_dis, optarg, strlen(optarg)); break; case 'p': parse_uri(optarg, &scheme, &user, &host, &rport); if (host == NULL) { fprintf(stderr, "error: missing in host in outbound proxy\n"); exit_code(2); } if (is_ip(host)) { address = getaddress(host); if (transport == 0) transport = SIP_UDP_TRANSPORT; } else { if (!rport) { address = getsrvadr(host, &rport, &tsp); if (tsp != 0) transport = tsp; } if (!address) { address = getaddress(host); if (address && verbose > 1) printf("using A record: %s\n", host); } if (!address){ fprintf(stderr, "error:unable to determine the outbound proxy " "address\n"); exit_code(2); } } outbound_proxy=1; break; case 'P': processes=str_to_int(optarg); break; case 'q': if (re) { /* previously allocated -- free */ regfree(re); } else { /* never tried -- allocate */ re=malloc(sizeof(regex_t)); }; if (!re) { fprintf(stderr, "Error: can't allocate RE\n"); exit_code(2); }; if (regcomp(re, optarg, REG_EXTENDED|REG_ICASE|REG_NEWLINE )!=0) { fprintf(stderr, "Error: compiling RE: %s\n", optarg ); exit_code(2); }; break; case 'r': port = 0; port=str_to_int(optarg); if (rport) { fprintf(stderr, "warning: you are overwritting the destination port with the r argument\n"); } rport = port; break; case 'R': randtrash=1; break; case 's': parse_uri(optarg, &scheme, &user, &host, &port); if (scheme == NULL) { fprintf(stderr, "error: missing scheme in sip uri\n"); exit_code(2); } if (strlen(optarg) == 4 && STRNCASECMP(optarg,"sips",4) == 0){ fprintf(stderr, "error: sips is not supported yet\n"); exit_code(2); } else if (strlen(optarg) != 3 || STRNCASECMP(optarg,"sip",3) != 0){ fprintf(stderr, "error: scheme of sip uri has to be sip\n"); exit_code(2); } if (user != NULL) { username = user; } if (host != NULL) { domainname = host; } else { fprintf(stderr, "error: missing hostname in sip uri\n"); exit_code(2); } if (port && !rport) { rport = port; } if (is_ip(domainname)) { address = getaddress(domainname); if (transport == 0) transport = SIP_UDP_TRANSPORT; } else { if (!rport && !address) { address = getsrvadr(domainname, &rport, &tsp); if (tsp != 0) transport = tsp; } if (!address) { address = getaddress(domainname); if (address && verbose > 1) printf("using A record: %s\n", domainname); } if (!address){ fprintf(stderr, "error:unable to determine the IP address for: %s\n", domainname); exit_code(2); } } if (port != 0) { backup = str_alloc(strlen(domainname)+1+6); snprintf(backup, strlen(domainname)+6, "%s:%i", domainname, port); domainname = backup; } uri_b=1; break; case 'S': fprintf(stderr, "warning: symmetric does not work with a-symmetric servers\n"); symmetric=1; break; case 't': trashchar=str_to_int(optarg); break; case 'T': trace=1; break; case 'U': usrloc=1; break; case 'u': auth_username=str_alloc(strlen(optarg) + 1); strncpy(auth_username, optarg, strlen(optarg)); break; case 'v': verbose++; break; case 'V': printf("sipsak %s by Nils Ohlmeier\n Copyright (C) 2002-2004" " FhG Fokus\n Copyright (C) 2004-2005 Nils Ohlmeier\n", SIPSAK_VERSION); printf(" compiled with DEFAULT_TIMEOUT=%i, FQDN_SIZE=%i", DEFAULT_TIMEOUT, FQDN_SIZE); #ifdef RAW_SUPPORT printf(", RAW_SUPPORT"); #endif #ifdef HAVE_GETOPT_LONG printf(", LONG_OPTS"); #endif #ifdef HAVE_GNUTLS printf(", GNUTLS_MD5"); #else # ifdef HAVE_FULL_OPENSSL printf(", OPENSSL_MD5"); # else printf(", INTERNAL_MD5"); # endif #endif #ifdef HAVE_CARES_H printf(", SRV_SUPPORT(ARES)"); #else # ifdef HAVE_RULI_H printf(", SRV_SUPPORT(RULI)"); # endif #endif #ifdef HAVE_STRCASESTR printf(", STR_CASE_INSENSITIVE"); #endif #ifdef HAVE_STRNCASECMP printf(", CMP_CASE_INSENSITIVE"); #endif printf("\n"); exit_code(0); break; case 'w': warning_ext=1; break; case 'W': nagios_warn = str_to_int(optarg); break; case 'x': expires_t=str_to_int(optarg); break; #ifdef HAVE_GETOPT_LONG case 'X': print_long_help(); break; #endif case 'z': rand_rem=str_to_int(optarg); if (rand_rem < 0 || rand_rem > 100) { fprintf(stderr, "error: z option must between 0 and 100\n"); exit_code(2); } break; default: fprintf(stderr, "error: unknown parameter %c\n", c); exit_code(2); break; } } if (rport == 0) { rport = 5060; } if (rport > 65535 || rport <= 0) { fprintf(stderr, "error: invalid remote port: %i\n", rport); exit_code(2); } if (transport == 0) { transport = SIP_UDP_TRANSPORT; } /* replace LF with CRLF if we read from a file */ if ((file_b) && (fix_crlf)) { insert_cr(buff); } /* lots of conditions to check */ if (trace) { if (usrloc || flood || randtrash) { fprintf(stderr, "error: trace can't be combined with usrloc, random or " "flood\n"); exit_code(2); } if (!uri_b) { fprintf(stderr, "error: for trace mode a SIPURI is realy needed\n"); exit_code(2); } if (file_b) { fprintf(stderr, "warning: file will be ignored for tracing."); } if (!username) { fprintf(stderr, "error: for trace mode without a file the SIPURI have to " "contain a username\n"); exit_code(2); } if (!via_ins){ fprintf(stderr, "warning: Via-Line is needed for tracing. Ignoring -i\n"); via_ins=1; } if (!warning_ext) { fprintf(stderr, "warning: IP extract from warning activated to be more " "informational\n"); warning_ext=1; } if (maxforw==-1) maxforw=255; } else if (usrloc || invite || message) { if (trace || flood || randtrash) { fprintf(stderr, "error: usrloc can't be combined with trace, random or " "flood\n"); exit_code(2); } if (!username || !uri_b) { fprintf(stderr, "error: for the USRLOC mode you have to give a SIPURI with " "a username\n at least\n"); exit_code(2); } if (namebeg>0 && nameend==-1) { fprintf(stderr, "error: if a starting numbers is given also an ending " "number have to be specified\n"); exit_code(2); } if (invite && message) { fprintf(stderr, "error: invite and message tests are XOR\n"); exit_code(2); } if (!usrloc && invite && !lport) { fprintf(stderr, "warning: Do NOT use the usrloc invite mode without " "registering sipsak before.\n See man page for " "details.\n"); exit_code(2); } if (contact_uri!=NULL) { if (invite || message) { fprintf(stderr, "error: Contact uri is not support for invites or " "messages\n"); exit_code(2); } if (nameend!=-1 || namebeg!=-1) { fprintf(stderr, "warning: ignoring starting or ending number if Contact" " is given\n"); nameend=namebeg=0; } if (rand_rem) { fprintf(stderr, "warning: ignoring -z option when Contact is given\n"); rand_rem=0; } } if (via_ins) { fprintf(stderr, "warning: ignoring -i option when in usrloc mode\n"); via_ins=0; } if (nameend==-1) nameend=0; if (namebeg==-1) namebeg=0; } else if (flood) { if (trace || usrloc || randtrash) { fprintf(stderr, "error: flood can't be combined with trace, random or " "usrloc\n"); exit_code(2); } if (!uri_b) { fprintf(stderr, "error: we need at least a sip uri for flood\n"); exit_code(2); } if (redirects) { fprintf(stderr, "warning: redirects are not expected in flood. " "disableing\n"); redirects=0; } } else if (randtrash) { if (trace || usrloc || flood) { fprintf(stderr, "error: random can't be combined with trace, flood or " "usrloc\n"); exit_code(2); } if (!uri_b) { fprintf(stderr, "error: need at least a sip uri for random\n"); exit_code(2); } if (redirects) { fprintf(stderr, "warning: redirects are not expected in random. " "disableing\n"); redirects=0; } if (verbose) { fprintf(stderr, "warning: random characters may destroy your terminal " "output\n"); } } else if (mes_body) { if (!message) { fprintf(stderr, "warning: to send a message mode (-M) is required. activating\n"); message=1; } if (!uri_b) { fprintf(stderr, "error: need at least a sip uri to send a meesage\n"); exit_code(2); } if (nameend==-1) nameend=0; if (namebeg==-1) namebeg=0; } else { if (!uri_b) { fprintf(stderr, "error: a spi uri is needed at least\n"); exit_code(2); } } switch (transport) { case SIP_TLS_TRANSPORT: transport_str = TRANSPORT_TLS_STR; break; case SIP_TCP_TRANSPORT: transport_str = TRANSPORT_TCP_STR; break; case SIP_UDP_TRANSPORT: transport_str = TRANSPORT_UDP_STR; break; default: fprintf(stderr, "unknown transport: %i\n", transport); exit_code(2); } /* determine our hostname */ get_fqdn(); /* this is not a cryptographic random number generator, but hey this is only a test-tool => should be satisfying*/ srand(time(0) ^ getpid()); if (processes > 1) { if (signal(SIGCHLD , sigchld_handler) == SIG_ERR ) { fprintf(stderr, "error: Could not install SIGCHLD handler\n"); exit_code(2); } } for(i = 0; i < processes - 1; i++) { if ((pid = fork()) < 0) { fprintf(stderr, "error: Cannot fork\n"); exit_code(2); } if (pid == 0){ /* child */ upp = (nameend - namebeg + 1) / processes; namebeg = namebeg + upp * i; nameend = namebeg + upp; shoot(&buff[0], sizeof(buff)); } else { if (lport) { lport++; } } /* Delay execution of children so that the * time of the first transmission gets spread over * the retransmission interval evenly */ ts.tv_sec = 0; ts.tv_nsec = (float)DEFAULT_TIMEOUT / (float)processes * (float)1000 * (float)1000; nanosleep(&ts, 0); } /* here we go...*/ if (processes > 1) { upp = (nameend - namebeg + 1) / processes; namebeg = namebeg + upp * i; nameend = namebeg + upp; } shoot(&buff[0], sizeof(buff)); /* normaly we won't come back here, but to satisfy the compiler */ return 0; }
/*! \brief * Extract Address of Record * In case of public GRUUs, also populates sip_instance * In case of temp GRUUs, also populates call_id */ int extract_aor(str* _uri, str* _a,str *sip_instance,str *call_id) { static char aor_buf[MAX_AOR_LEN]; memset(aor_buf, 0, MAX_AOR_LEN); str tmp; struct sip_uri puri; int user_len,tgruu_len,dec_size,i; str *magic; if (parse_uri(_uri->s, _uri->len, &puri) < 0) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } /* if have ;gr param and func caller is interested in * potentially extracting the sip instance */ if ((puri.gr.s && puri.gr.len) && sip_instance) { LM_DBG("has gruu\n"); /* ;gr param detected */ if (memcmp(puri.user.s,TEMP_GRUU,TEMP_GRUU_SIZE) == 0) { LM_DBG("temp gruu\n"); /* temp GRUU, decode and extract aor, sip_instance * and call_id */ tgruu_len = puri.user.len - TEMP_GRUU_SIZE; memcpy(tgruu_dec,puri.user.s+TEMP_GRUU_SIZE,tgruu_len); if (gruu_secret.s != NULL) magic = &gruu_secret; else magic = &default_gruu_secret; dec_size = base64decode((unsigned char *)tgruu_dec, (unsigned char *)tgruu_dec,tgruu_len); for (i=0;i<tgruu_len;i++) tgruu_dec[i] ^= magic->s[i%magic->len]; LM_DBG("decoded [%.*s]\n",dec_size,tgruu_dec); /* extract aor - skip tgruu generation time at * the beggining */ _a->s = (char *)memchr(tgruu_dec,' ',dec_size) + 1; if (_a->s == NULL) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } _a->len = (char *)memchr(_a->s,' ',dec_size - (_a->s-tgruu_dec)) - _a->s; if (_a->len < 0) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } sip_instance->s = _a->s+_a->len+1; /* skip ' ' */ if (sip_instance->s >= tgruu_dec + dec_size) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } sip_instance->len = (char *)memchr(sip_instance->s,' ', dec_size-(sip_instance->s-tgruu_dec)) - sip_instance->s; if (sip_instance->len < 0) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } call_id->s = sip_instance->s + sip_instance->len + 1; if (call_id->s >= tgruu_dec + dec_size) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } call_id->len = (tgruu_dec+dec_size) - call_id->s -1; LM_DBG("extracted aor [%.*s] and instance [%.*s] and callid [%.*s]\n",_a->len,_a->s, sip_instance->len,sip_instance->s,call_id->len,call_id->s); /* skip checks - done at save() */ return 0; } else { LM_DBG("public gruu\n"); *sip_instance = puri.gr_val; } } if ( (puri.user.len + puri.host.len + 1) > MAX_AOR_LEN || puri.user.len > USERNAME_MAX_SIZE || puri.host.len > DOMAIN_MAX_SIZE ) { rerrno = R_AOR_LEN; LM_ERR("Address Of Record too long\n"); return -2; } _a->s = aor_buf; _a->len = puri.user.len; if (un_escape(&puri.user, _a) < 0) { rerrno = R_UNESCAPE; LM_ERR("failed to unescape username\n"); return -3; } user_len = _a->len; if (reg_use_domain) { if (user_len) aor_buf[_a->len++] = '@'; /* strip prefix (if defined) */ if (realm_prefix.len && realm_prefix.len<puri.host.len && (memcmp(realm_prefix.s, puri.host.s, realm_prefix.len)==0) ) { memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len, puri.host.len - realm_prefix.len); _a->len += puri.host.len - realm_prefix.len; } else { memcpy(aor_buf + _a->len, puri.host.s, puri.host.len); _a->len += puri.host.len; } } if (case_sensitive && user_len) { tmp.s = _a->s + user_len + 1; tmp.len = _a->s + _a->len - tmp.s; strlower(&tmp); } else { strlower(_a); } return 0; }
int zmq::socket_base_t::connect (const char *addr_) { ENTER_MUTEX (); if (unlikely (ctx_terminated)) { errno = ETERM; EXIT_MUTEX (); return -1; } // Process pending commands, if any. int rc = process_commands (0, false); if (unlikely (rc != 0)) { EXIT_MUTEX (); return -1; } // Parse addr_ string. std::string protocol; std::string address; if (parse_uri (addr_, protocol, address) || check_protocol (protocol)) { EXIT_MUTEX (); return -1; } if (protocol == "inproc") { // TODO: inproc connect is specific with respect to creating pipes // as there's no 'reconnect' functionality implemented. Once that // is in place we should follow generic pipe creation algorithm. // Find the peer endpoint. endpoint_t peer = find_endpoint (addr_); // The total HWM for an inproc connection should be the sum of // the binder's HWM and the connector's HWM. int sndhwm = 0; if (peer.socket == NULL) sndhwm = options.sndhwm; else if (options.sndhwm != 0 && peer.options.rcvhwm != 0) sndhwm = options.sndhwm + peer.options.rcvhwm; int rcvhwm = 0; if (peer.socket == NULL) rcvhwm = options.rcvhwm; else if (options.rcvhwm != 0 && peer.options.sndhwm != 0) rcvhwm = options.rcvhwm + peer.options.sndhwm; // Create a bi-directional pipe to connect the peers. object_t *parents [2] = {this, peer.socket == NULL ? this : peer.socket}; pipe_t *new_pipes [2] = {NULL, NULL}; bool conflate = options.conflate && (options.type == ZMQ_DEALER || options.type == ZMQ_PULL || options.type == ZMQ_PUSH || options.type == ZMQ_PUB || options.type == ZMQ_SUB); int hwms [2] = {conflate? -1 : sndhwm, conflate? -1 : rcvhwm}; bool conflates [2] = {conflate, conflate}; rc = pipepair (parents, new_pipes, hwms, conflates); if (!conflate) { new_pipes[0]->set_hwms_boost(peer.options.sndhwm, peer.options.rcvhwm); new_pipes[1]->set_hwms_boost(options.sndhwm, options.rcvhwm); } errno_assert (rc == 0); if (!peer.socket) { // The peer doesn't exist yet so we don't know whether // to send the identity message or not. To resolve this, // we always send our identity and drop it later if // the peer doesn't expect it. msg_t id; rc = id.init_size (options.identity_size); errno_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [0]->write (&id); zmq_assert (written); new_pipes [0]->flush (); const endpoint_t endpoint = {this, options}; pend_connection (std::string (addr_), endpoint, new_pipes); } else { // If required, send the identity of the local socket to the peer. if (peer.options.recv_identity) { msg_t id; rc = id.init_size (options.identity_size); errno_assert (rc == 0); memcpy (id.data (), options.identity, options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [0]->write (&id); zmq_assert (written); new_pipes [0]->flush (); } // If required, send the identity of the peer to the local socket. if (options.recv_identity) { msg_t id; rc = id.init_size (peer.options.identity_size); errno_assert (rc == 0); memcpy (id.data (), peer.options.identity, peer.options.identity_size); id.set_flags (msg_t::identity); bool written = new_pipes [1]->write (&id); zmq_assert (written); new_pipes [1]->flush (); } // Attach remote end of the pipe to the peer socket. Note that peer's // seqnum was incremented in find_endpoint function. We don't need it // increased here. send_bind (peer.socket, new_pipes [1], false); } // Attach local end of the pipe to this socket object. attach_pipe (new_pipes [0]); // Save last endpoint URI last_endpoint.assign (addr_); // remember inproc connections for disconnect inprocs.insert (inprocs_t::value_type (std::string (addr_), new_pipes [0])); options.connected = true; EXIT_MUTEX (); return 0; } bool is_single_connect = (options.type == ZMQ_DEALER || options.type == ZMQ_SUB || options.type == ZMQ_REQ); if (unlikely (is_single_connect)) { const endpoints_t::iterator it = endpoints.find (addr_); if (it != endpoints.end ()) { // There is no valid use for multiple connects for SUB-PUB nor // DEALER-ROUTER nor REQ-REP. Multiple connects produces // nonsensical results. EXIT_MUTEX (); return 0; } } // Choose the I/O thread to run the session in. io_thread_t *io_thread = choose_io_thread (options.affinity); if (!io_thread) { errno = EMTHREAD; EXIT_MUTEX (); return -1; } address_t *paddr = new (std::nothrow) address_t (protocol, address, this->get_ctx ()); alloc_assert (paddr); // Resolve address (if needed by the protocol) if (protocol == "tcp") { // Do some basic sanity checks on tcp:// address syntax // - hostname starts with digit or letter, with embedded '-' or '.' // - IPv6 address may contain hex chars and colons. // - IPv6 link local address may contain % followed by interface name / zone_id // (Reference: https://tools.ietf.org/html/rfc4007) // - IPv4 address may contain decimal digits and dots. // - Address must end in ":port" where port is *, or numeric // - Address may contain two parts separated by ':' // Following code is quick and dirty check to catch obvious errors, // without trying to be fully accurate. const char *check = address.c_str (); if (isalnum (*check) || isxdigit (*check) || *check == '[') { check++; while (isalnum (*check) || isxdigit (*check) || *check == '.' || *check == '-' || *check == ':' || *check == '%' || *check == ';' || *check == ']' || *check == '_' ) { check++; } } // Assume the worst, now look for success rc = -1; // Did we reach the end of the address safely? if (*check == 0) { // Do we have a valid port string? (cannot be '*' in connect check = strrchr (address.c_str (), ':'); if (check) { check++; if (*check && (isdigit (*check))) rc = 0; // Valid } } if (rc == -1) { errno = EINVAL; LIBZMQ_DELETE(paddr); EXIT_MUTEX (); return -1; } // Defer resolution until a socket is opened paddr->resolved.tcp_addr = NULL; } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS else if (protocol == "ipc") { paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t (); alloc_assert (paddr->resolved.ipc_addr); int rc = paddr->resolved.ipc_addr->resolve (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(paddr); EXIT_MUTEX (); return -1; } } #endif if (protocol == "udp") { paddr->resolved.udp_addr = new (std::nothrow) udp_address_t (); alloc_assert (paddr->resolved.udp_addr); rc = paddr->resolved.udp_addr->resolve (address.c_str()); if (rc != 0) { LIBZMQ_DELETE(paddr); EXIT_MUTEX (); return -1; } } // TBD - Should we check address for ZMQ_HAVE_NORM??? #ifdef ZMQ_HAVE_OPENPGM if (protocol == "pgm" || protocol == "epgm") { struct pgm_addrinfo_t *res = NULL; uint16_t port_number = 0; int rc = pgm_socket_t::init_address(address.c_str(), &res, &port_number); if (res != NULL) pgm_freeaddrinfo (res); if (rc != 0 || port_number == 0) { EXIT_MUTEX (); return -1; } } #endif #if defined ZMQ_HAVE_TIPC else if (protocol == "tipc") { paddr->resolved.tipc_addr = new (std::nothrow) tipc_address_t (); alloc_assert (paddr->resolved.tipc_addr); int rc = paddr->resolved.tipc_addr->resolve (address.c_str()); if (rc != 0) { LIBZMQ_DELETE(paddr); EXIT_MUTEX (); return -1; } } #endif #if defined ZMQ_HAVE_VMCI else if (protocol == "vmci") { paddr->resolved.vmci_addr = new (std::nothrow) vmci_address_t (this->get_ctx ()); alloc_assert (paddr->resolved.vmci_addr); int rc = paddr->resolved.vmci_addr->resolve (address.c_str ()); if (rc != 0) { LIBZMQ_DELETE(paddr); EXIT_MUTEX (); return -1; } } #endif // Create session. session_base_t *session = session_base_t::create (io_thread, true, this, options, paddr); errno_assert (session); // PGM does not support subscription forwarding; ask for all data to be // sent to this pipe. (same for NORM, currently?) bool subscribe_to_all = protocol == "pgm" || protocol == "epgm" || protocol == "norm" || protocol == "udp"; pipe_t *newpipe = NULL; if (options.immediate != 1 || subscribe_to_all) { // Create a bi-directional pipe. object_t *parents [2] = {this, session}; pipe_t *new_pipes [2] = {NULL, NULL}; bool conflate = options.conflate && (options.type == ZMQ_DEALER || options.type == ZMQ_PULL || options.type == ZMQ_PUSH || options.type == ZMQ_PUB || options.type == ZMQ_SUB); int hwms [2] = {conflate? -1 : options.sndhwm, conflate? -1 : options.rcvhwm}; bool conflates [2] = {conflate, conflate}; rc = pipepair (parents, new_pipes, hwms, conflates); errno_assert (rc == 0); // Attach local end of the pipe to the socket object. attach_pipe (new_pipes [0], subscribe_to_all); newpipe = new_pipes [0]; // Attach remote end of the pipe to the session object later on. session->attach_pipe (new_pipes [1]); } // Save last endpoint URI paddr->to_string (last_endpoint); add_endpoint (addr_, (own_t *) session, newpipe); EXIT_MUTEX (); return 0; }
/* * search for P-CSCF contact in usrloc * @udomain_t* _d - domain to search in * @str* _contact - contact to search for - should be a SIP URI * @struct pontact** _c - contact to return to if found (null if not found) * @return 0 if found <>0 if not */ int get_pcontact(udomain_t* _d, str* _contact, str* _received_host, int received_port, struct pcontact** _c) { unsigned int sl, i, aorhash; struct pcontact* c; ppublic_t* impu; struct sip_uri needle_uri, impu_uri; int port_match = 0; str alias_host = {0, 0}; struct sip_uri contact_uri; if (parse_uri(_contact->s, _contact->len, &needle_uri) != 0 ) { LM_ERR("failed to parse search URI [%.*s]\n", _contact->len, _contact->s); return 1; } LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n", _contact->len, _contact->s); /* search in cache */ aorhash = get_aor_hash(_d, _contact, _received_host, received_port); sl = aorhash & (_d->size - 1); c = _d->table[sl].first; for (i = 0; i < _d->table[sl].n; i++) { if ((c->aorhash == aorhash) && (c->aor.len == _contact->len) && !memcmp(c->aor.s, _contact->s, _contact->len)) { *_c = c; return 0; } if(match_contact_host_port) { LM_DBG("Comparing needle user@host:port [%.*s@%.*s:%d] and contact_user@contact_host:port [%.*s@%.*s:%d]\n", needle_uri.user.len, needle_uri.user.s, needle_uri.host.len, needle_uri.host.s, needle_uri.port_no, c->contact_user.len, c->contact_user.s, c->contact_host.len, c->contact_host.s, c->contact_port); if((needle_uri.user.len == c->contact_user.len && (memcmp(needle_uri.user.s, c->contact_user.s, needle_uri.user.len) ==0)) && (needle_uri.host.len == c->contact_host.len && (memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) ==0)) && (needle_uri.port_no == c->contact_port)) { LM_DBG("Match!!\n"); *_c = c; return 0; } } LM_DBG("Searching for [%.*s] and comparing to [%.*s]\n", _contact->len, _contact->s, c->aor.len, c->aor.s); /* hosts HAVE to match */ if (lookup_check_received && ((needle_uri.host.len != c->received_host.len) || (memcmp(needle_uri.host.s, c->received_host.s, needle_uri.host.len)!=0))) { //can't possibly match LM_DBG("Lookup failed for [%.*s <=> %.*s]\n", needle_uri.host.len, needle_uri.host.s, c->received_host.len, c->received_host.s); c = c->next; continue; } /* one of the ports must match, either the initial registered port, the received port, or one if the security ports (server) */ if ((needle_uri.port_no != c->contact_port) && (needle_uri.port_no != c->received_port)) { //check security ports if (c->security) { switch (c->security->type) { case SECURITY_IPSEC: { ipsec_t* ipsec = c->security->data.ipsec; if (ipsec) { LM_DBG("security server port is %d\n", ipsec->port_us); LM_DBG("security client port is %d\n", ipsec->port_uc); if (ipsec->port_us == needle_uri.port_no) { LM_DBG("security port mathes contact\n"); port_match = 1; } } break; } case SECURITY_TLS: case SECURITY_NONE: LM_WARN("not implemented\n"); break; } } if (!port_match && c->security_temp) { switch (c->security_temp->type) { case SECURITY_IPSEC: { ipsec_t* ipsec = c->security_temp->data.ipsec; if (ipsec) { LM_DBG("temp security server port is %d\n", ipsec->port_us); LM_DBG("temp security client port is %d\n", ipsec->port_uc); if (ipsec->port_us == needle_uri.port_no) { LM_DBG("temp security port mathes contact\n"); port_match = 1; } } break; } case SECURITY_TLS: case SECURITY_NONE: LM_WARN("not implemented\n"); break; } } } else { port_match = 1; } if (!port_match){ LM_DBG("Port don't match: %d (contact) %d (received) != %d!\n", c->contact_port, c->received_port, needle_uri.port_no); c = c->next; continue; } /* user parts must match (if not wildcarded) with either primary contact OR with any userpart in the implicit set (associated URIs).. */ if((needle_uri.user.len == c->contact_user.len) && (memcmp(needle_uri.user.s, c->contact_user.s,needle_uri.user.len) == 0)) { LM_DBG("Needle user part matches contact user part therefore this is a match\n"); *_c = c; return 0; } else if ((needle_uri.user.len == 1) && (memcmp(needle_uri.user.s, "*", 1) == 0)) { /*wild card*/ LM_DBG("This a wild card user part - we must check if hosts match or needle host matches alias\n"); if(memcmp(needle_uri.host.s, c->contact_host.s, needle_uri.host.len) == 0) { LM_DBG("Needle host matches contact host therefore this is a match\n"); *_c = c; return 0; } else if ((parse_uri(c->aor.s, c->aor.len, &contact_uri) == 0) && ((get_alias_host_from_contact(&contact_uri.params, &alias_host)) == 0) && (memcmp(needle_uri.host.s, alias_host.s, alias_host.len) == 0)) { LM_DBG("Needle host matches contact alias therefore this is a match\n"); *_c = c; return 0; } } /* check impus user parts */ impu = c->head; while (impu) { if (parse_uri(impu->public_identity.s, impu->public_identity.len, &impu_uri) != 0) { LM_ERR("failed to parse IMPU URI [%.*s]...continuing\n", impu->public_identity.len, impu->public_identity.s); impu = impu->next; continue; } LM_DBG("comparing first %d chars of impu [%.*s] for contact userpart [%.*s]\n", needle_uri.user.len, impu->public_identity.len, impu->public_identity.s, needle_uri.user.len, needle_uri.user.s); if (needle_uri.user.len == impu_uri.user.len && (memcmp(needle_uri.user.s, impu_uri.user.s, impu_uri.user.len)==0)) { *_c = c; return 0; } impu = impu->next; } c = c->next; } return 1; /* Nothing found */ }
/* * handle HTTP request/response transaction of a thread * clinet-----(request)----->server * <------(data)------- */ void *doit(void *connfd) { int fd = *(int *)connfd; int fd_server; /* detach thread */ Pthread_detach(pthread_self()); rio_t rio; char buf[MAXLINE], object_buf[MAX_OBJECT_SIZE]; char method[MAXLINE], uri[MAXLINE], version[MAXLINE]; /* uri info */ char host[MAXLINE]; int port; char filename[MAXLINE]; /* Read request line and headers */ Rio_readinitb(&rio, fd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); /* request method is not GET */ if (strcmp(method, "GET")) { printerror(fd, method, "501", "Not Implemented", "tianqiw's proxy does not implement this method"); Close(fd); return NULL; } /* request method is GET * look for the object in cache */ cache_block *block = cache_match(cache_ptr, uri); if (block != NULL) { /* cache hit */ Rio_writen(fd, block->object, block->object_size); } else { /* cache miss */ parse_uri(uri, host, &port, filename); /* construct the request header */ char request_buf[MAXLINE]; requestHdr(&rio, request_buf, host, filename); /* send request to server */ if ((fd_server = open_clientfd_r(host, port)) < 0) { /* server connection error */ char longmsg[MAXBUF]; sprintf(longmsg, "Cannot open connection to server at <%s, %d>", host, port); printerror(fd, "Connection Failed", "404", "Not Found", longmsg); Close(fd); return NULL; } /* reset rio for server use */ memset(&rio, 0, sizeof(rio_t)); Rio_readinitb(&rio, fd_server); Rio_writen(fd_server, request_buf, strlen(request_buf)); /* get data from server and send to client */ size_t object_size = 0; size_t buflen; int is_exceed = 0; while ((buflen = Rio_readlineb(&rio, buf, MAXLINE))) { Rio_writen(fd, buf, buflen); /* size of the buffer exceeds the max object size * discard the buffer */ if ((object_size + buflen) > MAX_OBJECT_SIZE) { is_exceed = 1; } else { memcpy(object_buf + object_size, buf, buflen); object_size += buflen; } } /* if not exceed the max object size, insert to cache */ if (!is_exceed) { cache_insert(cache_ptr, uri, object_buf, object_size); } /* clear the buffer */ Close(fd_server); } Close(fd); return NULL; }
/* it checks if a user is member of a group */ int diameter_is_user_in(struct sip_msg* _m, char* _hf, char* _group) { str *grp, user_name, user, domain, uri; dig_cred_t* cred = 0; int hf_type; struct hdr_field* h; struct sip_uri puri; AAAMessage *req; AAA_AVP *avp; int ret; unsigned int tmp; char *p = NULL; grp = (str*)_group; /* via fixup */ hf_type = (int)(long)_hf; uri.s = 0; uri.len = 0; /* extract the uri according with the _hf parameter */ switch(hf_type) { case 1: /* Request-URI */ uri = *(GET_RURI(_m)); break; case 2: /* To */ if (get_to_uri(_m, &uri) < 0) { LM_ERR("failed to extract To\n"); return -2; } break; case 3: /* From */ if (get_from_uri(_m, &uri) < 0) { LM_ERR("failed to extract From URI\n"); return -3; } break; case 4: /* Credentials */ get_authorized_cred(_m->authorization, &h); if (!h) { get_authorized_cred(_m->proxy_auth, &h); if (!h) { LM_ERR("no authorized credentials found " "(error in scripts)\n"); return -4; } } cred = &((auth_body_t*)(h->parsed))->digest; break; } if (hf_type != 4) { if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse URI\n"); return -5; } user = puri.user; domain = puri.host; } else { user = cred->username.user; domain = cred->realm; } /* user@domain mode */ if (use_domain) { user_name.s = 0; user_name.len = user.len + domain.len; if(user_name.len>0) { user_name.len++; p = (char*)pkg_malloc(user_name.len); if (!p) { LM_ERR("no pkg memory left\n"); return -6; } user_name.s = p; memcpy(user_name.s, user.s, user.len); if(user.len>0) { user_name.s[user.len] = '@'; memcpy(user_name.s + user.len + 1, domain.s, domain.len); } else memcpy(user_name.s, domain.s, domain.len); } } else user_name = user; if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("can't create new AAA message!\n"); if(p) pkg_free(p); return -1; } /* Username AVP */ if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Usergroup AVP */ if( (avp=AAACreateAVP(AVP_User_Group, 0, 0, grp->s, grp->len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* SIP_MSGID AVP */ LM_DBG("******* m_id=%d\n", _m->id); tmp = _m->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), sizeof(tmp), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* ServiceType AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Destination-Realm AVP */ uri = *(GET_RURI(_m)); parse_uri(uri.s, uri.len, &puri); if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } #ifdef DEBUG AAAPrintMessage(req); #endif /* build a AAA message buffer */ if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed." "It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != AAA_USER_IN_GROUP) { LM_ERR("message sending to the DIAMETER backend authorization server" "failed or user is not in group\n"); goto error; } AAAFreeMessage(&req); return 1; error1: AAAFreeAVP(&avp); error: AAAFreeMessage(&req); return -1; }
/* * Check from Radius if a user belongs to a group. User-Name is digest * username or digest username@realm, SIP-Group is group, and Service-Type * is Group-Check. SIP-Group is SER specific attribute and Group-Check is * SER specific service type value. */ int radius_is_user_in(struct sip_msg* _m, char* _hf, char* _group) { str *grp, user_name, user, domain, uri; dig_cred_t* cred = 0; int hf_type; UINT4 service; VALUE_PAIR *send, *received; static char msg[4096]; struct hdr_field* h; struct sip_uri puri; grp = (str*)_group; /* via fixup */ send = received = 0; hf_type = (int)(long)_hf; uri.s = 0; uri.len = 0; switch(hf_type) { case 1: /* Request-URI */ if (get_request_uri(_m, &uri) < 0) { LOG(L_ERR, "radius_is_user_in(): Error while extracting Request-URI\n"); return -1; } break; case 2: /* To */ if (get_to_uri(_m, &uri) < 0) { LOG(L_ERR, "radius_is_user_in(): Error while extracting To\n"); return -2; } break; case 3: /* From */ if (get_from_uri(_m, &uri) < 0) { LOG(L_ERR, "radius_is_user_in(): Error while extracting From\n"); return -3; } break; case 4: /* Credentials */ get_authorized_cred(_m->authorization, &h); if (!h) { get_authorized_cred(_m->proxy_auth, &h); if (!h) { LOG(L_ERR, "radius_is_user_in(): No authorized credentials found (error in scripts)\n"); return -4; } } cred = &((auth_body_t*)(h->parsed))->digest; break; } if (hf_type != 4) { if (parse_uri(uri.s, uri.len, &puri) < 0) { LOG(L_ERR, "radius_is_user_in(): Error while parsing URI\n"); return -5; } user = puri.user; domain = puri.host; } else { user = cred->username.user; domain = *GET_REALM(cred); } if (use_domain) { user_name.len = user.len + domain.len + 1; user_name.s = (char*)pkg_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, "radius_is_user_in(): No memory left\n"); return -6; } memcpy(user_name.s, user.s, user.len); user_name.s[user.len] = '@'; memcpy(user_name.s + user.len + 1, domain.s, domain.len); } else { user_name = user; } if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_name.s, user_name.len, 0)) { LOG(L_ERR, "radius_is_user_in(): Error adding User-Name attribute\n"); rc_avpair_free(send); if (use_domain) pkg_free(user_name.s); return -7; } if (use_domain) pkg_free(user_name.s); if (!rc_avpair_add(rh, &send, attrs[A_SIP_GROUP].v, grp->s, grp->len, 0)) { LOG(L_ERR, "radius_is_user_in(): Error adding Sip-Group attribute\n"); return -8; } service = vals[V_GROUP_CHECK].v; if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) { LOG(L_ERR, "radius_is_user_in(): Error adding Service-Type attribute\n"); rc_avpair_free(send); return -9; } if (rc_auth(rh, 0, send, &received, msg) == OK_RC) { DBG("radius_is_user_in(): Success\n"); rc_avpair_free(send); rc_avpair_free(received); return 1; } else { DBG("radius_is_user_in(): Failure\n"); rc_avpair_free(send); rc_avpair_free(received); return -11; } }
// // Ref. RFC 3261 "12.2.1.1 Generating the Request" // int trans_layer::set_next_hop(list<sip_header*>& route_hdrs, cstring& r_uri, sockaddr_storage* remote_ip) { string next_hop; unsigned short next_port=0; //assert(msg->type == SIP_REQUEST); int err=0; if(!route_hdrs.empty()){ sip_header* fr = route_hdrs.front(); sip_nameaddr na; const char* c = fr->value.s; if(parse_nameaddr(&na, &c, fr->value.len)<0) { DBG("Parsing name-addr failed\n"); return -1; } if(parse_uri(&na.uri,na.addr.s,na.addr.len) < 0) { DBG("Parsing route uri failed\n"); return -1; } bool is_lr = false; if(!na.uri.params.empty()){ list<sip_avp*>::iterator it = na.uri.params.begin(); for(;it != na.uri.params.end(); it++){ if( ((*it)->name.len == 2) && (!memcmp((*it)->name.s,"lr",2)) ) { is_lr = true; break; } } } if (SipCtrlInterfaceFactory::outbound_host.empty()) { next_hop = c2stlstr(na.uri.host); next_port = na.uri.port; } else { next_hop = SipCtrlInterfaceFactory::outbound_host; next_port = SipCtrlInterfaceFactory::outbound_port; } if(!is_lr){ // detect beginning of next route enum { RR_PARAMS=0, RR_QUOTED, RR_SEP_SWS, // space(s) after ',' RR_NXT_ROUTE }; int st = RR_PARAMS; const char* end = fr->value.s + fr->value.len; for(;c<end;c++){ switch(st){ case RR_PARAMS: switch(*c){ case SP: case HTAB: case CR: case LF: break; case COMMA: st = RR_SEP_SWS; break; case DQUOTE: st = RR_QUOTED; break; } break; case RR_QUOTED: switch(*c){ case BACKSLASH: c++; break; case DQUOTE: st = RR_PARAMS; break; } break; case RR_SEP_SWS: switch(*c){ case SP: case HTAB: case CR: case LF: break; default: st = RR_NXT_ROUTE; goto nxt_route; } break; } } nxt_route: switch(st){ case RR_QUOTED: case RR_SEP_SWS: DBG("Malformed first route header\n"); case RR_PARAMS: // remove current route header from message DBG("delete (fr=0x%p)\n",fr); delete fr; // route_hdrs.front(); route_hdrs.pop_front(); DBG("route_hdrs.length() = %i\n",(int)route_hdrs.size()); break; case RR_NXT_ROUTE: // remove current route from this header fr->value.s = c; fr->value.len = end-c; break; } // copy r_uri at the end of // the route set. route_hdrs.push_back(new sip_header(0,"Route",r_uri)); r_uri = na.addr; } } else { if (SipCtrlInterfaceFactory::outbound_host.empty()) { sip_uri parsed_r_uri; err = parse_uri(&parsed_r_uri,r_uri.s,r_uri.len); if(err < 0){ ERROR("Invalid Request URI\n"); return -1; } next_hop = c2stlstr(parsed_r_uri.host); next_port = parsed_r_uri.port; } else { next_hop = SipCtrlInterfaceFactory::outbound_host; next_port = SipCtrlInterfaceFactory::outbound_port; } } DBG("next_hop:next_port is <%s:%u>\n", next_hop.c_str(), next_port); err = resolver::instance()->resolve_name(next_hop.c_str(), remote_ip,IPv4,UDP); if(err < 0){ ERROR("Unresolvable Request URI\n"); return -1; } ((sockaddr_in*)remote_ip)->sin_port = htons(next_port); return 0; }
/** * rewrites the request URI of msg by calculating a rule, using * crc32 for hashing. The request URI is used to determine tree node * the given _user is used to determine the routing tree. * * @param msg the current SIP message * @param _uri the URI to determine the route tree (string or pseudo-variable) * @param _domain the requested routing domain * * @return 1 on success, -1 on failure */ int user_route_uri(struct sip_msg * _msg, char * _uri, char * _domain) { pv_elem_t *model; str uri, user, str_domain, ruser, ruri; struct sip_uri puri; int carrier_id, domain, index; domain = (int)(long)_domain; struct rewrite_data * rd = NULL; struct carrier_tree * ct = NULL; if (!_uri) { LM_ERR("bad parameter\n"); return -1; } if (parse_sip_msg_uri(_msg) < 0) { return -1; } /* Retrieve uri from parameter */ model = (pv_elem_t*)_uri; if (pv_printf_s(_msg, model, &uri)<0) { LM_ERR("cannot print the format\n"); return -1; } if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("Error while parsing URI\n"); return -5; } user = puri.user; str_domain = puri.host; ruser.s = _msg->parsed_uri.user.s; ruser.len = _msg->parsed_uri.user.len; ruri.s = _msg->parsed_uri.user.s; ruri.len = _msg->parsed_uri.user.len; do { rd = get_data(); } while (rd == NULL); if ((carrier_id = load_user_carrier(&user, &str_domain)) < 0) { release_data(rd); return -1; } else if (carrier_id == 0) { index = rd->default_carrier_index; } else { if ((ct = get_carrier_tree(carrier_id, rd)) == NULL) { if (fallback_default) { index = rd->default_carrier_index; } else { LM_ERR("desired routing tree with id %i doesn't exist\n", carrier_id); release_data(rd); return -1; } } else { index = ct->index; } } release_data(rd); return carrier_rewrite_msg(index, domain, &ruri, _msg, &ruser, shs_call_id, alg_crc32); }
static int ki_xcaps_get(sip_msg_t* msg, str* uri, str* path) { struct sip_uri turi; str etag = {0, 0}; str body = {0, 0}; str new_body = {0, 0}; int ret = 0; xcap_uri_t xuri; str *ctype; str allow; if(uri->s==NULL || uri->len == 0) { LM_ERR("invalid uri parameter\n"); return -1; } if(path->s==NULL || path->len == 0) { LM_ERR("invalid path parameter\n"); return -1; } if(parse_uri(uri->s, uri->len, &turi)!=0) { LM_ERR("parsing uri parameter [%.*s]\n", uri->len, uri->s); goto error; } if(xcap_parse_uri(path, &xcaps_root, &xuri)<0) { LM_ERR("cannot parse xcap uri [%.*s]\n", path->len, path->s); goto error; } switch(xuri.type) { case DIRECTORY: if (strncmp(xuri.file.s, "directory.xml", xuri.file.len) == 0) { if (xcaps_get_directory(msg, &turi.user, &turi.host, &body) < 0) goto error; xcaps_send_reply(msg, 200, &xcaps_str_ok, NULL, &xcaps_str_appdrxml, &body); } else { xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL, NULL, NULL); } break; case XCAP_CAPS: xcaps_send_reply(msg, 501, &xcaps_str_notimplemented, NULL, NULL, NULL); break; case SEARCH: allow.s = xcaps_hdr_buf; allow.len = snprintf(allow.s, XCAPS_HDR_SIZE, "Allow: POST\r\n"); xcaps_send_reply(msg, 405, &xcaps_str_notallowed, &allow, NULL, NULL); break; default: if((ret=xcaps_get_db_etag(&turi.user, &turi.host, &xuri, &etag))<0) { LM_ERR("could not fetch etag for xcap document\n"); goto error; } if (ret==1) { /* doc not found */ xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL, NULL, NULL); return 1; } if((ret=check_preconditions(msg, etag))==-1) { xcaps_send_reply(msg, 412, &xcaps_str_precon, NULL, NULL, NULL); return -2; } else if (ret==-2) { xcaps_send_reply(msg, 304, &xcaps_str_notmod, NULL, NULL, NULL); return -2; } if((ret=xcaps_get_db_doc(&turi.user, &turi.host, &xuri, &body))<0) { LM_ERR("could not fetch xcap document\n"); goto error; } if(ret!=0) { /* doc not found */ xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL, NULL, NULL); break; } if(xuri.nss!=NULL && xuri.node.len>0) { if((new_body.s = pkg_malloc(body.len))==NULL) { LM_ERR("allocating package memory\n"); goto error; } new_body.len = body.len; if(xcaps_xpath_hack(&body, 0)<0) { LM_ERR("could not hack xcap document\n"); goto error; } if(xcaps_xpath_get(&body, &xuri.node, &new_body)<0) { LM_ERR("could not retrieve element from xcap document\n"); goto error; } if(new_body.len<=0) { /* element not found */ xcaps_send_reply(msg, 404, &xcaps_str_notfound, NULL, NULL, NULL); pkg_free(new_body.s); new_body.s = NULL; break; } if(xcaps_xpath_hack(&new_body, 1)<0) { LM_ERR("could not hack xcap document\n"); goto error; } memcpy(body.s, new_body.s, new_body.len); body.len = new_body.len; pkg_free(new_body.s); new_body.s = NULL; } /* doc or element found */ ctype = &xcaps_str_appxml; if(xuri.type==RESOURCE_LIST) ctype = &xcaps_str_apprlxml; else if(xuri.type==PRES_RULES) ctype = &xcaps_str_appapxml; else if(xuri.type==RLS_SERVICE) ctype = &xcaps_str_apprsxml; else if(xuri.type==USER_PROFILE) ctype = &xcaps_str_appupxml; else if(xuri.type==PRES_CONTENT) ctype = &xcaps_str_apppcxml; else if(xuri.type==PIDF_MANIPULATION) ctype = &xcaps_str_apppdxml; xcaps_send_reply(msg, 200, &xcaps_str_ok, &etag, ctype, &body); break; } return 1; error: if (new_body.s) pkg_free(new_body.s); xcaps_send_reply(msg, 500, &xcaps_str_srverr, NULL, NULL, NULL); return -1; }
int add_cc_agent( struct cc_data *data, str *id, str *location, str *skills, unsigned int logstate, unsigned int last_call_end) { struct cc_agent *agent, *prev_agent= 0; struct sip_uri uri; str skill; char *p; unsigned int n,skill_id; #ifdef STATISTICS char *name; str s; #endif /* is the agent a new one? - search by ID */ agent = get_agent_by_name( data, id, &prev_agent); if (agent==NULL) { /* new agent -> create and populate one */ agent = (struct cc_agent*)shm_malloc(sizeof(struct cc_agent)+id->len); if (agent==NULL) { LM_ERR("not enough shmem for a new agent\n"); goto error; } memset( agent, 0, sizeof(struct cc_agent) ); /* id */ agent->id.s = (char*)(agent+1); memcpy( agent->id.s, id->s, id->len); agent->id.len = id->len; /* location */ agent->location.s = (char*)shm_malloc(location->len); if (agent->location.s==NULL) { LM_ERR("not enough shmem for the location of the agent\n"); goto error; } memcpy( agent->location.s, location->s, location->len); agent->location.len = location->len; if (parse_uri( agent->location.s, agent->location.len, &uri)<0) { LM_ERR("location of the agent is not a SIP URI\n"); goto error; } agent->did = uri.user; /* LOG STATE */ agent->loged_in = logstate; /* set of skills */ if (skills && skills->len) { p = skills->s; while (p) { skill.s = p; p = q_memchr(skill.s, ',', skills->s+skills->len-skill.s); skill.len = p?(p-skill.s):(skills->s+skills->len-skill.s); trim(&skill); if (skill.len) { skill_id = get_skill_id(data,&skill); if (skill_id==0) { LM_ERR("cannot get skill id\n"); goto error; } n = agent->no_skills++; agent->skills[n] = skill_id; } if(p) p++; } } /* statistics */ #ifdef STATISTICS s.s = "cca_dist_incalls";s.len = 16 ; if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center", name, &agent->st_dist_incalls, STAT_SHM_NAME)!=0 ) { LM_ERR("failed to add stat variable\n"); goto error; } s.s = "cca_answ_incalls";s.len = 16 ; if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center", name, &agent->st_answ_incalls, STAT_SHM_NAME)!=0 ) { LM_ERR("failed to add stat variable\n"); goto error; } s.s = "cca_aban_incalls";s.len = 16 ; if ( (name=build_stat_name( &s, id->s))==0 || register_stat("call_center", name, &agent->st_aban_incalls, STAT_SHM_NAME)!=0 ) { LM_ERR("failed to add stat variable\n"); goto error; } s.s = "cca_att";s.len = 7 ; if ( (name=build_stat_name( &s, id->s))==0 || register_stat2("call_center", name, (stat_var **)cc_agent_get_att, STAT_SHM_NAME|STAT_IS_FUNC, (void*)agent, 0)!=0) { LM_ERR("failed to add stat variable\n"); goto error; } #endif if(last_call_end && (last_call_end + wrapup_time < (int)time(NULL))) { agent->state = CC_AGENT_WRAPUP; agent->last_call_end = last_call_end - startup_time; /* it will be a negative value */ } agent->is_new = 1; /* link the agent */ add_cc_agent_top(data, agent); data->totalnr_agents++; } else { /* agent already exists -> update only */ /* location - needs to be changed ? */ if ( agent->location.len!=location->len || memcmp(agent->location.s,location->s,location->len)!=0 ) { /* set new location */ if (agent->location.len < location->len ){ shm_free(agent->location.s); agent->location.s = (char*)shm_malloc(location->len); if (agent->location.s==NULL) { LM_ERR("not enough shmem for the location of the agent\n"); goto error1; } } memcpy( agent->location.s, location->s, location->len); agent->location.len = location->len; if (parse_uri( agent->location.s, agent->location.len, &uri)<0) { LM_ERR("location of the agent is not a SIP URI\n"); goto error1; } agent->did = uri.user; } /* if logstate changed - move between the lists TODO */ if(logstate != agent->loged_in) { agent_switch_login(data, agent, prev_agent); } /* skills - needs to be changed ? */ agent->no_skills = 0; if (skills && skills->len) { p = skills->s; while (p) { skill.s = p; p = q_memchr(skill.s, ',', skills->s+skills->len-skill.s); skill.len = p?(p-skill.s):(skills->s+skills->len-skill.s); trim(&skill); if (skill.len) { skill_id = get_skill_id(data,&skill); if (skill_id==0) { LM_ERR("cannot get skill id\n"); goto error1; } n = agent->no_skills++; agent->skills[n] = skill_id; } if(p) p++; } } agent->is_new = 1; } return 0; error1: remove_cc_agent(data, agent, prev_agent); error: if (agent) free_cc_agent(agent); return 0; }
int encode2format (struct sip_msg* msg, str* uri, struct uri_format *format) { int foo; char *string, *pos, *start, *end; struct sip_uri sipUri; int scheme_len; if (uri->s == NULL) return -1; string = uri->s; pos = q_memchr (string, '<', uri->len); if (pos != NULL) /* we are only interested of chars inside <> */ { start = q_memchr (string, ':', uri->len); if (start == NULL) return -2; if (start - pos < 4) return -3; if ((*(start-1)|0x20)=='s' && (start-pos)>4) /* if it ends in s: it is a sips or tels uri */ scheme_len=4; else scheme_len=3; start-=scheme_len; end = strchr (start, '>'); if (end == NULL) return -4; /* must be a match to < */ } else /* we do not have <> */ { pos=string; start = q_memchr (string, ':', uri->len); if (start == NULL) return -5; if (start - pos < 3) return -6; if ((*(start-1)|0x20)=='s' && (start-pos)>3) /* if it ends in s: it is a sips or tels uri */ scheme_len=4; else scheme_len=3; start = start - scheme_len; end = string + uri->len; } memset(format,0,sizeof(struct uri_format)); format->first = start - string + scheme_len+1 /* ':' */; format->second = end - string; /* --------------------------testing ------------------------------- */ /* sip:gva@[email protected];;transport=udp>;expires=2 INCORECT BEHAVIOR OF parse_uri,myfunction works good */ foo = parse_uri (start, end - start, &sipUri); if (foo != 0) { LOG(L_ERR,"ERROR: encode2format: parse_uri failed on [%.*s]." "Code %d \n", uri->len, uri->s, foo); return foo-10; } format->username = sipUri.user; format->password = sipUri.passwd; format->ip = sipUri.host; format->port = sipUri.port; format->protocol = sipUri.transport_val; format->transport=sipUri.transport; /* the whole transport header */ format->rest.s = sipUri.port.s?(sipUri.port.s+sipUri.port.len): (sipUri.host.s+sipUri.host.len); format->rest.len = (int)(end-format->rest.s); format->rcv_ip.s=ip_addr2a(&msg->rcv.src_ip); format->rcv_ip.len=strlen(format->rcv_ip.s); if (msg->rcv.src_port!=SIP_PORT){ format->rcv_port.s= int2str(msg->rcv.src_port, &format->rcv_port.len); }else{ format->rcv_port.s=0; format->rcv_port.len=0; } if (msg->rcv.proto!=PROTO_UDP){ switch(msg->rcv.proto){ case PROTO_TCP: format->rcv_proto=s_tcp; break; case PROTO_TLS: format->rcv_proto=s_tls; break; case PROTO_SCTP: format->rcv_proto=s_sctp; break; default: BUG("unknown proto %d\n", msg->rcv.proto); } }else{ format->rcv_proto.s=0; format->rcv_proto.len=0; } #ifdef EXTRA_DEBUG fprintf (stdout, "transport=[%.*s] transportval=[%.*s]\n", sipUri.transport.len,sipUri.transport.s,sipUri.transport_val.len,sipUri.transport_val.s); fprintf(stdout,"First %d,second %d\n",format->first,format->second); #endif return 0; }