]> git.ipfire.org Git - thirdparty/sarg.git/blob - ip2name.c
Merge commit 'c1cb6a2978a9c3b11d87f60ce4'
[thirdparty/sarg.git] / ip2name.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2011
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 #ifdef HAVE_WS2TCPIP_H
30 #include <ws2tcpip.h> //define getnameinfo on windows
31 #endif
32
33 void ip2name(char *ip,int ip_len)
34 {
35 #ifdef HAVE_GETNAMEINFO
36 struct sockaddr_storage sa;
37 int sockaddr_size;
38 char host[NI_MAXHOST];
39 int n1,n2,n3,n4,next=0;
40 int error;
41
42 memset(&sa,0,sizeof(sa));
43 if (sscanf(ip,"%d.%d.%d.%d%n",&n1,&n2,&n3,&n4,&next)==4 && ip[next]=='\0') {
44 struct sockaddr_in *s4=(struct sockaddr_in *)&sa;
45 if (inet_pton(AF_INET,ip,&s4->sin_addr)!=1) return;
46 sa.ss_family=AF_INET;
47 sockaddr_size=sizeof(*s4);
48 } else {
49 struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&sa;
50 if (inet_pton(AF_INET6,ip,&s6->sin6_addr)!=1) return;
51 sa.ss_family=AF_INET6;
52 sockaddr_size=sizeof(*s6);
53 }
54 #ifdef HAVE_SOCKADDR_SA_LEN
55 sa.ss_len=sockaddr_size;
56 #endif
57 error=getnameinfo((struct sockaddr *)&sa,sockaddr_size,host,sizeof(host),NULL,0,0);
58 if (error==EAI_AGAIN) {
59 /*
60 This is a temporary failure. According to the man page we should try again but
61 it doesn't say if the program should wait before trying again nor how many attempts
62 before it becomes a fatal error. I could find no clues on internet so I try once and
63 leave it at that. Considering the number of IP addresses to resolve and the absence
64 of serious consequences should some IP fail to be resolved properly, it is best
65 not waste too much time on this.
66 */
67 error=getnameinfo((struct sockaddr *)&sa,sizeof(sa),host,sizeof(host),NULL,0,0);
68 }
69 if (error==0) {
70 strncpy(ip,host,ip_len-1);
71 ip[ip_len-1]='\0';
72 } else {
73 debuga(_("IP to name resolution (getnameinfo) on IP address %s failed with error %d - %s\n"),ip,error,gai_strerror(error));
74 }
75 #else
76 struct in_addr addr;
77 struct hostent *hp;
78 char **p;
79
80 #ifdef HAVE_INET_ATON
81 if (inet_aton(ip,&addr) == 0)
82 return;
83 #else
84 addr.s_addr=inet_addr(ip);
85 if (addr.s_addr==-1) return;
86 #endif
87
88 hp = gethostbyaddr((void *)&addr, sizeof (addr), AF_INET);
89 if (hp == NULL)
90 return;
91
92 for (p = hp->h_addr_list; *p != 0; p++) {
93 struct in_addr in;
94
95 (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr));
96 strncpy(ip,hp->h_name,ip_len-1);
97 ip[ip_len-1]=0;
98 }
99 #endif
100 return;
101 }
102
103 void name2ip(char *name,int name_size)
104 {
105 #ifdef HAVE_GETADDRINFO
106 int error;
107 char *port;
108 struct addrinfo *res;
109 char *addr;
110
111 addr=name;
112 if (name[0]=='[') { //IPv6 address
113 port=strchr(name,']');
114 if (port) { //confirmed IPv6 address
115 *port='\0';
116 addr++;
117 }
118 } else { //IPv4 address
119 port=strchr(name,':');
120 if (port) *port='\0';
121 }
122
123 error=getaddrinfo(addr,NULL,NULL,&res);
124 if (error) {
125 freeaddrinfo(res);
126 debuga(_("Cannot resolve host name %s: %s\n"),name,gai_strerror(error));
127 exit(EXIT_FAILURE);
128 }
129 if (res->ai_family==AF_INET) {
130 struct sockaddr_in *s4=(struct sockaddr_in *)res->ai_addr;
131 struct in_addr *sa=&s4->sin_addr;
132 if (res->ai_addrlen<sizeof(*s4)) {
133 debuga(_("Short structure returned by getaddrinfo for an IPv4 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s4));
134 exit(EXIT_FAILURE);
135 }
136 inet_ntop(res->ai_family,sa,name,name_size);
137 } else if (res->ai_family==AF_INET6) {
138 struct sockaddr_in6 *s6=(struct sockaddr_in6 *)res->ai_addr;
139 struct in6_addr *sa6=&s6->sin6_addr;
140 if (res->ai_addrlen<sizeof(*s6)) {
141 debuga(_("Short structure returned by getaddrinfo for an IPv6 address: %d bytes instead of %d\n"),res->ai_addrlen,(int)sizeof(*s6));
142 exit(EXIT_FAILURE);
143 }
144 inet_ntop(res->ai_family,sa6,name,name_size);
145 } else {
146 debuga(_("Invalid address type %d returned when resolving host name \"%s\"\n"),res->ai_family,name);
147 }
148 freeaddrinfo(res);
149 #else
150 struct in_addr ia;
151 struct hostent *hp;
152 char *port;
153 char n1[4];
154 char n2[4];
155 char n3[4];
156 char n4[4];
157 struct getwordstruct gwarea;
158
159 port=strchr(name,':');
160 if (port) *port='\0';
161
162 if((hp=gethostbyname(name))==NULL)
163 return;
164
165 memcpy(&ia.s_addr,hp->h_addr_list[0],sizeof(ia.s_addr));
166 ia.s_addr=ntohl(ia.s_addr);
167 getword_start(&gwarea,inet_ntoa(ia));
168 if (getword(n4,sizeof(n4),&gwarea,'.')<0 || getword(n3,sizeof(n3),&gwarea,'.')<0 ||
169 getword(n2,sizeof(n2),&gwarea,'.')<0 || getword(n1,sizeof(n1),&gwarea,0)<0) {
170 printf("SARG: Maybe you have a broken record or garbage in your %s ip address.\n",gwarea.beginning);
171 exit(EXIT_FAILURE);
172 }
173 snprintf(name,name_size,"%s.%s.%s.%s",n1,n2,n3,n4);
174 #endif
175
176 return;
177 }