]> git.ipfire.org Git - thirdparty/sarg.git/blame - ip2name.c
Prepare the ip resolving for other resolving methods
[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"
e9b33b57 29#ifdef HAVE_WS2TCPIP_H
9bd92830 30#include <ws2tcpip.h> //define getnameinfo on windows
e9b33b57 31#endif
25697a35 32
2846a495
FM
33//! The possible return code of ip2name subfunctions.
34enum ip2name_retcode
35{
36 //! Error encountered during the
37 INRC_Error=-1,
38 //! No match found.
39 INRC_NotFound,
40 //! A match was found.
41 INRC_Found,
42};
43
44/*!
45Resolve the IP address using a reverse DNS entry.
46
47\param ip The IP address. It is replaced by the corresponding name if one
48can be found.
49\param ip_len The length of the \c ip buffer.
50
51\return One of the ::ip2name_retcode value.
52*/
53static enum ip2name_retcode ip2name_dns(char *ip,int ip_len)
9c7c6346 54{
72c27633 55#ifdef HAVE_GETNAMEINFO
9bd92830 56 struct sockaddr_storage sa;
a50c6319 57 int sockaddr_size;
9bd92830
FM
58 char host[NI_MAXHOST];
59 int n1,n2,n3,n4,next=0;
60 int error;
72c27633 61
9bd92830
FM
62 memset(&sa,0,sizeof(sa));
63 if (sscanf(ip,"%d.%d.%d.%d%n",&n1,&n2,&n3,&n4,&next)==4 && ip[next]=='\0') {
64 struct sockaddr_in *s4=(struct sockaddr_in *)&sa;
2846a495 65 if (inet_pton(AF_INET,ip,&s4->sin_addr)!=1) return(INRC_Error);
9bd92830 66 sa.ss_family=AF_INET;
a50c6319 67 sockaddr_size=sizeof(*s4);
9bd92830
FM
68 } else {
69 struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&sa;
2846a495 70 if (inet_pton(AF_INET6,ip,&s6->sin6_addr)!=1) return(INRC_Error);
9bd92830 71 sa.ss_family=AF_INET6;
a50c6319 72 sockaddr_size=sizeof(*s6);
9bd92830 73 }
a50c6319
FM
74#ifdef HAVE_SOCKADDR_SA_LEN
75 sa.ss_len=sockaddr_size;
76#endif
2846a495 77 error=getnameinfo((struct sockaddr *)&sa,sockaddr_size,host,sizeof(host),NULL,0,NI_NAMEREQD);
8fa27cb0
FM
78 if (error==EAI_AGAIN) {
79 /*
80 This is a temporary failure. According to the man page we should try again but
81 it doesn't say if the program should wait before trying again nor how many attempts
82 before it becomes a fatal error. I could find no clues on internet so I try once and
83 leave it at that. Considering the number of IP addresses to resolve and the absence
84 of serious consequences should some IP fail to be resolved properly, it is best
85 not waste too much time on this.
86 */
2846a495 87 error=getnameinfo((struct sockaddr *)&sa,sizeof(sa),host,sizeof(host),NULL,0,NI_NAMEREQD);
8fa27cb0 88 }
2846a495
FM
89 if (error==EAI_NONAME)
90 return(INRC_NotFound);
91 if (error!=0) {
9bd92830 92 debuga(_("IP to name resolution (getnameinfo) on IP address %s failed with error %d - %s\n"),ip,error,gai_strerror(error));
2846a495 93 return(INRC_Error);
9bd92830 94 }
2846a495
FM
95 safe_strcpy(ip,host,ip_len);
96#else //HAVE_GETNAMEINFO
9bd92830
FM
97 struct in_addr addr;
98 struct hostent *hp;
99 char **p;
2846a495 100 extern int h_errno;
25697a35 101
e9b33b57 102#ifdef HAVE_INET_ATON
9bd92830 103 if (inet_aton(ip,&addr) == 0)
2846a495 104 return(INRC_Error);
e9b33b57 105#else
9bd92830 106 addr.s_addr=inet_addr(ip);
2846a495 107 if (addr.s_addr==-1) return(INRC_Error);
e9b33b57 108#endif
25697a35 109
9bd92830 110 hp = gethostbyaddr((void *)&addr, sizeof (addr), AF_INET);
2846a495
FM
111 if (hp == NULL) {
112 if (h_errno==HOST_NOT_FOUND)
113 return(INRC_NotFound);
114 return(INRC_Error);
115 }
25697a35 116
9bd92830
FM
117 for (p = hp->h_addr_list; *p != 0; p++) {
118 struct in_addr in;
25697a35 119
9bd92830 120 (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
a87d4d11 121 safe_strcpy(ip,hp->h_name,ip_len);
9bd92830 122 }
72c27633 123#endif
2846a495
FM
124 return(INRC_Found);
125}
126
127/*!
128Convert an IP address into a name.
129
130\param ip The IP address. It is replaced by the corresponding name if one
131can be found.
132\param ip_len The length of the \c ip buffer.
133*/
134void ip2name(char *ip,int ip_len)
135{
136 enum ip2name_retcode Status;
137
138 Status=ip2name_dns(ip,ip_len);
139 if (Status==INRC_Found) return;
936c9905 140}
25697a35 141
4afbb7a5 142void name2ip(char *name,int name_size)
9c7c6346 143{
4afbb7a5
FM
144#ifdef HAVE_GETADDRINFO
145 int error;
146 char *port;
147 struct addrinfo *res;
148 char *addr;
149
150 addr=name;
151 if (name[0]=='[') { //IPv6 address
152 port=strchr(name,']');
153 if (port) { //confirmed IPv6 address
154 *port='\0';
155 addr++;
156 }
157 } else { //IPv4 address
158 port=strchr(name,':');
159 if (port) *port='\0';
160 }
161
162 error=getaddrinfo(addr,NULL,NULL,&res);
163 if (error) {
164 freeaddrinfo(res);
165 debuga(_("Cannot resolve host name %s: %s\n"),name,gai_strerror(error));
166 exit(EXIT_FAILURE);
167 }
168 if (res->ai_family==AF_INET) {
169 struct sockaddr_in *s4=(struct sockaddr_in *)res->ai_addr;
170 struct in_addr *sa=&s4->sin_addr;
171 if (res->ai_addrlen<sizeof(*s4)) {
45d00862 172 debuga(_("Short structure returned by getaddrinfo for an IPv4 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s4));
4afbb7a5
FM
173 exit(EXIT_FAILURE);
174 }
175 inet_ntop(res->ai_family,sa,name,name_size);
176 } else if (res->ai_family==AF_INET6) {
177 struct sockaddr_in6 *s6=(struct sockaddr_in6 *)res->ai_addr;
178 struct in6_addr *sa6=&s6->sin6_addr;
179 if (res->ai_addrlen<sizeof(*s6)) {
45d00862 180 debuga(_("Short structure returned by getaddrinfo for an IPv6 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s6));
4afbb7a5
FM
181 exit(EXIT_FAILURE);
182 }
183 inet_ntop(res->ai_family,sa6,name,name_size);
184 } else {
185 debuga(_("Invalid address type %d returned when resolving host name \"%s\"\n"),res->ai_family,name);
186 }
187 freeaddrinfo(res);
188#else
9bd92830
FM
189 struct in_addr ia;
190 struct hostent *hp;
191 char *port;
192 char n1[4];
193 char n2[4];
194 char n3[4];
195 char n4[4];
196 struct getwordstruct gwarea;
25697a35 197
9bd92830 198 port=strchr(name,':');
4afbb7a5 199 if (port) *port='\0';
25697a35 200
9bd92830
FM
201 if((hp=gethostbyname(name))==NULL)
202 return;
9c7c6346 203
9bd92830
FM
204 memcpy(&ia.s_addr,hp->h_addr_list[0],sizeof(ia.s_addr));
205 ia.s_addr=ntohl(ia.s_addr);
206 getword_start(&gwarea,inet_ntoa(ia));
207 if (getword(n4,sizeof(n4),&gwarea,'.')<0 || getword(n3,sizeof(n3),&gwarea,'.')<0 ||
007905af 208 getword(n2,sizeof(n2),&gwarea,'.')<0 || getword(n1,sizeof(n1),&gwarea,0)<0) {
9bd92830
FM
209 printf("SARG: Maybe you have a broken record or garbage in your %s ip address.\n",gwarea.beginning);
210 exit(EXIT_FAILURE);
211 }
4afbb7a5
FM
212 snprintf(name,name_size,"%s.%s.%s.%s",n1,n2,n3,n4);
213#endif
25697a35 214
9bd92830 215 return;
9c7c6346 216}