00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <string.h>
00040 #include <errno.h>
00041 #include <unistd.h>
00042 #include <sys/types.h>
00043 #include <sys/socket.h>
00044 #include <sys/utsname.h>
00045 #include <stdio.h>
00046
00047 #include <sys/ioctl.h>
00048 #include <net/if.h>
00049 #ifdef HAVE_SYS_SOCKIO_H
00050 #include <sys/sockio.h>
00051 #endif
00052
00053 #include "globals.h"
00054 #include "socket_info.h"
00055 #include "dprint.h"
00056 #include "mem/mem.h"
00057 #include "ut.h"
00058 #include "resolve.h"
00059 #include "name_alias.h"
00060
00061
00062
00063
00064
00065
00066 #define sock_listadd(head, el) \
00067 do{\
00068 if (*(head)==0) *(head)=(el); \
00069 else{ \
00070 for((el)->next=*(head); (el)->next->next;\
00071 (el)->next=(el)->next->next); \
00072 (el)->next->next=(el); \
00073 (el)->prev=(el)->next; \
00074 (el)->next=0; \
00075 }\
00076 }while(0)
00077
00078
00079
00080 #define sock_listins(el, after) \
00081 do{ \
00082 if ((after)){\
00083 (el)->next=(after)->next; \
00084 if ((after)->next) (after)->next->prev=(el); \
00085 (after)->next=(el); \
00086 (el)->prev=(after); \
00087 }else{ \
00088 (after)=(el); \
00089 (el)->next=(el)->prev=0; \
00090 }\
00091 }while(0)
00092
00093
00094 #define sock_listrm(head, el) \
00095 do {\
00096 if (*(head)==(el)) *(head)=(el)->next; \
00097 if ((el)->next) (el)->next->prev=(el)->prev; \
00098 if ((el)->prev) (el)->prev->next=(el)->next; \
00099 }while(0)
00100
00101
00102
00103
00104 static inline struct socket_info* new_sock_info( char* name,
00105 unsigned short port, unsigned short proto,
00106 enum si_flags flags)
00107 {
00108 struct socket_info* si;
00109
00110 si=(struct socket_info*) pkg_malloc(sizeof(struct socket_info));
00111 if (si==0) goto error;
00112 memset(si, 0, sizeof(struct socket_info));
00113 si->socket=-1;
00114 si->name.len=strlen(name);
00115 si->name.s=(char*)pkg_malloc(si->name.len+1);
00116 if (si->name.s==0) goto error;
00117 memcpy(si->name.s, name, si->name.len+1);
00118
00119 si->port_no=port;
00120 si->proto=proto;
00121 si->flags=flags;
00122 return si;
00123 error:
00124 LM_ERR("pkg memory allocation error\n");
00125 if (si) pkg_free(si);
00126 return 0;
00127 }
00128
00129
00130
00131
00132 static void free_sock_info(struct socket_info* si)
00133 {
00134 if(si){
00135 if(si->name.s) pkg_free(si->name.s);
00136 if(si->address_str.s) pkg_free(si->address_str.s);
00137 if(si->port_no_str.s) pkg_free(si->port_no_str.s);
00138 }
00139 }
00140
00141
00142
00143 static char* get_proto_name(unsigned short proto)
00144 {
00145 switch(proto){
00146 case PROTO_NONE:
00147 return "*";
00148 case PROTO_UDP:
00149 return "udp";
00150 #ifdef USE_TCP
00151 case PROTO_TCP:
00152 return "tcp";
00153 #endif
00154 #ifdef USE_TLS
00155 case PROTO_TLS:
00156 return "tls";
00157 #endif
00158 #ifdef USE_SCTP
00159 case PROTO_SCTP:
00160 return "sctp";
00161 #endif
00162 default:
00163 return "unknown";
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 struct socket_info* grep_sock_info(str* host, unsigned short port,
00177 unsigned short proto)
00178 {
00179 char* hname;
00180 int h_len;
00181 struct socket_info* si;
00182 struct socket_info** list;
00183 unsigned short c_proto;
00184 #ifdef USE_IPV6
00185 struct ip_addr* ip6;
00186 #endif
00187 h_len=host->len;
00188 hname=host->s;
00189 #ifdef USE_IPV6
00190 if ((h_len>2)&&((*hname)=='[')&&(hname[h_len-1]==']')){
00191
00192 hname++;
00193 h_len-=2;
00194 }
00195 #endif
00196 c_proto=proto?proto:PROTO_UDP;
00197 do{
00198
00199 if (c_proto==PROTO_NONE)
00200 list=&udp_listen;
00201 else
00202 list=get_sock_info_list(c_proto);
00203
00204 if (list==0){
00205 LM_WARN("unknown proto %d\n", c_proto);
00206 goto not_found;
00207 }
00208 for (si=*list; si; si=si->next){
00209 LM_DBG("checking if host==us: %d==%d && "
00210 " [%.*s] == [%.*s]\n",
00211 h_len,
00212 si->name.len,
00213 h_len, hname,
00214 si->name.len, si->name.s
00215 );
00216 if (port) {
00217 LM_DBG("checking if port %d matches port %d\n",
00218 si->port_no, port);
00219 if (si->port_no!=port) {
00220 continue;
00221 }
00222 }
00223 if ( (h_len==si->name.len) &&
00224 (strncasecmp(hname, si->name.s,
00225 si->name.len)==0) )
00226
00227
00228
00229 goto found;
00230
00231 #ifdef USE_IPV6
00232
00233 ip6=str2ip6(host);
00234 if (ip6){
00235 if (ip_addr_cmp(ip6, &si->address))
00236 goto found;
00237 else
00238 continue;
00239
00240 }
00241 #endif
00242
00243 if ( (!(si->flags&SI_IS_IP)) &&
00244 (h_len==si->address_str.len) &&
00245 (memcmp(hname, si->address_str.s,
00246 si->address_str.len)==0)
00247 )
00248 goto found;
00249 }
00250 }while( (proto==0) && (c_proto=next_proto(c_proto)) );
00251 not_found:
00252 LM_DBG("no match for: [%.*s:%d]\n", h_len, hname, port);
00253 return 0;
00254 found:
00255 LM_DBG("match found for: [%.*s:%d]\n", h_len, hname, port);
00256 return si;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
00271 unsigned short proto)
00272 {
00273 struct socket_info* si;
00274 struct socket_info** list;
00275 unsigned short c_proto;
00276
00277 c_proto=proto?proto:PROTO_UDP;
00278 do{
00279
00280 if (c_proto==PROTO_NONE)
00281 list=&udp_listen;
00282 else
00283 list=get_sock_info_list(c_proto);
00284
00285 if (list==0){
00286 LM_WARN("unknown proto %d\n", c_proto);
00287 goto not_found;
00288 }
00289 for (si=*list; si; si=si->next){
00290 if (port) {
00291 if (si->port_no!=port) {
00292 continue;
00293 }
00294 }
00295 if (ip_addr_cmp(ip, &si->address))
00296 goto found;
00297 }
00298 }while( (proto==0) && (c_proto=next_proto(c_proto)) );
00299 not_found:
00300 return 0;
00301 found:
00302 return si;
00303 }
00304
00305
00306
00307
00308
00309 int new_sock2list(char* name, unsigned short port, unsigned short proto,
00310 enum si_flags flags, struct socket_info** list)
00311 {
00312 struct socket_info* si;
00313
00314 si=new_sock_info(name, port, proto, flags);
00315 if (si==0){
00316 LM_ERR("new_sock_info failed\n");
00317 goto error;
00318 }
00319 sock_listadd(list, si);
00320 return 0;
00321 error:
00322 return -1;
00323 }
00324
00325
00326
00327
00328
00329 int add_listen_iface(char* name, unsigned short port, unsigned short proto,
00330 enum si_flags flags)
00331 {
00332 struct socket_info** list;
00333 unsigned short c_proto;
00334
00335 c_proto=(proto)?proto:PROTO_UDP;
00336 do{
00337 list=get_sock_info_list(c_proto);
00338 if (list==0){
00339 LM_ERR("get_sock_info_list failed\n");
00340 goto error;
00341 }
00342 if (port==0){
00343 port=
00344 #ifdef USE_TLS
00345 ((c_proto)==PROTO_TLS)?tls_port_no:
00346 #endif
00347 port_no;
00348 }
00349 #ifdef USE_TLS
00350 else if ((c_proto==PROTO_TLS) && (proto==0)){
00351
00352 port++;
00353 }
00354 #endif
00355 if (new_sock2list(name, port, c_proto, flags, list)<0){
00356 LM_ERR("new_sock2list failed\n");
00357 goto error;
00358 }
00359 }while( (proto==0) && (c_proto=next_proto(c_proto)));
00360 return 0;
00361 error:
00362 return -1;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 int add_interfaces(char* if_name, int family, unsigned short port,
00373 unsigned short proto,
00374 struct socket_info** list)
00375 {
00376 struct ifconf ifc;
00377 struct ifreq ifr;
00378 struct ifreq ifrcopy;
00379 char* last;
00380 char* p;
00381 int size;
00382 int lastlen;
00383 int s;
00384 char* tmp;
00385 struct ip_addr addr;
00386 int ret;
00387 enum si_flags flags;
00388
00389
00390 flags=SI_NONE;
00391 s=socket(family, SOCK_DGRAM, 0);
00392 ret=-1;
00393 lastlen=0;
00394 ifc.ifc_req=0;
00395 for (size=100; ; size*=2){
00396 ifc.ifc_len=size*sizeof(struct ifreq);
00397 ifc.ifc_req=(struct ifreq*) pkg_malloc(size*sizeof(struct ifreq));
00398 if (ifc.ifc_req==0){
00399 LM_ERR("memory allocation failure\n");
00400 goto error;
00401 }
00402 if (ioctl(s, SIOCGIFCONF, &ifc)==-1){
00403 if(errno==EBADF) return 0;
00404 LM_ERR("ioctl failed: %s\n", strerror(errno));
00405 goto error;
00406 }
00407 if ((lastlen) && (ifc.ifc_len==lastlen)) break;
00408
00409 lastlen=ifc.ifc_len;
00410
00411 pkg_free(ifc.ifc_req);
00412 }
00413
00414 last=(char*)ifc.ifc_req+ifc.ifc_len;
00415 for(p=(char*)ifc.ifc_req; p<last;
00416 p+=
00417 #ifdef __OS_linux
00418 sizeof(ifr)
00419 #else
00420 (sizeof(ifr.ifr_name)+
00421 #ifdef HAVE_SOCKADDR_SA_LEN
00422 MAX(ifr.ifr_addr.sa_len, sizeof(struct sockaddr))
00423 #else
00424 ( (ifr.ifr_addr.sa_family==AF_INET)?
00425 sizeof(struct sockaddr_in):
00426 ((ifr.ifr_addr.sa_family==AF_INET6)?
00427 sizeof(struct sockaddr_in6):sizeof(struct sockaddr)) )
00428 #endif
00429 )
00430 #endif
00431 )
00432 {
00433
00434
00435 memcpy(&ifr, p, sizeof(ifr));
00436 if (ifr.ifr_addr.sa_family!=family){
00437
00438
00439 continue;
00440 }
00441
00442
00443 ifrcopy=ifr;
00444 if (ioctl(s, SIOCGIFFLAGS, &ifrcopy)!=-1){
00445
00446 if (if_name==0){
00447
00448 if (!(ifrcopy.ifr_flags & IFF_UP)) continue;
00449 }
00450 }
00451
00452
00453
00454 if ((if_name==0)||
00455 (strncmp(if_name, ifr.ifr_name, sizeof(ifr.ifr_name))==0)){
00456
00457
00458 sockaddr2ip_addr(&addr,
00459 (struct sockaddr*)(p+(long)&((struct ifreq*)0)->ifr_addr));
00460 if ((tmp=ip_addr2a(&addr))==0) goto error;
00461
00462 if (ifrcopy.ifr_flags & IFF_LOOPBACK)
00463 flags|=SI_IS_LO;
00464
00465 if (new_sock2list(tmp, port, proto, flags, list)!=0){
00466 LM_ERR("new_sock2list failed\n");
00467 goto error;
00468 }
00469 ret=0;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 }
00479 pkg_free(ifc.ifc_req);
00480 close(s);
00481 return ret;
00482 error:
00483 if (ifc.ifc_req) pkg_free(ifc.ifc_req);
00484 close(s);
00485 return -1;
00486 }
00487
00488
00489
00490
00491 static int fix_socket_list(struct socket_info **list)
00492 {
00493 struct socket_info* si;
00494 struct socket_info* l;
00495 struct socket_info* next;
00496 char* tmp;
00497 int len;
00498 struct hostent* he;
00499 char** h;
00500
00501
00502
00503
00504 for (si=*list;si;){
00505 next=si->next;
00506 if (add_interfaces(si->name.s, AF_INET, si->port_no,
00507 si->proto, list)!=-1){
00508
00509 sock_listrm(list, si);
00510 free_sock_info(si);
00511 }
00512 si=next;
00513 }
00514
00515 #ifdef EXTRA_DEBUG
00516 LM_DBG("listening on \n");
00517 #endif
00518 for (si=*list;si;si=si->next){
00519
00520 if (si->port_no==0){
00521 #ifdef USE_TLS
00522 si->port_no= (si->proto==PROTO_TLS)?tls_port_no:port_no;
00523 #else
00524 si->port_no= port_no;
00525 #endif
00526 }
00527 tmp=int2str(si->port_no, &len);
00528 if (len>=MAX_PORT_LEN){
00529 LM_ERR("bad port number: %d\n", si->port_no);
00530 goto error;
00531 }
00532 si->port_no_str.s=(char*)pkg_malloc(len+1);
00533 if (si->port_no_str.s==0){
00534 LM_ERR("out of pkg memory.\n");
00535 goto error;
00536 }
00537 strncpy(si->port_no_str.s, tmp, len+1);
00538 si->port_no_str.len=len;
00539
00540 he=resolvehost(si->name.s,0);
00541 if (he==0){
00542 LM_ERR("could not resolve %s\n", si->name.s);
00543 goto error;
00544 }
00545
00546 if (strcasecmp(he->h_name, si->name.s)!=0){
00547 if (auto_aliases && add_alias(si->name.s, si->name.len,
00548 si->port_no, si->proto)<0){
00549 LM_ERR("add_alias failed\n");
00550 }
00551
00552 pkg_free(si->name.s);
00553 si->name.s=(char*)pkg_malloc(strlen(he->h_name)+1);
00554 if (si->name.s==0){
00555 LM_ERR("out of pkg memory.\n");
00556 goto error;
00557 }
00558 si->name.len=strlen(he->h_name);
00559 strncpy(si->name.s, he->h_name, si->name.len+1);
00560 }
00561
00562 if (auto_aliases) {
00563 for(h=he->h_aliases; h && *h; h++)
00564 if (add_alias(*h, strlen(*h), si->port_no, si->proto)<0){
00565 LM_ERR("add_alias failed\n");
00566 }
00567 }
00568 hostent2ip_addr(&si->address, he, 0);
00569
00570 if ((tmp=ip_addr2a(&si->address))==0) goto error;
00571 if (si->address.af == AF_INET6) {
00572 si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1+2);
00573 if (si->address_str.s==0){
00574 LM_ERR("out of pkg memory.\n");
00575 goto error;
00576 }
00577 si->address_str.s[0] = '[';
00578 strncpy( si->address_str.s+1 , tmp, strlen(tmp));
00579 si->address_str.s[1+strlen(tmp)] = ']';
00580 si->address_str.s[2+strlen(tmp)] = '\0';
00581 si->address_str.len=strlen(tmp) + 2;
00582 } else {
00583 si->address_str.s=(char*)pkg_malloc(strlen(tmp)+1);
00584 if (si->address_str.s==0){
00585 LM_ERR("out of pkg memory.\n");
00586 goto error;
00587 }
00588 strncpy(si->address_str.s, tmp, strlen(tmp)+1);
00589 si->address_str.len=strlen(tmp);
00590 }
00591
00592 if ( auto_aliases && (si->address_str.len==si->name.len) &&
00593 (strncasecmp(si->address_str.s, si->name.s,
00594 si->address_str.len)==0)
00595 ){
00596 si->flags|=SI_IS_IP;
00597
00598 he=rev_resolvehost(&si->address);
00599 if (he==0){
00600 LM_WARN("could not rev. resolve %s\n", si->name.s);
00601 }else{
00602
00603 if (add_alias(he->h_name, strlen(he->h_name),
00604 si->port_no, si->proto)<0){
00605 LM_ERR("add_alias failed\n");
00606 }
00607 for(h=he->h_aliases; h && *h; h++)
00608 if (add_alias(*h,strlen(*h),si->port_no,si->proto)<0){
00609 LM_ERR(" add_alias failed\n");
00610 }
00611 }
00612 }
00613
00614
00615 tmp = socket2str( si, 0, &si->sock_str.len);
00616 if (tmp==0) {
00617 LM_ERR("failed to convert socket to string");
00618 goto error;
00619 }
00620 si->sock_str.s=(char*)pkg_malloc(si->sock_str.len);
00621 if (si->sock_str.s==0) {
00622 LM_ERR("out of pkg memory.\n");
00623 goto error;
00624 }
00625 memcpy(si->sock_str.s, tmp, si->sock_str.len);
00626
00627 #ifdef USE_MCAST
00628
00629
00630
00631 if (is_mcast(&si->address)) {
00632 si->flags |= SI_IS_MCAST;
00633 }
00634 #endif
00635
00636 #ifdef EXTRA_DEBUG
00637 printf(" %.*s [%s]:%s%s\n", si->name.len,
00638 si->name.s, si->address_str.s, si->port_no_str.s,
00639 si->flags & SI_IS_MCAST ? " mcast" : "");
00640 #endif
00641 }
00642
00643 for (si=*list;si; si=si->next){
00644 for (l=si->next;l;){
00645 next=l->next;
00646 if ((si->port_no==l->port_no) &&
00647 (si->address.af==l->address.af) &&
00648 (memcmp(si->address.u.addr, l->address.u.addr, si->address.len)
00649 == 0)
00650 ){
00651 #ifdef EXTRA_DEBUG
00652 printf("removing duplicate %s [%s] == %s [%s]\n",
00653 si->name.s, si->address_str.s,
00654 l->name.s, l->address_str.s);
00655 #endif
00656
00657 if ((!(l->flags& SI_IS_IP)) && (
00658 (l->name.len!=si->name.len)||
00659 (strncmp(l->name.s, si->name.s, si->name.len)!=0))
00660 )
00661 add_alias(l->name.s, l->name.len, l->port_no, l->proto);
00662
00663
00664 sock_listrm(list, l);
00665 free_sock_info(l);
00666 }
00667 l=next;
00668 }
00669 }
00670
00671 #ifdef USE_MCAST
00672
00673 si=*list;
00674 while(si){
00675 if ((si->flags & SI_IS_MCAST) &&
00676 ((si->proto == PROTO_TCP)
00677 #ifdef USE_TLS
00678 || (si->proto == PROTO_TLS)
00679 #endif
00680 #ifdef USE_SCTP
00681 || (si->proto == PROTO_SCTP)
00682 #endif
00683 )){
00684 LM_WARN("removing entry %s:%s [%s]:%s\n",
00685 get_proto_name(si->proto), si->name.s,
00686 si->address_str.s, si->port_no_str.s);
00687 l = si;
00688 si=si->next;
00689 sock_listrm(list, l);
00690 free_sock_info(l);
00691 } else {
00692 si=si->next;
00693 }
00694 }
00695 #endif
00696
00697 return 0;
00698 error:
00699 return -1;
00700 }
00701
00702
00703
00704
00705
00706 int fix_all_socket_lists(void)
00707 {
00708 struct utsname myname;
00709
00710 if ((udp_listen==0)
00711 #ifdef USE_TCP
00712 && (tcp_listen==0)
00713 #ifdef USE_TLS
00714 && (tls_listen==0)
00715 #endif
00716 #endif
00717 #ifdef USE_SCTP
00718 && (sctp_listen==0)
00719 #endif
00720 ){
00721
00722 if (add_interfaces(0, AF_INET, 0, PROTO_UDP, &udp_listen)==0){
00723
00724 #ifdef USE_TCP
00725 if (!tcp_disable){
00726 if (add_interfaces(0, AF_INET, 0, PROTO_TCP, &tcp_listen)!=0)
00727 goto error;
00728 #ifdef USE_TLS
00729 if (!tls_disable){
00730 if (add_interfaces(0, AF_INET, 0, PROTO_TLS,
00731 &tls_listen)!=0)
00732 goto error;
00733 }
00734 #endif
00735 }
00736 #endif
00737 #ifdef USE_SCTP
00738 if (!sctp_disable){
00739 if (add_interfaces(0, AF_INET, 0, PROTO_SCTP, &sctp_listen)!=0)
00740 goto error;
00741 }
00742 #endif
00743 }else{
00744
00745
00746 if (uname (&myname) <0){
00747 LM_ERR("cannot determine hostname, try -l address\n");
00748 goto error;
00749 }
00750 if (add_listen_iface(myname.nodename, 0, 0, 0)!=0){
00751 LM_ERR("add_listen_iface failed \n");
00752 goto error;
00753 }
00754 }
00755 }
00756 if (fix_socket_list(&udp_listen)!=0){
00757 LM_ERR("fix_socket_list udp failed\n");
00758 goto error;
00759 }
00760 #ifdef USE_TCP
00761 if (!tcp_disable && (fix_socket_list(&tcp_listen)!=0)){
00762 LM_ERR("fix_socket_list tcp failed\n");
00763 goto error;
00764 }
00765 #ifdef USE_TLS
00766 if (!tls_disable && (fix_socket_list(&tls_listen)!=0)){
00767 LM_ERR("fix_socket_list tls failed\n");
00768 goto error;
00769 }
00770 #endif
00771 #endif
00772 #ifdef USE_SCTP
00773 if (!sctp_disable && (fix_socket_list(&sctp_listen)!=0)){
00774 LM_ERR("fix_socket_list sctp failed\n");
00775 goto error;
00776 }
00777 #endif
00778
00779 if ((udp_listen==0)
00780 #ifdef USE_TCP
00781 && (tcp_listen==0)
00782 #ifdef USE_TLS
00783 && (tls_listen==0)
00784 #endif
00785 #endif
00786 #ifdef USE_SCTP
00787 && (sctp_listen==0)
00788 #endif
00789 ){
00790 LM_ERR("no listening sockets\n");
00791 goto error;
00792 }
00793 return 0;
00794 error:
00795 return -1;
00796 }
00797
00798
00799
00800 void print_all_socket_lists(void)
00801 {
00802 struct socket_info *si;
00803 struct socket_info** list;
00804 unsigned short proto;
00805
00806
00807 proto=PROTO_UDP;
00808 do{
00809 list=get_sock_info_list(proto);
00810 for(si=list?*list:0; si; si=si->next){
00811 printf(" %s: %s [%s]:%s%s\n", get_proto_name(proto),
00812 si->name.s, si->address_str.s, si->port_no_str.s,
00813 si->flags & SI_IS_MCAST ? " mcast" : "");
00814 }
00815 }while((proto=next_proto(proto)));
00816 }
00817
00818
00819 void print_aliases(void)
00820 {
00821 struct host_alias* a;
00822
00823 for(a=aliases; a; a=a->next)
00824 if (a->port)
00825 printf(" %s: %.*s:%d\n", get_proto_name(a->proto),
00826 a->alias.len, a->alias.s, a->port);
00827 else
00828 printf(" %s: %.*s:*\n", get_proto_name(a->proto),
00829 a->alias.len, a->alias.s);
00830 }