summaryrefslogtreecommitdiff
path: root/bjnp-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'bjnp-utils.c')
-rw-r--r--bjnp-utils.c497
1 files changed, 271 insertions, 226 deletions
diff --git a/bjnp-utils.c b/bjnp-utils.c
index bcb37eb..fb2c77c 100644
--- a/bjnp-utils.c
+++ b/bjnp-utils.c
@@ -1,18 +1,19 @@
/*
- * TCP/IP IO communication implementation for
- * bjnp backend for the Common UNIX Printing System (CUPS).
- * Copyright 2008 by Louis Lagendijk
+ * utility functions
+ * bjnp backend for the Common UNIX Printing System (CUPS).
+ * Copyright 2008-2014 by Louis Lagendijk
*
- * These coded instructions, statements, and computer programs are the
- * property of Louis Lagendijk and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * "LICENSE" which should have been included with this file. If this
- * file is missing or damaged, see the license at "http://www.cups.org/".
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
*
- * This file is subject to the Apple OS-Developed Software exception.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Contents:
- * Utility functions
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -21,304 +22,348 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include "bjnp.h"
+#include "bjnp-protocol.h"
+#include "bjnp-io.h"
+#include "bjnp-commands.h"
+#include "bjnp-io.h"
-int sa_is_equal( const http_addr_t * sa1, const http_addr_t * sa2)
-{
- if ((sa1 == NULL) || (sa2 == NULL) )
- return 0;
+#define DES_TOKEN "DES:"
- if (sa1->addr.sa_family == sa2-> addr.sa_family)
- {
- if( sa1 -> addr.sa_family == AF_INET)
- {
- if ( (sa1->ipv4.sin_port == sa2->ipv4.sin_port) &&
- (sa1->ipv4.sin_addr.s_addr == sa2->ipv4.sin_addr.s_addr))
- {
- return 1;
+static int sa_is_equal(const http_addr_t sa1, const http_addr_t sa2)
+{
+ if (sa1.addr.sa_family == sa2.addr.sa_family) {
+ if (sa1.addr.sa_family == AF_INET) {
+ if ((sa1.ipv4.sin_port == sa2.ipv4.sin_port) &&
+ (sa1.ipv4.sin_addr.s_addr == sa2.ipv4.sin_addr.s_addr)) {
+ return 1;
}
}
+
#ifdef ENABLE_IPV6
- else if (sa1 -> addr.sa_family == AF_INET6 )
- {
- if ( (sa1-> ipv6.sin6_port == sa2->ipv6.sin6_port) &&
- (memcmp(&(sa1->ipv6.sin6_addr), &(sa2->ipv6.sin6_addr), sizeof(struct in6_addr)) == 0))
- {
- return 1;
+ else if (sa1.addr.sa_family == AF_INET6) {
+ if ((sa1.ipv6.sin6_port == sa2.ipv6.sin6_port) &&
+ (memcmp(&(sa1.ipv6.sin6_addr), &(sa2.ipv6.sin6_addr),
+ sizeof(struct in6_addr)) == 0)) {
+ return 1;
}
}
+
#endif
}
+
return 0;
}
-int sa_size( const http_addr_t *sa)
+int sa_size(const http_addr_t sa)
{
- switch (sa -> addr.sa_family)
- {
- case AF_INET:
- return (sizeof(struct sockaddr_in) );
+ switch (sa.addr.sa_family) {
+ case AF_INET:
+ return (sizeof(struct sockaddr_in));
#ifdef ENABLE_IPV6
- case AF_INET6:
- return (sizeof(struct sockaddr_in6) );
+
+ case AF_INET6:
+ return (sizeof(struct sockaddr_in6));
#endif
- default:
- /* should not occur */
- return sizeof( http_addr_t );
+
+ default:
+ /* should not occur */
+ return sizeof(http_addr_t);
}
}
-int get_protocol_family( const http_addr_t *sa)
+int get_protocol_family(const http_addr_t sa)
{
- switch (sa -> addr.sa_family)
- {
- case AF_INET:
- return PF_INET;
- break;
+ switch (sa.addr.sa_family) {
+ case AF_INET:
+ return PF_INET;
+ break;
#ifdef ENABLE_IPV6
- case AF_INET6:
- return PF_INET6;
- break;
+
+ case AF_INET6:
+ return PF_INET6;
+ break;
#endif
- default:
- /* should not occur */
- return -1;
+
+ default:
+ /* should not occur */
+ return -1;
}
}
-void get_address_info ( const http_addr_t *addr, char * addr_string, int *port)
+void get_address_info(const http_addr_t *addr, char *addr_string, int *port,
+ char *family)
{
- char tmp_addr[BJNP_HOST_MAX];
- if ( addr->addr.sa_family == AF_INET)
- {
- inet_ntop( AF_INET, &(addr -> ipv4.sin_addr.s_addr), addr_string, BJNP_HOST_MAX);
- *port = ntohs (addr->ipv4.sin_port);
+ char tmp_addr[BJNP_HOST_MAX];
+
+ if (addr->addr.sa_family == AF_INET) {
+ inet_ntop(AF_INET, &(addr -> ipv4.sin_addr.s_addr), addr_string,
+ BJNP_HOST_MAX);
+ *port = ntohs(addr->ipv4.sin_port);
+ strcpy(family, BJNP_FAMILY_IPV4);
}
+
#ifdef ENABLE_IPV6
- else if (addr->addr.sa_family == AF_INET6)
- {
- inet_ntop( AF_INET6, addr -> ipv6.sin6_addr.s6_addr, tmp_addr, sizeof(tmp_addr) );
-
- if (IN6_IS_ADDR_LINKLOCAL( &(addr -> ipv6.sin6_addr) ) )
- sprintf(addr_string, "[%s%%%d]", tmp_addr, addr -> ipv6.sin6_scope_id);
- else
- sprintf(addr_string, "[%s]", tmp_addr);
-
- *port = ntohs (addr->ipv6.sin6_port);
+ else if (addr->addr.sa_family == AF_INET6) {
+ inet_ntop(AF_INET6, addr->ipv6.sin6_addr.s6_addr, tmp_addr,
+ sizeof(tmp_addr));
+
+ if (IN6_IS_ADDR_LINKLOCAL(&(addr->ipv6.sin6_addr))) {
+ sprintf(addr_string, "[%s%%%d]", tmp_addr,
+ addr->ipv6.sin6_scope_id);
+ } else {
+ sprintf(addr_string, "[%s]", tmp_addr);
+ }
+
+ *port = ntohs(addr->ipv6.sin6_port);
+ strcpy(family, BJNP_FAMILY_IPV6);
}
+
#endif
- else
- {
- /* unknown address family, should not occur */
- strcpy(addr_string, "Unknown address family");
- *port = 0;
+ else {
+ /* unknown address family, should not occur */
+ strcpy(addr_string, "Unknown address family");
+ *port = 0;
+ strcpy(family, BJNP_FAMILY_UNKNOWN);
}
}
+void get_printer_address_info(const printer_t *printer, char *addr_string,
+ int *port, char *family)
+{
+ get_address_info(&(printer->printer_sa), addr_string, port, family);
+}
+
int
-parse_IEEE1284_to_model (char *printer_id, char *model)
+parse_IEEE1284_to_model(char *printer_id, char *model)
{
-/*
- * parses the IEEE1284 ID of the printer to retrieve make and model
- * of the printer
- * Returns: 0 = not found
- * 1 = found, model is set
- */
+ /*
+ * parses the IEEE1284 ID of the printer to retrieve make and model
+ * of the printer
+ * Returns: 0 = not found
+ * 1 = found, model is set
+ */
+
+ char s[BJNP_IEEE1284_MAX];
+ char *tok;
+ int len;
+
+ model[0] = '\0';
+ len = strlen(printer_id);
+
+ if ((len > BJNP_IEEE1284_MAX) || (len < 0)) {
+ bjnp_debug(LOG_ERROR, "printer id string (length) incorrect: %d\n",
+ len);
+ }
- char s[BJNP_IEEE1284_MAX];
- char *tok;
+ strcpy(s, printer_id);
- strcpy (s, printer_id);
- model[0] = '\0';
+ tok = strtok(s, ";");
- tok = strtok (s, ";");
- while (tok != NULL)
- {
- /* DES contains make and model */
+ while (tok != NULL) {
+ /* DES contains make and model */
- if (strncmp (tok, "DES:", 4) == 0)
- {
- strcpy (model, tok + 4);
- return 1;
- }
- tok = strtok (NULL, ";");
+ if (strncmp(tok, DES_TOKEN, strlen(DES_TOKEN)) == 0) {
+ strcpy(model, tok + strlen(DES_TOKEN));
+ return 1;
+ }
+
+ tok = strtok(NULL, ";");
}
- return 0;
+
+ return 0;
}
int
-charTo2byte (char d[], char s[], int len)
+charTo2byte(char d[], const char s[], int len)
{
- /*
- * copy ASCII string to 2 byte unicode string
- * Returns: number of characters copied
- */
-
- int done = 0;
- int copied = 0;
- int i;
-
- for (i = 0; i < len; i++)
- {
- d[2 * i] = '\0';
- if (s[i] == '\0')
- {
- done = 1;
- }
- if (done == 0)
- {
- d[2 * i + 1] = s[i];
- copied++;
- }
- else
- d[2 * i + 1] = '\0';
+ /*
+ * copy ASCII string to 2 byte unicode string
+ * Returns: number of characters copied
+ */
+
+ int done = 0;
+ int copied = 0;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ d[2 * i] = '\0';
+
+ if (s[i] == '\0') {
+ done = 1;
+ }
+
+ if (done == 0) {
+ d[2 * i + 1] = s[i];
+ copied++;
+ } else {
+ d[2 * i + 1] = '\0';
+ }
}
- return copied;
+
+ return copied;
}
-void u8tohex_string( uint8_t * input, char * str, int size)
+void u8tohex_string(uint8_t *input, char *str, int size)
{
- static const char hdigit[16] =
- { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
- 'e', 'f'
- };
- int i;
- for (i = 0; i < size; i++)
- {
- str[ 2 * i] = hdigit[ (input[i] >> 4) & 0xf];
- str[ 2 * 1 +1] = hdigit[ input[i] & 0xf];
+ static const char hdigit[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+ int i;
+
+ for (i = 0; i < size; i++) {
+ str[ 2 * i] = hdigit[(input[i] >> 4) & 0xf];
+ str[ 2 * 1 + 1] = hdigit[ input[i] & 0xf];
}
- str[2 * i] = '\0';
+
+ str[2 * i] = '\0';
}
int
-find_bin_string (const void *in, int len, char *lookfor, int size)
+find_bin_string(const void *in, int len, char *lookfor, int size)
{
- /*
- * looks for a new print command in the input stream
- * Returns: offset where lookfor is found or -1 when not found
- */
-
- int i;
- const char *buf = in;
-
- /* start at offset 1 to avoid match at start of input */
- for (i = 1; i < (len - size); i++)
- {
- if ((buf[i] == lookfor[0]) && (memcmp (buf + i, lookfor, size) == 0))
- {
- return i;
- }
+ /*
+ * looks for a new print command in the input stream
+ * Returns: offset where lookfor is found or -1 when not found
+ */
+
+ int i;
+ const char *buf = in;
+
+ /* start at offset 1 to avoid match at start of input */
+ for (i = 1; i < (len - size); i++) {
+ if ((buf[i] == lookfor[0]) && (memcmp(buf + i, lookfor, size) == 0)) {
+ return i;
+ }
}
- return -1;
+
+ return -1;
}
bjnp_address_type_t
-get_printer_host (const http_addr_t *printer_addr, char *name, int *port)
+get_printer_host(const http_addr_t printer_addr, char *name, int *port,
+ char *family)
{
- /*
- * lookup hostname for printers address
- */
-
- struct addrinfo *results;
- struct addrinfo *result;
- http_addr_t *res_address;
- char ip_address[BJNP_HOST_MAX];
- char service[64];
- int error;
- int match = 0;
- bjnp_address_type_t level;
+ /*
+ * lookup hostname for printers address
+ */
+
+ struct addrinfo *results;
+ struct addrinfo *result;
+ http_addr_t *res_address;
+ char ip_address[BJNP_HOST_MAX];
+ char service[64];
+ int error;
+ int match = 0;
+ bjnp_address_type_t level;
#ifdef ENABLE_IPV6
- if ( ( printer_addr -> addr.sa_family == AF_INET6 ) &&
- ( IN6_IS_ADDR_LINKLOCAL( &(printer_addr -> ipv6.sin6_addr ) ) ) )
- level = BJNP_ADDRESS_IS_LINK_LOCAL;
- else
- level = BJNP_ADDRESS_IS_GLOBAL;
+
+ if ((printer_addr.addr.sa_family == AF_INET6) &&
+ (IN6_IS_ADDR_LINKLOCAL(&(printer_addr.ipv6.sin6_addr)))) {
+ level = BJNP_ADDRESS_IS_LINK_LOCAL;
+ } else {
+ level = BJNP_ADDRESS_IS_GLOBAL;
+ }
+
#else
- level = BJNP_ADDRESS_IS_GLOBAL;
+ level = BJNP_ADDRESS_IS_GLOBAL;
#endif
- get_address_info( printer_addr, ip_address, port);
+ get_address_info(&printer_addr, ip_address, port, family);
- bjnp_debug (LOG_INFO, "Found printer at ip address: %s\n", ip_address);
+ bjnp_debug(LOG_INFO, "Found printer at ip address: %s(%s)\n", ip_address,
+ family);
- /* do reverse name lookup, if hostname can not be found return IP-address */
+ /* do reverse name lookup, if hostname cannot be found, return IP-addr */
- if( (error = getnameinfo( &(printer_addr-> addr) , sa_size( printer_addr),
- name, BJNP_HOST_MAX , NULL, 0, NI_NAMEREQD) ) != 0 )
- {
- bjnp_debug(LOG_DEBUG, "Name for %s not found : %s\n",
- ip_address, gai_strerror(error) );
- strcpy( name, ip_address );
- return level;
+ if ((error = getnameinfo(&(printer_addr.addr) , sa_size(printer_addr),
+ name, BJNP_HOST_MAX , NULL, 0, NI_NAMEREQD))
+ != 0) {
+ bjnp_debug(LOG_DEBUG, "Name for %s not found : %s\n",
+ ip_address, gai_strerror(error));
+ strcpy(name, ip_address);
+ return level;
}
- /* some buggy routers return rubbish if reverse lookup fails, so
- * we do a forward lookup to see if the result matches the ip-address */
+ /* some buggy routers return rubbish if reverse lookup fails, so
+ * we do a forward lookup to see if the result matches the ip-address */
- sprintf( service, "%d", *port);
- if (getaddrinfo( name, service, NULL, &results) == 0) {
+ sprintf(service, "%d", *port);
- result = results;
+ if (getaddrinfo(name, service, NULL, &results) == 0) {
- while (result != NULL) {
+ result = results;
- res_address = (http_addr_t *)result-> ai_addr;
+ while (result != NULL) {
- if(sa_is_equal( res_address, printer_addr)) {
+ res_address = (http_addr_t *)result-> ai_addr;
- /* found match, good */
+ if (sa_is_equal(*res_address, printer_addr)) {
- match = 1;
- break;
- }
- result = result-> ai_next;
- }
- freeaddrinfo(results);
+ /* found match, good */
- if (match == 1) {
- bjnp_debug (LOG_DEBUG, "Reverse lookup for %s succeeded, using as hostname\n", name);
- level = BJNP_ADDRESS_HAS_FQDN;
- }
- else {
- bjnp_debug (LOG_DEBUG,
- "Reverse lookup for %s succeeded, forward lookup failed, using IP-address %s instead\n",
+ match = 1;
+ break;
+ }
+
+ result = result-> ai_next;
+ }
+
+ freeaddrinfo(results);
+
+ if (match == 1) {
+ bjnp_debug(LOG_DEBUG, "Reverse lookup for %s succeeded, using as hostname\n",
+ name);
+ level = BJNP_ADDRESS_HAS_FQDN;
+ } else {
+ bjnp_debug(LOG_DEBUG,
+ "Reverse lookup for %s succeeded, forward lookup failed, using IP-address %s instead\n",
+ name, ip_address);
+ strcpy(name, ip_address);
+ }
+ } else {
+ /* lookup failed, use ip-address */
+ bjnp_debug(LOG_DEBUG, "Reverse lookup of %s failed, using IP-address %s\n",
name, ip_address);
- strcpy (name, ip_address);
+ strcpy(name, ip_address);
}
- } else {
- /* lookup failed, use ip-address */
- bjnp_debug (LOG_DEBUG, "Reverse lookup of %s failed, using IP-address %s\n", name, ip_address);
- strcpy (name, ip_address);
- }
- return level;
+
+ return level;
}
-char * bjnp_map_status(cups_sc_status_t status)
+char *bjnp_map_status(cups_sc_status_t status)
{
- switch(status)
- {
- case CUPS_SC_STATUS_BAD_MESSAGE:
- return "bad message";
- case CUPS_SC_STATUS_IO_ERROR:
- return "I/O error";
- case CUPS_SC_STATUS_NONE:
- return "no status";
- case CUPS_SC_STATUS_NOT_IMPLEMENTED:
- return "not implemented";
- case CUPS_SC_STATUS_NO_RESPONSE:
- return "no response";
- case CUPS_SC_STATUS_OK:
- return "status ok";
- case CUPS_SC_STATUS_TIMEOUT:
- return "timeout";
- case CUPS_SC_STATUS_TOO_BIG:
- return "message too big";
- default:
- return "unknown status, please report!";
+ switch (status) {
+ case CUPS_SC_STATUS_BAD_MESSAGE:
+ return "bad message";
+
+ case CUPS_SC_STATUS_IO_ERROR:
+ return "I/O error";
+
+ case CUPS_SC_STATUS_NONE:
+ return "no status";
+
+ case CUPS_SC_STATUS_NOT_IMPLEMENTED:
+ return "not implemented";
+
+ case CUPS_SC_STATUS_NO_RESPONSE:
+ return "no response";
+
+ case CUPS_SC_STATUS_OK:
+ return "status ok";
+
+ case CUPS_SC_STATUS_TIMEOUT:
+ return "timeout";
+
+ case CUPS_SC_STATUS_TOO_BIG:
+ return "message too big";
+
+ default:
+ return "unknown status, please report!";
}
}