]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/http-addr.c
e2ddb8cfbfeddd1d99b6089480a94e1556cc9558
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...
46 * 'httpAddrAny()' - Check for the "any" address.
49 int /* O - 1 if "any", 0 otherwise */
50 httpAddrAny(const http_addr_t
*addr
) /* I - Address to check */
53 if (addr
->addr
.sa_family
== AF_INET6
&&
54 IN6_IS_ADDR_UNSPECIFIED(&(addr
->ipv6
.sin6_addr
)))
58 if (addr
->addr
.sa_family
== AF_INET
&&
59 ntohl(addr
->ipv4
.sin_addr
.s_addr
) == 0x00000000)
67 * 'httpAddrEqual()' - Compare two addresses.
70 int /* O - 1 if equal, 0 if != */
71 httpAddrEqual(const http_addr_t
*addr1
, /* I - First address */
72 const http_addr_t
*addr2
) /* I - Second address */
74 if (addr1
->addr
.sa_family
!= addr2
->addr
.sa_family
)
78 if (addr1
->addr
.sa_family
== AF_LOCAL
)
79 return (!strcmp(addr1
->un
.sun_path
, addr2
->un
.sun_path
));
83 if (addr1
->addr
.sa_family
== AF_INET6
)
84 return (memcmp(&(addr1
->ipv6
.sin6_addr
), &(addr2
->ipv6
.sin6_addr
), 16) == 0);
87 return (addr1
->ipv4
.sin_addr
.s_addr
== addr2
->ipv4
.sin_addr
.s_addr
);
92 * 'httpAddrLoad()' - Load a host entry address into an HTTP address.
96 httpAddrLoad(const struct hostent
*host
, /* I - Host entry */
97 int port
, /* I - Port number */
98 int n
, /* I - Index into host entry */
99 http_addr_t
*addr
) /* O - Address to load */
102 if (host
->h_addrtype
== AF_INET6
)
105 addr
->ipv6
.sin6_port
= htons((u_short
)port
);
107 addr
->ipv6
.sin6_port
= htons(port
);
110 memcpy((char *)&(addr
->ipv6
.sin6_addr
), host
->h_addr_list
[n
],
112 addr
->ipv6
.sin6_family
= AF_INET6
;
115 #endif /* AF_INET6 */
117 if (host
->h_addrtype
== AF_LOCAL
)
119 addr
->un
.sun_family
= AF_LOCAL
;
120 strlcpy(addr
->un
.sun_path
, host
->h_addr_list
[n
], sizeof(addr
->un
.sun_path
));
123 #endif /* AF_LOCAL */
124 if (host
->h_addrtype
== AF_INET
)
127 addr
->ipv4
.sin_port
= htons((u_short
)port
);
129 addr
->ipv4
.sin_port
= htons(port
);
132 memcpy((char *)&(addr
->ipv4
.sin_addr
), host
->h_addr_list
[n
],
134 addr
->ipv4
.sin_family
= AF_INET
;
140 * 'httpAddrLocalhost()' - Check for the local loopback address.
143 int /* O - 1 if local host, 0 otherwise */
144 httpAddrLocalhost(const http_addr_t
*addr
)
145 /* I - Address to check */
148 if (addr
->addr
.sa_family
== AF_INET6
&&
149 (IN6_IS_ADDR_LOOPBACK(&(addr
->ipv6
.sin6_addr
)) ||
150 IN6_IS_ADDR_UNSPECIFIED(&(addr
->ipv6
.sin6_addr
))))
152 #endif /* AF_INET6 */
155 if (addr
->addr
.sa_family
== AF_LOCAL
)
157 #endif /* AF_LOCAL */
159 if (addr
->addr
.sa_family
== AF_INET
&&
160 ntohl(addr
->ipv4
.sin_addr
.s_addr
) == 0x7f000001)
168 # define ADDR_CAST (struct sockaddr *)
170 # define ADDR_CAST (char *)
175 * 'httpAddrLookup()' - Lookup the hostname associated with the address.
178 char * /* O - Host name */
179 httpAddrLookup(const http_addr_t
*addr
, /* I - Address to lookup */
180 char *name
, /* I - Host name buffer */
181 int namelen
) /* I - Size of name buffer */
183 struct hostent
*host
; /* Host from name service */
186 DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n",
187 addr
, name
, namelen
));
190 if (addr
->addr
.sa_family
== AF_INET6
)
191 host
= gethostbyaddr(ADDR_CAST
&(addr
->ipv6
.sin6_addr
),
192 sizeof(struct in6_addr
), AF_INET6
);
194 #endif /* AF_INET6 */
196 if (addr
->addr
.sa_family
== AF_LOCAL
)
198 strlcpy(name
, addr
->un
.sun_path
, namelen
);
202 #endif /* AF_LOCAL */
203 if (addr
->addr
.sa_family
== AF_INET
)
204 host
= gethostbyaddr(ADDR_CAST
&(addr
->ipv4
.sin_addr
),
205 sizeof(struct in_addr
), AF_INET
);
211 httpAddrString(addr
, name
, namelen
);
215 strlcpy(name
, host
->h_name
, namelen
);
222 * 'httpAddrString()' - Convert an IP address to a dotted string.
225 char * /* O - IP string */
226 httpAddrString(const http_addr_t
*addr
, /* I - Address to convert */
227 char *s
, /* I - String buffer */
228 int slen
) /* I - Length of string */
230 DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n",
234 if (addr
->addr
.sa_family
== AF_INET6
)
235 snprintf(s
, slen
, "[%x:%x:%x:%x]",
236 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[0]),
237 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[1]),
238 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[2]),
239 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[3]));
241 #endif /* AF_INET6 */
243 if (addr
->addr
.sa_family
== AF_LOCAL
)
244 strlcpy(s
, addr
->un
.sun_path
, slen
);
246 #endif /* AF_LOCAL */
247 if (addr
->addr
.sa_family
== AF_INET
)
249 unsigned temp
; /* Temporary address */
252 temp
= ntohl(addr
->ipv4
.sin_addr
.s_addr
);
254 snprintf(s
, slen
, "%d.%d.%d.%d", (temp
>> 24) & 255,
255 (temp
>> 16) & 255, (temp
>> 8) & 255, temp
& 255);
258 strlcpy(s
, "UNKNOWN", slen
);
260 DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s
));
267 * 'httpGetHostByName()' - Lookup a hostname or IP address, and return
268 * address records for the specified name.
271 struct hostent
* /* O - Host entry */
272 httpGetHostByName(const char *name
) /* I - Hostname or IP address */
274 int i
; /* Looping var */
275 const char *nameptr
; /* Pointer into name */
276 unsigned ip
[4]; /* IP address components */
277 _cups_globals_t
*cg
= _cupsGlobals();
278 /* Pointer to library globals */
281 DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name
));
284 * Avoid lookup delays and configuration problems when connecting
285 * to the localhost address...
288 if (!strcmp(name
, "localhost"))
292 * This function is needed because some operating systems have a
293 * buggy implementation of gethostbyname() that does not support
294 * IP addresses. If the first character of the name string is a
295 * number, then sscanf() is used to extract the IP components.
296 * We then pack the components into an IPv4 address manually,
297 * since the inet_aton() function is deprecated. We use the
298 * htonl() macro to get the right byte order for the address.
300 * We also support domain sockets when supported by the underlying
308 * A domain socket address, so make an AF_LOCAL entry and return it...
311 cg
->hostent
.h_name
= (char *)name
;
312 cg
->hostent
.h_aliases
= NULL
;
313 cg
->hostent
.h_addrtype
= AF_LOCAL
;
314 cg
->hostent
.h_length
= strlen(name
) + 1;
315 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
316 cg
->ip_ptrs
[0] = (char *)name
;
317 cg
->ip_ptrs
[1] = NULL
;
319 DEBUG_puts("httpGetHostByName: returning domain socket address...");
321 return (&cg
->hostent
);
323 #endif /* AF_LOCAL */
328 * A raw 128-bit IPv6 address of the form "[xxxx:xxxx:xxxx:xxxx]"
331 cg
->hostent
.h_name
= (char *)name
;
332 cg
->hostent
.h_aliases
= NULL
;
333 cg
->hostent
.h_addrtype
= AF_INET6
;
334 cg
->hostent
.h_length
= 16;
335 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
336 cg
->ip_ptrs
[0] = (char *)(cg
->ip_addrs
[0]);
337 cg
->ip_ptrs
[1] = NULL
;
339 for (i
= 0, nameptr
= name
+ 1; *nameptr
&& i
< 4; i
++)
343 else if (*nameptr
== ':')
344 cg
->ip_addrs
[0][i
] = 0;
346 cg
->ip_addrs
[0][i
] = htonl(strtoul(nameptr
, (char **)&nameptr
, 16));
348 if (*nameptr
== ':' || *nameptr
== ']')
354 cg
->ip_addrs
[0][i
] = 0;
361 DEBUG_puts("httpGetHostByName: returning IPv6 address...");
363 return (&cg
->hostent
);
365 #endif /* AF_INET6 */
367 for (nameptr
= name
; isdigit(*nameptr
& 255) || *nameptr
== '.'; nameptr
++);
372 * We have an IPv4 address; break it up and provide the host entry
376 if (sscanf(name
, "%u.%u.%u.%u", ip
, ip
+ 1, ip
+ 2, ip
+ 3) != 4)
377 return (NULL
); /* Must have 4 numbers */
379 if (ip
[0] > 255 || ip
[1] > 255 || ip
[2] > 255 || ip
[3] > 255)
380 return (NULL
); /* Invalid byte ranges! */
382 cg
->ip_addrs
[0][0] = htonl(((((((ip
[0] << 8) | ip
[1]) << 8) | ip
[2]) << 8) |
386 * Fill in the host entry and return it...
389 cg
->hostent
.h_name
= (char *)name
;
390 cg
->hostent
.h_aliases
= NULL
;
391 cg
->hostent
.h_addrtype
= AF_INET
;
392 cg
->hostent
.h_length
= 4;
393 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
394 cg
->ip_ptrs
[0] = (char *)cg
->ip_addrs
[0];
395 cg
->ip_ptrs
[1] = NULL
;
397 DEBUG_puts("httpGetHostByName: returning IPv4 address...");
399 return (&cg
->hostent
);
402 #ifdef HAVE_GETADDRINFO
405 * Use the getaddrinfo() function to get the IP address for the
409 struct addrinfo hints
, /* Address lookup hints */
410 *results
, /* Address lookup results */
411 *current
; /* Current result */
412 http_addr_t
*address
; /* Current address */
415 memset(&hints
, 0, sizeof(hints
));
416 hints
.ai_family
= PF_UNSPEC
;
417 hints
.ai_socktype
= SOCK_STREAM
;
418 hints
.ai_flags
= AI_CANONNAME
;
420 if (getaddrinfo(name
, NULL
, &hints
, &results
))
423 * If getaddrinfo() fails, try gethostbyname()...
426 return (gethostbyname(name
));
430 * Initialize hostent structure, preferring the IPv6 address...
433 for (current
= results
; current
; current
= current
->ai_next
)
434 if (current
->ai_family
== AF_INET6
)
439 for (current
= results
; current
; current
= current
->ai_next
)
440 if (current
->ai_family
== AF_INET
)
446 * No IPv4 or IPv6 addresses, try gethostbyname()...
449 freeaddrinfo(results
);
451 return (gethostbyname(name
));
455 strlcpy(cg
->hostname
, current
->ai_canonname
, sizeof(cg
->hostname
));
457 cg
->hostent
.h_name
= cg
->hostname
;
458 cg
->hostent
.h_aliases
= NULL
;
459 cg
->hostent
.h_addrtype
= current
->ai_family
;
460 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
462 if (current
->ai_family
== AF_INET6
)
463 cg
->hostent
.h_length
= 16;
465 cg
->hostent
.h_length
= 4;
468 * Convert the address info to a hostent structure...
471 for (i
= 0, current
= results
;
472 i
< CUPS_MAX_ADDRS
&& current
;
473 current
= current
->ai_next
)
474 if (current
->ai_family
== cg
->hostent
.h_addrtype
)
477 * Copy this address...
480 address
= (http_addr_t
*)(current
->ai_addr
);
482 if (current
->ai_family
== AF_INET
)
483 memcpy((char *)cg
->ip_addrs
[i
], (char *)&(address
->ipv4
.sin_addr
), 4);
485 memcpy((char *)cg
->ip_addrs
[i
], (char *)&(address
->ipv6
.sin6_addr
), 16);
487 cg
->ip_ptrs
[i
] = (char *)cg
->ip_addrs
[i
];
491 cg
->ip_ptrs
[i
] = NULL
;
494 * Free the getaddrinfo() results and return the hostent structure...
497 freeaddrinfo(results
);
499 return (&cg
->hostent
);
504 * Use the gethostbyname() function to get the IP address for
508 DEBUG_puts("httpGetHostByName: returning domain lookup address(es)...");
510 return (gethostbyname(name
));
512 #endif /* HAVE_GETADDRINFO */
517 * 'httpGetHostname()' - Get the FQDN for the local system.
519 * This function uses both gethostname() and gethostbyname() to
520 * get the local hostname with domain.
523 const char * /* O - FQDN for this system */
524 httpGetHostname(char *s
, /* I - String buffer for name */
525 int slen
) /* I - Size of buffer */
527 struct hostent
*host
; /* Host entry to get FQDN */
531 * Get the hostname...
534 gethostname(s
, slen
);
539 * The hostname is not a FQDN, so look it up...
542 if ((host
= gethostbyname(s
)) != NULL
)
543 strlcpy(s
, host
->h_name
, slen
);
547 * Return the hostname with as much domain info as we have...