int compare_rtpp(struct rtpp_node *r_node, struct rtpp_notify_node *n_node) { char buffer[BUF_LEN]; char *p; struct hostent *rtpp_server; if (r_node->rn_umode != n_node->mode) return 0; memcpy(buffer,r_node->rn_address,strlen(r_node->rn_address)); p = strrchr(buffer, ':'); if (!p) { LM_ERR("invalid address %s\n", r_node->rn_address); return 0; } *p = 0; rtpp_server = resolvehost(buffer, 0); if (!rtpp_server || !rtpp_server->h_addr) { LM_ERR("cannot resolve hostname %s\n", r_node->rn_address); return 0; } if (memcmp(n_node->addr, rtpp_server->h_addr, rtpp_server->h_length)!= 0) return 0; return 1; }
static union sockaddr_union *jsonrpc_get_dst(str *ip_port) { static union sockaddr_union _su; struct hostent *hentity; char *p, bk; str host; str port; int iport; int err; if (!ip_port || !ip_port->len) { LM_ERR("no IP:port specified!\n"); return NULL; } /* search for the port */ p = memchr(ip_port->s, ':', ip_port->len); if (!p) { LM_ERR("invalid IP:port %.*s\n", ip_port->len, ip_port->s); return NULL; } host.s = ip_port->s; host.len = p - ip_port->s; /* remaining should be port */ port.s = p + 1; port.len = ip_port->len - (host.len + 1/* : */); trim(&port); iport = str2s(port.s, port.len, &err); if (iport <= 0 || err != 0 || iport > 65535) { LM_ERR("Invalid port specified [%.*s]\n", port.len, port.s); return NULL; } trim(&host); /* null terminate host */ bk = host.s[host.len]; host.s[host.len] = 0; hentity = resolvehost(host.s, 0); host.s[host.len] = bk; if (!hentity) { LM_ERR("cannot resolve host %s\n", host.s); return NULL; } if(hostent2su(&_su, hentity, 0, iport)){ LM_ERR("failed to resolve %s\n", host.s); return NULL; } return &_su; }
uint32_t rc_get_ipaddr (char *host) { const struct hostent* he; struct in_addr** addr_list; he=resolvehost(host, 0/*do test if is ip*/); /* FIXME the function is not for IPV6 */ addr_list = (struct in_addr **)he->h_addr_list; if (addr_list[0]) return addr_list[0]->s_addr; return 0; }
int net_listen(char *server, int port) { int fd; struct sockaddr_in sin; int on = 1; memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = htons(port); if (!inet_aton(server, &sin.sin_addr)) { struct hostent *host; LM_DBG("resolving %s...\n", server); if (!(host = resolvehost(server,0))) { LM_ERR("resolving %s failed (%s).\n", server, hstrerror(h_errno)); return -1; } memcpy(&sin.sin_addr, host->h_addr_list[0], host->h_length); } if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { LM_ERR("socket() failed: %s\n", strerror(errno)); return -1; } LM_DBG("listening on %s:%d\n", inet_ntoa(sin.sin_addr), port); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { LM_WARN("setsockopt(SO_REUSEADDR) failed: %s\n",strerror(errno)); } if (bind(fd, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) { LM_ERR("bind() failed: %s\n", strerror(errno)); close(fd); return -1; } if (listen(fd, 1) < 0) { LM_ERR("listen() failed: %s\n", strerror(errno)); close(fd); return -1; } return fd; }
struct rtpp_notify_node *new_rtpp_notify_node(struct rtpp_node *crt_rtpp) { char buffer[BUF_LEN]; char *p; struct hostent *rtpp_server; struct rtpp_notify_node *rtpp_lst; rtpp_lst = (struct rtpp_notify_node*) shm_malloc(sizeof(struct rtpp_notify_node)); if (!rtpp_lst) { LM_ERR("no shm more memory\n"); return NULL; } rtpp_lst->mode = crt_rtpp->rn_umode; rtpp_lst->index = 0; rtpp_lst->next = NULL; memcpy(buffer,crt_rtpp->rn_address,strlen(crt_rtpp->rn_address)); p = strrchr(buffer, ':'); if (!p) { LM_ERR("invalid address %s\n", crt_rtpp->rn_address); goto error; } *p = 0; rtpp_server = resolvehost(buffer, 0); if (!rtpp_server || !rtpp_server->h_addr) { LM_ERR("cannot resolve hostname %s\n", crt_rtpp->rn_address); goto error; } rtpp_lst->addr = (char*)shm_malloc(rtpp_server->h_length); if (!rtpp_lst->addr) { LM_ERR("no more shm memory\n"); goto error; } memcpy(rtpp_lst->addr,rtpp_server->h_addr,rtpp_server->h_length); return rtpp_lst; error: shm_free(rtpp_lst); return NULL; }
int net_connect(char *server, int port) { int fd; struct sockaddr_in sin; memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_port = htons(port); if (!inet_aton(server, &sin.sin_addr)) { struct hostent *host; LM_DBG("resolving %s...\n", server); if (!(host = resolvehost(server,0))) { LM_ERR("resolving %s failed (%s).\n", server, hstrerror(h_errno)); return -1; } memcpy(&sin.sin_addr, host->h_addr_list[0], host->h_length); } if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { LM_ERR("socket() failed: %s\n", strerror(errno)); return -1; } LM_DBG("connecting to %s:%d...\n", inet_ntoa(sin.sin_addr), port); if (connect(fd, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) { LM_ERR("connect() failed: %s\n", strerror(errno)); close(fd); return -1; } LM_DBG("connected to %s:%d...\n", inet_ntoa(sin.sin_addr), port); return fd; }
/** * connect to JABBER server */ int xj_jcon_connect(xj_jcon jbc) { struct sockaddr_in address; struct hostent *he; int sock; // open connection to server if((sock = socket(AF_INET, SOCK_STREAM, 0))<0) { LM_DBG("failed to create the socket\n"); return -1; } #ifdef XJ_EXTRA_DEBUG LM_DBG("socket [%d]\n", sock); #endif he=resolvehost(jbc->hostname,0); if(he == NULL) { LM_DBG("failed to get info about Jabber server address\n"); return -1; } // fill the fields of the address memcpy(&address.sin_addr, he->h_addr, he->h_length); address.sin_family=AF_INET; address.sin_port=htons(jbc->port); // try to connect with Jabber server if (connect(sock, (struct sockaddr *)&address, sizeof(address))<0) { LM_DBG("failed to connect with Jabber server\n"); return -1; } jbc->sock = sock; return 0; }
/* it initializes the TCP connection */ int init_mytcp(char* host, int port) { int sockfd; struct sockaddr_in serv_addr; struct hostent *server; sockfd = socket(PF_INET, SOCK_STREAM, 0); if (sockfd < 0) { LM_ERR("error creating the socket\n"); return -1; } server = resolvehost(host,0); if (server == NULL) { LM_ERR("error finding the host\n"); return -1; } memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = PF_INET; memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length); serv_addr.sin_port = htons(port); if (connect(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { LM_ERR("error connecting to the " "DIAMETER client\n"); return -1; } return sockfd; }
/* internal sip srv resolver: resolves a host name trying: * - SRV lookup if the address is not an ip *port==0. The result of the SRV * query will be used for an A/AAAA lookup. * - normal A/AAAA lookup (either fallback from the above or if *port!=0 * and *proto!=0 or port==0 && proto==0) * when performing SRV lookup (*port==0) it will use *proto to look for * tcp or udp hosts, otherwise proto is unused; if proto==0 => no SRV lookup * If zt is set, name will be assumed to be 0 terminated and some copy * operations will be avoided. * If is_srv is set it will assume name has the srv prefixes for sip already * appended and it's already 0-term'ed; if not it will append them internally. * If ars !=0, it will first try to look through them and only if the SRV * record is not found it will try doing a DNS query (ars will not be * freed, the caller should take care of them) * returns: hostent struct & *port filled with the port from the SRV record; * 0 on error */ struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port, char* proto, int is_srv, struct rdata* ars) { struct hostent* he; struct ip_addr* ip; static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups and null. term strings */ struct rdata* l; struct srv_rdata* srv; struct rdata* srv_head; char* srv_target; char srv_proto; /* init */ srv_head=0; srv_target=0; if (name->len >= MAX_DNS_NAME) { LOG(L_ERR, "sip_resolvehost: domain name too long\n"); he=0; goto end; } #ifdef RESOLVE_DBG DBG("srv_sip_resolvehost: %.*s:%d proto=%d\n", name->len, name->s, port?(int)*port:-1, proto?(int)*proto:-1); #endif if (is_srv){ /* skip directly to srv resolving */ srv_proto=(proto)?*proto:0; *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; if (zt){ srv_target=name->s; /* name.s must be 0 terminated in this case */ }else{ memcpy(tmp, name->s, name->len); tmp[name->len] = '\0'; srv_target=tmp; } goto do_srv; /* skip to the actual srv query */ } if (proto){ /* makes sure we have a protocol set*/ if (*proto==0) *proto=srv_proto=PROTO_UDP; /* default */ else srv_proto=*proto; }else{ srv_proto=PROTO_UDP; } /* try SRV if no port specified (draft-ietf-sip-srv-06) */ if ((port)&&(*port==0)){ *port=(srv_proto==PROTO_TLS)?SIPS_PORT:SIP_PORT; /* just in case we don't find another */ /* check if it's an ip address */ if (((ip=str2ip(name))!=0) #ifdef USE_IPV6 || ((ip=str2ip6(name))!=0) #endif ){ /* we are lucky, this is an ip address */ he=ip_addr2he(name, ip); goto end; } if ((name->len+SRV_MAX_PREFIX_LEN+1)>MAX_DNS_NAME){ LOG(L_WARN, "WARNING: sip_resolvehost: domain name too long (%d)," " unable to perform SRV lookup\n", name->len); }else{ switch(srv_proto){ case PROTO_NONE: /* no proto specified, use udp */ if (proto) *proto=PROTO_UDP; /* no break */ case PROTO_UDP: memcpy(tmp, SRV_UDP_PREFIX, SRV_UDP_PREFIX_LEN); memcpy(tmp+SRV_UDP_PREFIX_LEN, name->s, name->len); tmp[SRV_UDP_PREFIX_LEN + name->len] = '\0'; break; case PROTO_TCP: memcpy(tmp, SRV_TCP_PREFIX, SRV_TCP_PREFIX_LEN); memcpy(tmp+SRV_TCP_PREFIX_LEN, name->s, name->len); tmp[SRV_TCP_PREFIX_LEN + name->len] = '\0'; break; case PROTO_TLS: memcpy(tmp, SRV_TLS_PREFIX, SRV_TLS_PREFIX_LEN); memcpy(tmp+SRV_TLS_PREFIX_LEN, name->s, name->len); tmp[SRV_TLS_PREFIX_LEN + name->len] = '\0'; break; case PROTO_SCTP: memcpy(tmp, SRV_SCTP_PREFIX, SRV_SCTP_PREFIX_LEN); memcpy(tmp+SRV_SCTP_PREFIX_LEN, name->s, name->len); tmp[SRV_SCTP_PREFIX_LEN + name->len] = '\0'; break; default: LOG(L_CRIT, "BUG: sip_resolvehost: unknown proto %d\n", srv_proto); he=0; goto end; } srv_target=tmp; do_srv: /* try to find the SRV records inside previous ARs first*/ for (l=ars; l; l=l->next){ if (l->type!=T_SRV) continue; srv=(struct srv_rdata*) l->rdata; if (srv==0){ LOG(L_CRIT, "sip_resolvehost: BUG: null rdata\n"); /* cleanup on exit only */ break; } he=resolvehost(srv->name); if (he!=0){ /* we found it*/ #ifdef RESOLVE_DBG DBG("sip_resolvehost: found SRV(%s) = %s:%d in AR\n", srv_target, srv->name, srv->port); #endif *port=srv->port; /* cleanup on exit */ goto end; } } srv_head=get_record(srv_target, T_SRV, RES_ONLY_TYPE); for(l=srv_head; l; l=l->next){ if (l->type!=T_SRV) continue; /*should never happen*/ srv=(struct srv_rdata*) l->rdata; if (srv==0){ LOG(L_CRIT, "sip_resolvehost: BUG: null rdata\n"); /* cleanup on exit only */ break; } he=resolvehost(srv->name); if (he!=0){ /* we found it*/ #ifdef RESOLVE_DBG DBG("sip_resolvehost: SRV(%s) = %s:%d\n", srv_target, srv->name, srv->port); #endif *port=srv->port; /* cleanup on exit */ goto end; } } if (is_srv){ /* if the name was already into SRV format it doesn't make * any sense to fall back to A/AAAA */ he=0; goto end; } /* cleanup on exit */ #ifdef RESOLVE_DBG DBG("sip_resolvehost: no SRV record found for %.*s," " trying 'normal' lookup...\n", name->len, name->s); #endif } } /*skip_srv:*/ if (likely(!zt)){ memcpy(tmp, name->s, name->len); tmp[name->len] = '\0'; he=resolvehost(tmp); }else{ he=resolvehost(name->s); } end: #ifdef RESOLVE_DBG DBG("srv_sip_resolvehost: returning %p (%.*s:%d proto=%d)\n", he, name->len, name->s, port?(int)*port:-1, proto?(int)*proto:-1); #endif if (srv_head) free_rdata_list(srv_head); return he; }
/* eval_elem helping function, returns an op param */ inline static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype) { struct hostent* he; char ** h; int ret; str tmp; ret=-1; switch(subtype){ case NET_ST: switch(op){ case EQUAL_OP: ret=(matchnet(ip, (struct net*) param)==1); break; case DIFF_OP: ret=(matchnet(ip, (struct net*) param)!=1); break; default: goto error_op; } break; case STRING_ST: case RE_ST: switch(op){ case EQUAL_OP: case MATCH_OP: /* 1: compare with ip2str*/ ret=comp_str(ip_addr2a(ip), param, op, subtype); if (ret==1) break; /* 2: resolve (name) & compare w/ all the ips */ if (subtype==STRING_ST){ he=resolvehost((char*)param); if (he==0){ DBG("comp_ip: could not resolve %s\n", (char*)param); }else if (he->h_addrtype==ip->af){ for(h=he->h_addr_list;(ret!=1)&& (*h); h++){ ret=(memcmp(ip->u.addr, *h, ip->len)==0); } if (ret==1) break; } } /* 3: (slow) rev dns the address * and compare with all the aliases * !!??!! review: remove this? */ he=rev_resolvehost(ip); if (he==0){ print_ip( "comp_ip: could not rev_resolve ip address:" " ", ip, "\n"); ret=0; }else{ /* compare with primary host name */ ret=comp_str(he->h_name, param, op, subtype); /* compare with all the aliases */ for(h=he->h_aliases; (ret!=1) && (*h); h++){ ret=comp_str(*h, param, op, subtype); } } break; case DIFF_OP: ret=comp_ip(ip, param, EQUAL_OP, subtype); if (ret>=0) ret=!ret; break; default: goto error_op; } break; case MYSELF_ST: /* check if it's one of our addresses*/ tmp.s=ip_addr2a(ip); tmp.len=strlen(tmp.s); ret=check_self_op(op, &tmp, 0); break; default: LOG(L_CRIT, "BUG: comp_ip: invalid type for " " src_ip or dst_ip (%d)\n", subtype); ret=-1; } return ret; error_op: LOG(L_CRIT, "BUG: comp_ip: invalid operator %d\n", op); return -1; }
/* 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; }
int xl_mod_init() { #ifdef HOST_NAME_MAX #define HOSTNAME_MAX HOST_NAME_MAX #else #define HOSTNAME_MAX 256 #endif char *s, *d; struct hostent *he; int i; s=(char*)pkg_malloc(HOSTNAME_MAX); if (gethostname(s, HOSTNAME_MAX)<0) { str_fullname.len = 0; str_fullname.s = NULL; str_hostname.len = 0; str_hostname.s = NULL; str_domainname.len = 0; str_domainname.s = NULL; } else { str_fullname.len = strlen(s); str_fullname.s = s; d=strchr(s, '.'); if (d) { str_hostname.len=d-s; str_hostname.s=s; str_domainname.len=str_fullname.len-str_hostname.len-1; str_domainname.s=d+1; } else { str_hostname=str_fullname; str_domainname.len=0; str_domainname.s=NULL; } } pkg_realloc(s, str_fullname.len+1); /* this will leave the ending \0 */ str_ipaddr.len=0; str_ipaddr.s=NULL; s=(char*)pkg_malloc(HOSTNAME_MAX); if (str_fullname.len) { he=resolvehost(str_fullname.s); if (he) { if ((strlen(he->h_name)!=str_fullname.len) || strncmp(he->h_name, str_fullname.s, str_fullname.len)) { LOG(L_WARN, "WARNING: xl_mod_init: DIFFERENT hostname '%.*s' and gethostbyname '%s'\n", str_fullname.len, ZSW(str_hostname.s), he->h_name); } if (he->h_addr_list) { for (i=0; he->h_addr_list[i]; i++) { if (inet_ntop(he->h_addrtype, he->h_addr_list[i], s, HOSTNAME_MAX)) { if (!i) { str_ipaddr.len=strlen(s); str_ipaddr.s=(char*)pkg_malloc(str_ipaddr.len); if (str_ipaddr.s) { memcpy(str_ipaddr.s, s, str_ipaddr.len); } else { str_ipaddr.len=0; LOG(L_ERR, "ERROR: xl_mod_init: No memory left for str_ipaddr\n"); } } else { LOG(L_WARN, "WARNING: xl_mod_init: more IP %s not used\n", s); } } } } else { LOG(L_WARN, "WARNING: xl_mod_init: can't resolve hostname's address\n"); } } } pkg_free(s); DBG("Hostname: %.*s\n", str_hostname.len, ZSW(str_hostname.s)); DBG("Domainname: %.*s\n", str_domainname.len, ZSW(str_domainname.s)); DBG("Fullname: %.*s\n", str_fullname.len, ZSW(str_fullname.s)); DBG("IPaddr: %.*s\n", str_ipaddr.len, ZSW(str_ipaddr.s)); return 0; }
static evi_reply_sock* datagram_parse(str socket, int is_unix) { evi_reply_sock *sock = NULL; unsigned short port = 0; char *p = NULL, *host = 0; int len = 0; struct hostent *hentity; if (!socket.len || !socket.s) { LM_ERR("no socket specified\n"); return NULL; } len = socket.len; host = socket.s; if (!is_unix) { p = memchr(host, COLON_C, len); if (!p || p == host) { LM_ERR("port not specified <%.*s>\n", len, host); return NULL; } port = str2s(p + 1, host + len - p - 1, 0); if (port == 0) { LM_DBG("malformed port: %.*s\n", (int)(host + len - p - 1), p + 1); return NULL; } LM_DBG("port is %d\n", port); len = p - host; } /* host */ if (!host || len <= 0) { LM_ERR("malformed address %s\n", host); goto error; } sock = shm_malloc(sizeof(evi_reply_sock) + len); if (!sock) { LM_ERR("no more memory for socket\n"); return NULL; } memset(sock, 0, sizeof(evi_reply_sock)); /* only UDP has port */ if (port) { sock->flags = EVI_PORT; sock->port = port; /* also build sockaddr */ *p = 0; hentity = resolvehost(host, 0); if (!hentity) { LM_ERR("cannot resolve host %s\n", host); goto error; } if(hostent2su(&sock->src_addr.udp_addr, hentity, 0, port)){ LM_ERR("failed to resolve %s\n", host); goto error; } sock->flags |= EVI_SOCKET | DGRAM_UDP_FLAG; } else { sock->src_addr.unix_addr.sun_family = AF_LOCAL; memcpy(sock->src_addr.unix_addr.sun_path, host, len); sock->src_addr.unix_addr.sun_path[len] = 0; sock->flags |= EVI_SOCKET | DGRAM_UNIX_FLAG; } LM_DBG("address is <%.*s>\n", len, host); sock->address.s = (char *) (sock + 1); sock->address.len = len; memcpy(sock->address.s, host, len); sock->flags |= EVI_ADDRESS; /* needs expire */ sock->flags |= EVI_EXPIRE; return sock; error: if (sock) shm_free(sock); return NULL; }
/** * @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; }
static int mi_mod_init(void) { unsigned int port_no; int n; struct stat filestat; struct hostent * host; char *p, *host_s; str port_str; /* checking the mi_socket module param */ LM_DBG("testing socket existance...\n"); if( mi_socket==NULL || *mi_socket == 0) { LM_ERR("no DATAGRAM_ socket configured\n"); return -1; } LM_DBG("the socket's name/address is %s\n", mi_socket); memset( &mi_dtgram_addr, 0, sizeof(mi_dtgram_addr) ); if(strncmp(mi_socket, "udp:",4) == 0) { /*for an UDP socket*/ LM_DBG("we have an udp socket\n"); /*separate proto and host */ p = mi_socket+4; if( (*(p)) == '\0') { LM_ERR("malformed ip address\n"); return -1; } host_s=p; LM_DBG("the remaining address after separating the protocol is %s\n",p); if( (p = strrchr(p+1, ':')) == 0 ) { LM_ERR("no port specified\n"); return -1; } /*the address contains a port number*/ *p = '\0'; p++; port_str.s = p; port_str.len = strlen(p); LM_DBG("the port string is %s\n", p); if(str2int(&port_str, &port_no) != 0 ) { LM_ERR("there is not a valid number port\n"); return -1; } *p = '\0'; if (port_no<1024 || port_no>MAX_NB_PORT) { LM_ERR("invalid port number; must be in [1024,%d]\n",MAX_NB_PORT); return -1; } if(! (host = resolvehost(host_s)) ) { LM_ERR("failed to resolve %s\n", host_s); return -1; } LM_DBG("the ip is %s\n",host_s); if(hostent2su( &(mi_dtgram_addr.udp_addr), host, 0, port_no ) !=0){ LM_ERR("failed to resolve %s\n", mi_socket); return -1; } mi_socket_domain = host->h_addrtype; goto done; } /* in case of a Unix socket*/ LM_DBG("we have an UNIX socket\n"); n=stat(mi_socket, &filestat); if( n==0) { LM_INFO("the socket %s already exists, trying to delete it...\n", mi_socket); if(config_check==0) { if (unlink(mi_socket)<0) { LM_ERR("cannot delete old socket: %s\n", strerror(errno)); return -1; } } } else if (n<0 && errno!=ENOENT) { LM_ERR("socket stat failed:%s\n", strerror(errno)); return -1; } /* check mi_unix_socket_mode */ if(!mi_unix_socket_mode) { LM_WARN("cannot specify mi_unix_socket_mode = 0, forcing it to rw-------\n"); mi_unix_socket_mode = S_IRUSR| S_IWUSR; } if (mi_unix_socket_uid_s) { if (user2uid(&mi_unix_socket_uid, &mi_unix_socket_gid, mi_unix_socket_uid_s)<0) { LM_ERR("bad user name %s\n", mi_unix_socket_uid_s); return -1; } } if (mi_unix_socket_gid_s) { if (group2gid(&mi_unix_socket_gid, mi_unix_socket_gid_s)<0) { LM_ERR("bad group name %s\n", mi_unix_socket_gid_s); return -1; } } /*create the unix socket address*/ mi_dtgram_addr.unix_addr.sun_family = AF_LOCAL; memcpy( mi_dtgram_addr.unix_addr.sun_path, mi_socket, strlen(mi_socket)); done: /* add space for extra processes */ register_procs(mi_procs[0].no); /* add child to update local config framework structures */ cfg_register_child(mi_procs[0].no); return 0; }
/* 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; }
/* Find all the NetBIOS names associated using supplied host name */ struct NodeStatusInfo * SMBGetNodeStatus(const char *hostName, uint32_t *outCount) { struct NodeStatusInfo *outAddr = NULL, *listAddr; CFMutableArrayRef addressArray = NULL; CFMutableDataRef theData; CFMutableArrayRef nbrrArray; CFIndex ii; uint32_t jj; struct connectAddress *conn; struct nb_ctx ctx; struct smb_prefs prefs; int error; bzero(&ctx, sizeof(struct nb_ctx)); /* Read the preference files */ readPreferences(&prefs, NULL, NULL, FALSE, TRUE); /* Resolve the host name into a list of address */ error = resolvehost(hostName, &addressArray, NULL, NBNS_UDP_PORT_137, TRUE, FALSE); if (error) { goto done; } /* Allocate the memory needed to hold the list of address and info */ listAddr = outAddr = malloc(CFArrayGetCount(addressArray) * sizeof(struct NodeStatusInfo)); if (outAddr == NULL) { error = ENOMEM; goto done; } for (ii=0; ii < CFArrayGetCount(addressArray); ii++) { theData = (CFMutableDataRef)CFArrayGetValueAtIndex(addressArray, ii); if (! theData) { continue; } conn = (struct connectAddress *)(void *)CFDataGetMutableBytePtr(theData); if (!conn) { continue; } memcpy(&listAddr->node_storage, &conn->storage, sizeof(conn->storage)); listAddr->node_servername[0] = (char)0; listAddr->node_workgroupname[0] = (char)0; listAddr->node_nbrrArray = NULL; /* Creating the array causes nbns_getnodestatus to return a full list */ nbrrArray = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks ); listAddr->node_errno = nbns_getnodestatus(&conn->addr, &ctx, &prefs, NULL, listAddr->node_servername, listAddr->node_workgroupname, nbrrArray); if (nbrrArray && (listAddr->node_errno == 0)) { struct NBResourceRecord *nbrrDest; listAddr->node_nbrrArrayCnt = (uint32_t)CFArrayGetCount(nbrrArray); if (listAddr->node_nbrrArrayCnt) { listAddr->node_nbrrArray = malloc(listAddr->node_nbrrArrayCnt * sizeof(struct NBResourceRecord)); } nbrrDest = listAddr->node_nbrrArray; if (listAddr->node_nbrrArray) for (jj=0; jj < listAddr->node_nbrrArrayCnt; jj++) { struct NBResourceRecord *nbrrSrc = NULL; theData = (CFMutableDataRef)CFArrayGetValueAtIndex(nbrrArray, jj); if (theData) { nbrrSrc = (struct NBResourceRecord *)(void *)CFDataGetMutableBytePtr(theData); } if (nbrrSrc == NULL) { listAddr->node_errno = ENOMEM; break; } memcpy(nbrrDest, nbrrSrc, sizeof(*nbrrSrc)); nbrrDest++; } } if ((listAddr->node_errno) && (listAddr->node_nbrrArray)) { free(listAddr->node_nbrrArray); listAddr->node_nbrrArray = NULL; listAddr->node_nbrrArrayCnt = 0; } /* Done release it */ if (nbrrArray) { CFRelease(nbrrArray); } listAddr++; *outCount += 1; } if (*outCount == 0) { free(outAddr); outAddr = NULL; /* Didn't really find any */ error = EHOSTUNREACH; } done: if (addressArray) { CFRelease(addressArray); } releasePreferenceInfo(&prefs); errno = error; return outAddr; }
/** * stats socket sould be an IP_address:port or unix://path/to_file * TODO handling unix sockets and IPv6 !! * * returns * 0 if no stats * 1 if stats properly started * -1 if error */ int start_stats_server(char *stats_socket) { char *p,*port; unsigned short stats_port; struct hostent *he; /*use sockaddr_storage ??*/ struct sockaddr_in su; int optval; use_stats=0; port=(char *)0; he=(struct hostent *)0; stats_fd=-1; p=stats_socket; if(p==0 || *p==0) return 0; if(!init_seas_stats_table()){ LM_ERR("unable to init stats table, disabling statistics\n"); return -1; } while(*p){ if(*p == ':'){ *p=0; port=p+1; break; } } if(!(he=resolvehost(stats_socket,0))) goto error; if(port==(char*)0 || *port==0) stats_port=5088; else if(!(stats_port=str2s(port,strlen(port),0))){ LM_ERR("invalid port %s\n",port); goto error; } if((stats_fd=socket(he->h_addrtype, SOCK_STREAM, 0))==-1){ LM_ERR("trying to open server socket (%s)\n",strerror(errno)); goto error; } optval=1; if (setsockopt(stats_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval))==-1) { LM_ERR("setsockopt (%s)\n",strerror(errno)); goto error; } su.sin_family = he->h_addrtype; su.sin_port=htons(stats_port); memcpy(&su.sin_addr,he->h_addr_list[0],4); if((bind(stats_fd,(struct sockaddr*)&su,sizeof(struct sockaddr_in)))==-1){ LM_ERR( "bind (%s)\n",strerror(errno)); goto error; } if(listen(stats_fd, 10)==-1){ LM_ERR( "listen (%s)\n",strerror(errno)); goto error; } if(!(pid=fork())){/*child*/ signal(SIGTERM,sig_handler); serve_stats(stats_fd); printf("statistics Server Process exits !!\n"); exit(0); }else if(pid>0){/*parent*/ close(stats_fd); }else{/*error*/ LM_ERR("failed to create stats server process\n"); goto error; } use_stats=1; return 1; error: if(stats_fd!=-1) close(stats_fd); destroy_seas_stats_table(); return -1; }
/* * This is the parsing function * The socket grammar should be: * ip ':' port '/optional/path' ':' method */ static evi_reply_sock* xmlrpc_parse(str socket) { evi_reply_sock *sock = NULL; unsigned short port = 0; char *p = NULL; str host, path=str_init(NULL); struct hostent *hentity; int len; struct xmlrpc_sock_param *params; int http_buf_len=0; if (!socket.len || !socket.s) { LM_ERR("no socket specified\n"); return NULL; } if (!(params=shm_malloc(sizeof(struct xmlrpc_sock_param)))) { LM_ERR("no more pkg mem!\n"); return NULL; } memset(params, 0, sizeof(struct xmlrpc_sock_param)); /* extract host */ host.s = socket.s; p = memchr(socket.s, COLON_C, socket.len); if (!p || p == socket.s) { LM_ERR("port not specified <%.*s>\n", socket.len, socket.s); return NULL; } host.len = p - socket.s; /* used to resolve host */ *p = '\0'; /* skip colon */ socket.s += host.len + 1; socket.len -= host.len + 1; LM_DBG("host is %.*s - remains <%.*s>[%d]\n", host.len, host.s, socket.len, socket.s, socket.len); if (!socket.len || *socket.s == '\0') { LM_ERR("invalid port number\n"); return NULL; } p = memchr(socket.s, COLON_C, socket.len); if (!p || p == socket.s) { LM_ERR("method not specified <%.*s>\n", socket.len, socket.s); return NULL; } port = str2s(socket.s, p - socket.s, 0); if (port == 0) { /* most probably we've got path */ if ((path.s=(q_memchr(socket.s, SLASH_C, p-socket.s)))==NULL) { LM_ERR("malformed port: %.*s\n",(int)(p - socket.s), socket.s); return NULL; } else { port=str2s(socket.s, path.s-socket.s, 0); if (port == 0) { LM_ERR("malformed port: %.*s\n",(int)(p - socket.s), socket.s); return NULL; } path.len = p - path.s; socket.len -= ((path.s+path.len)-socket.s); socket.s = path.s+path.len; } /* will use this later for allocation */ http_buf_len=LENOF(XMLRPC_HTTP_METHOD) + path.len + LENOF(XMLRPC_HTTP_PROTO_HOST); } /* jump over ':' */ socket.len = socket.len - (p - socket.s + 1); socket.s = p + 1; LM_DBG("port is %hu - remains <%.*s>[%d]\n", port, socket.len, socket.s, socket.len); if (socket.len <= 0 || *socket.s == '\0') { LM_ERR("invalid method name\n"); return NULL; } len = sizeof(evi_reply_sock) + host.len + sizeof(struct xmlrpc_sock_param) + socket.len /* this is method */+ http_buf_len; sock = shm_malloc(len); if (!sock) { LM_ERR("no more memory for socket\n"); return NULL; } memset(sock, 0, len); /* only UDP has port */ sock->flags = EVI_PORT; sock->port = port; /* also build sockaddr */ hentity = resolvehost(host.s, 0); if (!hentity) { LM_ERR("cannot resolve host %s\n", host.s); goto error; } if(hostent2su(&sock->src_addr.udp_addr, hentity, 0, port)){ LM_ERR("failed to resolve %s\n", host.s); goto error; } sock->flags |= EVI_SOCKET; /* address */ sock->address.s = (char*)(sock+1); sock->address.len = host.len; memcpy(sock->address.s, host.s, host.len); sock->flags |= EVI_ADDRESS; /* copy parameters: path and method */ params = (struct xmlrpc_sock_param*)(sock->address.s + host.len); params->method.s = (char*)(params+1); memcpy(params->method.s, socket.s, socket.len); params->method.len = socket.len; if (http_buf_len) { /* build only once; not for every message */ params->first_line.s = (char*)(params->method.s+socket.len); memcpy(params->method.s, socket.s, socket.len); params->first_line.len = 0; memcpy(params->first_line.s, XMLRPC_HTTP_METHOD, LENOF(XMLRPC_HTTP_METHOD)); params->first_line.len = LENOF(XMLRPC_HTTP_METHOD); memcpy(params->first_line.s+params->first_line.len, path.s, path.len); params->first_line.len += path.len; memcpy(params->first_line.s+params->first_line.len, XMLRPC_HTTP_PROTO_HOST, LENOF(XMLRPC_HTTP_PROTO_HOST)); params->first_line.len += LENOF(XMLRPC_HTTP_PROTO_HOST); } else { params->first_line.s = XMLRPC_HTTP_CONST; params->first_line.len = LENOF(XMLRPC_HTTP_CONST); } sock->flags |= EVI_PARAMS; /* needs expire */ sock->flags |= EVI_EXPIRE|XMLRPC_FLAG; sock->params= params; return sock; error: if (sock) shm_free(sock); 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; }
/*! \brief eval_elem helping function, returns an op param */ inline static int comp_ip(struct sip_msg *msg, int op, struct ip_addr* ip, operand_t *opd) { struct hostent* he; char ** h; int ret; str tmp; ret=-1; switch(opd->type){ case NET_ST: switch(op){ case EQUAL_OP: ret=(matchnet(ip, (struct net*)opd->v.data)==1); break; case DIFF_OP: ret=(matchnet(ip, (struct net*)opd->v.data)!=1); break; default: goto error_op; } break; case STR_ST: case RE_ST: switch(op){ case EQUAL_OP: case MATCH_OP: /* 1: compare with ip2str*/ ret=comp_str(ip_addr2a(ip), opd->v.data, op, opd->type); if (ret==1) break; /* 2: resolve (name) & compare w/ all the ips */ if (opd->type==STR_ST){ he=resolvehost((char*)opd->v.data,0); if (he==0){ LM_DBG("could not resolve %s\n",(char*)opd->v.data); }else if (he->h_addrtype==(int)ip->af){ for(h=he->h_addr_list;(ret!=1)&& (*h); h++){ ret=(memcmp(ip->u.addr, *h, ip->len)==0); } if (ret==1) break; } } /* 3: (slow) rev dns the address * and compare with all the aliases * !!??!! review: remove this? */ if(received_dns & DO_REV_DNS) { he=rev_resolvehost(ip); if (he==0){ print_ip("comp_ip: could not rev_resolve ip" " address: ", ip, "\n"); ret=0; }else{ /* compare with primary host name */ ret=comp_str(he->h_name, opd->v.data, op, opd->type); /* compare with all the aliases */ for(h=he->h_aliases; (ret!=1) && (*h); h++){ ret=comp_str(*h, opd->v.data, op, opd->type); } } } else { return 0; } break; case DIFF_OP: ret=comp_ip(msg, op, ip, opd); if (ret>=0) ret=!ret; break; default: goto error_op; } break; case MYSELF_ST: /* check if it's one of our addresses*/ tmp.s=ip_addr2a(ip); tmp.len=strlen(tmp.s); ret=check_self_op(op, &tmp, 0); break; default: LM_CRIT("invalid type for src_ip or dst_ip (%d)\n", opd->type); ret=-1; } return ret; error_op: LM_CRIT("invalid operator %d\n", op); return -1; }
/* * This is the parsing function * The socket grammar should be: * ip ':' port ':' method */ static evi_reply_sock* xmlrpc_parse(str socket) { evi_reply_sock *sock = NULL; unsigned short port = 0; char *p = NULL; str host, *method; struct hostent *hentity; int len; if (!socket.len || !socket.s) { LM_ERR("no socket specified\n"); return NULL; } /* extract host */ host.s = socket.s; p = memchr(socket.s, COLON_C, socket.len); if (!p || p == socket.s) { LM_ERR("port not specified <%.*s>\n", socket.len, socket.s); return NULL; } host.len = p - socket.s; /* used to resolve host */ *p = '\0'; /* skip colon */ socket.s += host.len + 1; socket.len -= host.len + 1; LM_DBG("host is %.*s - remains <%.*s>[%d]\n", host.len, host.s, socket.len, socket.s, socket.len); if (!socket.len || *socket.s == '\0') { LM_ERR("invalid port number\n"); return NULL; } p = memchr(socket.s, COLON_C, socket.len); if (!p || p == socket.s) { LM_ERR("method not specified <%.*s>\n", socket.len, socket.s); return NULL; } port = str2s(socket.s, p - socket.s, 0); if (port == 0) { LM_DBG("malformed port: %.*s\n",(int)(p - socket.s), socket.s); return NULL; } /* skip colon */ socket.len = socket.len - (p - socket.s + 1); socket.s = p + 1; LM_DBG("port is %hu - remains <%.*s>[%d]\n", port, socket.len, socket.s, socket.len); if (socket.len <= 0 || *socket.s == '\0') { LM_ERR("invalid method name\n"); return NULL; } LM_DBG("method is %.*s[%d]\n", socket.len, socket.s, socket.len); len = sizeof(evi_reply_sock) - sizeof(void*) + sizeof(str) + host.len + socket.len; sock = shm_malloc(len); if (!sock) { LM_ERR("no more memory for socket\n"); return NULL; } memset(sock, 0, len); /* only UDP has port */ sock->flags = EVI_PORT; sock->port = port; /* also build sockaddr */ hentity = resolvehost(host.s, 0); if (!hentity) { LM_ERR("cannot resolve host %s\n", host.s); goto error; } if(hostent2su(&sock->src_addr.udp_addr, hentity, 0, port)){ LM_ERR("failed to resolve %s\n", host.s); goto error; } sock->flags |= EVI_SOCKET; /* copy method - this should point to same address as params*/ method = (str *) &sock->params; method->s = (char *) (method + 1); method->len = socket.len; memcpy(method->s, socket.s, socket.len); sock->flags |= EVI_PARAMS; /* address should point below method name */ sock->address.s = method->s + method->len; sock->address.len = host.len; memcpy(sock->address.s, host.s, host.len); sock->flags |= EVI_ADDRESS; /* needs expire */ sock->flags |= EVI_EXPIRE|XMLRPC_FLAG; return sock; error: if (sock) shm_free(sock); return NULL; }
/* 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; }
int jsonrpc_dgram_mod_init(void) { unsigned int port_no; int n; struct stat filestat; struct hostent *host; char *p, *host_s; str port_str; int len; int sep; /* checking the mi_socket module param */ LM_DBG("testing socket existance...\n"); if( jsonrpc_dgram_socket==NULL || *jsonrpc_dgram_socket == 0) { LM_ERR("no DATAGRAM_ socket configured\n"); return -1; } LM_DBG("the socket's name/address is %s\n", jsonrpc_dgram_socket); memset( &jsonrpc_dgram_addr, 0, sizeof(jsonrpc_dgram_sockaddr_t) ); if(strlen(jsonrpc_dgram_socket)<6) { LM_ERR("lenght of socket address is too short: %s\n", jsonrpc_dgram_socket); return -1; } if(strncmp(jsonrpc_dgram_socket, "udp:", 4) == 0) { /*for an UDP socket*/ LM_DBG("udp socket provided\n"); /*separate proto and host */ p = jsonrpc_dgram_socket+4; if( (*(p)) == '\0') { LM_ERR("malformed ip address\n"); return -1; } host_s=p; LM_DBG("remaining address after separating the protocol is %s\n", p); if( (p = strrchr(p+1, ':')) == 0 ) { LM_ERR("no port specified\n"); return -1; } /*the address contains a port number*/ *p = '\0'; p++; port_str.s = p; port_str.len = strlen(p); LM_DBG("the port string is %s\n", p); if(str2int(&port_str, &port_no) != 0 ) { LM_ERR("there is not a valid number port\n"); return -1; } *p = '\0'; if (port_no<1024 || port_no>65535) { LM_ERR("invalid port number; must be in [1024,65535]\n"); return -1; } if(! (host = resolvehost(host_s)) ) { LM_ERR("failed to resolve %s\n", host_s); return -1; } LM_DBG("the ip is %s\n",host_s); if(hostent2su( &(jsonrpc_dgram_addr.udp_addr), host, 0, port_no ) !=0) { LM_ERR("failed to resolve %s\n", jsonrpc_dgram_socket); return -1; } jsonrpc_dgram_socket_domain = host->h_addrtype; goto done; } /* in case of a Unix socket*/ LM_DBG("UNIX socket provided\n"); if(*jsonrpc_dgram_socket != '/') { if(runtime_dir!=NULL && *runtime_dir!=0) { len = strlen(runtime_dir); sep = 0; if(runtime_dir[len-1]!='/') { sep = 1; } len += sep + strlen(jsonrpc_dgram_socket); p = pkg_malloc(len + 1); if(p==NULL) { LM_ERR("no more pkg\n"); return -1; } strcpy(p, runtime_dir); if(sep) strcat(p, "/"); strcat(p, jsonrpc_dgram_socket); jsonrpc_dgram_socket = p; LM_DBG("unix socket path is [%s]\n", jsonrpc_dgram_socket); } } n=stat(jsonrpc_dgram_socket, &filestat); if( n==0) { LM_INFO("the socket %s already exists, trying to delete it...\n", jsonrpc_dgram_socket); if(config_check==0) { if (unlink(jsonrpc_dgram_socket)<0) { LM_ERR("cannot delete old socket: %s\n", strerror(errno)); return -1; } } } else if (n<0 && errno!=ENOENT) { LM_ERR("socket stat failed:%s\n", strerror(errno)); return -1; } /* check mi_unix_socket_mode */ if(!jsonrpc_dgram_unix_socket_mode) { LM_WARN("cannot specify jsonrpc_dgram_unix_socket_mode = 0," " forcing it to rw-------\n"); jsonrpc_dgram_unix_socket_mode = S_IRUSR| S_IWUSR; } if (jsonrpc_dgram_unix_socket_uid_s) { if (user2uid(&jsonrpc_dgram_unix_socket_uid, &jsonrpc_dgram_unix_socket_gid, jsonrpc_dgram_unix_socket_uid_s)<0) { LM_ERR("bad user name %s\n", jsonrpc_dgram_unix_socket_uid_s); return -1; } } if (jsonrpc_dgram_unix_socket_gid_s) { if (group2gid(&jsonrpc_dgram_unix_socket_gid, jsonrpc_dgram_unix_socket_gid_s)<0) { LM_ERR("bad group name %s\n", jsonrpc_dgram_unix_socket_gid_s); return -1; } } /*create the unix socket address*/ jsonrpc_dgram_addr.unix_addr.sun_family = AF_LOCAL; if(strlen(jsonrpc_dgram_socket) >= sizeof(jsonrpc_dgram_addr.unix_addr.sun_path)-1) { LM_ERR("socket path is too long\n"); return -1; } memcpy(jsonrpc_dgram_addr.unix_addr.sun_path, jsonrpc_dgram_socket, strlen(jsonrpc_dgram_socket)); done: /* add space for extra processes */ register_procs(jsonrpc_dgram_workers); /* add child to update local config framework structures */ cfg_register_child(jsonrpc_dgram_workers); return 0; }
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; }
/* opens, binds and listens-on a control tcp socket * returns socket fd or -1 on error */ int init_tcpudp_sock(union sockaddr_union* sa_un, char* address, int port, enum socket_protos type) { union sockaddr_union su; struct hostent* he; int s; int optval; s=-1; if ((type!=UDP_SOCK) && (type!=TCP_SOCK)){ LOG(L_CRIT, "BUG: init_tcpudp_sock called with bad type: %d\n", type); goto error; } memset(&su, 0, sizeof (su)); /* if no address specified, or address=='*', listen on all * ipv4 addresses */ if ((address==0)||((*address)==0)||((*address=='*') && (*(address+1)==0))){ su.sin.sin_family=AF_INET; su.sin.sin_port=htons(port); su.sin.sin_addr.s_addr=INADDR_ANY; #ifdef HAVE_SOCKADDR_SA_LEN su.sin.sin_len=sizeof(struct sockaddr_in); #endif }else{ he=resolvehost(address); if (he==0){ LOG(L_ERR, "ERROR: init_tcpudp_sock: bad address %s\n", address); goto error; } if (hostent2su(&su, he, 0, port)==-1) goto error; } s=socket(AF2PF(su.s.sa_family), (type==TCP_SOCK)?SOCK_STREAM:SOCK_DGRAM,0); if (s==-1){ LOG(L_ERR, "ERROR: init_tcpudp_sock: cannot create tcp socket:" " %s [%d]\n", strerror(errno), errno); goto error; } /* REUSEADDR */ optval=1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))==-1){ LOG(L_ERR, "ERROR: init_tcpudp_sock: setsockopt: %s [%d]\n", strerror(errno), errno); /* continue */ } /* tos */ optval=IPTOS_LOWDELAY; if (setsockopt(s, IPPROTO_IP, IP_TOS, (void*)&optval,sizeof(optval)) ==-1){ LOG(L_WARN, "WARNING: init_tcpudp_sock: setsockopt tos: %s\n", strerror(errno)); /* continue since this is not critical */ } if (set_non_blocking(s)==-1){ LOG(L_ERR, "ERROR: init_tcpudp_sock: set non blocking failed\n"); } if (bind(s, &su.s, sockaddru_len(su))==-1){ LOG(L_ERR, "ERROR: init_tcpudp_sock: bind: %s [%d]\n", strerror(errno), errno); goto error; } if ((type==TCP_SOCK) && (listen(s, 128)==-1)){ LOG(L_ERR, "ERROR: init_tcpudp_sock: listen: %s [%d]\n", strerror(errno), errno); goto error; } *sa_un=su; return s; error: if (s!=-1) close(s); 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; }
/* 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; }