2 * "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $"
4 * HTTP address routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * httpAddrAny() - Check for the "any" address.
27 * httpAddrEqual() - Compare two addresses.
28 * httpAddrLoad() - Load a host entry address into an HTTP address.
29 * httpAddrLocalhost() - Check for the local loopback address.
30 * httpAddrLookup() - Lookup the hostname associated with the address.
31 * httpAddrString() - Convert an IP address to a dotted string.
32 * httpGetHostByName() - Lookup a hostname or IP address, and return
33 * address records for the specified name.
37 * Include necessary headers...
40 #pragma ident "%Z%%M% %I% %E% SMI"
49 * 'httpAddrAny()' - Check for the "any" address.
52 int /* O - 1 if "any", 0 otherwise */
53 httpAddrAny(const http_addr_t
*addr
) /* I - Address to check */
56 if (addr
->addr
.sa_family
== AF_INET6
&&
57 IN6_IS_ADDR_UNSPECIFIED(&(addr
->ipv6
.sin6_addr
)))
61 if (addr
->addr
.sa_family
== AF_INET
&&
62 ntohl(addr
->ipv4
.sin_addr
.s_addr
) == 0x00000000)
70 * 'httpAddrEqual()' - Compare two addresses.
73 int /* O - 1 if equal, 0 if != */
74 httpAddrEqual(const http_addr_t
*addr1
, /* I - First address */
75 const http_addr_t
*addr2
) /* I - Second address */
77 if (addr1
->addr
.sa_family
!= addr2
->addr
.sa_family
)
81 if (addr1
->addr
.sa_family
== AF_INET6
)
82 return (memcmp(&(addr1
->ipv6
.sin6_addr
), &(addr2
->ipv6
.sin6_addr
), 16) == 0);
85 return (addr1
->ipv4
.sin_addr
.s_addr
== addr2
->ipv4
.sin_addr
.s_addr
);
90 * 'httpAddrLoad()' - Load a host entry address into an HTTP address.
94 httpAddrLoad(const struct hostent
*host
, /* I - Host entry */
95 int port
, /* I - Port number */
96 int n
, /* I - Index into host entry */
97 http_addr_t
*addr
) /* O - Address to load */
100 if (host
->h_addrtype
== AF_INET6
)
103 addr
->ipv6
.sin6_port
= htons((u_short
)port
);
105 addr
->ipv6
.sin6_port
= htons(port
);
108 memcpy((char *)&(addr
->ipv6
.sin6_addr
), host
->h_addr_list
[n
],
110 addr
->ipv6
.sin6_family
= AF_INET6
;
113 #endif /* AF_INET6 */
115 if (host
->h_addrtype
== AF_LOCAL
)
117 addr
->un
.sun_family
= AF_LOCAL
;
118 strlcpy(addr
->un
.sun_path
, host
->h_addr_list
[n
], sizeof(addr
->un
.sun_path
));
121 #endif /* AF_LOCAL */
122 if (host
->h_addrtype
== AF_INET
)
125 addr
->ipv4
.sin_port
= htons((u_short
)port
);
127 addr
->ipv4
.sin_port
= htons(port
);
130 memcpy((char *)&(addr
->ipv4
.sin_addr
), host
->h_addr_list
[n
],
132 addr
->ipv4
.sin_family
= AF_INET
;
138 * 'httpAddrLocalhost()' - Check for the local loopback address.
141 int /* O - 1 if local host, 0 otherwise */
142 httpAddrLocalhost(const http_addr_t
*addr
)
143 /* I - Address to check */
146 if (addr
->addr
.sa_family
== AF_INET6
&&
147 IN6_IS_ADDR_LOOPBACK(&(addr
->ipv6
.sin6_addr
)))
149 #endif /* AF_INET6 */
152 if (addr
->addr
.sa_family
== AF_LOCAL
)
154 #endif /* AF_LOCAL */
156 if (addr
->addr
.sa_family
== AF_INET
&&
157 ntohl(addr
->ipv4
.sin_addr
.s_addr
) == 0x7f000001)
165 # define ADDR_CAST (struct sockaddr *)
167 # define ADDR_CAST (char *)
172 * 'httpAddrLookup()' - Lookup the hostname associated with the address.
175 char * /* O - Host name */
176 httpAddrLookup(const http_addr_t
*addr
, /* I - Address to lookup */
177 char *name
, /* I - Host name buffer */
178 int namelen
) /* I - Size of name buffer */
180 struct hostent
*host
; /* Host from name service */
183 DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n",
184 addr
, name
, namelen
));
187 if (addr
->addr
.sa_family
== AF_INET6
)
188 host
= gethostbyaddr(ADDR_CAST
&(addr
->ipv6
.sin6_addr
),
189 sizeof(struct in6_addr
), AF_INET6
);
191 #endif /* AF_INET6 */
193 if (addr
->addr
.sa_family
== AF_LOCAL
)
195 strlcpy(name
, addr
->un
.sun_path
, namelen
);
199 #endif /* AF_LOCAL */
200 if (addr
->addr
.sa_family
== AF_INET
)
201 host
= gethostbyaddr(ADDR_CAST
&(addr
->ipv4
.sin_addr
),
202 sizeof(struct in_addr
), AF_INET
);
208 httpAddrString(addr
, name
, namelen
);
212 strlcpy(name
, host
->h_name
, namelen
);
219 * 'httpAddrString()' - Convert an IP address to a dotted string.
222 char * /* O - IP string */
223 httpAddrString(const http_addr_t
*addr
, /* I - Address to convert */
224 char *s
, /* I - String buffer */
225 int slen
) /* I - Length of string */
227 DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n",
231 if (addr
->addr
.sa_family
== AF_INET6
)
232 snprintf(s
, slen
, "%u.%u.%u.%u",
233 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[0]),
234 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[1]),
235 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[2]),
236 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[3]));
238 #endif /* AF_INET6 */
240 if (addr
->addr
.sa_family
== AF_LOCAL
)
241 strlcpy(s
, addr
->un
.sun_path
, slen
);
243 #endif /* AF_LOCAL */
244 if (addr
->addr
.sa_family
== AF_INET
)
246 unsigned temp
; /* Temporary address */
249 temp
= ntohl(addr
->ipv4
.sin_addr
.s_addr
);
251 snprintf(s
, slen
, "%d.%d.%d.%d", (temp
>> 24) & 255,
252 (temp
>> 16) & 255, (temp
>> 8) & 255, temp
& 255);
255 strlcpy(s
, "UNKNOWN", slen
);
257 DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s
));
264 * 'httpGetHostByName()' - Lookup a hostname or IP address, and return
265 * address records for the specified name.
268 struct hostent
* /* O - Host entry */
269 httpGetHostByName(const char *name
) /* I - Hostname or IP address */
271 const char *nameptr
; /* Pointer into name */
272 unsigned ip
[4]; /* IP address components */
273 static unsigned packed_ip
; /* Packed IPv4 address */
274 static char *packed_ptr
[2]; /* Pointer to packed address */
275 static struct hostent host_ip
; /* Host entry for IP/domain address */
278 DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name
));
280 #if defined(__APPLE__)
281 /* OS X hack to avoid it's ocassional long delay in lookupd */
282 static const char sLoopback
[] = "127.0.0.1";
283 if (strcmp(name
, "localhost") == 0)
285 #endif /* __APPLE__ */
288 * This function is needed because some operating systems have a
289 * buggy implementation of gethostbyname() that does not support
290 * IP addresses. If the first character of the name string is a
291 * number, then sscanf() is used to extract the IP components.
292 * We then pack the components into an IPv4 address manually,
293 * since the inet_aton() function is deprecated. We use the
294 * htonl() macro to get the right byte order for the address.
296 * We also support domain sockets when supported by the underlying
304 * A domain socket address, so make an AF_LOCAL entry and return it...
307 host_ip
.h_name
= (char *)name
;
308 host_ip
.h_aliases
= NULL
;
309 host_ip
.h_addrtype
= AF_LOCAL
;
310 host_ip
.h_length
= strlen(name
) + 1;
311 host_ip
.h_addr_list
= packed_ptr
;
312 packed_ptr
[0] = (char *)name
;
313 packed_ptr
[1] = NULL
;
315 DEBUG_puts("httpGetHostByName: returning domain socket address...");
319 #endif /* AF_LOCAL */
321 for (nameptr
= name
; isdigit(*nameptr
& 255) || *nameptr
== '.'; nameptr
++);
326 * We have an IP address; break it up and provide the host entry
327 * to the caller. Currently only supports IPv4 addresses, although
328 * it should be trivial to support IPv6 in CUPS 1.2.
331 if (sscanf(name
, "%u.%u.%u.%u", ip
, ip
+ 1, ip
+ 2, ip
+ 3) != 4)
332 return (NULL
); /* Must have 4 numbers */
334 if (ip
[0] > 255 || ip
[1] > 255 || ip
[2] > 255 || ip
[3] > 255)
335 return (NULL
); /* Invalid byte ranges! */
337 packed_ip
= htonl(((((((ip
[0] << 8) | ip
[1]) << 8) | ip
[2]) << 8) | ip
[3]));
340 * Fill in the host entry and return it...
343 host_ip
.h_name
= (char *)name
;
344 host_ip
.h_aliases
= NULL
;
345 host_ip
.h_addrtype
= AF_INET
;
346 host_ip
.h_length
= 4;
347 host_ip
.h_addr_list
= packed_ptr
;
348 packed_ptr
[0] = (char *)(&packed_ip
);
349 packed_ptr
[1] = NULL
;
351 DEBUG_puts("httpGetHostByName: returning IPv4 address...");
358 * Use the gethostbyname() function to get the IP address for
362 DEBUG_puts("httpGetHostByName: returning domain lookup address(es)...");
364 return (gethostbyname(name
));
370 * End of "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $".