"Fossies" - the Fresh Open Source Software Archive

Member "sarg-2.4.0/ip2name.c" (22 Dec 2019, 9268 Bytes) of package /linux/privat/sarg-2.4.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ip2name.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.11_vs_2.4.0.

    1 /*
    2  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
    3  *                                                            1998, 2015
    4  *
    5  * SARG donations:
    6  *      please look at http://sarg.sourceforge.net/donations.php
    7  * Support:
    8  *     http://sourceforge.net/projects/sarg/forums/forum/363374
    9  * ---------------------------------------------------------------------
   10  *
   11  *  This program is free software; you can redistribute it and/or modify
   12  *  it under the terms of the GNU General Public License as published by
   13  *  the Free Software Foundation; either version 2 of the License, or
   14  *  (at your option) any later version.
   15  *
   16  *  This program is distributed in the hope that it will be useful,
   17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19  *  GNU General Public License for more details.
   20  *
   21  *  You should have received a copy of the GNU General Public License
   22  *  along with this program; if not, write to the Free Software
   23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   24  *
   25  */
   26 
   27 #include "include/conf.h"
   28 #include "include/defs.h"
   29 #include "include/ip2name.h"
   30 #include "include/dichotomic.h"
   31 
   32 //! Associate a name or alias to a module.
   33 struct Ip2NameModules
   34 {
   35     //! The name of the module
   36     const char *Name;
   37     //! The structure to access the module functions.
   38     struct Ip2NameProcess *Process;
   39 };
   40 
   41 extern struct Ip2NameProcess Ip2NameDns;
   42 extern struct Ip2NameProcess Ip2NameExec;
   43 
   44 //! The list of the modules available to resolve an IP address into a name.
   45 static const struct Ip2NameModules ModulesList[]=
   46 {
   47     {"dns",&Ip2NameDns},
   48     {"exec",&Ip2NameExec},
   49     {"yes",&Ip2NameDns},//for historical compatibility
   50     {"no",NULL},//does nothing for compatibility with previous versions
   51 };
   52 
   53 //! The chain of the configured modules to try to resolve an IP.
   54 static struct Ip2NameProcess *FirstModule=NULL;
   55 //! The list of the names found so far.
   56 static DichotomicObject KnownIp=NULL;
   57 
   58 /*!
   59 Add a new module to the list of the configured modules.
   60 */
   61 static void ip2name_chainmodule(struct Ip2NameProcess *Module)
   62 {
   63     struct Ip2NameProcess *Chain;
   64     struct Ip2NameProcess *Last;
   65 
   66     if (debug) debuga(__FILE__,__LINE__,_("Chaining IP resolving module \"%s\"\n"),Module->Name);
   67 
   68     Last=NULL;
   69     for (Chain=FirstModule ; Chain ; Chain=Chain->Next) {
   70         if (Chain==Module) {
   71             debuga(__FILE__,__LINE__,_("Ignoring duplicate module \"%s\" to resolve an IP address\n"),Module->Name);
   72             return;
   73         }
   74         Last=Chain;
   75     }
   76 
   77     if (Last)
   78         Last->Next=Module;
   79     else {
   80         FirstModule=Module;
   81         Ip2Name=true;
   82     }
   83 }
   84 
   85 /*!
   86 Add a new module to the list of the configured modules.
   87 
   88 \param list The list of the modules name to chain.
   89 */
   90 static void ip2name_buildmoduleslist(const char *list)
   91 {
   92     const char *candidate;
   93     int length;
   94     int ModuleIdx;
   95 
   96     while (*list) {
   97         candidate=list;
   98         while (*candidate && (unsigned char)*candidate<=' ') candidate++;
   99         for (length=0 ; (unsigned char)candidate[length]>' ' ; length++);
  100         for (ModuleIdx=0 ; ModuleIdx<sizeof(ModulesList)/sizeof(*ModulesList) ; ModuleIdx++) {
  101             if (strncasecmp(candidate,ModulesList[ModuleIdx].Name,length)==0 && ModulesList[ModuleIdx].Name[length]=='\0') {
  102                 // module found
  103                 if (ModulesList[ModuleIdx].Process)
  104                     ip2name_chainmodule(ModulesList[ModuleIdx].Process);
  105                 break;
  106             }
  107         }
  108         if (ModuleIdx>=sizeof(ModulesList)/sizeof(*ModulesList)) {
  109             debuga(__FILE__,__LINE__,_("Unknown module \"%.*s\" to resolve the IP addresses\n"),length,candidate);
  110             exit(EXIT_FAILURE);
  111         }
  112         list=candidate+length;
  113     }
  114 }
  115 
  116 /*!
  117 Configure a module whose name is given as an argument. The parameters to configure
  118 follow the module name after one or more space or tabs.
  119 
  120 \param module The name of the module, a space and the configuration options.
  121 */
  122 static void ip2name_configmodule(const char *module)
  123 {
  124     int length;
  125     unsigned int ModuleIdx;
  126 
  127     for (length=0 ; module[length] && (unsigned char)module[length]>' ' ; length++);
  128     for (ModuleIdx=0 ; ModuleIdx<sizeof(ModulesList)/sizeof(*ModulesList) ; ModuleIdx++) {
  129         if (strncasecmp(module,ModulesList[ModuleIdx].Name,length)==0 && ModulesList[ModuleIdx].Name[length]=='\0') {
  130             // module found
  131             if (ModulesList[ModuleIdx].Process) {
  132                 if (!ModulesList[ModuleIdx].Process->Configure) {
  133                     debuga(__FILE__,__LINE__,_("No option to configure for module %s\n"),ModulesList[ModuleIdx].Name);
  134                     exit(EXIT_FAILURE);
  135                 }
  136                 while (module[length] && (unsigned char)module[length]<=' ') length++;
  137                 ModulesList[ModuleIdx].Process->Configure(ModulesList[ModuleIdx].Name,module+length);
  138             }
  139             break;
  140         }
  141     }
  142 }
  143 
  144 /*!
  145 Configure a module to resolve an IP address into a name.
  146 
  147 \param param The parameter found in the configuration file.
  148 It always begins after the "resolv_ip".
  149 
  150 \retval 1 Parameter processed.
  151 \retval 0 Parameter ignored.
  152 */
  153 int ip2name_config(const char *param)
  154 {
  155     // module to add to the list
  156     if (*param==' ') {
  157         ip2name_buildmoduleslist(param);
  158         return(1);
  159     }
  160 
  161     // parameter for a module?
  162     if (*param=='_') {
  163         ip2name_configmodule(param+1);
  164         return(1);
  165     }
  166 
  167     return(0);
  168 }
  169 
  170 /*!
  171 Require the use of the DNS to resolve the IP addresses.
  172 */
  173 void ip2name_forcedns(void)
  174 {
  175     struct Ip2NameProcess *DnsModule=NULL;
  176     int i;
  177     struct Ip2NameProcess *Chain;
  178     struct Ip2NameProcess *Last;
  179 
  180     // find the dns module
  181     for (i=0 ; i<sizeof(ModulesList)/sizeof(*ModulesList) ; i++) {
  182         if (strcmp("dns",ModulesList[i].Name)==0) {
  183             // module found
  184             DnsModule=ModulesList[i].Process;
  185             break;
  186         }
  187     }
  188     if (!DnsModule) {
  189         debuga(__FILE__,__LINE__,_("No known module to resolve an IP address using the DNS\n"));
  190         exit(EXIT_FAILURE);
  191     }
  192 
  193     // add the module to the list if it isn't there yet
  194     Last=NULL;
  195     for (Chain=FirstModule ; Chain && Chain!=DnsModule ; Chain=Chain->Next) {
  196         Last=Chain;
  197     }
  198     if (debug) debuga(__FILE__,__LINE__,_("Chaining IP resolving module \"%s\"\n"),DnsModule->Name);
  199     if (Last)
  200         Last->Next=DnsModule;
  201     else {
  202         FirstModule=DnsModule;
  203         Ip2Name=true;
  204     }
  205 }
  206 
  207 /*!
  208 Convert an IP address into a name.
  209 
  210 \param ip The IP address. It is replaced by the corresponding name if one
  211 can be found.
  212 \param ip_len The length of the \c ip buffer.
  213 
  214 The function does nothing if no module are configured.
  215 */
  216 void ip2name(char *ip,int ip_len)
  217 {
  218     struct Ip2NameProcess *Module;
  219     enum ip2name_retcode Status;
  220     const char *Name;
  221     char OrigIp[80];
  222 
  223     if (!KnownIp) {
  224         KnownIp=Dichotomic_Create();
  225         if (!KnownIp) {
  226             debuga(__FILE__,__LINE__,_("Not enough memory to store the names corresponding to the IP address\n"));
  227             exit(EXIT_FAILURE);
  228         }
  229     }
  230 
  231     Name=Dichotomic_Search(KnownIp,ip);
  232     if (Name) {
  233         safe_strcpy(ip,Name,ip_len);
  234         return;
  235     }
  236 
  237     safe_strcpy(OrigIp,ip,sizeof(OrigIp));
  238     for (Module=FirstModule ; Module ; Module=Module->Next) {
  239         if (Module->Resolve) {
  240             Status=Module->Resolve(ip,ip_len);
  241             if (Status==INRC_Found) break;
  242         }
  243     }
  244     Dichotomic_Insert(KnownIp,OrigIp,ip);
  245 }
  246 
  247 /*!
  248 Release the memory allocated to resolve the IP addresses
  249 into names.
  250 */
  251 void ip2name_cleanup(void)
  252 {
  253     Dichotomic_Destroy(&KnownIp);
  254 }
  255 
  256 void name2ip(char *name,int name_size)
  257 {
  258 #ifdef HAVE_GETADDRINFO
  259     int error;
  260     char *port;
  261     struct addrinfo *res=NULL;
  262     char *addr;
  263 
  264     addr=name;
  265     if (name[0]=='[') { //IPv6 address
  266         port=strchr(name,']');
  267         if (port) { //confirmed IPv6 address
  268             *port='\0';
  269             addr++;
  270         }
  271     } else { //IPv4 address
  272         port=strchr(name,':');
  273         if (port) *port='\0';
  274     }
  275 
  276     error=getaddrinfo(addr,NULL,NULL,&res);
  277     if (error) {
  278         if (res) freeaddrinfo(res);
  279         debuga(__FILE__,__LINE__,_("Cannot resolve host name \"%s\": %s\n"),name,gai_strerror(error));
  280     } else {
  281         if (res->ai_family==AF_INET) {
  282             struct sockaddr_in *s4=(struct sockaddr_in *)res->ai_addr;
  283             struct in_addr *sa=&s4->sin_addr;
  284             if (res->ai_addrlen<sizeof(*s4)) {
  285                 debuga(__FILE__,__LINE__,_("Short structure returned by getaddrinfo for an IPv4 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s4));
  286                 exit(EXIT_FAILURE);
  287             }
  288             inet_ntop(res->ai_family,sa,name,name_size);
  289         } else if (res->ai_family==AF_INET6) {
  290             struct sockaddr_in6 *s6=(struct sockaddr_in6 *)res->ai_addr;
  291             struct in6_addr *sa6=&s6->sin6_addr;
  292             if (res->ai_addrlen<sizeof(*s6)) {
  293                 debuga(__FILE__,__LINE__,_("Short structure returned by getaddrinfo for an IPv6 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s6));
  294                 exit(EXIT_FAILURE);
  295             }
  296             inet_ntop(res->ai_family,sa6,name,name_size);
  297         } else {
  298             debuga(__FILE__,__LINE__,_("Invalid address type %d returned when resolving host name \"%s\"\n"),res->ai_family,name);
  299         }
  300         freeaddrinfo(res);
  301     }
  302 #else
  303     struct in_addr ia;
  304     struct hostent *hp;
  305     char *port;
  306     char n1[4];
  307     char n2[4];
  308     char n3[4];
  309     char n4[4];
  310     struct getwordstruct gwarea;
  311 
  312     port=strchr(name,':');
  313     if (port) *port='\0';
  314 
  315     if ((hp=gethostbyname(name))==NULL)
  316         return;
  317 
  318     memcpy(&ia.s_addr,hp->h_addr_list[0],sizeof(ia.s_addr));
  319     ia.s_addr=ntohl(ia.s_addr);
  320     getword_start(&gwarea,inet_ntoa(ia));
  321     if (getword(n4,sizeof(n4),&gwarea,'.')<0 || getword(n3,sizeof(n3),&gwarea,'.')<0 ||
  322         getword(n2,sizeof(n2),&gwarea,'.')<0 || getword(n1,sizeof(n1),&gwarea,0)<0) {
  323         debuga(__FILE__,__LINE__,_("Invalid IPv4 address \"%s\"\n"),gwarea.beginning);
  324         exit(EXIT_FAILURE);
  325     }
  326     snprintf(name,name_size,"%s.%s.%s.%s",n1,n2,n3,n4);
  327 #endif
  328 
  329     return;
  330 }