void rtpproxy_pre_fwd(struct sip_msg *msg, cb_type_t cb_type, void *mod_args, void *core_args) { struct proxy_l *p; struct ip_addr ip; char *cp; struct force_rtpp_args *args; assert(cb_type == REQ_PRE_FORWARD); p = (struct proxy_l *)core_args; args = (struct force_rtpp_args *)mod_args; if (args->raddr.s != NULL) return; hostent2ip_addr(&ip, &p->host, p->addr_idx); cp = ip_addr2a(&ip); args->raddr.len = strlen(cp); if (ip.af == AF_INET) { args->raddr.s = pkg_malloc(args->raddr.len + 1); if (args->raddr.s == NULL) { LM_ERR("out of pkg memory\n"); return; } sprintf(args->raddr.s, "%s", cp); } else { args->raddr.len += 2; args->raddr.s = pkg_malloc(args->raddr.len + 1); if (args->raddr.s == NULL) { LM_ERR("out of pkg memory\n"); return; } sprintf(args->raddr.s, "[%s]", cp); } force_rtp_proxy_body(msg, args, NULL, NULL); }
/* * Check if from user is a valid enum based user, and check to make sure * that the src_ip == an srv record that maps to the enum from user. */ int is_from_user_enum_2(struct sip_msg* _msg, char* _suffix, char* _service) { struct ip_addr addr; struct hostent* he; unsigned short zp; unsigned short proto; char *user_s; int user_len, i, j; char name[MAX_DOMAIN_SIZE]; char uri[MAX_URI_SIZE]; struct sip_uri *furi; struct sip_uri luri; struct rdata* head; str* suffix; str* service; struct rdata* l; struct naptr_rdata* naptr; str pattern, replacement, result; char string[17]; if (parse_from_header(_msg) < 0) { LM_ERR("Failed to parse From header\n"); return -1; } if(_msg->from==NULL || get_from(_msg)==NULL) { LM_DBG("No From header\n"); return -1; } if ((furi = parse_from_uri(_msg)) == NULL) { LM_ERR("Failed to parse From URI\n"); return -1; } suffix = (str*)_suffix; service = (str*)_service; if (is_e164(&(furi->user)) == -1) { LM_ERR("From URI user is not an E164 number\n"); return -1; } /* assert: the from user is a valid formatted e164 string */ user_s = furi->user.s; user_len = furi->user.len; j = 0; for (i = user_len - 1; i > 0; i--) { name[j] = user_s[i]; name[j + 1] = '.'; j = j + 2; } memcpy(name + j, suffix->s, suffix->len + 1); head = get_record(name, T_NAPTR); if (head == 0) { LM_DBG("No NAPTR record found for %s.\n", name); return -3; } /* we have the naptr records, loop and find an srv record with */ /* same ip address as source ip address, if we do then true is returned */ for (l = head; l; l = l->next) { if (l->type != T_NAPTR) continue; /*should never happen*/ naptr = (struct naptr_rdata*)l->rdata; if (naptr == 0) { LM_ERR("Null rdata in DNS response\n"); free_rdata_list(head); return -4; } LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags " "'%.*s', slen %u, services '%.*s', rlen %u, " "regexp '%.*s'\n", name, naptr->order, naptr->pref, naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags), naptr->services_len, (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len, (int)(naptr->regexp_len), ZSW(naptr->regexp)); if (sip_match(naptr, service) != 0) { if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len, &pattern, &replacement) < 0) { free_rdata_list(head); /*clean up*/ LM_ERR("Parsing of NAPTR regexp failed\n"); return -5; } #ifdef LATER if ((pattern.len == 4) && (strncmp(pattern.s, "^.*$", 4) == 0)) { LM_DBG("Resulted in replacement: '%.*s'\n", replacement.len, ZSW(replacement.s)); retval = set_uri(_msg, replacement.s, replacement.len); free_rdata_list(head); /*clean up*/ return retval; } #endif result.s = &(uri[0]); result.len = MAX_URI_SIZE; /* Avoid making copies of pattern and replacement */ pattern.s[pattern.len] = (char)0; replacement.s[replacement.len] = (char)0; /* We have already checked the size of _msg->parsed_uri.user.s */ memcpy(&(string[0]), user_s, user_len); string[user_len] = (char)0; if (reg_replace(pattern.s, replacement.s, &(string[0]), &result) < 0) { pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; LM_ERR("Regexp replace failed\n"); free_rdata_list(head); /*clean up*/ return -6; } LM_DBG("Resulted in replacement: '%.*s'\n", result.len, ZSW(result.s)); if(parse_uri(result.s, result.len, &luri) < 0) { LM_ERR("Parsing of URI <%.*s> failed\n", result.len, result.s); free_rdata_list(head); /*clean up*/ return -7; } pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; zp = 0; proto = PROTO_NONE; he = sip_resolvehost(&luri.host, &zp, &proto, (luri.type==SIPS_URI_T)?1:0 , 0); hostent2ip_addr(&addr, he, 0); if(ip_addr_cmp(&addr, &_msg->rcv.src_ip)) { free_rdata_list(head); return(1); } } } free_rdata_list(head); /*clean up*/ LM_DBG("FAIL\n"); /* must not have found the record */ return(-8); }
int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri, char* resource, unsigned int flags) { struct lb_res_str_list *lb_rl; struct lb_res_str *r; struct lb_dst *dst; struct lb_resource *res; struct sip_uri puri; struct proxy_l *proxy; union sockaddr_union sau; int len; int i; LM_DBG("uri=<%s>, grp=%d, res=<%s>\n",uri, group, resource); /* check uri */ len = strlen(uri); if(parse_uri(uri, len, &puri)!=0 ) { LM_ERR("bad uri [%.*s] for destination\n", len, uri); return -1; } /* parse the resources string */ lb_rl = parse_resources_list( resource, 1); if (lb_rl==NULL) { LM_ERR("failed to parse resourse string <%s>\n",resource); return -1; } /*add new destination */ dst = (struct lb_dst*)shm_malloc( sizeof(struct lb_dst) + lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*))); if (dst==NULL) { LM_ERR("failed to get shmem\n"); goto error; } memset( dst, 0, sizeof(struct lb_dst)+ lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*)) ); dst->rmap = (struct lb_resource_map*)(dst+1); dst->uri.s = (char*)(dst->rmap + lb_rl->n); dst->uri.len = len; memcpy( dst->uri.s , uri, len); dst->profile_id.s = dst->uri.s + len; dst->profile_id.len = snprintf(dst->profile_id.s, 2+2*sizeof(struct lb_dst*), "%X", id); dst->id = id; dst->group = group; dst->rmap_no = lb_rl->n; dst->flags = flags; /* add or update resource list */ for( i=0 ; i<lb_rl->n ; i++) { r = lb_rl->resources + i; LM_DBG(" setting for uri=<%s> (%d) resource=<%.*s>, val=%d\n", uri, data->dst_no+1, r->name.len, r->name.s, r->val); res = get_resource_by_name( data, &r->name); if (res==NULL) { /* add new resource */ res = add_lb_resource(data, &r->name); if (res==NULL) { LM_ERR("failed to create new resource\n"); goto error; } } /* set the proper bit in the resource */ if (lb_set_resource_bitmask( res, data->dst_no)==-1 ) { LM_ERR("failed to set destination bit\n"); goto error; } /* set the pointer and the max load */ dst->rmap[i].resource = res; dst->rmap[i].max_load = r->val; } /* Do a SIP wise DNS-Lookup for the domain part */ proxy = mk_proxy( &puri.host, puri.port_no, puri.proto, (puri.type==SIPS_URI_T)); if (proxy==NULL) { LM_ERR("could not resolve %.*s\n", puri.host.len, puri.host.s); goto error; } hostent2ip_addr( &dst->ips[0], &proxy->host, proxy->addr_idx); dst->ports[0] = proxy->port; dst->ips_cnt = 1; LM_DBG("first dst ip addr [%s]:%d\n", ip_addr2a(&dst->ips[0]), dst->ports[0]); /* get the next available IPs from DNS */ while (dst->ips_cnt<LB_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &dst->ips[dst->ips_cnt], &sau); dst->ports[dst->ips_cnt] = proxy->port; LM_DBG("additional dst ip addr [%s]:%d\n", ip_addr2a(&dst->ips[dst->ips_cnt]), dst->ports[dst->ips_cnt]); /* one more IP found */ dst->ips_cnt++; } /* free al the helper structures */ free_proxy(proxy); pkg_free(proxy); /* link at the end */ if (data->last_dst==NULL) { data->dsts = data->last_dst = dst; } else { data->last_dst->next = dst; data->last_dst = dst; } data->dst_no++; pkg_free(lb_rl); return 0; error: shm_free(dst); pkg_free(lb_rl); return -1; }
/** Initializes seas module. It first parses the listen_sockets parameter * which has the form "ip_address[:port]", creates the pipe to * communicate with the dispatcher. */ static int seas_init(void) { char *p,*port; struct hostent *he; struct socket_info *si; int c_pipe[2],mierr,i; /** Populate seas_functions*/ if (load_tm_api(&seas_f.tmb)!=0) { LM_ERR( "can't load TM API\n"); return -1; } if(!(seas_f.t_check_orig_trans = find_export("t_check_trans", 0, 0))){ LM_ERR( "Seas requires transaction module (t_check_trans not found)\n"); return -1; } /** Populate seas_functions*/ c_pipe[0]=c_pipe[1]=-1; p=seas_listen_socket; port=(char *)0; seas_listen_port=5080; /*if the seas_listen_socket configuration string is empty, use default values*/ if(p==NULL || *p==0){ si=get_first_socket(); seas_listen_ip=&si->address; } else {/*if config string is not empty, then try to find host first, and maybe port..*/ while(*p){ if(*p == ':'){ *p=0; port=p+1; break; } p++; } if(!(he=resolvehost(seas_listen_socket,0))) goto error; if(!(seas_listen_ip=pkg_malloc(sizeof(struct ip_addr)))) goto error; hostent2ip_addr(seas_listen_ip, he, 0); if(port!=(char *)0 && (seas_listen_port=str2s(port,strlen(port),&mierr))==0){ LM_ERR("invalid port %s \n",port); goto error; } } memset(unc_as_t,0,2*MAX_UNC_AS_NR*sizeof(struct unc_as));//useless because unc_as_t is in bss? if (pipe(c_pipe)==-1) { LM_ERR("cannot create pipe!\n"); goto error; } read_pipe=c_pipe[0]; write_pipe=c_pipe[1]; seas_init_tags(); if(0>start_stats_server(seas_stats_socket)) goto error; if(0>prepare_ha()) goto error; if(0>parse_cluster_cfg()) goto error; return 0; error: for(i=0;i<2;i++) if(c_pipe[i]!=-1) close(c_pipe[i]); if(seas_listen_ip!=0) pkg_free(seas_listen_ip); if(use_stats) stop_stats_server(); return -1; }
int add_dst( rt_data_t *r, /* id */ char *id, /* ip address */ char* ip, /* strip len */ int strip, /* pri prefix */ char* pri, /* dst type*/ int type, /* dst attrs*/ char* attrs, /* probe_mode */ int probing, /* socket */ struct socket_info *sock, /* state */ int state ) { static unsigned id_counter = 0; pgw_t *pgw=NULL, *tmp=NULL; struct sip_uri uri; int l_ip,l_pri,l_attrs,l_id; #define GWABUF_MAX_SIZE 512 char gwabuf[GWABUF_MAX_SIZE]; union sockaddr_union sau; struct proxy_l *proxy; unsigned int sip_prefix; str gwas; if (NULL==r || NULL==ip) { LM_ERR("invalid parametres\n"); goto err_exit; } l_id = strlen(id); l_ip = strlen(ip); l_pri = pri?strlen(pri):0; l_attrs = attrs?strlen(attrs):0; /* check if GW address starts with 'sip' or 'sips' */ if (l_ip>5) { if ( strncasecmp("sip:", ip, 4)==0) sip_prefix = 4; else if ( strncasecmp("sips:", ip, 5)==0) sip_prefix = 5; else sip_prefix = 0; } else sip_prefix = 0; if( sip_prefix==0 ) { if(l_ip+4>=GWABUF_MAX_SIZE) { LM_ERR("GW address (%d) longer " "than %d\n",l_ip+4,GWABUF_MAX_SIZE); goto err_exit; } memcpy(gwabuf, "sip:", 4); memcpy(gwabuf+4, ip, l_ip); gwas.s = gwabuf; gwas.len = 4+l_ip; } else { gwas.s = ip; gwas.len = l_ip; } /* parse the normalized address as a SIP URI */ memset(&uri, 0, sizeof(struct sip_uri)); if(parse_uri(gwas.s, gwas.len, &uri)!=0) { LM_ERR("invalid uri <%.*s>\n", gwas.len, gwas.s); goto err_exit; } /* update the sip_prefix to skip to domain part */ if (uri.user.len) sip_prefix += uri.host.s - uri.user.s; /* allocate new structure */ pgw = (pgw_t*)shm_malloc(sizeof(pgw_t) + l_id + (l_ip-sip_prefix) + l_pri + l_attrs); if (NULL==pgw) { LM_ERR("no more shm mem (%u)\n", (unsigned int)(sizeof(pgw_t)+l_id+l_ip-sip_prefix+l_pri +l_attrs)); goto err_exit; } memset(pgw,0,sizeof(pgw_t)); /* set probing related flags */ switch(probing) { case 0: break; case 1: pgw->flags |= DR_DST_PING_DSBL_FLAG; break; case 2: pgw->flags |= DR_DST_PING_PERM_FLAG; break; default: goto err_exit; } /* set state related flags */ switch(state) { case 0: break; case 1: pgw->flags |= DR_DST_STAT_DSBL_FLAG|DR_DST_STAT_NOEN_FLAG; break; case 2: pgw->flags |= DR_DST_STAT_DSBL_FLAG; break; default: goto err_exit; } /* set outbound socket */ pgw->sock = sock; pgw->_id = ++id_counter; pgw->id.len= l_id; pgw->id.s = (char*)(pgw+1); memcpy(pgw->id.s, id, l_id); pgw->ip_str.len= l_ip-sip_prefix; pgw->ip_str.s = (char*)(pgw+1)+l_id; memcpy(pgw->ip_str.s, ip+sip_prefix, l_ip-sip_prefix); if (pri) { pgw->pri.len = l_pri; pgw->pri.s = ((char*)(pgw+1))+l_id+l_ip-sip_prefix; memcpy(pgw->pri.s, pri, l_pri); } if (attrs) { pgw->attrs.len = l_attrs; pgw->attrs.s = ((char*)(pgw+1))+l_id+l_ip-sip_prefix+l_pri; memcpy(pgw->attrs.s, attrs, l_attrs); } pgw->strip = strip; pgw->type = type; /* add address in the global list of destinations/GWs */ proxy = mk_proxy(&uri.host,uri.port_no,uri.proto,(uri.type==SIPS_URI_T)); if (proxy==NULL) { if(dr_force_dns) { LM_ERR("cannot resolve <%.*s>\n", uri.host.len, uri.host.s); goto err_exit; } else { LM_DBG("cannot resolve <%.*s> - won't be used" " by is_from_gw()\n", uri.host.len, uri.host.s); goto done; } } hostent2ip_addr( &pgw->ips[0], &proxy->host, proxy->addr_idx); pgw->ports[0] = proxy->port; LM_DBG("first gw ip addr [%s]\n", ip_addr2a(&pgw->ips[0])); pgw->ips_no = 1; while (pgw->ips_no<DR_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &pgw->ips[pgw->ips_no], &sau); pgw->ports[pgw->ips_no] = proxy->port; LM_DBG("additional gw ip addr [%s]\n", ip_addr2a( &pgw->ips[pgw->ips_no] ) ); pgw->ips_no++; } free_proxy(proxy); pkg_free(proxy); done: if(NULL==r->pgw_l) r->pgw_l = pgw; else { tmp = r->pgw_l; while(NULL != tmp->next) tmp = tmp->next; tmp->next = pgw; } return 0; err_exit: if(NULL!=pgw) shm_free(pgw); return -1; }
static struct socket_info* find_socket(str* received) { struct sip_uri puri; param_hooks_t hooks; struct hostent* he; struct ip_addr ip; struct socket_info* si; param_t* params; unsigned short port; char* buf; int error; if (!received) return 0; si = 0; if (parse_uri(received->s, received->len, &puri) < 0) { LOG(L_ERR, "find_socket: Error while parsing received URI\n"); return 0; } if (parse_params(&puri.params, CLASS_URI, &hooks, ¶ms) < 0) { LOG(L_ERR, "find_socket: Error while parsing received URI parameters\n"); return 0; } if (!hooks.uri.dstip || !hooks.uri.dstip->body.s || !hooks.uri.dstip->body.len) goto end; buf = (char*)pkg_malloc(hooks.uri.dstip->body.len + 1); if (!buf) { LOG(L_ERR, "find_socket: No memory left\n"); goto end; } memcpy(buf, hooks.uri.dstip->body.s, hooks.uri.dstip->body.len); buf[hooks.uri.dstip->body.len] = '\0'; he = resolvehost(buf); if (he == 0) { LOG(L_ERR, "find_socket: Unable to resolve '%s'\n", buf); pkg_free(buf); goto end; } pkg_free(buf); if (hooks.uri.dstport && hooks.uri.dstport->body.s && hooks.uri.dstport->body.len) { port = str2s(hooks.uri.dstport->body.s, hooks.uri.dstport->body.len, &error); if (error != 0) { LOG(L_ERR, "find_socket: Unable to convert port number\n"); goto end; } } else { port = 0; } hostent2ip_addr(&ip, he, 0); si = find_si(&ip, port, puri.proto); if (si == 0) { LOG(L_ERR, "find_socket: Unable to find socket, using the default one\n"); goto end; } end: if (params) free_params(params); return si; }
/** * @brief build a dmq node */ dmq_node_t *build_dmq_node(str *uri, int shm) { dmq_node_t *ret = NULL; param_hooks_t hooks; param_t *params; /* For DNS-Lookups */ static char hn[256]; struct hostent *he; LM_DBG("build_dmq_node %.*s with %s memory\n", STR_FMT(uri), shm ? "shm" : "private"); if(shm) { ret = shm_malloc(sizeof(dmq_node_t)); if(ret == NULL) { LM_ERR("no more shm\n"); goto error; } memset(ret, 0, sizeof(dmq_node_t)); if(shm_str_dup(&ret->orig_uri, uri) < 0) { goto error; } } else { ret = pkg_malloc(sizeof(dmq_node_t)); if(ret == NULL) { LM_ERR("no more pkg\n"); goto error; } memset(ret, 0, sizeof(dmq_node_t)); if(pkg_str_dup(&ret->orig_uri, uri) < 0) { goto error; } } set_default_dmq_node_params(ret); if(parse_uri(ret->orig_uri.s, ret->orig_uri.len, &ret->uri) < 0 || ret->uri.host.len > 254) { LM_ERR("error parsing uri\n"); goto error; } /* if any parameters found, parse them */ if(parse_params(&ret->uri.params, CLASS_ANY, &hooks, ¶ms) < 0) { LM_ERR("error parsing params\n"); goto error; } /* if any params found */ if(params) { if(set_dmq_node_params(ret, params) < 0) { free_params(params); LM_ERR("error setting parameters\n"); goto error; } free_params(params); } else { LM_DBG("no dmqnode params found\n"); } /* resolve hostname */ strncpy(hn, ret->uri.host.s, ret->uri.host.len); hn[ret->uri.host.len] = '\0'; he = resolvehost(hn); if(he == 0) { LM_ERR("could not resolve %.*s\n", ret->uri.host.len, ret->uri.host.s); goto error; } hostent2ip_addr(&ret->ip_address, he, 0); return ret; error: if(ret != NULL) { destroy_dmq_node(ret, shm); } return NULL; }
/*! \brief Adds the proxies in the proxy list & resolves the hostnames * \return 0 if ok, <0 on error */ static int fix_actions(struct action* a) { struct action *t; int ret; cmd_export_t* cmd; struct hostent* he; struct ip_addr ip; struct socket_info* si; str host; int proto=PROTO_NONE, port; struct proxy_l *p; struct bl_head *blh; int i; str s; pv_elem_t *model=NULL; pv_elem_t *models[5]; xl_level_p xlp; if (a==0){ LM_CRIT("null pointer\n"); return E_BUG; } for(t=a; t!=0; t=t->next){ switch(t->type){ case ROUTE_T: if (t->elem[0].type!=NUMBER_ST){ LM_ALERT("BUG in route() type %d\n", t->elem[0].type); ret = E_BUG; goto error; } if ((t->elem[0].u.number>RT_NO)||(t->elem[0].u.number<0)){ LM_ALERT("invalid routing table number in" "route(%lu)\n", t->elem[0].u.number); ret = E_CFG; goto error; } if ( rlist[t->elem[0].u.number].a==NULL ) { LM_ERR("called route %d is not defined\n", (int)t->elem[0].u.number); ret = E_CFG; goto error; } break; case FORWARD_T: if (sl_fwd_disabled>0) { LM_ERR("stateless forwarding disabled, but forward() " "is used!!\n"); ret = E_CFG; goto error; } sl_fwd_disabled = 0; if (t->elem[0].type==NOSUBTYPE) break; case SEND_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("invalid type %d (should be string)\n", t->type); ret = E_BUG; goto error; } ret = parse_phostport( t->elem[0].u.string, strlen(t->elem[0].u.string), &host.s, &host.len, &port, &proto); if (ret!=0) { LM_ERR("ERROR:fix_actions: FORWARD/SEND bad " "argument\n"); ret = E_CFG; goto error; } p = add_proxy( &host,(unsigned short)port, proto); if (p==0) { LM_ERR("forward/send failed to add proxy"); ret = E_CFG; goto error; } t->elem[0].type = PROXY_ST; t->elem[0].u.data = (void*)p; break; case IF_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for if (should be expr)\n", t->elem[0].type); ret = E_BUG; goto error; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {...} (should be" "action)\n", t->elem[1].type); ret = E_BUG; goto error; }else if( (t->elem[2].type!=ACTIONS_ST) &&(t->elem[2].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {} else{...}(should" "be action)\n", t->elem[2].type); ret = E_BUG; goto error; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } if ( (t->elem[2].type==ACTIONS_ST)&&(t->elem[2].u.data) ){ if((ret=fix_actions((struct action*)t->elem[2].u.data))<0) return ret; } break; case WHILE_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for while (should be expr)\n", t->elem[0].type); ret = E_BUG; goto error; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for while() {...} (should be" "action)\n", t->elem[1].type); ret = E_BUG; goto error; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case SWITCH_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case CASE_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case DEFAULT_T: if ( (t->elem[0].type==ACTIONS_ST)&&(t->elem[0].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[0].u.data))<0) return ret; } break; case MODULE_T: cmd = (cmd_export_t*)t->elem[0].u.data; LM_DBG("fixing %s, line %d\n", cmd->name, t->line); if (cmd->fixup){ if (cmd->param_no==0){ ret=cmd->fixup( 0, 0); if (ret<0) goto error; } else { for (i=1; i<=cmd->param_no; i++) { ret=cmd->fixup(&t->elem[i].u.data, i); t->elem[i].type=MODFIXUP_ST; if (ret<0) goto error; } } } break; case FORCE_SEND_SOCKET_T: if (t->elem[0].type!=SOCKID_ST){ LM_CRIT("invalid subtype %d for force_send_socket\n", t->elem[0].type); ret = E_BUG; goto error; } he=resolvehost(((struct socket_id*)t->elem[0].u.data)->name,0); if (he==0){ LM_ERR(" could not resolve %s\n", ((struct socket_id*)t->elem[0].u.data)->name); ret = E_BAD_ADDRESS; goto error; } hostent2ip_addr(&ip, he, 0); si=find_si(&ip, ((struct socket_id*)t->elem[0].u.data)->port, ((struct socket_id*)t->elem[0].u.data)->proto); if (si==0){ LM_ERR("bad force_send_socket" " argument: %s:%d (opensips doesn't listen on it)\n", ((struct socket_id*)t->elem[0].u.data)->name, ((struct socket_id*)t->elem[0].u.data)->port); ret = E_BAD_ADDRESS; goto error; } t->elem[0].u.data=si; t->elem[0].type=SOCKETINFO_ST; break; case SET_DEBUG_T: if (t->elem[0].type==NOSUBTYPE) break; if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("fix_actions: BUG in setdebug() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } /* normalize the value */ if (t->elem[0].u.number>L_DBG) t->elem[0].u.number = L_DBG; else if (t->elem[0].u.number<L_ALERT) t->elem[0].u.number = L_ALERT; break; case SETFLAG_T: case RESETFLAG_T: case ISFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } if (!flag_in_range( t->elem[0].u.number )) { ret=E_CFG; goto error; } break; case SETSFLAG_T: case RESETSFLAG_T: case ISSFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxsflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } t->elem[0].u.number = fixup_flag( t->elem[0].u.number ); if (t->elem[0].u.data==0) { ret=E_CFG; goto error; } break; case SETBFLAG_T: case RESETBFLAG_T: case ISBFLAGSET_T: if (t->elem[0].type!=NUMBER_ST || t->elem[1].type!=NUMBER_ST) { LM_CRIT("bad xxxbflag() type " "%d,%d\n", t->elem[0].type, t->elem[0].type); ret=E_BUG; goto error; } t->elem[1].u.number = fixup_flag( t->elem[1].u.number ); if (t->elem[1].u.data==0) { ret=E_CFG; goto error; } break; case EQ_T: case COLONEQ_T: case PLUSEQ_T: case MINUSEQ_T: case DIVEQ_T: case MULTEQ_T: case MODULOEQ_T: case BANDEQ_T: case BOREQ_T: case BXOREQ_T: if (t->elem[1].u.data){ if ((ret=fix_expr((struct expr*)t->elem[1].u.data))<0) return ret; } break; case USE_BLACKLIST_T: case UNUSE_BLACKLIST_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("bad [UN]USE_BLACKLIST type %d\n",t->elem[0].type); ret=E_BUG; goto error; } host.s = t->elem[0].u.string; host.len = strlen(host.s); if ( strcasecmp(host.s,"all")==0 ) { blh = NULL; } else { blh = get_bl_head_by_name(&host); if (blh==NULL) { LM_ERR("[UN]USE_BLACKLIST - list " "%s not configured\n", t->elem[0].u.string); ret=E_CFG; goto error; } } t->elem[0].type = BLACKLIST_ST; t->elem[0].u.data = blh; break; case CACHE_STORE_T: case CACHE_FETCH_T: case CACHE_REMOVE_T: /* attr name */ s.s = (char*)t->elem[1].u.data; s.len = strlen(s.s); if(s.len==0) { LM_ERR("param 2 is empty string!\n"); return E_CFG; } if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n", s.s); ret=E_BUG; goto error; } t->elem[1].u.data = (void*)model; if (t->type==CACHE_REMOVE_T) break; /* value */ if (t->type==CACHE_FETCH_T) { if(((pv_spec_p)t->elem[2].u.data)->type!= PVT_AVP) { LM_ERR("Wrong type for the third argument - " "must be an AVP\n"); ret=E_BUG; goto error; } } else { s.s = (char*)t->elem[2].u.data; s.len = strlen(s.s); if(s.len==0) { LM_ERR("param 2 is empty string!\n"); return E_CFG; } if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n",s.s); ret=E_BUG; goto error; } t->elem[2].u.data = (void*)model; } break; case XDBG_T: case XLOG_T: s.s = (char*)t->elem[1].u.data; if (s.s == NULL) { /* commands have only one parameter */ s.s = (char *)t->elem[0].u.data; s.len = strlen(s.s); if(s.len==0) { LM_ERR("param is empty string!\n"); return E_CFG; } if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n", s.s); ret=E_BUG; goto error; } t->elem[0].u.data = (void*)model; t->elem[0].type = SCRIPTVAR_ELEM_ST; } else { /* there are two parameters */ s.s = (char *)t->elem[0].u.data; s.len = strlen(s.s); if (s.len == 0) { LM_ERR("param is empty string\n"); return E_CFG; } xlp = (xl_level_p)pkg_malloc(sizeof(xl_level_t)); if(xlp == NULL) { LM_ERR("no more memory\n"); return E_UNSPEC; } memset(xlp, 0, sizeof(xl_level_t)); if(s.s[0]==PV_MARKER) { xlp->type = 1; if(pv_parse_spec(&s, &xlp->v.sp)==NULL) { LM_ERR("invalid level param\n"); return E_UNSPEC; } } else { xlp->type = 0; switch(s.s[2]) { case 'A': xlp->v.level = L_ALERT; break; case 'C': xlp->v.level = L_CRIT; break; case 'E': xlp->v.level = L_ERR; break; case 'W': xlp->v.level = L_WARN; break; case 'N': xlp->v.level = L_NOTICE; break; case 'I': xlp->v.level = L_INFO; break; case 'D': xlp->v.level = L_DBG; break; default: LM_ERR("unknown log level\n"); return E_UNSPEC; } } t->elem[0].u.data = xlp; s.s = t->elem[1].u.data; s.len = strlen(s.s); if (pv_parse_format(&s, &model) || model == NULL) { LM_ERR("wrong fomat [%s] for value param\n",s.s); ret=E_BUG; goto error; } t->elem[1].u.data = model; t->elem[1].type = SCRIPTVAR_ELEM_ST; } break; case CONSTRUCT_URI_T: for (i=0;i<5;i++) { s.s = (char*)t->elem[i].u.data; s.len = strlen(s.s); if(s.len==0) continue; if(pv_parse_format(&s ,&(models[i])) || models[i]==NULL) { LM_ERR("wrong format [%s] for value param!\n",s.s); ret=E_BUG; goto error; } t->elem[i].u.data = (void*)models[i]; } if (((pv_spec_p)t->elem[5].u.data)->type != PVT_AVP) { LM_ERR("Wrong type for the third argument - " "must be an AVP\n"); ret=E_BUG; goto error; } break; } } return 0; error: LM_ERR("fixing failed (code=%d) at cfg line %d\n", ret, t->line); return ret; }
/* returns 0 if ok, <0 on error */ static int fix_actions(struct action* a) { struct action *t; struct proxy_l* p; char *tmp; int ret; cmd_export_t* cmd; struct sr_module* mod; str s; struct hostent* he; struct ip_addr ip; struct socket_info* si; if (a==0){ LOG(L_CRIT,"BUG: fix_actions: null pointer\n"); return E_BUG; } for(t=a; t!=0; t=t->next){ switch(t->type){ case FORWARD_T: case FORWARD_TLS_T: case FORWARD_TCP_T: case FORWARD_UDP_T: case SEND_T: case SEND_TCP_T: switch(t->p1_type){ case IP_ST: tmp=strdup(ip_addr2a( (struct ip_addr*)t->p1.data)); if (tmp==0){ LOG(L_CRIT, "ERROR: fix_actions:" "memory allocation failure\n"); return E_OUT_OF_MEM; } t->p1_type=STRING_ST; t->p1.string=tmp; /* no break */ case STRING_ST: s.s = t->p1.string; s.len = strlen(s.s); p=add_proxy(&s, t->p2.number, 0); /* FIXME proto*/ if (p==0) return E_BAD_ADDRESS; t->p1.data=p; t->p1_type=PROXY_ST; break; case URIHOST_ST: break; default: LOG(L_CRIT, "BUG: fix_actions: invalid type" "%d (should be string or number)\n", t->type); return E_BUG; } break; case IF_T: if (t->p1_type!=EXPR_ST){ LOG(L_CRIT, "BUG: fix_actions: invalid subtype" "%d for if (should be expr)\n", t->p1_type); return E_BUG; }else if( (t->p2_type!=ACTIONS_ST)&&(t->p2_type!=NOSUBTYPE) ){ LOG(L_CRIT, "BUG: fix_actions: invalid subtype" "%d for if() {...} (should be action)\n", t->p2_type); return E_BUG; }else if( (t->p3_type!=ACTIONS_ST)&&(t->p3_type!=NOSUBTYPE) ){ LOG(L_CRIT, "BUG: fix_actions: invalid subtype" "%d for if() {} else{...}(should be action)\n", t->p3_type); return E_BUG; } if (t->p1.data){ if ((ret=fix_expr((struct expr*)t->p1.data))<0) return ret; } if ( (t->p2_type==ACTIONS_ST)&&(t->p2.data) ){ if ((ret=fix_actions((struct action*)t->p2.data))<0) return ret; } if ( (t->p3_type==ACTIONS_ST)&&(t->p3.data) ){ if ((ret=fix_actions((struct action*)t->p3.data))<0) return ret; } break; case MODULE_T: if ((mod=find_module(t->p1.data, &cmd))!=0){ DBG("fixing %s %s\n", mod->path, cmd->name); if (cmd->fixup){ if (cmd->param_no>0){ ret=cmd->fixup(&t->p2.data, 1); t->p2_type=MODFIXUP_ST; if (ret<0) return ret; } if (cmd->param_no>1){ ret=cmd->fixup(&t->p3.data, 2); t->p3_type=MODFIXUP_ST; if (ret<0) return ret; } } } break; case FORCE_SEND_SOCKET_T: if (t->p1_type!=SOCKID_ST){ LOG(L_CRIT, "BUG: fix_actions: invalid subtype" "%d for force_send_socket\n", t->p1_type); return E_BUG; } he=resolvehost(((struct socket_id*)t->p1.data)->name); if (he==0){ LOG(L_ERR, "ERROR: fix_actions: force_send_socket:" " could not resolve %s\n", ((struct socket_id*)t->p1.data)->name); return E_BAD_ADDRESS; } hostent2ip_addr(&ip, he, 0); si=find_si(&ip, ((struct socket_id*)t->p1.data)->port, ((struct socket_id*)t->p1.data)->proto); if (si==0){ LOG(L_ERR, "ERROR: fix_actions: bad force_send_socket" " argument: %s:%d (ser doesn't listen on it)\n", ((struct socket_id*)t->p1.data)->name, ((struct socket_id*)t->p1.data)->port); return E_BAD_ADDRESS; } t->p1.data=si; t->p1_type=SOCKETINFO_ST; break; } } return 0; }
/* returns 0 if ok, <0 on error */ static int fix_actions(struct action* a) { struct action *t; int ret; cmd_export_t* cmd; struct hostent* he; struct ip_addr ip; struct socket_info* si; str host; int proto=PROTO_NONE, port; struct proxy_l *p; struct bl_head *blh; if (a==0){ LM_CRIT("null pointer\n"); return E_BUG; } for(t=a; t!=0; t=t->next){ switch(t->type){ case FORWARD_T: if (t->elem[0].type==NOSUBTYPE) break; case SEND_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("invalid type %d (should be string)\n", t->type); return E_BUG; } ret = parse_phostport( t->elem[0].u.string, strlen(t->elem[0].u.string), &host.s, &host.len, &port, &proto); if (ret!=0) { LM_ERR("ERROR:fix_actions: FORWARD/SEND bad " "argument\n"); return E_CFG; } p = add_proxy( &host,(unsigned short)port, proto); if (p==0) { LM_ERR("forward/send failed to add proxy"); return E_CFG; } t->elem[0].type = PROXY_ST; t->elem[0].u.data = (void*)p; break; case IF_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for if (should be expr)\n", t->elem[0].type); return E_BUG; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {...} (should be" "action)\n", t->elem[1].type); return E_BUG; }else if( (t->elem[2].type!=ACTIONS_ST) &&(t->elem[2].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for if() {} else{...}(should" "be action)\n", t->elem[2].type); return E_BUG; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } if ( (t->elem[2].type==ACTIONS_ST)&&(t->elem[2].u.data) ){ if((ret=fix_actions((struct action*)t->elem[2].u.data))<0) return ret; } break; case WHILE_T: if (t->elem[0].type!=EXPR_ST){ LM_CRIT("invalid subtype %d for while (should be expr)\n", t->elem[0].type); return E_BUG; }else if( (t->elem[1].type!=ACTIONS_ST) &&(t->elem[1].type!=NOSUBTYPE) ){ LM_CRIT("invalid subtype %d for while() {...} (should be" "action)\n", t->elem[1].type); return E_BUG; } if (t->elem[0].u.data){ if ((ret=fix_expr((struct expr*)t->elem[0].u.data))<0) return ret; } if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case SWITCH_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case CASE_T: if ( (t->elem[1].type==ACTIONS_ST)&&(t->elem[1].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[1].u.data))<0) return ret; } break; case DEFAULT_T: if ( (t->elem[0].type==ACTIONS_ST)&&(t->elem[0].u.data) ){ if ((ret=fix_actions((struct action*)t->elem[0].u.data))<0) return ret; } break; case MODULE_T: cmd = (cmd_export_t*)t->elem[0].u.data; LM_DBG("fixing %s, line %d\n", cmd->name, t->line); if (cmd->fixup){ if (cmd->param_no>0){ ret=cmd->fixup(&t->elem[1].u.data, 1); t->elem[1].type=MODFIXUP_ST; if (ret<0) goto error; } if (cmd->param_no>1){ ret=cmd->fixup(&t->elem[2].u.data, 2); t->elem[2].type=MODFIXUP_ST; if (ret<0) goto error; } if (cmd->param_no==0){ ret=cmd->fixup( 0, 0); if (ret<0) goto error; } } break; case FORCE_SEND_SOCKET_T: if (t->elem[0].type!=SOCKID_ST){ LM_CRIT("invalid subtype %d for force_send_socket\n", t->elem[0].type); return E_BUG; } he=resolvehost(((struct socket_id*)t->elem[0].u.data)->name,0); if (he==0){ LM_ERR(" could not resolve %s\n", ((struct socket_id*)t->elem[0].u.data)->name); ret = E_BAD_ADDRESS; goto error; } hostent2ip_addr(&ip, he, 0); si=find_si(&ip, ((struct socket_id*)t->elem[0].u.data)->port, ((struct socket_id*)t->elem[0].u.data)->proto); if (si==0){ LM_ERR("bad force_send_socket" " argument: %s:%d (ser doesn't listen on it)\n", ((struct socket_id*)t->elem[0].u.data)->name, ((struct socket_id*)t->elem[0].u.data)->port); ret = E_BAD_ADDRESS; goto error; } t->elem[0].u.data=si; t->elem[0].type=SOCKETINFO_ST; break; case SET_DEBUG_T: if (t->elem[0].type==NOSUBTYPE) break; if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("fix_actions: BUG in setdebug() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } /* normalize the value */ if (t->elem[0].u.number>L_DBG) t->elem[0].u.number = L_DBG; else if (t->elem[0].u.number<L_ALERT) t->elem[0].u.number = L_ALERT; break; case SETFLAG_T: case RESETFLAG_T: case ISFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } if (!flag_in_range( t->elem[0].u.number )) { ret=E_CFG; goto error; } break; case SETSFLAG_T: case RESETSFLAG_T: case ISSFLAGSET_T: if (t->elem[0].type!=NUMBER_ST) { LM_CRIT("bad xxxsflag() type %d\n", t->elem[0].type ); ret=E_BUG; goto error; } t->elem[0].u.number = fixup_flag( t->elem[0].u.number ); if (t->elem[0].u.data==0) { ret=E_CFG; goto error; } break; case SETBFLAG_T: case RESETBFLAG_T: case ISBFLAGSET_T: if (t->elem[0].type!=NUMBER_ST || t->elem[1].type!=NUMBER_ST) { LM_CRIT("bad xxxbflag() type " "%d,%d\n", t->elem[0].type, t->elem[0].type); ret=E_BUG; goto error; } t->elem[1].u.number = fixup_flag( t->elem[1].u.number ); if (t->elem[1].u.data==0) { ret=E_CFG; goto error; } break; case EQ_T: case COLONEQ_T: case PLUSEQ_T: case MINUSEQ_T: case DIVEQ_T: case MULTEQ_T: case MODULOEQ_T: case BANDEQ_T: case BOREQ_T: case BXOREQ_T: if (t->elem[1].u.data){ if ((ret=fix_expr((struct expr*)t->elem[1].u.data))<0) return ret; } break; case USE_BLACKLIST_T: if (t->elem[0].type!=STRING_ST) { LM_CRIT("bad USE_BLACKLIST type %d\n", t->elem[0].type); ret=E_BUG; goto error; } host.s = t->elem[0].u.string; host.len = strlen(host.s); blh = get_bl_head_by_name(&host); if (blh==NULL) { LM_ERR("USE_BLACKLIST - list " "%s not configured\n", t->elem[0].u.string); ret=E_CFG; goto error; } t->elem[0].type = BLACKLIST_ST; t->elem[0].u.data = blh; break; } } return 0; error: LM_ERR("fixing failed (code=%d) at cfg line %d\n", ret, t->line); return ret; }
/* fixes a socket list => resolve addresses, * interface names, fills missing members, remove duplicates * fills type_flags if not null with SOCKET_T_IPV4 and/or SOCKET_T_IPV6*/ static int fix_socket_list(struct socket_info **list, int* type_flags) { struct socket_info* si; struct socket_info* l; struct socket_info* next; char* tmp; int len; struct hostent* he; char** h; if (type_flags) *type_flags=0; /* try to change all the interface names into addresses * --ugly hack */ for (si=*list;si;){ next=si->next; if (add_interfaces(si->name.s, AF_INET, si->port_no, si->proto, list)!=-1){ /* success => remove current entry (shift the entire array)*/ sock_listrm(list, si); free_sock_info(si); } si=next; } /* get ips & fill the port numbers*/ #ifdef EXTRA_DEBUG DBG("Listening on \n"); #endif for (si=*list;si;si=si->next){ /* fix port number, port_no should be !=0 here */ if (si->port_no==0){ #ifdef USE_TLS si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no; #else si->port_no= port_no; #endif } tmp=int2str(si->port_no, &len); if (len>=MAX_PORT_LEN){ LOG(L_ERR, "ERROR: fix_socket_list: bad port number: %d\n", si->port_no); goto error; } si->port_no_str.s=(char*)pkg_malloc(len+1); if (si->port_no_str.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } strncpy(si->port_no_str.s, tmp, len+1); si->port_no_str.len=len; /* get "official hostnames", all the aliases etc. */ he=resolvehost(si->name.s); if (he==0){ LOG(L_ERR, "ERROR: fix_socket_list: could not resolve %s\n", si->name.s); goto error; } /* check if we got the official name */ if (strcasecmp(he->h_name, si->name.s)!=0){ if (add_alias(si->name.s, si->name.len, si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n"); } /* change the official name */ pkg_free(si->name.s); si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1); if (si->name.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } si->name.len=strlen(he->h_name); strncpy(si->name.s, he->h_name, si->name.len+1); } /* add the aliases*/ for(h=he->h_aliases; h && *h; h++) if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n"); } hostent2ip_addr(&si->address, he, 0); /*convert to ip_addr format*/ if (type_flags){ *type_flags|=(si->address.af==AF_INET)?SOCKET_T_IPV4:SOCKET_T_IPV6; } if ((tmp=ip_addr2a(&si->address))==0) goto error; si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1); if (si->address_str.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } strncpy(si->address_str.s, tmp, strlen(tmp)+1); /* set is_ip (1 if name is an ip address, 0 otherwise) */ si->address_str.len=strlen(tmp); if ( (si->address_str.len==si->name.len)&& (strncasecmp(si->address_str.s, si->name.s, si->address_str.len)==0) ){ si->flags|=SI_IS_IP; /* do rev. DNS on it (for aliases)*/ he=rev_resolvehost(&si->address); if (he==0){ LOG(L_WARN, "WARNING: fix_socket_list:" " could not rev. resolve %s\n", si->name.s); }else{ /* add the aliases*/ if (add_alias(he->h_name, strlen(he->h_name), si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list:" "add_alias failed\n"); } for(h=he->h_aliases; h && *h; h++) if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list:" " add_alias failed\n"); } } } #ifdef USE_MCAST /* Check if it is an multicast address and * set the flag if so */ if (is_mcast(&si->address)) { si->flags |= SI_IS_MCAST; } #endif /* USE_MCAST */ #ifdef EXTRA_DEBUG printf(" %.*s [%s]:%s%s\n", si->name.len, si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); #endif } /* removing duplicate addresses*/ for (si=*list;si; si=si->next){ for (l=si->next;l;){ next=l->next; if ((si->port_no==l->port_no) && (si->address.af==l->address.af) && (memcmp(si->address.u.addr, l->address.u.addr, si->address.len) == 0) ){ #ifdef EXTRA_DEBUG printf("removing duplicate %s [%s] == %s [%s]\n", si->name.s, si->address_str.s, l->name.s, l->address_str.s); #endif /* add the name to the alias list*/ if ((!(l->flags& SI_IS_IP)) && ( (l->name.len!=si->name.len)|| (strncmp(l->name.s, si->name.s, si->name.len)!=0)) ) add_alias(l->name.s, l->name.len, l->port_no, l->proto); /* remove l*/ sock_listrm(list, l); free_sock_info(l); } l=next; } } #ifdef USE_MCAST /* Remove invalid multicast entries */ si=*list; while(si){ if ((si->flags & SI_IS_MCAST) && ((si->proto == PROTO_TCP) #ifdef USE_TLS || (si->proto == PROTO_TLS) #endif /* USE_TLS */ )){ LOG(L_WARN, "WARNING: removing entry %s:%s [%s]:%s\n", get_proto_name(si->proto), si->name.s, si->address_str.s, si->port_no_str.s); l = si; si=si->next; sock_listrm(list, l); free_sock_info(l); } else { si=si->next; } } #endif /* USE_MCAST */ return 0; error: return -1; }
int add_dst( rt_data_t *r, /* id */ int id, /* ip address */ char* ip, /* strip len */ int strip, /* pri prefix */ char* pri, /* dst type*/ int type, /* dst attrs*/ char* attrs, /* probe_mode */ int probing ) { pgw_t *pgw=NULL, *tmp=NULL; struct sip_uri uri; int l_ip,l_pri,l_attrs; #define GWABUF_MAX_SIZE 512 char gwabuf[GWABUF_MAX_SIZE]; union sockaddr_union sau; struct proxy_l *proxy; str gwas; if (NULL==r || NULL==ip) { LM_ERR("invalid parametres\n"); goto err_exit; } l_ip = strlen(ip); l_pri = pri?strlen(pri):0; l_attrs = attrs?strlen(attrs):0; pgw = (pgw_t*)shm_malloc(sizeof(pgw_t) + l_ip + l_pri + l_attrs); if (NULL==pgw) { LM_ERR("no more shm mem (%u)\n", (unsigned int)(sizeof(pgw_t)+l_ip+l_pri +l_attrs)); goto err_exit; } memset(pgw,0,sizeof(pgw_t)); switch(probing) { case 0: pgw->flags = 0; break; case 1: pgw->flags = DR_DST_PING_DSBL_FLAG; break; case 2: pgw->flags = DR_DST_PING_PERM_FLAG; break; default: goto err_exit; } pgw->ip_str.len= l_ip; pgw->ip_str.s = (char*)(pgw+1); memcpy(pgw->ip_str.s, ip, l_ip); if (pri) { pgw->pri.len = l_pri; pgw->pri.s = ((char*)(pgw+1))+l_ip; memcpy(pgw->pri.s, pri, l_pri); } if (attrs) { pgw->attrs.len = l_attrs; pgw->attrs.s = ((char*)(pgw+1))+l_ip+l_pri; memcpy(pgw->attrs.s, attrs, l_attrs); } pgw->id = id; pgw->strip = strip; pgw->type = type; /* add address in the list */ if(pgw->ip_str.len<5 || (strncasecmp("sip:", ip, 4) && strncasecmp("sips:", ip, 5))) { if(pgw->ip_str.len+4>=GWABUF_MAX_SIZE) { LM_ERR("GW address (%d) longer " "than %d\n",pgw->ip_str.len+4,GWABUF_MAX_SIZE); goto err_exit; } memcpy(gwabuf, "sip:", 4); memcpy(gwabuf+4, ip, l_ip); gwas.s = gwabuf; gwas.len = 4+l_ip; } else { gwas.s = ip; gwas.len = l_ip; } memset(&uri, 0, sizeof(struct sip_uri)); if(parse_uri(gwas.s, gwas.len, &uri)!=0) { LM_ERR("invalid uri <%.*s>\n", gwas.len, gwas.s); goto err_exit; } proxy = mk_proxy(&uri.host,uri.port_no,uri.proto,(uri.type==SIPS_URI_T)); if (proxy==NULL) { if(dr_force_dns) { LM_ERR("cannot resolve <%.*s>\n", uri.host.len, uri.host.s); goto err_exit; } else { LM_DBG("cannot resolve <%.*s> - won't be used" " by is_from_gw()\n", uri.host.len, uri.host.s); goto done; } } hostent2ip_addr( &pgw->ips[0], &proxy->host, proxy->addr_idx); pgw->port = uri.port_no; LM_DBG("first gw ip addr [%s]\n", ip_addr2a(&pgw->ips[0])); pgw->ips_no = 1; while (pgw->ips_no<DR_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &pgw->ips[pgw->ips_no], &sau); LM_DBG("additional gw ip addr [%s]\n", ip_addr2a( &pgw->ips[pgw->ips_no] ) ); pgw->ips_no++; } free_proxy(proxy); pkg_free(proxy); done: if(NULL==r->pgw_l) r->pgw_l = pgw; else { tmp = r->pgw_l; while(NULL != tmp->next) tmp = tmp->next; tmp->next = pgw; } return 0; err_exit: if(NULL!=pgw) shm_free(pgw); return -1; }
int add_dst( rt_data_t *r, /* id */ int id, /* ip address */ char* ip, /* strip len */ int strip, /* pri prefix */ char* pri, /* dst type*/ int type, /* dst attrs*/ char* attrs ) { pgw_t *pgw=NULL, *tmp=NULL; pgw_addr_t *tmpa=NULL; struct hostent* he; struct sip_uri uri; struct ip_addr ipa; int l_ip,l_pri,l_attrs; #define GWABUF_MAX_SIZE 512 char gwabuf[GWABUF_MAX_SIZE]; str gwas; if (NULL==r || NULL==ip) { LM_ERR("invalid parametres\n"); goto err_exit; } l_ip = strlen(ip); l_pri = pri?strlen(pri):0; l_attrs = attrs?strlen(attrs):0; pgw = (pgw_t*)shm_malloc(sizeof(pgw_t) + l_ip + l_pri + l_attrs); if (NULL==pgw) { LM_ERR("no more shm mem (%u)\n", (unsigned int)(sizeof(pgw_t)+l_ip+l_pri +l_attrs)); goto err_exit; } memset(pgw,0,sizeof(pgw_t)); pgw->ip.len= l_ip; pgw->ip.s = (char*)(pgw+1); memcpy(pgw->ip.s, ip, l_ip); if (pri) { pgw->pri.len = l_pri; pgw->pri.s = ((char*)(pgw+1))+l_ip; memcpy(pgw->pri.s, pri, l_pri); } if (attrs) { pgw->attrs.len = l_attrs; pgw->attrs.s = ((char*)(pgw+1))+l_ip+l_pri; memcpy(pgw->attrs.s, attrs, l_attrs); } pgw->id = id; pgw->strip = strip; pgw->type = type; /* add address in the list */ if(pgw->ip.len<5 || (strncasecmp("sip:", ip, 4) &&strncasecmp("sips:", ip, 5))) { if(pgw->ip.len+4>=GWABUF_MAX_SIZE) { LM_ERR("GW address (%d) longer " "than %d\n",pgw->ip.len+4,GWABUF_MAX_SIZE); goto err_exit; } memcpy(gwabuf, "sip:", 4); memcpy(gwabuf+4, ip, pgw->ip.len); gwas.s = gwabuf; gwas.len = 4+pgw->ip.len; } else { gwas.s = ip; gwas.len = pgw->ip.len; } memset(&uri, 0, sizeof(struct sip_uri)); if(parse_uri(gwas.s, gwas.len, &uri)!=0) { LM_ERR("invalid uri <%.*s>\n", gwas.len, gwas.s); goto err_exit; } /* note we discard the port discovered by the resolve function - we are interested only in the port that was actually configured. */ if ((he=sip_resolvehost( &uri.host, NULL, (char*)(void*)&uri.proto))==0 ) { if(dr_force_dns) { LM_ERR("cannot resolve <%.*s>\n", uri.host.len, uri.host.s); goto err_exit; } else { LM_DBG("cannot resolve <%.*s> - won't be used" " by is_from_gw()\n", uri.host.len, uri.host.s); goto done; } } hostent2ip_addr(&ipa, he, 0); tmpa = r->pgw_addr_l; while(tmpa) { if(tmpa->type==type && uri.port_no==tmpa->port && ip_addr_cmp(&ipa, &tmpa->ip)) { LM_DBG("gw ip addr [%s]:%d loaded\n", ip_addr2a(&ipa), uri.port_no); goto done; } tmpa = tmpa->next; } LM_DBG("new gw ip addr [%s]\n", ip); tmpa = (pgw_addr_t*)shm_malloc(sizeof(pgw_addr_t)); if(tmpa==NULL) { LM_ERR("no more shm mem (%u)\n", (unsigned int)sizeof(pgw_addr_t)); goto err_exit; } memset(tmpa, 0, sizeof(pgw_addr_t)); memcpy(&tmpa->ip, &ipa, sizeof(struct ip_addr)); tmpa->port = uri.port_no; tmpa->type = type; tmpa->strip = strip; tmpa->next = r->pgw_addr_l; r->pgw_addr_l = tmpa; done: if(NULL==r->pgw_l) r->pgw_l = pgw; else { tmp = r->pgw_l; while(NULL != tmp->next) tmp = tmp->next; tmp->next = pgw; } return 0; err_exit: if(NULL!=pgw) shm_free(pgw); return -1; }
int add_dest2list(int id, str uri, struct socket_info *sock, int flags, int weight, str attrs, int list_idx, int * setn) { ds_dest_p dp = NULL; ds_set_p sp = NULL; struct sip_uri puri; /* For DNS-Lookups */ struct proxy_l *proxy; union sockaddr_union sau; /* check uri */ if(parse_uri(uri.s, uri.len, &puri)!=0 || puri.host.len>254) { LM_ERR("bad uri [%.*s]\n", uri.len, uri.s); goto err; } /* get dest set */ sp = ds_lists[list_idx]; while(sp) { if(sp->id == id) break; sp = sp->next; } if(sp==NULL) { sp = (ds_set_p)shm_malloc(sizeof(ds_set_t)); if(sp==NULL) { LM_ERR("no more memory.\n"); goto err; } memset(sp, 0, sizeof(ds_set_t)); sp->next = ds_lists[list_idx]; ds_lists[list_idx] = sp; *setn = *setn+1; } sp->id = id; sp->nr++; dp = (ds_dest_p)shm_malloc(sizeof(ds_dest_t)); if(dp==NULL) { LM_ERR("no more memory!\n"); goto err; } memset(dp, 0, sizeof(ds_dest_t)); /* store uri and attrs strings */ dp->uri.s = (char*)shm_malloc( (uri.len+1+attrs.len+1)*sizeof(char)); if(dp->uri.s==NULL) { LM_ERR("no more shm memory!\n"); goto err; } memcpy(dp->uri.s, uri.s, uri.len); dp->uri.s[uri.len]='\0'; dp->uri.len = uri.len; if (attrs.len) { dp->attrs.s = dp->uri.s + dp->uri.len + 1; memcpy(dp->attrs.s, attrs.s, attrs.len); dp->attrs.s[attrs.len]='\0'; dp->attrs.len = attrs.len; } /* copy flags, weight & socket */ dp->flags = flags; dp->weight = weight; dp->sock = sock; /* Do a DNS-Lookup for the Host-Name: */ proxy = mk_proxy( &puri.host, puri.port_no, puri.proto, (puri.type==SIPS_URI_T)); if (proxy==NULL) { LM_ERR("could not resolve %.*s, skipping it\n", puri.host.len, puri.host.s); goto err; } hostent2ip_addr( &dp->ips[0], &proxy->host, proxy->addr_idx); dp->ports[0] = proxy->port; dp->ips_cnt = 1; LM_DBG("first gw ip addr [%s]:%d\n", ip_addr2a(&dp->ips[0]), dp->ports[0]); /* get the next available IPs from DNS */ while (dp->ips_cnt<DS_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &dp->ips[dp->ips_cnt], &sau); dp->ports[dp->ips_cnt] = proxy->port; LM_DBG("additional gw ip addr [%s]:%d\n", ip_addr2a(&dp->ips[dp->ips_cnt]), dp->ports[dp->ips_cnt]); /* one more IP found */ dp->ips_cnt++; } /* free al the helper structures */ free_proxy(proxy); pkg_free(proxy); dp->next = sp->dlist; sp->dlist = dp; LM_DBG("dest [%d/%d] <%.*s> successfully loaded\n", sp->id, sp->nr, dp->uri.len, dp->uri.s); return 0; err: /* free allocated memory */ if(dp!=NULL) { if(dp->uri.s!=NULL) shm_free(dp->uri.s); shm_free(dp); } return -1; }
/* fixes a socket list => resolve addresses, * interface names, fills missing members, remove duplicates */ static int fix_socket_list(struct socket_info **list) { struct socket_info* si; struct socket_info* l; struct socket_info* next; char* tmp; int len; struct hostent* he; char** h; /* try to change all the interface names into addresses * --ugly hack */ for (si=*list;si;){ next=si->next; if (add_interfaces(si->name.s, AF_INET, si->port_no, si->proto, list)!=-1){ /* success => remove current entry (shift the entire array)*/ sock_listrm(list, si); free_sock_info(si); } si=next; } /* get ips & fill the port numbers*/ #ifdef EXTRA_DEBUG LM_DBG("listening on \n"); #endif LM_DBG("fix_socket_list"); for (si=*list;si;si=si->next){ /* fix the number of processes per interface */ if (si->children==0 && (si->proto==PROTO_UDP || si->proto==PROTO_SCTP)) si->children = children_no; /* fix port number, port_no should be !=0 here */ if (si->port_no==0){ #ifdef USE_TLS si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no; #else si->port_no= port_no; #endif } tmp=int2str(si->port_no, &len); if (len>=MAX_PORT_LEN){ LM_ERR("bad port number: %d\n", si->port_no); goto error; } si->port_no_str.s=(char*)pkg_malloc(len+1); if (si->port_no_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } strncpy(si->port_no_str.s, tmp, len+1); si->port_no_str.len=len; LM_DBG("resolvehost [%.*s] ",si->name.len,si->name.s); /* get "official hostnames", all the aliases etc. */ he=resolvehost(si->name.s,0); if (he==0){ LM_ERR("could not resolve %s\n", si->name.s); goto error; } LM_DBG("aliases [%.*s] == [%.*s] ", (int)strlen(he->h_name),he->h_name, si->name.len, si->name.s); /* check if we got the official name */ if (strcasecmp(he->h_name, si->name.s)!=0){ if (auto_aliases && add_alias(si->name.s, si->name.len, si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } /* change the official name */ pkg_free(si->name.s); si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1); if (si->name.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } si->name.len=strlen(he->h_name); strncpy(si->name.s, he->h_name, si->name.len+1); } /* add the aliases*/ if (auto_aliases) { for(h=he->h_aliases; h && *h; h++){ LM_DBG("h_alias [%.*s] ",(int)strlen(*h),*h); if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } } } hostent2ip_addr(&si->address, he, 0); /*convert to ip_addr format*/ if ((tmp=ip_addr2a(&si->address))==0) goto error; if (si->address.af == AF_INET6) { si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1+2); if (si->address_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } si->address_str.s[0] = '['; strncpy( si->address_str.s+1 , tmp, strlen(tmp)); si->address_str.s[1+strlen(tmp)] = ']'; si->address_str.s[2+strlen(tmp)] = '\0'; si->address_str.len=strlen(tmp) + 2; } else { si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1); if (si->address_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } strncpy(si->address_str.s, tmp, strlen(tmp)+1); si->address_str.len=strlen(tmp); } /* set is_ip (1 if name is an ip address, 0 otherwise) */ if ( auto_aliases && (si->address_str.len==si->name.len) && (strncasecmp(si->address_str.s, si->name.s, si->address_str.len)==0) ){ si->flags|=SI_IS_IP; /* do rev. DNS on it (for aliases)*/ he=rev_resolvehost(&si->address); if (he==0){ LM_WARN("could not rev. resolve %s\n", si->name.s); }else{ /* add the aliases*/ if (add_alias(he->h_name, strlen(he->h_name), si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } for(h=he->h_aliases; h && *h; h++) if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){ LM_ERR(" add_alias failed\n"); } } } /* Now build an ip_addr structure for the adv_name, if there is one * so that find_si can find it later easily. Doing this so that * we can force_send_socket() on an advertised name. Generally there * is little interest in dealing with an advertised name as anything * other than an opaque string that we blindly put into the SIP * message. */ if(si->adv_name_str.len) { /* If adv_name_str is already an IP, this is kinda foolish cus it * converts it to ip_addr, then to he, then here we go back to * ip_addr, but it's either that, or we duplicate the logic to * check for an ip address here, and still we might have to call * resolvehost(). */ he=resolvehost(si->adv_name_str.s,0); if (he==0){ LM_ERR("ERROR: fix_socket_list: could not resolve " "advertised name %s\n", si->adv_name_str.s); goto error; } hostent2ip_addr(&si->adv_address, he, 0); /*convert to ip_addr */ /* build and set string encoding for the adv socket info * This is usefful for the usrloc module when it's generating * or updating the socket on a location record, so we'll generate * it up front just like the regular sock_str so we don't have * to worry about it later. */ tmp = socket2str( si, 0, &si->adv_sock_str.len, 1); if (tmp==0) { LM_ERR("ERROR: fix_socket_list: failed to convert " "socket to string (adv)\n"); goto error; } si->adv_sock_str.s=(char*)pkg_malloc(si->adv_sock_str.len); if (si->adv_sock_str.s==0) { LM_ERR("ERROR: fix_socket_list: out of memory.\n"); goto error; } memcpy(si->adv_sock_str.s, tmp, si->adv_sock_str.len); } /* build and set string encoding for the real socket info */ tmp = socket2str( si, 0, &si->sock_str.len, 0); if (tmp==0) { LM_ERR("failed to convert socket to string"); goto error; } si->sock_str.s=(char*)pkg_malloc(si->sock_str.len); if (si->sock_str.s==0) { LM_ERR("out of pkg memory.\n"); goto error; } memcpy(si->sock_str.s, tmp, si->sock_str.len); #ifdef USE_MCAST /* Check if it is an multicast address and * set the flag if so */ if (is_mcast(&si->address)) { si->flags |= SI_IS_MCAST; } #endif /* USE_MCAST */ #ifdef EXTRA_DEBUG printf(" %.*s [%s]:%s%s\n", si->name.len, si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); #endif } /* removing duplicate addresses*/ for (si=*list;si; si=si->next){ for (l=si->next;l;){ next=l->next; if ((si->port_no==l->port_no) && (si->address.af==l->address.af) && (memcmp(si->address.u.addr, l->address.u.addr, si->address.len) == 0) ){ #ifdef EXTRA_DEBUG printf("removing duplicate %s [%s] == %s [%s]\n", si->name.s, si->address_str.s, l->name.s, l->address_str.s); #endif /* add the name to the alias list*/ if ((!(l->flags& SI_IS_IP)) && ( (l->name.len!=si->name.len)|| (strncmp(l->name.s, si->name.s, si->name.len)!=0)) ) add_alias(l->name.s, l->name.len, l->port_no, l->proto); /* remove l*/ sock_listrm(list, l); free_sock_info(l); } l=next; } } #ifdef USE_MCAST /* Remove invalid multicast entries */ si=*list; while(si){ if ((si->flags & SI_IS_MCAST) && ((si->proto == PROTO_TCP) #ifdef USE_TLS || (si->proto == PROTO_TLS) #endif /* USE_TLS */ #ifdef USE_SCTP || (si->proto == PROTO_SCTP) #endif )){ LM_WARN("removing entry %s:%s [%s]:%s\n", get_proto_name(si->proto), si->name.s, si->address_str.s, si->port_no_str.s); l = si; si=si->next; sock_listrm(list, l); free_sock_info(l); } else { si=si->next; } } #endif /* USE_MCAST */ return 0; error: return -1; }