]> git.ipfire.org Git - thirdparty/sarg.git/blame_incremental - ip2name.c
Add support to decompress xz files
[thirdparty/sarg.git] / ip2name.c
... / ...
CommitLineData
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.
33struct 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
41extern struct Ip2NameProcess Ip2NameDns;
42extern struct Ip2NameProcess Ip2NameExec;
43
44//! The list of the modules available to resolve an IP address into a name.
45static 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.
54static struct Ip2NameProcess *FirstModule=NULL;
55//! The list of the names found so far.
56static DichotomicObject KnownIp=NULL;
57
58/*!
59Add a new module to the list of the configured modules.
60*/
61static 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/*!
86Add a new module to the list of the configured modules.
87
88\param list The list of the modules name to chain.
89*/
90static 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/*!
117Configure a module whose name is given as an argument. The parameters to configure
118follow 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*/
122static 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/*!
145Configure a module to resolve an IP address into a name.
146
147\param param The parameter found in the configuration file.
148It always begins after the "resolv_ip".
149
150\retval 1 Parameter processed.
151\retval 0 Parameter ignored.
152*/
153int 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/*!
171Require the use of the DNS to resolve the IP addresses.
172*/
173void 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/*!
208Convert an IP address into a name.
209
210\param ip The IP address. It is replaced by the corresponding name if one
211can be found.
212\param ip_len The length of the \c ip buffer.
213
214The function does nothing if no module are configured.
215*/
216void 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/*!
248Release the memory allocated to resolve the IP addresses
249into names.
250*/
251void ip2name_cleanup(void)
252{
253 Dichotomic_Destroy(&KnownIp);
254}
255
256void 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}