]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/http-addr.c
121b47ddbbd15915ffb34fa1ca0e579b11f0433a
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 * 'httpAddrLength()' - Return the length of the address in bytes.
95 int /* O - Length in bytes */
96 httpAddrLength(const http_addr_t
*addr
) /* I - Address */
99 if (addr
->addr
.sa_family
== AF_INET6
)
100 return (sizeof(addr
->ipv6
));
102 #endif /* AF_INET6 */
104 if (addr
->addr
.sa_family
== AF_LOCAL
)
105 return (sizeof(addr
->un
.sun_family
) + strlen(addr
->un
.sun_path
));
107 #endif /* AF_LOCAL */
108 if (addr
->addr
.sa_family
== AF_INET
)
109 return (sizeof(addr
->ipv4
));
117 * 'httpAddrLoad()' - Load a host entry address into an HTTP address.
121 httpAddrLoad(const struct hostent
*host
, /* I - Host entry */
122 int port
, /* I - Port number */
123 int n
, /* I - Index into host entry */
124 http_addr_t
*addr
) /* O - Address to load */
127 if (host
->h_addrtype
== AF_INET6
)
130 addr
->ipv6
.sin6_port
= htons((u_short
)port
);
132 addr
->ipv6
.sin6_port
= htons(port
);
135 memcpy((char *)&(addr
->ipv6
.sin6_addr
), host
->h_addr_list
[n
],
137 addr
->ipv6
.sin6_family
= AF_INET6
;
140 #endif /* AF_INET6 */
142 if (host
->h_addrtype
== AF_LOCAL
)
144 addr
->un
.sun_family
= AF_LOCAL
;
145 strlcpy(addr
->un
.sun_path
, host
->h_addr_list
[n
], sizeof(addr
->un
.sun_path
));
148 #endif /* AF_LOCAL */
149 if (host
->h_addrtype
== AF_INET
)
152 addr
->ipv4
.sin_port
= htons((u_short
)port
);
154 addr
->ipv4
.sin_port
= htons(port
);
157 memcpy((char *)&(addr
->ipv4
.sin_addr
), host
->h_addr_list
[n
],
159 addr
->ipv4
.sin_family
= AF_INET
;
165 * 'httpAddrLocalhost()' - Check for the local loopback address.
168 int /* O - 1 if local host, 0 otherwise */
169 httpAddrLocalhost(const http_addr_t
*addr
)
170 /* I - Address to check */
173 if (addr
->addr
.sa_family
== AF_INET6
&&
174 (IN6_IS_ADDR_LOOPBACK(&(addr
->ipv6
.sin6_addr
)) ||
175 IN6_IS_ADDR_UNSPECIFIED(&(addr
->ipv6
.sin6_addr
))))
177 #endif /* AF_INET6 */
180 if (addr
->addr
.sa_family
== AF_LOCAL
)
182 #endif /* AF_LOCAL */
184 if (addr
->addr
.sa_family
== AF_INET
&&
185 ntohl(addr
->ipv4
.sin_addr
.s_addr
) == 0x7f000001)
193 # define ADDR_CAST (struct sockaddr *)
195 # define ADDR_CAST (char *)
200 * 'httpAddrLookup()' - Lookup the hostname associated with the address.
203 char * /* O - Host name */
204 httpAddrLookup(const http_addr_t
*addr
, /* I - Address to lookup */
205 char *name
, /* I - Host name buffer */
206 int namelen
) /* I - Size of name buffer */
208 struct hostent
*host
; /* Host from name service */
211 DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n",
212 addr
, name
, namelen
));
215 if (addr
->addr
.sa_family
== AF_INET6
)
216 host
= gethostbyaddr(ADDR_CAST
&(addr
->ipv6
.sin6_addr
),
217 sizeof(struct in6_addr
), AF_INET6
);
219 #endif /* AF_INET6 */
221 if (addr
->addr
.sa_family
== AF_LOCAL
)
223 strlcpy(name
, addr
->un
.sun_path
, namelen
);
227 #endif /* AF_LOCAL */
228 if (addr
->addr
.sa_family
== AF_INET
)
229 host
= gethostbyaddr(ADDR_CAST
&(addr
->ipv4
.sin_addr
),
230 sizeof(struct in_addr
), AF_INET
);
236 httpAddrString(addr
, name
, namelen
);
240 strlcpy(name
, host
->h_name
, namelen
);
247 * 'httpAddrString()' - Convert an IP address to a dotted string.
250 char * /* O - IP string */
251 httpAddrString(const http_addr_t
*addr
, /* I - Address to convert */
252 char *s
, /* I - String buffer */
253 int slen
) /* I - Length of string */
255 DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n",
259 if (addr
->addr
.sa_family
== AF_INET6
)
260 snprintf(s
, slen
, "[%x:%x:%x:%x]",
261 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[0]),
262 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[1]),
263 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[2]),
264 ntohl(addr
->ipv6
.sin6_addr
.s6_addr32
[3]));
266 #endif /* AF_INET6 */
268 if (addr
->addr
.sa_family
== AF_LOCAL
)
269 strlcpy(s
, addr
->un
.sun_path
, slen
);
271 #endif /* AF_LOCAL */
272 if (addr
->addr
.sa_family
== AF_INET
)
274 unsigned temp
; /* Temporary address */
277 temp
= ntohl(addr
->ipv4
.sin_addr
.s_addr
);
279 snprintf(s
, slen
, "%d.%d.%d.%d", (temp
>> 24) & 255,
280 (temp
>> 16) & 255, (temp
>> 8) & 255, temp
& 255);
283 strlcpy(s
, "UNKNOWN", slen
);
285 DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s
));
292 * 'httpGetHostByName()' - Lookup a hostname or IP address, and return
293 * address records for the specified name.
296 struct hostent
* /* O - Host entry */
297 httpGetHostByName(const char *name
) /* I - Hostname or IP address */
299 int i
; /* Looping var */
300 const char *nameptr
; /* Pointer into name */
301 unsigned ip
[4]; /* IP address components */
302 _cups_globals_t
*cg
= _cupsGlobals();
303 /* Pointer to library globals */
306 DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name
));
309 * Avoid lookup delays and configuration problems when connecting
310 * to the localhost address...
313 if (!strcmp(name
, "localhost"))
317 * This function is needed because some operating systems have a
318 * buggy implementation of gethostbyname() that does not support
319 * IP addresses. If the first character of the name string is a
320 * number, then sscanf() is used to extract the IP components.
321 * We then pack the components into an IPv4 address manually,
322 * since the inet_aton() function is deprecated. We use the
323 * htonl() macro to get the right byte order for the address.
325 * We also support domain sockets when supported by the underlying
333 * A domain socket address, so make an AF_LOCAL entry and return it...
336 cg
->hostent
.h_name
= (char *)name
;
337 cg
->hostent
.h_aliases
= NULL
;
338 cg
->hostent
.h_addrtype
= AF_LOCAL
;
339 cg
->hostent
.h_length
= strlen(name
) + 1;
340 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
341 cg
->ip_ptrs
[0] = (char *)name
;
342 cg
->ip_ptrs
[1] = NULL
;
344 DEBUG_puts("httpGetHostByName: returning domain socket address...");
346 return (&cg
->hostent
);
348 #endif /* AF_LOCAL */
353 * A raw 128-bit IPv6 address of the form "[xxxx:xxxx:xxxx:xxxx]"
356 cg
->hostent
.h_name
= (char *)name
;
357 cg
->hostent
.h_aliases
= NULL
;
358 cg
->hostent
.h_addrtype
= AF_INET6
;
359 cg
->hostent
.h_length
= 16;
360 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
361 cg
->ip_ptrs
[0] = (char *)(cg
->ip_addrs
[0]);
362 cg
->ip_ptrs
[1] = NULL
;
364 for (i
= 0, nameptr
= name
+ 1; *nameptr
&& i
< 4; i
++)
368 else if (*nameptr
== ':')
369 cg
->ip_addrs
[0][i
] = 0;
371 cg
->ip_addrs
[0][i
] = htonl(strtoul(nameptr
, (char **)&nameptr
, 16));
373 if (*nameptr
== ':' || *nameptr
== ']')
379 cg
->ip_addrs
[0][i
] = 0;
386 DEBUG_puts("httpGetHostByName: returning IPv6 address...");
388 return (&cg
->hostent
);
390 #endif /* AF_INET6 */
392 for (nameptr
= name
; isdigit(*nameptr
& 255) || *nameptr
== '.'; nameptr
++);
397 * We have an IPv4 address; break it up and provide the host entry
401 if (sscanf(name
, "%u.%u.%u.%u", ip
, ip
+ 1, ip
+ 2, ip
+ 3) != 4)
402 return (NULL
); /* Must have 4 numbers */
404 if (ip
[0] > 255 || ip
[1] > 255 || ip
[2] > 255 || ip
[3] > 255)
405 return (NULL
); /* Invalid byte ranges! */
407 cg
->ip_addrs
[0][0] = htonl(((((((ip
[0] << 8) | ip
[1]) << 8) | ip
[2]) << 8) |
411 * Fill in the host entry and return it...
414 cg
->hostent
.h_name
= (char *)name
;
415 cg
->hostent
.h_aliases
= NULL
;
416 cg
->hostent
.h_addrtype
= AF_INET
;
417 cg
->hostent
.h_length
= 4;
418 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
419 cg
->ip_ptrs
[0] = (char *)cg
->ip_addrs
[0];
420 cg
->ip_ptrs
[1] = NULL
;
422 DEBUG_puts("httpGetHostByName: returning IPv4 address...");
424 return (&cg
->hostent
);
427 #ifdef HAVE_GETADDRINFO
430 * Use the getaddrinfo() function to get the IP address for the
434 struct addrinfo hints
, /* Address lookup hints */
435 *results
, /* Address lookup results */
436 *current
; /* Current result */
437 http_addr_t
*address
; /* Current address */
440 memset(&hints
, 0, sizeof(hints
));
441 hints
.ai_family
= PF_UNSPEC
;
442 hints
.ai_socktype
= SOCK_STREAM
;
443 hints
.ai_flags
= AI_CANONNAME
;
445 if (getaddrinfo(name
, NULL
, &hints
, &results
))
448 * If getaddrinfo() fails, try gethostbyname()...
451 return (gethostbyname(name
));
455 * Initialize hostent structure, preferring the IPv6 address...
458 for (current
= results
; current
; current
= current
->ai_next
)
459 if (current
->ai_family
== AF_INET6
)
464 for (current
= results
; current
; current
= current
->ai_next
)
465 if (current
->ai_family
== AF_INET
)
471 * No IPv4 or IPv6 addresses, try gethostbyname()...
474 freeaddrinfo(results
);
476 return (gethostbyname(name
));
480 strlcpy(cg
->hostname
, current
->ai_canonname
, sizeof(cg
->hostname
));
482 cg
->hostent
.h_name
= cg
->hostname
;
483 cg
->hostent
.h_aliases
= NULL
;
484 cg
->hostent
.h_addrtype
= current
->ai_family
;
485 cg
->hostent
.h_addr_list
= cg
->ip_ptrs
;
487 if (current
->ai_family
== AF_INET6
)
488 cg
->hostent
.h_length
= 16;
490 cg
->hostent
.h_length
= 4;
493 * Convert the address info to a hostent structure...
496 for (i
= 0, current
= results
;
497 i
< CUPS_MAX_ADDRS
&& current
;
498 current
= current
->ai_next
)
499 if (current
->ai_family
== cg
->hostent
.h_addrtype
)
502 * Copy this address...
505 address
= (http_addr_t
*)(current
->ai_addr
);
507 if (current
->ai_family
== AF_INET
)
508 memcpy((char *)cg
->ip_addrs
[i
], (char *)&(address
->ipv4
.sin_addr
), 4);
510 memcpy((char *)cg
->ip_addrs
[i
], (char *)&(address
->ipv6
.sin6_addr
), 16);
512 cg
->ip_ptrs
[i
] = (char *)cg
->ip_addrs
[i
];
516 cg
->ip_ptrs
[i
] = NULL
;
519 * Free the getaddrinfo() results and return the hostent structure...
522 freeaddrinfo(results
);
524 return (&cg
->hostent
);
529 * Use the gethostbyname() function to get the IP address for
533 DEBUG_puts("httpGetHostByName: returning domain lookup address(es)...");
535 return (gethostbyname(name
));
537 #endif /* HAVE_GETADDRINFO */
542 * 'httpGetHostname()' - Get the FQDN for the local system.
544 * This function uses both gethostname() and gethostbyname() to
545 * get the local hostname with domain.
548 const char * /* O - FQDN for this system */
549 httpGetHostname(char *s
, /* I - String buffer for name */
550 int slen
) /* I - Size of buffer */
552 struct hostent
*host
; /* Host entry to get FQDN */
556 * Get the hostname...
559 gethostname(s
, slen
);
564 * The hostname is not a FQDN, so look it up...
567 if ((host
= gethostbyname(s
)) != NULL
)
568 strlcpy(s
, host
->h_name
, slen
);
572 * Return the hostname with as much domain info as we have...