/* * return 0 on success, -1 on error */ int fix_all_socket_lists(void) { int i; int found = 0; static char buf[PROTO_NAME_MAX_SIZE /* currently we shouldn't hardcode that much */]; char *p; #if 0 /* TODO: decide what to do with this */ struct utsname myname; if ((udp_listen==0) && (tcp_listen==0) && (tls_listen==0) && (sctp_listen==0) ){ /* get all listening ipv4 interfaces */ if (add_interfaces(0, AF_INET, 0, PROTO_UDP, &udp_listen)==0){ /* if ok, try to add the others too */ if (!tcp_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_TCP, &tcp_listen)!=0) goto error; if (!tls_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_TLS, &tls_listen)!=0) goto error; } } if (!sctp_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_SCTP, &sctp_listen)!=0) goto error; } }else{ /* if error fall back to get hostname */ /* get our address, only the first one */ if (uname (&myname) <0){ LM_ERR("cannot determine hostname, try -l address\n"); goto error; } if (add_listen_iface(myname.nodename, 0, 0, 0, 0, 0, 0)!=0){ LM_ERR("add_listen_iface failed \n"); goto error; } } } #endif for (i = PROTO_FIRST; i < PROTO_LAST; i++) { if (protos[i].id != PROTO_NONE) { if (fix_socket_list(&protos[i].listeners)!=0) { LM_ERR("fix_socket_list for %d failed\n", protos[i].id); goto error; } found++; } else if (protos[i].listeners) { p = proto2str(i, buf); if (p == NULL) goto error; *p = '\0'; LM_ERR("listeners found for protocol %s, but no module " "can handle it, %d, %d \n", buf,i,protos[i].id); goto error; } } if (!found){ LM_ERR("no listening sockets\n"); goto error; } return 0; error: return -1; }
/* fix all 3 socket lists, fills socket_types if non-null * return 0 on success, -1 on error */ int fix_all_socket_lists(int* socket_types) { struct utsname myname; int flags; if (socket_types) *socket_types=0; if ((udp_listen==0) #ifdef USE_TCP && (tcp_listen==0) #ifdef USE_TLS && (tls_listen==0) #endif #endif ){ /* get all listening ipv4 interfaces */ if (add_interfaces(0, AF_INET, 0, PROTO_UDP, &udp_listen)==0){ /* if ok, try to add the others too */ #ifdef USE_TCP if (!tcp_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_TCP, &tcp_listen)!=0) goto error; #ifdef USE_TLS if (!tls_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_TLS, &tls_listen)!=0) goto error; } #endif } #endif }else{ /* if error fall back to get hostname */ /* get our address, only the first one */ if (uname (&myname) <0){ LOG(L_ERR, "ERROR: fix_all_socket_lists: cannot determine" " hostname, try -l address\n"); goto error; } if (add_listen_iface(myname.nodename, 0, 0, 0)!=0){ LOG(L_ERR, "ERROR: fix_all_socket_lists: add_listen_iface " "failed \n"); goto error; } } } if (fix_socket_list(&udp_listen, &flags)!=0){ LOG(L_ERR, "ERROR: fix_all_socket_lists: fix_socket_list" " udp failed\n"); goto error; } if (flags && socket_types){ *socket_types|=flags|SOCKET_T_UDP; } #ifdef USE_TCP if (!tcp_disable && (fix_socket_list(&tcp_listen, &flags)!=0)){ LOG(L_ERR, "ERROR: fix_all_socket_lists: fix_socket_list" " tcp failed\n"); goto error; } if (flags && socket_types){ *socket_types|=flags|SOCKET_T_TCP; } #ifdef USE_TLS if (!tls_disable && (fix_socket_list(&tls_listen, &flags)!=0)){ LOG(L_ERR, "ERROR: fix_all_socket_lists: fix_socket_list" " tls failed\n"); goto error; } if (flags && socket_types){ *socket_types|=flags|SOCKET_T_TLS; } #endif #endif if ((udp_listen==0) #ifdef USE_TCP && (tcp_listen==0) #ifdef USE_TLS && (tls_listen==0) #endif #endif ){ LOG(L_ERR, "ERROR: fix_all_socket_lists: no listening sockets\n"); goto error; } return 0; error: return -1; }
/* fixes a socket list => resolve addresses, * interface names, fills missing members, remove duplicates * fills type_flags if not null with SOCKET_T_IPV4 and/or SOCKET_T_IPV6*/ static int fix_socket_list(struct socket_info **list, int* type_flags) { struct socket_info* si; struct socket_info* l; struct socket_info* next; char* tmp; int len; struct hostent* he; char** h; if (type_flags) *type_flags=0; /* try to change all the interface names into addresses * --ugly hack */ for (si=*list;si;){ next=si->next; if (add_interfaces(si->name.s, AF_INET, si->port_no, si->proto, list)!=-1){ /* success => remove current entry (shift the entire array)*/ sock_listrm(list, si); free_sock_info(si); } si=next; } /* get ips & fill the port numbers*/ #ifdef EXTRA_DEBUG DBG("Listening on \n"); #endif for (si=*list;si;si=si->next){ /* fix port number, port_no should be !=0 here */ if (si->port_no==0){ #ifdef USE_TLS si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no; #else si->port_no= port_no; #endif } tmp=int2str(si->port_no, &len); if (len>=MAX_PORT_LEN){ LOG(L_ERR, "ERROR: fix_socket_list: bad port number: %d\n", si->port_no); goto error; } si->port_no_str.s=(char*)pkg_malloc(len+1); if (si->port_no_str.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } strncpy(si->port_no_str.s, tmp, len+1); si->port_no_str.len=len; /* get "official hostnames", all the aliases etc. */ he=resolvehost(si->name.s); if (he==0){ LOG(L_ERR, "ERROR: fix_socket_list: could not resolve %s\n", si->name.s); goto error; } /* check if we got the official name */ if (strcasecmp(he->h_name, si->name.s)!=0){ if (add_alias(si->name.s, si->name.len, si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n"); } /* change the official name */ pkg_free(si->name.s); si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1); if (si->name.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } si->name.len=strlen(he->h_name); strncpy(si->name.s, he->h_name, si->name.len+1); } /* add the aliases*/ for(h=he->h_aliases; h && *h; h++) if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list: add_alias failed\n"); } hostent2ip_addr(&si->address, he, 0); /*convert to ip_addr format*/ if (type_flags){ *type_flags|=(si->address.af==AF_INET)?SOCKET_T_IPV4:SOCKET_T_IPV6; } if ((tmp=ip_addr2a(&si->address))==0) goto error; si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1); if (si->address_str.s==0){ LOG(L_ERR, "ERROR: fix_socket_list: out of memory.\n"); goto error; } strncpy(si->address_str.s, tmp, strlen(tmp)+1); /* set is_ip (1 if name is an ip address, 0 otherwise) */ si->address_str.len=strlen(tmp); if ( (si->address_str.len==si->name.len)&& (strncasecmp(si->address_str.s, si->name.s, si->address_str.len)==0) ){ si->flags|=SI_IS_IP; /* do rev. DNS on it (for aliases)*/ he=rev_resolvehost(&si->address); if (he==0){ LOG(L_WARN, "WARNING: fix_socket_list:" " could not rev. resolve %s\n", si->name.s); }else{ /* add the aliases*/ if (add_alias(he->h_name, strlen(he->h_name), si->port_no, si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list:" "add_alias failed\n"); } for(h=he->h_aliases; h && *h; h++) if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){ LOG(L_ERR, "ERROR: fix_socket_list:" " add_alias failed\n"); } } } #ifdef USE_MCAST /* Check if it is an multicast address and * set the flag if so */ if (is_mcast(&si->address)) { si->flags |= SI_IS_MCAST; } #endif /* USE_MCAST */ #ifdef EXTRA_DEBUG printf(" %.*s [%s]:%s%s\n", si->name.len, si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); #endif } /* removing duplicate addresses*/ for (si=*list;si; si=si->next){ for (l=si->next;l;){ next=l->next; if ((si->port_no==l->port_no) && (si->address.af==l->address.af) && (memcmp(si->address.u.addr, l->address.u.addr, si->address.len) == 0) ){ #ifdef EXTRA_DEBUG printf("removing duplicate %s [%s] == %s [%s]\n", si->name.s, si->address_str.s, l->name.s, l->address_str.s); #endif /* add the name to the alias list*/ if ((!(l->flags& SI_IS_IP)) && ( (l->name.len!=si->name.len)|| (strncmp(l->name.s, si->name.s, si->name.len)!=0)) ) add_alias(l->name.s, l->name.len, l->port_no, l->proto); /* remove l*/ sock_listrm(list, l); free_sock_info(l); } l=next; } } #ifdef USE_MCAST /* Remove invalid multicast entries */ si=*list; while(si){ if ((si->flags & SI_IS_MCAST) && ((si->proto == PROTO_TCP) #ifdef USE_TLS || (si->proto == PROTO_TLS) #endif /* USE_TLS */ )){ LOG(L_WARN, "WARNING: removing entry %s:%s [%s]:%s\n", get_proto_name(si->proto), si->name.s, si->address_str.s, si->port_no_str.s); l = si; si=si->next; sock_listrm(list, l); free_sock_info(l); } else { si=si->next; } } #endif /* USE_MCAST */ return 0; error: return -1; }
int main(int argc,char **argv) { int r; char *options; char *tmp; char c; options="P:p:i:I:a:n:u:g:w:c:vhDEws:"; use_interfaces = -1; while((c=getopt(argc,argv,options))!=-1){ switch(c){ case 'i': /* use interfaces specified by their number (!?) */ if (use_interfaces == 0) { fprintf(stderr, "either only -i or -I option can be used\n"); goto error; } use_interfaces = 1; first_interface = optarg[0]-'1'; second_interface = optarg[2]-'1'; fprintf(stderr,"using intefaces: %d and %d\n",first_interface,second_interface); break; case 'I': /* IPv4 addresses */ if (use_interfaces == 1) { fprintf(stderr, "either only -i or -I option can be used\n"); goto error; } use_interfaces = 0; if (sscanf(optarg, "%15[^,],%15s", first_address, second_address) != 2) { fprintf(stderr,"invalid specification of IP addresses\n"); goto error; } break; case 'p': tmp = 0; default_port = strtol(optarg, &tmp, 10); if (tmp &&(*tmp)){ fprintf(stderr, "bad port number: -p [%s] %d\n", optarg,default_port); goto error; } break; case 'a': tmp = 0; default_alternate_port = strtol(optarg, &tmp, 10); if (tmp &&(*tmp)){ fprintf(stderr, "bad port number: -p %s\n", optarg); goto error; } break; case 'n': children_no=strtol(optarg, &tmp, 10); if ((tmp==0) ||(*tmp)){ fprintf(stderr, "bad process number: -n %s\n",optarg); goto error; } break; case 'D': dont_fork=0; break; case 'E': log_stderr=1; break; case 'v': printf("version: %s\n", version); printf("compiled: %s\n",compiled); exit(0); break; case 'h': printf("%s",help_msg); exit(0); break; case 'w': working_dir=optarg; break; case 't': chroot_dir=optarg; break; case 'u': user=optarg; break; case 'g': group=optarg; break; case 'P': pid_file=optarg; break; case 'c': # ifdef USE_TLS tls_cert_file=optarg; # endif break; case 'k': # ifdef USE_TLS tls_pkey_file=optarg; # endif break; case '?': goto error; default: abort(); } } /* use interfaces for configuration by default */ if (use_interfaces == -1) { use_interfaces = 1; } if ((dont_fork == 0) && (daemonize() < 0)) { return -1; } if (use_interfaces) { /* * Get interfaces with IPv4 addresses */ if (add_interfaces(0, AF_INET, 0) == -1) { LOG("error finding addresses\n"); return -1; } for (r=0; r<sock_no;) { if (add_interfaces(sock_info[r].name.s, AF_INET,sock_info[r].port_no)!=-1) { /* success => remove current entry (shift the entire array)*/ free(sock_info[r].name.s); memmove(&sock_info[r], &sock_info[r+1],(sock_no-r)*sizeof(struct socket_info)); sock_no --; continue; } r++; } LOG("Located interfaces\n"); for(r=0;r<sock_no;r++) { LOG(" [%.*s] ", sock_info[r].name.len,sock_info[r].name.s); LOG("ip->");print_ip(&(sock_info[r].address)); LOG("\n"); } } LOG("Before daemonize pid is [%d] parent [%d]\n",getpid(),getppid()); /* INSTALL SIGNAL HANDLERS HERE, SO WE SHOULD NOT RECEIVE SIGNALS FROM daemonize */ signal(SIGINT,handle_sigs); signal(SIGTERM,handle_sigs); signal(SIGHUP,handle_sigs); signal(SIGPIPE,handle_sigs); signal(SIGCHLD,handle_sigs); /* create the childs */ r = start_server(); return (0); error: cleanup(0); return -1; //dealocari }
/* fix all 3 socket lists * return 0 on success, -1 on error */ int fix_all_socket_lists(void) { struct utsname myname; if ((udp_listen==0) #ifdef USE_TCP && (tcp_listen==0) #ifdef USE_TLS && (tls_listen==0) #endif #endif #ifdef USE_SCTP && (sctp_listen==0) #endif ){ /* get all listening ipv4 interfaces */ if (add_interfaces(0, AF_INET, 0, PROTO_UDP, &udp_listen)==0){ /* if ok, try to add the others too */ #ifdef USE_TCP if (!tcp_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_TCP, &tcp_listen)!=0) goto error; #ifdef USE_TLS if (!tls_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_TLS, &tls_listen)!=0) goto error; } #endif } #endif #ifdef USE_SCTP if (!sctp_disable){ if (add_interfaces(0, AF_INET, 0, PROTO_SCTP, &sctp_listen)!=0) goto error; } #endif }else{ /* if error fall back to get hostname */ /* get our address, only the first one */ if (uname (&myname) <0){ LM_ERR("cannot determine hostname, try -l address\n"); goto error; } if (add_listen_iface(myname.nodename, 0, 0, 0, 0, 0, 0)!=0){ LM_ERR("add_listen_iface failed \n"); goto error; } } } if (fix_socket_list(&udp_listen)!=0){ LM_ERR("fix_socket_list udp failed\n"); goto error; } #ifdef USE_TCP if (!tcp_disable && (fix_socket_list(&tcp_listen)!=0)){ LM_ERR("fix_socket_list tcp failed\n"); goto error; } #ifdef USE_TLS if (!tls_disable && (fix_socket_list(&tls_listen)!=0)){ LM_ERR("fix_socket_list tls failed\n"); goto error; } #endif #endif #ifdef USE_SCTP if (!sctp_disable && (fix_socket_list(&sctp_listen)!=0)){ LM_ERR("fix_socket_list sctp failed\n"); goto error; } #endif if ((udp_listen==0) #ifdef USE_TCP && (tcp_listen==0) #ifdef USE_TLS && (tls_listen==0) #endif #endif #ifdef USE_SCTP && (sctp_listen==0) #endif ){ LM_ERR("no listening sockets\n"); goto error; } return 0; error: return -1; }
/* fixes a socket list => resolve addresses, * interface names, fills missing members, remove duplicates */ static int fix_socket_list(struct socket_info **list) { struct socket_info* si; struct socket_info* l; struct socket_info* next; char* tmp; int len; struct hostent* he; char** h; /* try to change all the interface names into addresses * --ugly hack */ for (si=*list;si;){ next=si->next; if (add_interfaces(si->name.s, AF_INET, si->port_no, si->proto, list)!=-1){ /* success => remove current entry (shift the entire array)*/ sock_listrm(list, si); free_sock_info(si); } si=next; } /* get ips & fill the port numbers*/ #ifdef EXTRA_DEBUG LM_DBG("listening on \n"); #endif LM_DBG("fix_socket_list"); for (si=*list;si;si=si->next){ /* fix the number of processes per interface */ if (si->children==0 && (si->proto==PROTO_UDP || si->proto==PROTO_SCTP)) si->children = children_no; /* fix port number, port_no should be !=0 here */ if (si->port_no==0){ #ifdef USE_TLS si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no; #else si->port_no= port_no; #endif } tmp=int2str(si->port_no, &len); if (len>=MAX_PORT_LEN){ LM_ERR("bad port number: %d\n", si->port_no); goto error; } si->port_no_str.s=(char*)pkg_malloc(len+1); if (si->port_no_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } strncpy(si->port_no_str.s, tmp, len+1); si->port_no_str.len=len; LM_DBG("resolvehost [%.*s] ",si->name.len,si->name.s); /* get "official hostnames", all the aliases etc. */ he=resolvehost(si->name.s,0); if (he==0){ LM_ERR("could not resolve %s\n", si->name.s); goto error; } LM_DBG("aliases [%.*s] == [%.*s] ", (int)strlen(he->h_name),he->h_name, si->name.len, si->name.s); /* check if we got the official name */ if (strcasecmp(he->h_name, si->name.s)!=0){ if (auto_aliases && add_alias(si->name.s, si->name.len, si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } /* change the official name */ pkg_free(si->name.s); si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1); if (si->name.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } si->name.len=strlen(he->h_name); strncpy(si->name.s, he->h_name, si->name.len+1); } /* add the aliases*/ if (auto_aliases) { for(h=he->h_aliases; h && *h; h++){ LM_DBG("h_alias [%.*s] ",(int)strlen(*h),*h); if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } } } hostent2ip_addr(&si->address, he, 0); /*convert to ip_addr format*/ if ((tmp=ip_addr2a(&si->address))==0) goto error; if (si->address.af == AF_INET6) { si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1+2); if (si->address_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } si->address_str.s[0] = '['; strncpy( si->address_str.s+1 , tmp, strlen(tmp)); si->address_str.s[1+strlen(tmp)] = ']'; si->address_str.s[2+strlen(tmp)] = '\0'; si->address_str.len=strlen(tmp) + 2; } else { si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1); if (si->address_str.s==0){ LM_ERR("out of pkg memory.\n"); goto error; } strncpy(si->address_str.s, tmp, strlen(tmp)+1); si->address_str.len=strlen(tmp); } /* set is_ip (1 if name is an ip address, 0 otherwise) */ if ( auto_aliases && (si->address_str.len==si->name.len) && (strncasecmp(si->address_str.s, si->name.s, si->address_str.len)==0) ){ si->flags|=SI_IS_IP; /* do rev. DNS on it (for aliases)*/ he=rev_resolvehost(&si->address); if (he==0){ LM_WARN("could not rev. resolve %s\n", si->name.s); }else{ /* add the aliases*/ if (add_alias(he->h_name, strlen(he->h_name), si->port_no, si->proto)<0){ LM_ERR("add_alias failed\n"); } for(h=he->h_aliases; h && *h; h++) if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){ LM_ERR(" add_alias failed\n"); } } } /* Now build an ip_addr structure for the adv_name, if there is one * so that find_si can find it later easily. Doing this so that * we can force_send_socket() on an advertised name. Generally there * is little interest in dealing with an advertised name as anything * other than an opaque string that we blindly put into the SIP * message. */ if(si->adv_name_str.len) { /* If adv_name_str is already an IP, this is kinda foolish cus it * converts it to ip_addr, then to he, then here we go back to * ip_addr, but it's either that, or we duplicate the logic to * check for an ip address here, and still we might have to call * resolvehost(). */ he=resolvehost(si->adv_name_str.s,0); if (he==0){ LM_ERR("ERROR: fix_socket_list: could not resolve " "advertised name %s\n", si->adv_name_str.s); goto error; } hostent2ip_addr(&si->adv_address, he, 0); /*convert to ip_addr */ /* build and set string encoding for the adv socket info * This is usefful for the usrloc module when it's generating * or updating the socket on a location record, so we'll generate * it up front just like the regular sock_str so we don't have * to worry about it later. */ tmp = socket2str( si, 0, &si->adv_sock_str.len, 1); if (tmp==0) { LM_ERR("ERROR: fix_socket_list: failed to convert " "socket to string (adv)\n"); goto error; } si->adv_sock_str.s=(char*)pkg_malloc(si->adv_sock_str.len); if (si->adv_sock_str.s==0) { LM_ERR("ERROR: fix_socket_list: out of memory.\n"); goto error; } memcpy(si->adv_sock_str.s, tmp, si->adv_sock_str.len); } /* build and set string encoding for the real socket info */ tmp = socket2str( si, 0, &si->sock_str.len, 0); if (tmp==0) { LM_ERR("failed to convert socket to string"); goto error; } si->sock_str.s=(char*)pkg_malloc(si->sock_str.len); if (si->sock_str.s==0) { LM_ERR("out of pkg memory.\n"); goto error; } memcpy(si->sock_str.s, tmp, si->sock_str.len); #ifdef USE_MCAST /* Check if it is an multicast address and * set the flag if so */ if (is_mcast(&si->address)) { si->flags |= SI_IS_MCAST; } #endif /* USE_MCAST */ #ifdef EXTRA_DEBUG printf(" %.*s [%s]:%s%s\n", si->name.len, si->name.s, si->address_str.s, si->port_no_str.s, si->flags & SI_IS_MCAST ? " mcast" : ""); #endif } /* removing duplicate addresses*/ for (si=*list;si; si=si->next){ for (l=si->next;l;){ next=l->next; if ((si->port_no==l->port_no) && (si->address.af==l->address.af) && (memcmp(si->address.u.addr, l->address.u.addr, si->address.len) == 0) ){ #ifdef EXTRA_DEBUG printf("removing duplicate %s [%s] == %s [%s]\n", si->name.s, si->address_str.s, l->name.s, l->address_str.s); #endif /* add the name to the alias list*/ if ((!(l->flags& SI_IS_IP)) && ( (l->name.len!=si->name.len)|| (strncmp(l->name.s, si->name.s, si->name.len)!=0)) ) add_alias(l->name.s, l->name.len, l->port_no, l->proto); /* remove l*/ sock_listrm(list, l); free_sock_info(l); } l=next; } } #ifdef USE_MCAST /* Remove invalid multicast entries */ si=*list; while(si){ if ((si->flags & SI_IS_MCAST) && ((si->proto == PROTO_TCP) #ifdef USE_TLS || (si->proto == PROTO_TLS) #endif /* USE_TLS */ #ifdef USE_SCTP || (si->proto == PROTO_SCTP) #endif )){ LM_WARN("removing entry %s:%s [%s]:%s\n", get_proto_name(si->proto), si->name.s, si->address_str.s, si->port_no_str.s); l = si; si=si->next; sock_listrm(list, l); free_sock_info(l); } else { si=si->next; } } #endif /* USE_MCAST */ return 0; error: return -1; }