]> git.ipfire.org Git - thirdparty/sarg.git/blame - ip2name.c
Fix the reported year in the extended log
[thirdparty/sarg.git] / ip2name.c
CommitLineData
25697a35 1/*
94ff9470 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
61d965f3 3 * 1998, 2012
25697a35
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
25697a35
GS
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"
5f3cfd1d 28#include "include/defs.h"
51b166d4 29#include "include/ip2name.h"
0326d73b 30#include "include/dichotomic.h"
25697a35 31
51b166d4
FM
32//! Associate a name or alias to a module.
33struct Ip2NameModules
2846a495 34{
51b166d4
FM
35 //! The name of the module
36 const char *Name;
37 //! The structure to access the module functions.
38 struct Ip2NameProcess *Process;
2846a495
FM
39};
40
51b166d4 41extern struct Ip2NameProcess Ip2NameDns;
1e312c82 42extern struct Ip2NameProcess Ip2NameExec;
51b166d4
FM
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},
1e312c82 48 {"exec",&Ip2NameExec},
51b166d4
FM
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;
0326d73b
FM
55//! The list of the names found so far.
56static DichotomicObject KnownIp=NULL;
51b166d4 57
2846a495 58/*!
51b166d4
FM
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(_("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(_("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}
2846a495 84
51b166d4
FM
85/*!
86Add a new module to the list of the configured modules.
2846a495 87
51b166d4 88\param list The list of the modules name to chain.
2846a495 89*/
51b166d4 90static void ip2name_buildmoduleslist(const char *list)
9c7c6346 91{
51b166d4
FM
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(_("Unknown module \"%.*s\" to resolve the IP addresses\n"),length,candidate);
110 exit(EXIT_FAILURE);
111 }
112 list=candidate+length;
113 }
114}
115
1e312c82
FM
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(_("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
51b166d4
FM
144/*!
145Configure a module to resolve an IP address into a name.
72c27633 146
51b166d4
FM
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=='_') {
1e312c82
FM
163 ip2name_configmodule(param+1);
164 return(1);
9bd92830 165 }
51b166d4
FM
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 }
8fa27cb0 187 }
51b166d4
FM
188 if (!DnsModule) {
189 if (debugz) debuga(_("No known module to resolve an IP address using the DNS\n"));
190 exit(EXIT_FAILURE);
9bd92830 191 }
51b166d4
FM
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;
2846a495 197 }
51b166d4
FM
198 if (debug) debuga(_("Chaining IP resolving module \"%s\"\n"),DnsModule->Name);
199 if (Last)
200 Last->Next=DnsModule;
201 else {
202 FirstModule=DnsModule;
203 Ip2Name=true;
9bd92830 204 }
2846a495
FM
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.
51b166d4
FM
213
214The function does nothing if no module are configured.
2846a495
FM
215*/
216void ip2name(char *ip,int ip_len)
217{
51b166d4 218 struct Ip2NameProcess *Module;
2846a495 219 enum ip2name_retcode Status;
0326d73b
FM
220 const char *Name;
221 char OrigIp[80];
222
223 if (!KnownIp) {
224 KnownIp=Dichotomic_Create();
225 if (!KnownIp) {
226 debuga(_("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 }
2846a495 236
0326d73b 237 safe_strcpy(OrigIp,ip,sizeof(OrigIp));
51b166d4
FM
238 for (Module=FirstModule ; Module ; Module=Module->Next) {
239 if (Module->Resolve) {
240 Status=Module->Resolve(ip,ip_len);
0326d73b 241 if (Status==INRC_Found) break;
51b166d4
FM
242 }
243 }
0326d73b
FM
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);
936c9905 254}
25697a35 255
4afbb7a5 256void name2ip(char *name,int name_size)
9c7c6346 257{
4afbb7a5
FM
258#ifdef HAVE_GETADDRINFO
259 int error;
260 char *port;
261 struct addrinfo *res;
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 freeaddrinfo(res);
279 debuga(_("Cannot resolve host name %s: %s\n"),name,gai_strerror(error));
280 exit(EXIT_FAILURE);
281 }
282 if (res->ai_family==AF_INET) {
283 struct sockaddr_in *s4=(struct sockaddr_in *)res->ai_addr;
284 struct in_addr *sa=&s4->sin_addr;
285 if (res->ai_addrlen<sizeof(*s4)) {
45d00862 286 debuga(_("Short structure returned by getaddrinfo for an IPv4 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s4));
4afbb7a5
FM
287 exit(EXIT_FAILURE);
288 }
289 inet_ntop(res->ai_family,sa,name,name_size);
290 } else if (res->ai_family==AF_INET6) {
291 struct sockaddr_in6 *s6=(struct sockaddr_in6 *)res->ai_addr;
292 struct in6_addr *sa6=&s6->sin6_addr;
293 if (res->ai_addrlen<sizeof(*s6)) {
45d00862 294 debuga(_("Short structure returned by getaddrinfo for an IPv6 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s6));
4afbb7a5
FM
295 exit(EXIT_FAILURE);
296 }
297 inet_ntop(res->ai_family,sa6,name,name_size);
298 } else {
299 debuga(_("Invalid address type %d returned when resolving host name \"%s\"\n"),res->ai_family,name);
300 }
301 freeaddrinfo(res);
302#else
9bd92830
FM
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;
25697a35 311
9bd92830 312 port=strchr(name,':');
4afbb7a5 313 if (port) *port='\0';
25697a35 314
9bd92830
FM
315 if((hp=gethostbyname(name))==NULL)
316 return;
9c7c6346 317
9bd92830
FM
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 ||
007905af 322 getword(n2,sizeof(n2),&gwarea,'.')<0 || getword(n1,sizeof(n1),&gwarea,0)<0) {
9bd92830
FM
323 printf("SARG: Maybe you have a broken record or garbage in your %s ip address.\n",gwarea.beginning);
324 exit(EXIT_FAILURE);
325 }
4afbb7a5
FM
326 snprintf(name,name_size,"%s.%s.%s.%s",n1,n2,n3,n4);
327#endif
25697a35 328
9bd92830 329 return;
9c7c6346 330}