/** * \brief Initialize C node server and returns listen socket. */ int erl_init_node(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie) { /* identifies a specific instance of a C node. */ short creation = getpid(); struct addrinfo *ai = NULL; struct sockaddr *addr = NULL; ip_addr_t ip; char nodename[MAXNODELEN]; int result; int listen_fd; int port; unsigned timeout_ms = CONNECT_TIMEOUT; int epmdfd; /* copy the nodename into something we can modify */ if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) { LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1); return -1; } if ((listen_fd = erl_passive_socket(hostname->s, 128, &ai)) == -1) { return -1; } /* use first ip address only, it's internal Erlang connection to empd */ addr = (struct sockaddr*) ai->ai_addr; if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) { LM_CRIT("failed to initialize self as node %s\n", nodename); erl_close_socket(listen_fd); return -1; } port = sockaddr_port(addr); sockaddr2ip_addr(&ip, addr); /* publish */ if ((epmdfd = ei_publish_tmo(ec, port, timeout_ms)) == -1) { LM_ERR("Failed to publish port %u to epmd, check is epmd started\n", port); erl_close_socket(listen_fd); return -1; } else { LM_DBG("listen on %s:%u[%u]/[%d] as %s\n",ip_addr2strz(&ip),port,listen_fd,epmdfd,nodename); } freeaddrinfo(ai); return listen_fd; }
/** * @brief Initialize Erlang connection */ int erl_init_ec(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie) { /* identifies a specific instance of a C node. */ short creation = getpid(); struct addrinfo *ai = NULL; struct sockaddr *addr = NULL; ip_addr_t ip; char nodename[MAXNODELEN]; int result; int port; /* copy the nodename into something we can modify */ if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) { LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1); return -1; } if (erl_active_socket(hostname->s, 128, &ai)) { return -1; } addr = (struct sockaddr*) ai->ai_addr; sockaddr2ip_addr(&ip,addr); if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) { LM_CRIT("failed to initialize self as cnode name %s\n", nodename); return -1; } port = sockaddr_port(addr); LM_DBG("initialized ec for cnode '%s' on %.*s[%s] creation %d.\n", nodename, STR_FMT(hostname), ip_addr2strz(&ip), creation); freeaddrinfo(ai); return 0; }
/* add all family type addresses of interface if_name to the socket_info array * if if_name==0, adds all addresses on all interfaces * WARNING: it only works with ipv6 addresses on FreeBSD * return: -1 on error, 0 on success */ int add_interfaces(char* if_name, int family, unsigned short port, unsigned short proto, struct socket_info** list) { struct ifconf ifc; struct ifreq ifr; struct ifreq ifrcopy; char* last; char* p; int size; int lastlen; int s; char* tmp; struct ip_addr addr; int ret; enum si_flags flags; #ifdef HAVE_SOCKADDR_SA_LEN #ifndef MAX #define MAX(a,b) ( ((a)>(b))?(a):(b)) #endif #endif /* ipv4 or ipv6 only*/ flags=SI_NONE; s=socket(family, SOCK_DGRAM, 0); ret=-1; lastlen=0; ifc.ifc_req=0; for (size=100; ; size*=2){ ifc.ifc_len=size*sizeof(struct ifreq); ifc.ifc_req=(struct ifreq*) pkg_malloc(size*sizeof(struct ifreq)); if (ifc.ifc_req==0){ LOG(L_ERR, "ERROR: add_interfaces: memory allocation failure\n"); goto error; } if (ioctl(s, SIOCGIFCONF, &ifc)==-1){ if(errno==EBADF) return 0; /* invalid descriptor => no such ifs*/ LOG(L_ERR, "ERROR: add_interfaces: ioctl failed: %s\n", strerror(errno)); goto error; } if ((lastlen) && (ifc.ifc_len==lastlen)) break; /*success, len not changed*/ lastlen=ifc.ifc_len; /* try a bigger array*/ pkg_free(ifc.ifc_req); } last=(char*)ifc.ifc_req+ifc.ifc_len; for(p=(char*)ifc.ifc_req; p<last; p+= #ifdef __OS_linux sizeof(ifr) /* works on x86_64 too */ #else (sizeof(ifr.ifr_name)+ #ifdef HAVE_SOCKADDR_SA_LEN MAX(ifr.ifr_addr.sa_len, sizeof(struct sockaddr)) #else ( (ifr.ifr_addr.sa_family==AF_INET)? sizeof(struct sockaddr_in): ((ifr.ifr_addr.sa_family==AF_INET6)? sizeof(struct sockaddr_in6):sizeof(struct sockaddr)) ) #endif ) #endif ) { /* copy contents into ifr structure * warning: it might be longer (e.g. ipv6 address) */ memcpy(&ifr, p, sizeof(ifr)); if (ifr.ifr_addr.sa_family!=family){ /*printf("strange family %d skipping...\n", ifr->ifr_addr.sa_family);*/ continue; } /*get flags*/ ifrcopy=ifr; if (ioctl(s, SIOCGIFFLAGS, &ifrcopy)!=-1){ /* ignore errors */ /* ignore down ifs only if listening on all of them*/ if (if_name==0){ /* if if not up, skip it*/ if (!(ifrcopy.ifr_flags & IFF_UP)) continue; } } if ((if_name==0)|| (strncmp(if_name, ifr.ifr_name, sizeof(ifr.ifr_name))==0)){ /*add address*/ sockaddr2ip_addr(&addr, (struct sockaddr*)(p+(long)&((struct ifreq*)0)->ifr_addr)); if ((tmp=ip_addr2a(&addr))==0) goto error; /* check if loopback */ if (ifrcopy.ifr_flags & IFF_LOOPBACK) flags|=SI_IS_LO; /* add it to one of the lists */ if (new_sock2list(tmp, port, proto, flags, list)!=0){ LOG(L_ERR, "ERROR: add_interfaces: new_sock2list failed\n"); goto error; } ret=0; } /* printf("%s:\n", ifr->ifr_name); printf(" "); print_sockaddr(&(ifr->ifr_addr)); printf(" "); ls_ifflags(ifr->ifr_name, family, options); printf("\n");*/ } pkg_free(ifc.ifc_req); /*clean up*/ close(s); return ret; error: if (ifc.ifc_req) pkg_free(ifc.ifc_req); close(s); return -1; }
int run_mi_reg_list(void *e_data, void *data, void *r_data) { struct mi_root* rpl_tree = (struct mi_root*)data; struct mi_node *node, *node1; struct mi_attr* attr; reg_record_t *rec = (reg_record_t*)e_data; int len; char* p; struct ip_addr addr; node = add_mi_node_child(&rpl_tree->node, MI_DUP_VALUE, "AOR", 3, rec->td.rem_uri.s, rec->td.rem_uri.len); if(node == NULL) goto error; p = int2str(rec->expires, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "expires", 7, p, len); if(attr == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "state", 5, uac_reg_state[rec->state].s, uac_reg_state[rec->state].len); if(node1 == NULL) goto error; p = ctime(&rec->last_register_sent); len = strlen(p)-1; node1 = add_mi_node_child(node, MI_DUP_VALUE, "last_register_sent", 18, p, len); if(node1 == NULL) goto error; p = ctime(&rec->registration_timeout); len = strlen(p)-1; node1 = add_mi_node_child(node, MI_DUP_VALUE, "registration_t_out", 18, p, len); if(node1 == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "registrar", 9, rec->td.rem_target.s, rec->td.rem_target.len); if(node1 == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "binding", 7, rec->contact_uri.s, rec->contact_uri.len); if(node1 == NULL) goto error; if(rec->td.loc_uri.s != rec->td.rem_uri.s) { node1 = add_mi_node_child(node, MI_DUP_VALUE, "third_party_registrant", 12, rec->td.loc_uri.s, rec->td.loc_uri.len); if(node1 == NULL) goto error; } if (rec->td.obp.s && rec->td.obp.len) { node1 = add_mi_node_child(node, MI_DUP_VALUE, "proxy", 5, rec->td.obp.s, rec->td.obp.len); if(node1 == NULL) goto error; } switch(rec->td.forced_to_su.s.sa_family) { case AF_UNSPEC: break; case AF_INET: case AF_INET6: node1 = add_mi_node_child(node, MI_DUP_VALUE, "dst_IP", 6, (rec->td.forced_to_su.s.sa_family==AF_INET)?"IPv4":"IPv6", 4); sockaddr2ip_addr(&addr, &rec->td.forced_to_su.s); p = ip_addr2a(&addr); if (p == NULL) goto error; len = strlen(p); attr = add_mi_attr(node1, MI_DUP_VALUE, "ip", 2, p, len); if(attr == NULL) goto error; break; default: LM_ERR("unexpected sa_family [%d]\n", rec->td.forced_to_su.s.sa_family); node1 = add_mi_node_child(node, MI_DUP_VALUE, "dst_IP", 6, "Error", 5); p = int2str(rec->td.forced_to_su.s.sa_family, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "sa_family", 9, p, len); if(attr == NULL) goto error; } /* action successfuly completed on current list element */ return 0; /* continue list traversal */ error: LM_ERR("Unable to create reply\n"); return -1; /* exit list traversal */ }
static struct mi_root* mi_reg_list(struct mi_root* cmd, void* param) { struct mi_root *rpl_tree; struct mi_node *rpl=NULL, *node, *node1; struct mi_attr* attr; reg_record_t *rec; int i, len; char* p; struct ip_addr addr; rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==NULL) return NULL; rpl = &rpl_tree->node; for(i = 0; i< reg_hsize; i++) { lock_get(®_htable[i].lock); rec = reg_htable[i].first; while (rec) { node = add_mi_node_child(rpl, MI_DUP_VALUE, "AOR", 3, rec->td.rem_uri.s, rec->td.rem_uri.len); if(node == NULL) goto error; p = int2str(rec->state, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "state", 5, p, len); if(attr == NULL) goto error; p = int2str(rec->expires, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "expires", 7, p, len); if(attr == NULL) goto error; p = int2str((unsigned int)rec->last_register_sent, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "last_register_sent", 18, p, len); if(attr == NULL) goto error; p = int2str((unsigned int)rec->registration_timeout, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "registration_timeout", 20, p, len); if(attr == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "registrar", 9, rec->td.rem_target.s, rec->td.rem_target.len); if(node1 == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "binding", 7, rec->contact_uri.s, rec->contact_uri.len); if(node1 == NULL) goto error; if(rec->td.loc_uri.s != rec->td.rem_uri.s) { node1 = add_mi_node_child(node, MI_DUP_VALUE, "third_party_registrant", 12, rec->td.loc_uri.s, rec->td.loc_uri.len); if(node1 == NULL) goto error; } if (rec->td.obp.s && rec->td.obp.len) { node1 = add_mi_node_child(node, MI_DUP_VALUE, "proxy", 5, rec->td.obp.s, rec->td.obp.len); if(node1 == NULL) goto error; } switch(rec->td.forced_to_su.s.sa_family) { case AF_UNSPEC: break; case AF_INET: case AF_INET6: node1 = add_mi_node_child(node, MI_DUP_VALUE, "dst_IP", 6, (rec->td.forced_to_su.s.sa_family==AF_INET)? "IPv4":"IPv6", 4); sockaddr2ip_addr(&addr, &rec->td.forced_to_su.s); p = ip_addr2a(&addr); if (p == NULL) goto error; len = strlen(p); attr = add_mi_attr(node1, MI_DUP_VALUE, "ip", 2, p, len); if(attr == NULL) goto error; break; default: LM_ERR("unexpected sa_family [%d]\n", rec->td.forced_to_su.s.sa_family); node1 = add_mi_node_child(node, MI_DUP_VALUE, "dst_IP", 6, "Error", 5); p = int2str(rec->td.forced_to_su.s.sa_family, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "sa_family", 9, p, len); if(attr == NULL) goto error; } rec = rec->next; } lock_release(®_htable[i].lock); } return rpl_tree; error: lock_release(®_htable[i].lock); LM_ERR("Unable to create reply\n"); free_mi_tree(rpl_tree); return NULL; }
/* add all family type addresses of interface if_name to the socket_info array * if if_name==0, adds all addresses on all interfaces * WARNING: it only works with ipv6 addresses on FreeBSD * return: -1 on error, 0 on success */ int add_interfaces(char* if_name, int family, unsigned short port) { struct ifconf ifc; struct ifreq ifr; struct ifreq ifrcopy; char* last; char* p; int size; int lastlen; int s; char* tmp; struct ip_addr addr; int ret; #ifdef HAVE_SOCKADDR_SA_LEN #ifndef MAX #define MAX(a,b) ( ((a)>(b))?(a):(b)) #endif #endif /* ipv4 or ipv6 only*/ s=socket(family, SOCK_DGRAM, 0); ret=-1; lastlen=0; ifc.ifc_req=0; for (size=10; ; size*=2) { ifc.ifc_len=size*sizeof(struct ifreq); ifc.ifc_req=(struct ifreq*) malloc(size*sizeof(struct ifreq)); if (ifc.ifc_req==0) { fprintf(stderr, "memory allocation failure\n"); goto error; } if (ioctl(s, SIOCGIFCONF, &ifc)==-1) { if(errno==EBADF) return 0; /* invalid descriptor => no such ifs*/ fprintf(stderr, "ioctl failed: %s\n", strerror(errno)); goto error; } if ((lastlen) && (ifc.ifc_len==lastlen)) break; /*success, len not changed*/ lastlen=ifc.ifc_len; /* try a bigger array*/ free(ifc.ifc_req); } last=(char*)ifc.ifc_req+ifc.ifc_len; for(p=(char*)ifc.ifc_req; p<last; p+=(sizeof(ifr.ifr_name)+ #ifdef HAVE_SOCKADDR_SA_LEN MAX(ifr.ifr_addr.sa_len, sizeof(struct sockaddr)) #else (sizeof(struct sockaddr_in)) /* ( (ifr.ifr_addr.sa_family==AF_INET)?sizeof(struct sockaddr_in):((ifr.ifr_addr.sa_family==AF_INET6)?sizeof(struct sockaddr_in6):sizeof(struct sockaddr)) )*/ #endif ) ) { /* copy contents into ifr structure * warning: it might be longer (e.g. ipv6 address) */ memcpy(&ifr, p, sizeof(ifr)); if (ifr.ifr_addr.sa_family!=family) { printf("strange family %d skipping...\n",ifr.ifr_addr.sa_family); continue; } /*get flags*/ ifrcopy=ifr; if (ioctl(s, SIOCGIFFLAGS, &ifrcopy)!=-1) { /* ignore errors */ /* ignore down ifs only if listening on all of them*/ if (if_name==0) { /* if if not up, skip it*/ if (!(ifrcopy.ifr_flags & IFF_UP)) continue; } } if ((if_name==0)|| (strncmp(if_name, ifr.ifr_name, sizeof(ifr.ifr_name))==0)) { /*add address*/ if (sock_no<MAX_LISTEN) { sockaddr2ip_addr(&addr,(struct sockaddr*)(p+(long)&((struct ifreq*)0)->ifr_addr)); if ((tmp=ip_addr2a(&addr))==0) goto error; /* fill the strings*/ sock_info[sock_no].address = addr; sock_info[sock_no].name.s=(char*)malloc(strlen(tmp)+1); if(sock_info[sock_no].name.s==0) { fprintf(stderr, "Out of memory.\n"); goto error; } /* fill in the new name and port */ sock_info[sock_no].name.len=strlen(tmp); strncpy(sock_info[sock_no].name.s, tmp,sock_info[sock_no].name.len+1); sock_info[sock_no].port_no=port; /* mark if loopback */ if (ifrcopy.ifr_flags & IFF_LOOPBACK) sock_info[sock_no].is_lo=1; sock_no++; ret=0; }else { fprintf(stderr, "Too many addresses (max %d)\n", MAX_LISTEN); goto error; } } /* DBG("%s:\n", ifr.ifr_name); print_sockaddr(&(ifr.ifr_addr)); DBG(" "); ls_ifflags(ifr.ifr_name, family, 0); DBG("\n"); */ } free(ifc.ifc_req); /*clean up*/ close(s); return ret; error: if (ifc.ifc_req) free(ifc.ifc_req); close(s); return -1; }