/*! \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; }
struct bl_head *create_bl_head(int owner, int flags, struct bl_rule *head, struct bl_rule *tail, str *name) { unsigned int i; i = used_heads; if (i==max_heads) { LM_ERR("too many lists\n"); return NULL; } if (get_bl_head_by_name(name)!=NULL) { LM_CRIT("duplicated name!\n"); return NULL; } if ( flags&BL_READONLY_LIST && flags&BL_DO_EXPIRE){ LM_CRIT("RO lists cannot accept EXPIRES!\n"); return NULL; } /* copy list name */ if (no_shm) blst_heads[i].name.s = (char*)pkg_malloc(name->len + 1); else blst_heads[i].name.s = (char*)shm_malloc(name->len + 1); if (blst_heads[i].name.s==NULL) { LM_ERR("no more pkg memory!\n"); return NULL; } memcpy( blst_heads[i].name.s, name->s, name->len); blst_heads[i].name.s[name->len] = '\0'; blst_heads[i].name.len = name->len; /* build lock? */ if (!no_shm && !(flags&BL_READONLY_LIST)) { if ( (blst_heads[i].lock=lock_alloc())==NULL ) { LM_ERR("failed to create lock!\n"); shm_free(blst_heads[i].name.s); return NULL; } if ( lock_init(blst_heads[i].lock)==NULL ) { LM_ERR("failed to init lock!\n"); shm_free(blst_heads[i].name.s); lock_dealloc(blst_heads[i].lock); return NULL; } } used_heads++; blst_heads[i].owner = owner; blst_heads[i].flags = flags; blst_heads[i].first = head; blst_heads[i].last = tail; if (flags&BL_BY_DEFAULT) bl_default_marker |= (1<<i); return blst_heads + i; }
/* 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; }