Index: backend/lpd.c =================================================================== --- backend/lpd.c (revision 4753) +++ backend/lpd.c (working copy) @@ -536,7 +536,6 @@ int manual_copies, /* I - Do copies by hand... */ int timeout) /* I - Timeout... */ { - int i; /* Looping var */ FILE *fp; /* Job file */ char localhost[255]; /* Local host name */ int error; /* Error number */ @@ -546,12 +545,14 @@ char control[10240], /* LPD control 'file' */ *cptr; /* Pointer into control file string */ char status; /* Status byte from command */ - http_addr_t addr; /* Socket address */ - struct hostent *hostaddr; /* Host address */ int copy; /* Copies written */ size_t nbytes; /* Number of bytes written */ off_t tbytes; /* Total bytes written */ char buffer[65536]; /* Output buffer */ + char port_str[32]; /* Port string */ + struct addrinfo hints, /* httpGetAddrInfo hints */ + *res0, /* Base of address list */ + *res; /* Address */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ @@ -573,6 +574,12 @@ signal(SIGALRM, lpd_timeout); #endif /* HAVE_SIGSET */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; /* protocol family for socket */ + hints.ai_socktype = SOCK_STREAM; /* socket type */ + hints.ai_protocol = IPPROTO_TCP; /* protocol for socket */ + snprintf(port_str, sizeof(port_str), "%d", port); + /* * Loop forever trying to print the file... */ @@ -580,10 +587,10 @@ while (!abort_job) { /* - * First try to reserve a port for this connection... + * Resolve hostname to a list of protocols/addresses... */ - if ((hostaddr = httpGetHostByName(hostname)) == NULL) + if (httpGetAddrInfo(hostname, port_str, &hints, &res0) != 0) { fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n", hostname, hstrerror(h_errno)); @@ -593,128 +600,131 @@ fprintf(stderr, "INFO: Attempting to connect to host %s for printer %s\n", hostname, printer); - for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024;;) + for (res = res0; res; res = res->ai_next) { /* - * Stop if this job has been cancelled... + * Try to reserve a port for this connection... */ - if (abort_job) - return (CUPS_BACKEND_FAILED); - - /* - * Choose the next priviledged port... - */ - - lport --; - - if (lport < 721 && reserve == RESERVE_RFC1179) - lport = 731; - else if (lport < 1) - lport = 1023; - -#ifdef HAVE_GETEUID - if (geteuid() || !reserve) -#else - if (getuid() || !reserve) -#endif /* HAVE_GETEUID */ + for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024;;) { /* - * Just create a regular socket... + * Stop if this job has been cancelled... */ - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - { - perror("ERROR: Unable to create socket"); - return (CUPS_BACKEND_FAILED); - } - - lport = 0; - } - else - { + + if (abort_job) + break; + /* - * We're running as root and want to comply with RFC 1179. Reserve a - * priviledged lport between 721 and 731... + * Choose the next priviledged port... */ - - if ((fd = rresvport_af(&lport, hostaddr->h_addrtype)) < 0) + + lport --; + + if (lport < 721 && reserve == RESERVE_RFC1179) + lport = 731; + else if (lport < 1) + lport = 1023; + + #ifdef HAVE_GETEUID + if (geteuid() || !reserve) + #else + if (getuid() || !reserve) + #endif /* HAVE_GETEUID */ { - perror("ERROR: Unable to reserve port"); - sleep(1); - - continue; + /* + * Just create a regular socket... + */ + + if ((fd = socket(res->ai_family, SOCK_STREAM, 0)) < 0) + { + /* may work with a different family... */ + perror("DEBUG: Unable to create socket"); + break; + } + + lport = 0; } + else + { + /* + * We're running as root and want to comply with RFC 1179. Reserve a + * priviledged lport between 721 and 731... + */ + + if ((fd = rresvport_af(&lport, res->ai_family)) < 0) + { + /* may work with a different family... */ + perror("DEBUG: Unable to reserve port"); + sleep(1); + + continue; + } + else + break; + } } + if (fd < 0 || abort_job) + continue; + /* * Connect to the printer or server... */ - for (i = 0; hostaddr->h_addr_list[i]; i ++) - { - if (abort_job) - { - close(fd); - return (CUPS_BACKEND_FAILED); - } + if (connect(fd, res->ai_addr, res->ai_addrlen) >= 0) + break; - httpAddrLoad(hostaddr, port, i, &addr); + error = errno; + close(fd); + fd = -1; + } - if (!connect(fd, (struct sockaddr *)&addr, sizeof(addr))) - break; - } + httpFreeAddrInfo(res0); - if (!hostaddr->h_addr_list[i]) + if (fd < 0) + { + if (getenv("CLASS") != NULL) { - error = errno; - close(fd); - fd = -1; + /* + * If the CLASS environment variable is set, the job was submitted + * to a class and not to a specific queue. In this case, we want + * to abort immediately so that the job can be requeued on the next + * available printer in the class. + */ - if (getenv("CLASS") != NULL) - { - /* - * If the CLASS environment variable is set, the job was submitted - * to a class and not to a specific queue. In this case, we want - * to abort immediately so that the job can be requeued on the next - * available printer in the class. - */ + fprintf(stderr, "INFO: Unable to connect to %s, queuing on next printer in class...\n", + hostname); - fprintf(stderr, "INFO: Unable to connect to %s, queuing on next printer in class...\n", - hostname); + /* + * Sleep 5 seconds to keep the job from requeuing too rapidly... + */ - /* - * Sleep 5 seconds to keep the job from requeuing too rapidly... - */ + sleep(5); - sleep(5); + return (CUPS_BACKEND_FAILED); + } - return (CUPS_BACKEND_FAILED); - } + if (error == ECONNREFUSED || error == EHOSTDOWN || + error == EHOSTUNREACH) + { + fprintf(stderr, "WARNING: Network host \'%s\' is busy, down, or unreachable; will retry in 30 seconds...\n", + hostname); + sleep(30); + } + else if (error == EADDRINUSE) + { + /* + * Try on another port... + */ - if (error == ECONNREFUSED || error == EHOSTDOWN || - error == EHOSTUNREACH) - { - fprintf(stderr, "WARNING: Network host \'%s\' is busy, down, or unreachable; will retry in 30 seconds...\n", - hostname); - sleep(30); - } - else if (error == EADDRINUSE) - { - /* - * Try on another port... - */ - - sleep(1); - } - else - { - perror("ERROR: Unable to connect to printer; will retry in 30 seconds..."); - sleep(30); - } + sleep(1); } else - break; + { + perror("ERROR: Unable to connect to printer; will retry in 30 seconds..."); + sleep(30); + } } fprintf(stderr, "INFO: Connected to %s...\n", hostname); Index: backend/socket.c =================================================================== --- backend/socket.c (revision 4753) +++ backend/socket.c (working copy) @@ -68,19 +68,17 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { - int i; /* Looping var */ char method[255], /* Method in URI */ hostname[1024], /* Hostname */ username[255], /* Username info (not used) */ - resource[1024]; /* Resource info (not used) */ + resource[1024], /* Resource info (not used) */ + port_str[32]; /* Port string */ int fp; /* Print file */ int copies; /* Number of copies to print */ int port; /* Port number */ int delay; /* Delay for retries... */ int fd; /* AppSocket */ int error; /* Error code (if any) */ - http_addr_t addr; /* Socket address */ - struct hostent *hostaddr; /* Host address */ int rbytes; /* Number of bytes read */ int wbytes; /* Number of bytes written */ int nbytes; /* Number of bytes read */ @@ -90,6 +88,9 @@ struct timeval timeout; /* Timeout for select() */ fd_set input, /* Input set for select() */ output; /* Output set for select() */ + struct addrinfo hints, /* Hints for httpGetAddrInfo */ + *res0, /* Base of httpGetAddrInfo list */ + *res; /* Looping var */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ @@ -166,16 +167,26 @@ port = 9100; /* Default to HP JetDirect/Tektronix PhaserShare */ /* - * Then try to connect to the remote host... + * Resolve hostname to a list of protocols/addresses... */ - if ((hostaddr = httpGetHostByName(hostname)) == NULL) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; /* protocol family for socket */ + hints.ai_socktype = SOCK_STREAM; /* socket type */ + hints.ai_protocol = IPPROTO_TCP; /* protocol for socket */ + snprintf(port_str, sizeof(port_str), "%d", port); + + if (httpGetAddrInfo(hostname, port_str, &hints, &res0) != 0) { fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n", hostname, hstrerror(h_errno)); return (CUPS_BACKEND_STOP); } + /* + * Then try to connect to the remote host... + */ + fprintf(stderr, "INFO: Attempting to connect to host %s on port %d\n", hostname, port); @@ -185,65 +196,67 @@ { for (delay = 5;;) { - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - { - perror("ERROR: Unable to create socket"); - return (CUPS_BACKEND_FAILED); - } + /* + * Try each of the possible addresses/protocols... + */ - for (i = 0; hostaddr->h_addr_list[i]; i ++) + for (res = res0; res; res = res->ai_next) { - httpAddrLoad(hostaddr, port, i, &addr); + if ((fd = socket(res->ai_family, res->ai_socktype, + res->ai_protocol)) < 0) + { + /* may work with a different family... */ + perror("DEBUG: Unable to create socket"); + continue; + } - if (!connect(fd, (struct sockaddr *)&addr, sizeof(addr))) + if (connect(fd, res->ai_addr, res->ai_addrlen) >= 0) break; - } - if (!hostaddr->h_addr_list[i]) - { error = errno; close(fd); fd = -1; + } - if (getenv("CLASS") != NULL) - { - /* - * If the CLASS environment variable is set, the job was submitted - * to a class and not to a specific queue. In this case, we want - * to abort immediately so that the job can be requeued on the next - * available printer in the class. - */ + if (fd >= 0) + break; - fprintf(stderr, "INFO: Unable to connect to \"%s\", queuing on next printer in class...\n", - hostname); + if (getenv("CLASS") != NULL) + { + /* + * If the CLASS environment variable is set, the job was submitted + * to a class and not to a specific queue. In this case, we want + * to abort immediately so that the job can be requeued on the next + * available printer in the class. + */ - /* - * Sleep 5 seconds to keep the job from requeuing too rapidly... - */ + fprintf(stderr, "INFO: Unable to connect to \"%s\", queuing on next printer in class...\n", + hostname); - sleep(5); + /* + * Sleep 5 seconds to keep the job from requeuing too rapidly... + */ - return (CUPS_BACKEND_FAILED); - } + sleep(5); - if (error == ECONNREFUSED || error == EHOSTDOWN || - error == EHOSTUNREACH) - { - fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n", - hostname, delay); - sleep(delay); + return (CUPS_BACKEND_FAILED); + } - if (delay < 30) - delay += 5; - } - else - { - perror("ERROR: Unable to connect to printer (retrying in 30 seconds)"); - sleep(30); - } + if (error == ECONNREFUSED || error == EHOSTDOWN || + error == EHOSTUNREACH) + { + fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n", + hostname, delay); + sleep(delay); + + if (delay < 30) + delay += 5; } else - break; + { + perror("ERROR: Unable to connect to printer (retrying in 30 seconds)"); + sleep(30); + } } /* @@ -411,9 +424,11 @@ } /* - * Close the input file and return... + * Free addresses and close the input file before returning... */ + httpFreeAddrInfo(res0); + if (fp != 0) close(fp); Index: config-scripts/cups-network.m4 =================================================================== --- config-scripts/cups-network.m4 (revision 4753) +++ config-scripts/cups-network.m4 (working copy) @@ -29,7 +29,7 @@ AC_CHECK_LIB(nsl,gethostbyaddr,NETLIBS="$NETLIBS -lnsl") fi -AC_CHECK_FUNCS(getaddrinfo getifaddrs hstrerror rresvport_af) +AC_CHECK_FUNCS(getaddrinfo getnameinfo gethostbyname2 getifaddrs hstrerror rresvport_af) AC_CHECK_MEMBER(struct sockaddr.sa_len,,,[#include ]) AC_CHECK_HEADER(sys/sockio.h,AC_DEFINE(HAVE_SYS_SOCKIO_H)) @@ -64,7 +64,15 @@ if test x$enable_domainsocket != xno; then if test "x$default_domainsocket" = x; then - CUPS_DEFAULT_DOMAINSOCKET="$CUPS_STATEDIR/cups.sock" + case "$uname" in + Darwin*) + # Darwin and MacOS X... + CUPS_DEFAULT_DOMAINSOCKET="$localstatedir/run/cupsd" + ;; + *) + CUPS_DEFAULT_DOMAINSOCKET="$CUPS_STATEDIR/cups.sock" + ;; + esac else CUPS_DEFAULT_DOMAINSOCKET="$default_domainsocket" fi Index: config-scripts/cups-compiler.m4 =================================================================== --- config-scripts/cups-compiler.m4 (revision 4753) +++ config-scripts/cups-compiler.m4 (working copy) @@ -41,12 +41,20 @@ if test -n "$GCC"; then if test -z "$OPTIM"; then if test "x$with_optim" = x; then - if test $uname = HP-UX; then - # GCC under HP-UX has bugs with -O2 - OPTIM="-O1" - else - OPTIM="-O2" - fi + case $uname in + HP-UX*) + if test $uname = HP-UX; then + # GCC under HP-UX has bugs with -O2 + OPTIM="-O1" + else + OPTIM="-O2" + fi + ;; + Darwin*) + # Apple likes to optimize for size and include debugging information + OPTIM="-Os -g" + ;; + esac else OPTIM="$with_optim $OPTIM" fi Index: cups/http.c =================================================================== --- cups/http.c (revision 4753) +++ cups/http.c (working copy) @@ -87,6 +87,7 @@ #include "globals.h" #include "debug.h" #include +#include #include #include #ifndef WIN32 @@ -290,9 +291,15 @@ int port, /* I - Port number */ http_encryption_t encryption) /* I - Type of encryption to use */ { - int i; /* Looping var */ http_t *http; /* New HTTP connection */ - struct hostent *hostaddr; /* Host address data */ + char port_str[32]; /* Port string */ + struct addrinfo hints, /* Address lookup hints */ + *results, /* Address lookup results */ + *current; /* Current result */ +#ifdef AF_LOCAL + struct hostent hostent; /* */ + char *ip_ptrs[2]; /* */ +#endif /* AF_LOCAL */ DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)\n", @@ -307,40 +314,27 @@ * Lookup the host... */ - if ((hostaddr = httpGetHostByName(host)) == NULL) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + snprintf(port_str, sizeof(port_str), "%d", port); + + if (getaddrinfo(host, port_str, &hints, &results)) { - /* - * This hack to make users that don't have a localhost entry in - * their hosts file or DNS happy... - */ - - if (strcasecmp(host, "localhost") != 0) return (NULL); - else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL) - return (NULL); } /* - * Verify that it is an IPv4, IPv6, or domain address... - */ - - if ((hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4) -#ifdef AF_INET6 - && (hostaddr->h_addrtype != AF_INET6 || hostaddr->h_length != 16) -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - && (hostaddr->h_addrtype != AF_LOCAL) -#endif /* AF_LOCAL */ - ) - return (NULL); - - /* * Allocate memory for the structure... */ http = calloc(sizeof(http_t), 1); if (http == NULL) + { + httpFreeAddrInfo(results); return (NULL); + } http->version = HTTP_1_1; http->blocking = 1; @@ -357,31 +351,117 @@ http->encryption = encryption; /* + * If we're about to use a loopback address and have a domain socket try it instead... + */ + +#ifdef AF_LOCAL + if (((results->ai_family == AF_INET && ntohl(((struct sockaddr_in *)results->ai_addr)->sin_addr.s_addr) == 0x7f000001) +# ifdef AF_INET6 + || (results->ai_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)results->ai_addr)->sin6_addr))) +# endif /* AF_INET6 */ + ) && _cupsGlobals()->server_domainsocket[0] != '\0') + { + /* + * Load the address... + */ + + hostent.h_name = _cupsGlobals()->server_domainsocket; + hostent.h_aliases = NULL; + hostent.h_addrtype = AF_LOCAL; + hostent.h_length = strlen(hostent.h_name) + 1; + hostent.h_addr_list = ip_ptrs; + ip_ptrs[0] = hostent.h_name; + ip_ptrs[1] = NULL; + + httpAddrLoad(&hostent, 0, 0, &(http->hostaddr)); + + /* + * Connect to the remote system... + */ + + if (!httpReconnect(http)) + { + httpFreeAddrInfo(results); + return (http); + } + } +#endif /* AF_LOCAL */ + + + /* * Loop through the addresses we have until one of them connects... */ strlcpy(http->hostname, host, sizeof(http->hostname)); - for (i = 0; hostaddr->h_addr_list[i]; i ++) + for (current = results; current; current = current->ai_next) { /* * Load the address... */ - httpAddrLoad(hostaddr, port, i, &(http->hostaddr)); + memset(&http->hostaddr, 0, sizeof(http->hostaddr)); + +#ifdef AF_INET6 + if (current->ai_family == AF_INET6) + { +# ifdef WIN32 + http->hostaddr.ipv6.sin6_port = htons((u_short)((struct sockaddr_in6 *)current->ai_addr)->sin6_port); +# else + http->hostaddr.ipv6.sin6_port = htons(((struct sockaddr_in6 *)current->ai_addr)->sin6_port); +# endif /* WIN32 */ + + memcpy((char *)&(http->hostaddr.ipv6.sin6_addr), &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr, + ((struct sockaddr_in6 *)current->ai_addr)->sin6_len); + http->hostaddr.ipv6.sin6_family = AF_INET6; + } + else +#endif /* AF_INET6 */ +#ifdef AF_LOCAL + if (current->ai_family == AF_LOCAL) + { + http->hostaddr.un.sun_family = AF_LOCAL; + strlcpy(http->hostaddr.un.sun_path, ((struct sockaddr_un *)current->ai_addr)->sun_path, + sizeof(http->hostaddr.un.sun_path)); + http->hostaddr.un.sun_len = offsetof(struct sockaddr_un, sun_path) + + strlen(http->hostaddr.un.sun_path) + 1; + } + else +#endif /* AF_LOCAL */ + if (current->ai_family == AF_INET) + { +# ifdef WIN32 + http->hostaddr.ipv4.sin_port = htons((u_short)((struct sockaddr_in *)current->ai_addr)->sin_port); +# else + http->hostaddr.ipv4.sin_port = htons(((struct sockaddr_in *)current->ai_addr)->sin_port); +# endif /* WIN32 */ + + memcpy((char *)&(http->hostaddr.ipv4.sin_addr), &((struct sockaddr_in *)current->ai_addr)->sin_addr, + ((struct sockaddr_in *)current->ai_addr)->sin_len); + http->hostaddr.ipv4.sin_family = AF_INET; + } + else + { + /* Unknown address type */ + continue; + } /* * Connect to the remote system... */ if (!httpReconnect(http)) + { + httpFreeAddrInfo(results); return (http); + } } /* * Could not connect to any known address - bail out! */ + httpFreeAddrInfo(results); free(http); return (NULL); } Index: cups/http.h =================================================================== --- cups/http.h (revision 4753) +++ cups/http.h (working copy) @@ -432,6 +432,11 @@ extern const char *httpGetHostname(char *s, int slen); extern off_t httpGetLength2(http_t *http); extern void httpSetLength(http_t *http, off_t length); +extern struct hostent *httpGetHostByName2(const char *name, int af); +extern int httpGetAddrInfo(const char *hostname, const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +void httpFreeAddrInfo(struct addrinfo *ai); /* Index: cups/http-support.c =================================================================== --- cups/http-support.c (revision 4753) +++ cups/http-support.c (working copy) @@ -100,10 +100,16 @@ * Range check input... */ - if (uri == NULL || scheme == NULL || username == NULL || host == NULL || - port == NULL || resource == NULL) + if (uri == NULL || port == NULL || + scheme == NULL || schemelen <= 0 || + username == NULL || usernamelen <= 0 || + host == NULL || hostlen <= 0 || + resource == NULL || resourcelen <= 0) return; + *scheme = *username = *host = *resource = '\0'; + *port = 0; + /* * Grab the scheme portion of the URI... */ @@ -122,25 +128,32 @@ * Standard URI with scheme... */ - uri = http_copy_decode(host, uri, hostlen, ":"); + if (*uri == '[') + { + uri = http_copy_decode(host, uri+1, hostlen, "]/?"); + if (*uri != ']') + return; + uri ++; + } + else + uri = http_copy_decode(host, uri, hostlen, ":?"); + if (*uri == ':') uri ++; /* - * If the scheme contains a period or slash, then it's probably + * If the scheme contains a period, slash or colon, then it's probably * hostname/filename... */ - if (strchr(host, '.') || strchr(host, '/') || !*uri) + if (strpbrk(host, "./:") || !*uri) { if ((ptr = strchr(host, '/')) != NULL) { strlcpy(resource, ptr, resourcelen); *ptr = '\0'; } - else - resource[0] = '\0'; if (isdigit(*uri & 255)) { @@ -157,7 +170,6 @@ *port = 631; strlcpy(scheme, "http", schemelen); - username[0] = '\0'; return; } else @@ -181,10 +193,6 @@ */ http_copy_decode(resource, uri, resourcelen, ""); - - username[0] = '\0'; - host[0] = '\0'; - *port = 0; return; } @@ -205,15 +213,7 @@ uri = http_copy_decode(username, uri, usernamelen, "@") + 1; } - else - { - /* - * No username:password combo... - */ - username[0] = '\0'; - } - /* * Grab the hostname... */ @@ -224,10 +224,15 @@ * Get IPv6 address... */ - uri = http_copy_decode(host, uri, hostlen, "]"); + uri = http_copy_decode(host, uri+1, hostlen, "]/?"); - if (*uri == ']') - uri ++; + if (*uri != ']') + { + *host = '\0'; + return; + } + + uri ++; } else { @@ -235,7 +240,7 @@ * Get IPv4 address or hostname... */ - uri = http_copy_decode(host, uri, hostlen, ":/"); + uri = http_copy_decode(host, uri, hostlen, ":/?"); } if (*uri != ':') @@ -266,22 +271,21 @@ *port = strtol(uri + 1, (char **)&uri, 10); } - if (!*uri) + /* + * The remaining portion is the resource string... + */ + + if (*uri == '?' || *uri == '\0') { /* - * No resource path... + * Hostname but no port or path... */ resource[0] = '/'; - resource[1] = '\0'; - return; + http_copy_decode(resource+1, uri, resourcelen-1, ""); } - - /* - * The remaining portion is the resource string... - */ - - http_copy_decode(resource, uri, resourcelen, ""); + else + http_copy_decode(resource, uri, resourcelen, ""); } Index: cups/usersys.c =================================================================== --- cups/usersys.c (revision 4753) +++ cups/usersys.c (working copy) @@ -254,6 +254,20 @@ ippSetPort(atoi(port)); } + +#ifdef AF_LOCAL + /* + * If the server specifies a domain socket remember it and set server to localhost. + */ + + if (cg->server[0] == '/') + { + strlcpy(cg->server_domainsocket, cg->server, sizeof(cg->server)); + strlcpy(cg->server, "localhost", sizeof(cg->server)); + } + else + strlcpy(cg->server_domainsocket, CUPS_DEFAULT_DOMAINSOCKET, sizeof(cg->server_domainsocket)); +#endif /* AF_LOCAL */ } return (cg->server); Index: cups/http-addr.c =================================================================== --- cups/http-addr.c (revision 4753) +++ cups/http-addr.c (working copy) @@ -31,6 +31,10 @@ * httpAddrString() - Convert an IP address to a dotted string. * httpGetHostByName() - Lookup a hostname or IP address, and return * address records for the specified name. + * httpGetHostByName2()- Lookup a hostname or IP address in a given family, + * and return address records for the specified name. + * httpGetAddrInfo() - Get a list of IP addresses and port numbers. + * httpFreeAddrInfo() - Free list of addresses returned by httpGetAddrInfo. */ /* @@ -40,6 +44,7 @@ #include "globals.h" #include "debug.h" #include +#include /* @@ -102,7 +107,7 @@ #endif /* AF_INET6 */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) - return (sizeof(addr->un.sun_family) + strlen(addr->un.sun_path)); + return (offsetof(struct sockaddr_un, sun_path) + strlen(addr->un.sun_path) + 1); else #endif /* AF_LOCAL */ if (addr->addr.sa_family == AF_INET) @@ -123,6 +128,8 @@ int n, /* I - Index into host entry */ http_addr_t *addr) /* O - Address to load */ { + memset(addr, 0, sizeof(*addr)); + #ifdef AF_INET6 if (host->h_addrtype == AF_INET6) { @@ -143,6 +150,8 @@ { addr->un.sun_family = AF_LOCAL; strlcpy(addr->un.sun_path, host->h_addr_list[n], sizeof(addr->un.sun_path)); + addr->un.sun_len = offsetof(struct sockaddr_un, sun_path) + + strlen(addr->un.sun_path) + 1; } else #endif /* AF_LOCAL */ @@ -255,20 +264,27 @@ DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n", addr, s, slen)); -#ifdef AF_INET6 - if (addr->addr.sa_family == AF_INET6) - snprintf(s, slen, "[%x:%x:%x:%x]", - ntohl(addr->ipv6.sin6_addr.s6_addr32[0]), - ntohl(addr->ipv6.sin6_addr.s6_addr32[1]), - ntohl(addr->ipv6.sin6_addr.s6_addr32[2]), - ntohl(addr->ipv6.sin6_addr.s6_addr32[3])); - else -#endif /* AF_INET6 */ #ifdef AF_LOCAL if (addr->addr.sa_family == AF_LOCAL) strlcpy(s, addr->un.sun_path, slen); else #endif /* AF_LOCAL */ + { +#ifdef HAVE_GETNAMEINFO + char serv[1024]; + if (getnameinfo(&addr->addr, addr->addr.sa_len, s, slen, + serv, sizeof(serv), NI_NUMERICHOST) != 0) + strlcpy(s, "", slen); +#else +#ifdef AF_INET6 + if (addr->addr.sa_family == AF_INET6) + snprintf(s, slen, "[%x:%x:%x:%x]", + ntohl(addr->ipv6.sin6_addr.s6_addr32[0]), + ntohl(addr->ipv6.sin6_addr.s6_addr32[1]), + ntohl(addr->ipv6.sin6_addr.s6_addr32[2]), + ntohl(addr->ipv6.sin6_addr.s6_addr32[3])); + else +#endif /* AF_INET6 */ if (addr->addr.sa_family == AF_INET) { unsigned temp; /* Temporary address */ @@ -282,6 +298,9 @@ else strlcpy(s, "UNKNOWN", slen); +#endif /* HAVE_GETNAMEINFO */ + } + DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s)); return (s); @@ -296,6 +315,22 @@ struct hostent * /* O - Host entry */ httpGetHostByName(const char *name) /* I - Hostname or IP address */ { + return httpGetHostByName2(name, AF_UNSPEC); +} + + +/* + * 'httpGetHostByName2()' - Lookup a hostname or IP address, and return + * address records for the specified name. + */ + +struct hostent * /* O - Host entry */ +httpGetHostByName2(const char *name, /* I - Hostname or IP address */ + int af) /* I - Address family */ +{ +#ifdef HAVE_GETHOSTBYNAME2 + return (gethostbyname2(name, af)); +#else int i; /* Looping var */ const char *nameptr; /* Pointer into name */ unsigned ip[4]; /* IP address components */ @@ -306,14 +341,6 @@ DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name)); /* - * Avoid lookup delays and configuration problems when connecting - * to the localhost address... - */ - - if (!strcmp(name, "localhost")) - name = "127.0.0.1"; - - /* * This function is needed because some operating systems have a * buggy implementation of gethostbyname() that does not support * IP addresses. If the first character of the name string is a @@ -327,7 +354,7 @@ */ #ifdef AF_LOCAL - if (name[0] == '/') + if (name[0] == '/' && (af == AF_UNSPEC || af == AF_LOCAL)) { /* * A domain socket address, so make an AF_LOCAL entry and return it... @@ -347,7 +374,7 @@ } #endif /* AF_LOCAL */ #ifdef AF_INET6 - if (name[0] == '[') + if (name[0] == '[' && (af == AF_UNSPEC || af == AF_INET6)) { /* * A raw 128-bit IPv6 address of the form "[xxxx:xxxx:xxxx:xxxx]" @@ -438,7 +465,7 @@ memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; + hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; @@ -535,6 +562,7 @@ return (gethostbyname(name)); } #endif /* HAVE_GETADDRINFO */ +#endif /* HAVE_GETHOSTBYNAME2 */ } @@ -577,5 +605,87 @@ /* + * 'httpGetAddrInfo()' - Get a list of IP addresses and port numbers + * for host hostname and service servname. + */ + +int /* O - 0 on success */ +httpGetAddrInfo(const char *hostname, /* I - Hostname or IP address */ + const char *servname, /* I - Service name */ + const struct addrinfo *hints, /* I - Hints */ + struct addrinfo **res) /* O - List of addresses */ +{ +#ifdef AF_LOCAL + int len; /* Length of socket address */ + struct sockaddr_un *sun; /* Domain socket address */ + + /* + * Since not all getaddrinfo implimentations support UNIX domain + * sockets we'll do it ourselves... + */ + + if (((hostname && *hostname == '/') || (servname && *servname == '/')) && + (hints == NULL || hints->ai_family == PF_UNSPEC || hints->ai_family == PF_UNIX)) + { + if (hostname == NULL) + hostname = servname; + + if ((*res = (struct addrinfo *)calloc(1, sizeof(struct addrinfo))) == NULL) + return EAI_MEMORY; + + // Calculate length of the binary representation + len = offsetof(struct sockaddr_un, sun_path) + strlen(hostname) + 1; + + if ((sun = (struct sockaddr_un *)calloc(1, len)) == NULL) + { + free(*res); + return EAI_MEMORY; + } + + /* + * Fill the socket address and address info structures... + */ + + sun->sun_family = AF_UNIX; + sun->sun_len = len; + strcpy(sun->sun_path, hostname); + + (*res)->ai_family = AF_UNIX; + (*res)->ai_addrlen = len; + (*res)->ai_addr = (struct sockaddr *)sun; + (*res)->ai_canonname = strdup(hostname); + + return 0; + } +#endif /* AF_LOCAL */ + +#ifdef HAVE_GETADDRINFO + return getaddrinfo(hostname, servname, hints, res); +#else + + /* TO DO */ + +#endif /* HAVE_GETADDRINFO */ +} + + +/* + * 'httpFreeAddrInfo()' - Free the list of addresses returned by httpGetAddrInfo. + */ + +void +httpFreeAddrInfo(struct addrinfo *ai) /* I - List of addresses */ +{ +#ifdef HAVE_GETADDRINFO + freeaddrinfo(ai); +#else + + /* TO DO */ + +#endif /* HAVE_GETADDRINFO */ +} + + +/* * End of "$Id$". */ Index: cups/globals.h =================================================================== --- cups/globals.h (revision 4753) +++ cups/globals.h (working copy) @@ -121,6 +121,10 @@ server[256]; /* Server address */ const char *(*password_cb)(const char *); /* Password callback */ +#ifdef AF_LOCAL + char server_domainsocket[104]; + /* Domain socket */ +#endif /* AF_LOCAL */ /* util.c */ http_t *http; /* Current server connection */ Index: test/uritest.c =================================================================== --- test/uritest.c (revision 0) +++ test/uritest.c (revision 0) @@ -0,0 +1,118 @@ +/* + * "$Id$" + * + * URI parse test for the Common UNIX Printing System (CUPS). + * + */ + +#include +#include +#include + +struct uri_test +{ + int result; + const char *uri, + *scheme, + *username, + *hostname, + *resource; + int port; +}; + +struct uri_test uri_tests[] = +{ + { 0, "/path/to/file/index.html", "http", "", "", "/path/to/file/index.html", 631 }, + + { 0, "http://localhost", "http", "", "localhost", "/", 80 }, + { 0, "http://127.0.0.1", "http", "", "127.0.0.1", "/", 80 }, + { 0, "http://[::1]", "http", "", "::1", "/", 80 }, + { 0, "http://[fe80::1]", "http", "", "fe80::1", "/", 80 }, + + { 0, "https://localhost/", "https", "", "localhost", "/", 443 }, + { 0, "https://127.0.0.1/", "https", "", "127.0.0.1", "/", 443 }, + { 0, "https://[::1]/", "https", "", "::1", "/", 443 }, + + { 0, "ipp://localhost/index.html", "ipp", "", "localhost", "/index.html", 631 }, + { 0, "ipp://127.0.0.1/index.html", "ipp", "", "127.0.0.1", "/index.html", 631 }, + { 0, "ipp://[::1]/index.html", "ipp", "", "::1", "/index.html", 631 }, + + { 0, "http://localhost?a=b", "http", "", "localhost", "/?a=b", 80 }, + { 0, "http://127.0.0.1?a=b", "http", "", "127.0.0.1", "/?a=b", 80 }, + { 0, "http://[::1]?a=b", "http", "", "::1", "/?a=b", 80 }, + { 0, "http://[::1]/?a=b,c=d", "http", "", "::1", "/?a=b,c=d", 80 }, + + { 0, "ipp://localhost:443/index.html?a=b", "ipp", "", "localhost", "/index.html?a=b", 443 }, + { 0, "ipp://127.0.0.1:443/index.html?a=b", "ipp", "", "127.0.0.1", "/index.html?a=b", 443 }, + { 0, "ipp://[::1]:443/index.html?a=b", "ipp", "", "::1", "/index.html?a=b", 443 }, + { 0, "ipp://[::1]:443/index.html?a=b", "ipp", "", "::1", "/index.html?a=b", 443 }, + + { 0, "lpd://user@localhost/index.html", "lpd", "user", "localhost", "/index.html", 515 }, + { 0, "socket://user@127.0.0.1/index.html", "socket", "user", "127.0.0.1", "/index.html", 9100 }, + { 0, "unknown://user@[::1]/index.html", "unknown", "user", "::1", "/index.html", 0 }, + + { 0, "lpd://user:password@localhost/index.html", "lpd", "user:password", "localhost", "/index.html", 515 }, + { 0, "socket://user:password@127.0.0.1/index.html", "socket", "user:password", "127.0.0.1", "/index.html", 9100 }, + { 0, "unknown://user:password@[::1]/index.html", "unknown", "user:password", "::1", "/index.html", 0 }, + + { 0, "/path/to/file/index.html", "http", "", "", "/path/to/file/index.html", 631 }, + { 0, "/error/include/../contact.html.var", "http", "", "", "/error/include/../contact.html.var", 631 }, + { 0, "/", "http", "", "", "/", 631 }, + { 0, "/manual/", "http", "", "", "/manual/", 631 }, + + { 0, "http://[fe80::1]/index.html?arg1=opt1", "http", "", "fe80::1", "/index.html?arg1=opt1", 80 }, + { 0, "http://[fe80::1]?arg1=opt1,arg2=opt2", "http", "", "fe80::1", "/?arg1=opt1,arg2=opt2", 80 }, + + { 1, "http://[/::1]/index.html", "http", "", "", "", 0 }, + { 1, "http://[", "http", "", "", "", 0 }, + { 1, "http://[?::1]/index.html", "http", "", "", "", 0 }, + { 1, "http://127.0.0.1:9999a/index.html", "http", "", "127.0.0.1", "", 9999 }, + { 1, "http://[::127.0.0.1]:9999/index.html", "http", "", "[::127.0.0.1]", "/index.html", 9999 }, + { 1, "http://[::127.0.0.1]:9999a/index.html", "http", "", "[::127.0.0.1]", "", 9999 } +}; + + +int main(void) +{ + int i, /* */ + port; /* */ + char scheme[1024], /* */ + username[1024], /* */ + hostname[1024], /* */ + resource[1024]; /* */ + const char *failed; /* */ + struct uri_test *t; /* */ + + for (i = 0; i < sizeof(uri_tests) / sizeof(uri_tests[0]); i++) + { + t = &uri_tests[i]; + + httpSeparate2(t->uri, scheme, sizeof(scheme), + username, sizeof(username), + hostname, sizeof(hostname), + &port, + resource, sizeof(resource)); + + if (strcmp(scheme, t->scheme)) failed = "scheme"; + else if (strcmp(username, t->username)) failed = "user"; + else if (strcmp(hostname, t->hostname)) failed = "hostname"; + else if (strcmp(resource, t->resource)) failed = "resource"; + else if (port != t->port) failed = "port"; + else failed = NULL; + + if (failed && !t->result) + { + fprintf(stderr, "failure for testcase %d; uri %s: bad %s\n", i, + t->uri, failed); + + fprintf(stderr, " scheme: %s\n" + " username: %s\n" + " hostname: %s\n" + " resource: %s\n" + " port: %d\n", + scheme, username, hostname, resource, port); + } + } + + return 0; +} Index: test/Makefile =================================================================== --- test/Makefile (revision 4753) +++ test/Makefile (working copy) @@ -29,7 +29,7 @@ # Make all targets... # -all: ipptest +all: ipptest uritest # @@ -37,7 +37,7 @@ # clean: - $(RM) ipptest ipptest.o + $(RM) ipptest ipptest.o uritest uritest.o # @@ -65,6 +65,15 @@ # +# uritest +# + +uritest: uritest.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o uritest uritest.o $(LIBS) + + +# # purify target for doing tests on the CUPS API... # Index: config.h.in =================================================================== --- config.h.in (revision 4753) +++ config.h.in (working copy) @@ -268,10 +268,12 @@ /* - * Do we have getaddrinfo()? + * Do we have getaddrinfo(), getnameinfo() & gethostbyname2()? */ #undef HAVE_GETADDRINFO +#undef HAVE_GETNAMEINFO +#undef HAVE_GETHOSTBYNAME2 /* Index: scheduler/client.c =================================================================== --- scheduler/client.c (revision 4753) +++ scheduler/client.c (working copy) @@ -51,6 +51,9 @@ #include #include "cupsd.h" +#ifdef HAVE_CDSASSL +#include +#endif /* HAVE_CDSASSL */ /* @@ -68,6 +71,7 @@ char *command, char *options, int root); #ifdef HAVE_CDSASSL +static CFArrayRef CDSAGetServerCerts(); static OSStatus CDSAReadFunc(SSLConnectionRef connection, void *data, size_t *dataLength); static OSStatus CDSAWriteFunc(SSLConnectionRef connection, @@ -84,7 +88,7 @@ { int i; /* Looping var */ int count; /* Count of connections on a host */ - int val; /* Parameter value */ + socklen_t val; /* Parameter value */ cupsd_client_t *con; /* New client pointer */ const struct hostent *host; /* Host entry for address */ char *hostname; /* Hostname for address */ @@ -117,7 +121,11 @@ * Accept the client and get the remote address... */ +#ifdef AF_INET6 + val = sizeof(struct sockaddr_storage); +#else val = sizeof(struct sockaddr_in); +#endif /* AF_INET6 */ if ((con->http.fd = accept(lis->fd, (struct sockaddr *)&(con->http.hostaddr), &val)) < 0) @@ -226,7 +234,7 @@ * Do double lookups as needed... */ - if ((host = httpGetHostByName(con->http.hostname)) != NULL) + if ((host = httpGetHostByName2(con->http.hostname, con->http.hostaddr.addr.sa_family)) != NULL) { /* * See if the hostname maps to the same IP address... @@ -304,8 +312,8 @@ * Get the local address the client connected to... */ - i = sizeof(temp); - if (getsockname(con->http.fd, (struct sockaddr *)&temp, &i)) + val = sizeof(temp); + if (getsockname(con->http.fd, (struct sockaddr *)&temp, &val)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get local address - %s", strerror(errno)); @@ -423,8 +431,6 @@ int error; /* Error code */ gnutls_certificate_server_credentials *credentials; /* TLS credentials */ -#elif defined(HAVE_CDSASSL) - int status; /* Error status */ #endif /* HAVE_LIBSSL */ @@ -493,7 +499,7 @@ free(conn); # elif defined(HAVE_CDSASSL) - status = SSLClose((SSLContextRef)con->http.tls); + SSLClose((SSLContextRef)con->http.tls); SSLDisposeContext((SSLContextRef)con->http.tls); # endif /* HAVE_LIBSSL */ @@ -734,13 +740,9 @@ #elif defined(HAVE_CDSASSL) OSStatus error; /* Error info */ SSLContextRef conn; /* New connection */ - SSLProtocol tryVersion; /* Protocol version */ const char *hostName; /* Local hostname */ int allowExpired; /* Allow expired certificates? */ int allowAnyRoot; /* Allow any root certificate? */ - SSLProtocol *negVersion; /* Negotiated protocol version */ - SSLCipherSuite *negCipher; /* Negotiated cypher */ - CFArrayRef *peerCerts; /* Certificates */ conn = NULL; @@ -748,6 +750,17 @@ allowExpired = 1; allowAnyRoot = 1; + if (ServerCertificatesArray == NULL) + ServerCertificatesArray = CDSAGetServerCerts(); + + if (ServerCertificatesArray == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "EncryptClient: Could not find signing key in keychain \"%s\"", + ServerCertificate); + error = errSSLBadConfiguration; + } + if (!error) error = SSLSetIOFuncs(conn, CDSAReadFunc, CDSAWriteFunc); @@ -790,7 +803,7 @@ con->http.hostname); cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdEncryptClient: CDSA error code is %d", error); + "cupsdEncryptClient: CDSA error code is %d", (int)error); con->http.error = error; con->http.status = HTTP_ERROR; @@ -3421,6 +3434,94 @@ #if defined(HAVE_CDSASSL) /* + * 'CDSAGetServerCerts()' - Convert a keychain name into the CFArrayRef + * required by SSLSetCertificate. + * + * For now we assumes that there is exactly one SecIdentity in the + * keychain - i.e. there is exactly one matching cert/private key pair. + * In the future we will search a keychain for a SecIdentity matching a + * specific criteria. We also skip the operation of adding additional + * non-signing certs from the keychain to the CFArrayRef. + * + * To create a self-signed certificate for testing use the certtool. + * Executing the following as root will do it: + * + * certtool c c v k=CUPS + */ + +static CFArrayRef +CDSAGetServerCerts(void) +{ + OSStatus err; /* Error info */ + SecKeychainRef kcRef; /* Keychain reference */ + SecIdentitySearchRef srchRef; /* Search reference */ + SecIdentityRef identity; /* Identity */ + CFArrayRef ca; /* Certificate array */ + + + kcRef = NULL; + srchRef = NULL; + identity = NULL; + ca = NULL; + + err = SecKeychainOpen(ServerCertificate, &kcRef); + + if (err) + cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\", error %d.", + ServerCertificate, (int)err); + else + { + /* + * Search for "any" identity matching specified key use; + * in this app, we expect there to be exactly one. + */ + + err = SecIdentitySearchCreate(kcRef, CSSM_KEYUSE_SIGN, &srchRef); + + if (err) + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "Cannot find signing key in keychain \"%s\", error %d", + ServerCertificate, (int)err); + else + { + err = SecIdentitySearchCopyNext(srchRef, &identity); + + if (err) + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "Cannot find signing key in keychain \"%s\", error %d", + ServerCertificate, (int)err); + else + { + if (CFGetTypeID(identity) != SecIdentityGetTypeID()) + cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentitySearchCopyNext CFTypeID failure!"); + else + { + /* + * Found one. Place it in a CFArray. + * TBD: snag other (non-identity) certs from keychain and add them + * to array as well. + */ + + ca = CFArrayCreate(NULL, (const void **)&identity, 1, NULL); + + if (ca == nil) + cupsdLogMessage(CUPSD_LOG_ERROR, "CFArrayCreate error"); + } + + /*CFRelease(identity);*/ + } + + /*CFRelease(srchRef);*/ + } + + /*CFRelease(kcRef);*/ + } + + return ca; +} + + +/* * 'CDSAReadFunc()' - Read function for CDSA decryption code. */ Index: scheduler/conf.c =================================================================== --- scheduler/conf.c (revision 4753) +++ scheduler/conf.c (working copy) @@ -1092,6 +1092,8 @@ address->un.sun_family = AF_LOCAL; strcpy(address->un.sun_path, value); + address->un.sun_len = offsetof(struct sockaddr_un, sun_path) + + strlen(address->un.sun_path) + 1; return (1); } @@ -1719,6 +1721,13 @@ cups_file_t *incfile; /* Include file */ char incname[1024]; /* Include filename */ struct group *group; /* Group */ + cupsd_listener_t *lis; /* New listeners array */ + char *hostname, /* Host name */ + *servicename; /* Service name or port string */ + int ssl; /* SSL directive? */ + struct addrinfo hints, /* Hints for httpGetAddrInfo */ + *res0, /* Base of httpGetAddrInfo list */ + *res; /* Looping var */ /* @@ -1791,112 +1800,88 @@ return (0); } } - else if (!strcasecmp(line, "Port") || !strcasecmp(line, "Listen")) + else if (!strcasecmp(line, "Port") || !strcasecmp(line, "Listen") +#ifdef HAVE_SSL + || !strcasecmp(line, "SSLPort") || !strcasecmp(line, "SSLListen") +#endif /* HAVE_SSL */ + ) { /* * Add a listening address to the list... */ - cupsd_listener_t *lis; /* New listeners array */ + hostname = NULL; + servicename = NULL; + ssl = 0; - - if (NumListeners == 0) - lis = malloc(sizeof(cupsd_listener_t)); - else - lis = realloc(Listeners, (NumListeners + 1) * sizeof(cupsd_listener_t)); - - if (!lis) + if (!strcasecmp(line, "Listen") || !strcasecmp(line, "SSLListen")) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate %s at line %d - %s.", - line, linenum, strerror(errno)); - continue; + hostname = value; + servicename = "ipp"; /* or "631" for portability? */ } + else + servicename = value; - Listeners = lis; - lis += NumListeners; - - memset(lis, 0, sizeof(cupsd_listener_t)); - -#if defined(AF_INET6) && !defined(__OpenBSD__) - if (get_address(value, INADDR_ANY, IPP_PORT, AF_INET6, &(lis->address))) -#else - if (get_address(value, INADDR_ANY, IPP_PORT, AF_INET, &(lis->address))) -#endif /* AF_INET6 && !__OpenBSD__ */ + if (!strcasecmp(line, "SSLPort") || !strcasecmp(line, "SSLListen")) { - httpAddrString(&(lis->address), temp, sizeof(temp)); - -#ifdef AF_INET6 - if (lis->address.addr.sa_family == AF_INET6) - cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv6)", temp, - ntohs(lis->address.ipv6.sin6_port)); - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (lis->address.addr.sa_family == AF_LOCAL) - cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s (Domain)", temp); - else -#endif /* AF_LOCAL */ - cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv4)", temp, - ntohs(lis->address.ipv4.sin_port)); - - NumListeners ++; + ssl = 1; + servicename = "https"; /* or "443" for portability? */ } - else - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad %s address %s at line %d.", line, - value, linenum); - } -#ifdef HAVE_SSL - else if (!strcasecmp(line, "SSLPort") || !strcasecmp(line, "SSLListen")) - { - /* - * Add a listening address to the list... - */ - cupsd_listener_t *lis; /* New listeners array */ - - - if (NumListeners == 0) - lis = malloc(sizeof(cupsd_listener_t)); - else - lis = realloc(Listeners, (NumListeners + 1) * sizeof(cupsd_listener_t)); - - if (!lis) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; /* protocol family for socket */ + hints.ai_socktype = SOCK_STREAM; /* socket type */ + hints.ai_protocol = IPPROTO_TCP; /* protocol for socket */ + + if (!httpGetAddrInfo(hostname, servicename, &hints, &res0)) { + for (res = res0; res; res = res->ai_next) + { + if (NumListeners == 0) + lis = malloc(sizeof(cupsd_listener_t)); + else + lis = realloc(Listeners, (NumListeners + 1) * sizeof(cupsd_listener_t)); + + if (!lis) + { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate %s at line %d - %s.", - line, linenum, strerror(errno)); - continue; - } + line, linenum, strerror(errno)); + continue; + } + + Listeners = lis; + lis += NumListeners; + + memset(lis, 0, sizeof(cupsd_listener_t)); + + memcpy(&lis->address.addr, res->ai_addr, res->ai_addrlen); - Listeners = lis; - lis += NumListeners; + httpAddrString(&(lis->address), temp, sizeof(temp)); - if (get_address(value, INADDR_ANY, IPP_PORT, AF_INET, &(lis->address))) - { - httpAddrString(&(lis->address), temp, sizeof(temp)); - #ifdef AF_INET6 - if (lis->address.addr.sa_family == AF_INET6) + if (lis->address.addr.sa_family == AF_INET6) cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv6)", temp, - ntohs(lis->address.ipv6.sin6_port)); - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (lis->address.addr.sa_family == AF_LOCAL) - cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s (Domain)", temp); - else + ntohs(lis->address.ipv6.sin6_port)); + else + #endif /* AF_INET6 */ + #ifdef AF_LOCAL + if (lis->address.addr.sa_family == AF_LOCAL) + cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s (Domain)", temp); + else #endif /* AF_LOCAL */ - cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv4)", temp, - ntohs(lis->address.ipv4.sin_port)); - lis->encryption = HTTP_ENCRYPT_ALWAYS; - NumListeners ++; + cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv4)", temp, + ntohs(lis->address.ipv4.sin_port)); + + NumListeners ++; + } + + httpFreeAddrInfo(res0); } else cupsdLogMessage(CUPSD_LOG_ERROR, "Bad %s address %s at line %d.", line, value, linenum); } -#endif /* HAVE_SSL */ else if (!strcasecmp(line, "BrowseAddress")) { /* @@ -1958,6 +1943,11 @@ ntohs(dira->to.ipv6.sin6_port)); else #endif /* AF_INET6 */ +#ifdef AF_LOCAL + if (dira->to.addr.sa_family == AF_LOCAL) + cupsdLogMessage(CUPSD_LOG_INFO, "Sending browsing info to %s (Unix)", temp); + else +#endif /* AF_LOCAL */ cupsdLogMessage(CUPSD_LOG_INFO, "Sending browsing info to %s:%d (IPv4)", temp, ntohs(dira->to.ipv4.sin_port)); @@ -2202,9 +2192,10 @@ * nnn.nnn.nnn.nnn * nnn.nnn.nnn.nnn/mm * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm + * [::1] */ - if (value[0] == '*' || value[0] == '.' || !isdigit(value[0])) + if (value[0] == '*' || value[0] == '.' || !(value[0] == '[' || isdigit(value[0]))) { /* * Host or domain name... @@ -2939,96 +2930,7 @@ } -#ifdef HAVE_CDSASSL -/* - * 'CDSAGetServerCerts()' - Convert a keychain name into the CFArrayRef - * required by SSLSetCertificate. - * - * For now we assumes that there is exactly one SecIdentity in the - * keychain - i.e. there is exactly one matching cert/private key pair. - * In the future we will search a keychain for a SecIdentity matching a - * specific criteria. We also skip the operation of adding additional - * non-signing certs from the keychain to the CFArrayRef. - * - * To create a self-signed certificate for testing use the certtool. - * Executing the following as root will do it: - * - * certtool c c v k=CUPS - */ -CFArrayRef -CDSAGetServerCerts(void) -{ - OSStatus err; /* Error info */ - SecKeychainRef kcRef; /* Keychain reference */ - SecIdentitySearchRef srchRef; /* Search reference */ - SecIdentityRef identity; /* Identity */ - CFArrayRef ca; /* Certificate array */ - - - kcRef = NULL; - srchRef = NULL; - identity = NULL; - ca = NULL; - err = SecKeychainOpen(ServerCertificate, &kcRef); - - if (err) - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\", error %d.", - ServerCertificate, err); - else - { - /* - * Search for "any" identity matching specified key use; - * in this app, we expect there to be exactly one. - */ - - err = SecIdentitySearchCreate(kcRef, CSSM_KEYUSE_SIGN, &srchRef); - - if (err) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot find signing key in keychain \"%s\", error %d", - ServerCertificate, err); - else - { - err = SecIdentitySearchCopyNext(srchRef, &identity); - - if (err) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot find signing key in keychain \"%s\", error %d", - ServerCertificate, err); - else - { - if (CFGetTypeID(identity) != SecIdentityGetTypeID()) - cupsdLogMessage(CUPSD_LOG_ERROR, - "SecIdentitySearchCopyNext CFTypeID failure!"); - else - { - /* - * Found one. Place it in a CFArray. - * TBD: snag other (non-identity) certs from keychain and add them - * to array as well. - */ - - ca = CFArrayCreate(NULL, (const void **)&identity, 1, NULL); - - if (ca == nil) - cupsdLogMessage(CUPSD_LOG_ERROR, "CFArrayCreate error"); - } - - /*CFRelease(identity);*/ - } - - /*CFRelease(srchRef);*/ - } - - /*CFRelease(kcRef);*/ - } - - return ca; -} -#endif /* HAVE_CDSASSL */ - - /* * End of "$Id$". */ Index: scheduler/listen.c =================================================================== --- scheduler/listen.c (revision 4753) +++ scheduler/listen.c (working copy) @@ -130,7 +130,12 @@ memset(&ServerAddr, 0, sizeof(ServerAddr)); - if ((host = httpGetHostByName(ServerName)) != NULL) +#ifdef AF_INET6 + if ((host = httpGetHostByName2(ServerName, AF_INET6)) == NULL) +#endif /* AF_INET6 */ + host = httpGetHostByName2(ServerName, AF_INET); + + if (host != NULL) { /* * Found the server's address! Index: scheduler/server.c =================================================================== --- scheduler/server.c (revision 4753) +++ scheduler/server.c (working copy) @@ -77,8 +77,6 @@ */ gnutls_global_init(); -#elif defined(HAVE_CDSASSL) - ServerCertificatesArray = CDSAGetServerCerts(); #endif /* HAVE_LIBSSL */ /* Index: scheduler/cups-lpd.c =================================================================== --- scheduler/cups-lpd.c (revision 4753) +++ scheduler/cups-lpd.c (working copy) @@ -103,7 +103,7 @@ *list, /* Pointer to list */ *agent, /* Pointer to user */ status; /* Status for client */ - int hostlen; /* Size of client address */ + socklen_t hostlen; /* Size of client address */ http_addr_t hostaddr; /* Address of client */ char hostname[256], /* Name of client */ hostip[256], /* IP address */