diff options
author | Till Kamppeter <till.kamppeter@gmail.com> | 2016-02-13 22:22:24 -0200 |
---|---|---|
committer | Till Kamppeter <till.kamppeter@gmail.com> | 2016-02-13 22:22:24 -0200 |
commit | aa40a1e8fe0c4ed29d21c5f79e682ac7bef1c33f (patch) | |
tree | 66996e1a8b1ad790b09c0890ac7986873b7d435a /bjnp-discover.c | |
parent | 879e6db06338166657609930768f76d8d7e7afbb (diff) |
Imported Upstream version 2.0
Diffstat (limited to 'bjnp-discover.c')
-rw-r--r-- | bjnp-discover.c | 848 |
1 files changed, 426 insertions, 422 deletions
diff --git a/bjnp-discover.c b/bjnp-discover.c index 9f005aa..eccddd3 100644 --- a/bjnp-discover.c +++ b/bjnp-discover.c @@ -1,522 +1,526 @@ /* - * TCP/IP IO communication implementation for - * bjnp backend for the Common UNIX Printing System (CUPS). - * Copyright 2008 by Louis Lagendijk + * Printer discovery implementation for + * 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 file is subject to the Apple OS-Developed Software exception. + * 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. * - * Contents: - * <to be added> + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "bjnp.h" +#include "config.h" #include <errno.h> #include <sys/types.h> +#include <sys/socket.h> #include <net/if.h> #ifdef HAVE_GETIFADDRS #include <ifaddrs.h> #endif +#include "bjnp.h" #include "bjnp-protocol.h" +#include "bjnp-commands.h" -static int create_broadcast_socket( const http_addr_t * local_addr ) +static int create_broadcast_socket(const http_addr_t *local_addr) { - int sockfd = -1; - int broadcast = 1; - int ipv6_v6only = 1; + int sockfd = -1; + int broadcast = 1; + int ipv6_v6only = 1; - if ((sockfd = socket (local_addr-> addr.sa_family, SOCK_DGRAM, 0)) == -1) - { - bjnp_debug - (LOG_CRIT, "create_broadcast_socket: can not open socket - %s", - strerror (errno)); - return -1; + if ((sockfd = socket(local_addr-> addr.sa_family, SOCK_DGRAM, 0)) == -1) { + bjnp_debug + (LOG_CRIT, "create_broadcast_socket: cannot open socket - %s", + strerror(errno)); + return -1; } - /* Set broadcast flag on socket */ - - if (setsockopt - (sockfd, SOL_SOCKET, SO_BROADCAST, (const char *) &broadcast, - sizeof (broadcast)) != 0) - { - bjnp_debug - (LOG_CRIT, - "create_broadcast_socket: setting socket option SO_BROADCAST failed - %s", - strerror (errno)); - close (sockfd); - return -1; + /* Set broadcast flag on socket */ + + if (setsockopt + (sockfd, SOL_SOCKET, SO_BROADCAST, (const char *) &broadcast, + sizeof(broadcast)) != 0) { + bjnp_debug + (LOG_CRIT, + "create_broadcast_socket: setting socket option SO_BROADCAST failed - %s", + strerror(errno)); + close(sockfd); + return -1; }; #ifdef ENABLE_IPV6 - /* For an IPv6 socket, bind to v6 only so a V6 socket can co-exist with a v4 socket */ - if ( (local_addr -> addr.sa_family == AF_INET6) && ( setsockopt - (sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6_v6only, - sizeof (ipv6_v6only)) != 0) ) - { - bjnp_debug - (LOG_CRIT, - "create_broadcast_socket: setting socket option IPV6_V6ONLY failed - %s", - strerror (errno)); - close (sockfd); - return -1; + + /* For an IPv6 socket, bind to v6 only so a V6 socket can co-exist with a v4 socket */ + if ((local_addr -> addr.sa_family == AF_INET6) && (setsockopt + (sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6_v6only, + sizeof(ipv6_v6only)) != 0)) { + bjnp_debug + (LOG_CRIT, + "create_broadcast_socket: setting socket option IPV6_V6ONLY failed - %s", + strerror(errno)); + close(sockfd); + return -1; }; + #endif - if (bind - (sockfd, &(local_addr->addr), - (socklen_t) sa_size( local_addr)) != 0) - { - bjnp_debug - (LOG_CRIT, - "create_broadcast_socket: bind socket to local address failed - %s\n", - strerror (errno)); - close (sockfd); - return -1; + if (bind(sockfd, &(local_addr->addr), (socklen_t) sa_size(*local_addr)) != 0) { + bjnp_debug + (LOG_CRIT, + "create_broadcast_socket: bind socket to local address failed - %s\n", + strerror(errno)); + close(sockfd); + return -1; } - return sockfd; + + return sockfd; } -static int -prepare_socket(const char *if_name, const http_addr_t *local_sa, - const http_addr_t *broadcast_sa, http_addr_t * dest_sa) +static int +prepare_socket(const char *if_name, const http_addr_t *local_sa, + const http_addr_t *broadcast_sa, http_addr_t *dest_sa) { - /* - * Prepare a socket for broadcast or multicast - * Input: - * if_name: the name of the interface - * local_sa: local address to use - * broadcast_sa: broadcast address to use, if NULL we use all hosts - * dest_sa: (write) where to return destination address of broadcast - * retuns: open socket or -1 - */ - - int socket = -1; - http_addr_t local_sa_copy; - - if ( local_sa == NULL ) - { - bjnp_debug (LOG_DEBUG, - "%s is not a valid IPv4 interface, skipping...\n", - if_name); - return -1; + /* + * Prepare a socket for broadcast or multicast + * Input: + * if_name: the name of the interface + * local_sa: local address to use + * broadcast_sa: broadcast address to use, if NULL we use all hosts + * dest_sa: (write) where to return destination address of broadcast + * retuns: open socket or -1 + */ + + int socket = -1; + http_addr_t local_sa_copy; + + if (local_sa == NULL) { + bjnp_debug(LOG_DEBUG, + "%s is not a valid IPv4 interface, skipping...\n", + if_name); + return -1; } - memset( &local_sa_copy, 0, sizeof(local_sa_copy) ); - memcpy( &local_sa_copy, local_sa, sa_size(local_sa) ); + memset(&local_sa_copy, 0, sizeof(local_sa_copy)); + memcpy(&local_sa_copy, local_sa, sa_size(*local_sa)); - switch( local_sa_copy.addr.sa_family ) - { - case AF_INET: - { - local_sa_copy.ipv4.sin_port = htons(BJNP_PORT_PRINT); + switch (local_sa_copy.addr.sa_family) { + case AF_INET: { + local_sa_copy.ipv4.sin_port = htons(BJNP_PORT_PRINT); - if (local_sa_copy.ipv4.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) - { - /* not a valid interface */ + if (local_sa_copy.ipv4.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) { + /* not a valid interface */ - bjnp_debug (LOG_DEBUG, + bjnp_debug(LOG_DEBUG, "%s is not a valid IPv4 interface, skipping...\n", - if_name); - return -1; - } + if_name); + return -1; + } - /* send broadcasts to the broadcast address of the interface */ + /* send broadcasts to the broadcast address of the interface */ - memcpy(dest_sa, broadcast_sa, sa_size(dest_sa) ); - dest_sa -> ipv4.sin_port = htons(BJNP_PORT_PRINT); - if ( (socket = create_broadcast_socket( &local_sa_copy) ) != -1) - { - bjnp_debug (LOG_DEBUG, "%s is IPv4 capable, sending broadcast, socket = %d\n", - if_name, socket); - } - else - { - bjnp_debug (LOG_DEBUG, "%s is IPv4 capable, but failed to create a socket.\n", - if_name); - return -1; + memcpy(dest_sa, broadcast_sa, sa_size(*dest_sa)); + dest_sa -> ipv4.sin_port = htons(BJNP_PORT_PRINT); + + if ((socket = create_broadcast_socket(&local_sa_copy)) != -1) { + bjnp_debug(LOG_DEBUG, "%s is IPv4 capable, sending broadcast, socket = %d\n", + if_name, socket); + } else { + bjnp_debug(LOG_DEBUG, "%s is IPv4 capable, but failed to create a socket.\n", + if_name); + return -1; + } } - } - break; + break; #ifdef ENABLE_IPV6 - case AF_INET6: - { - local_sa_copy.ipv6.sin6_port = htons(BJNP_PORT_PRINT); - if (IN6_IS_ADDR_LOOPBACK( &(local_sa_copy.ipv6.sin6_addr) ) ) - { - /* not a valid interface */ + case AF_INET6: { + local_sa_copy.ipv6.sin6_port = htons(BJNP_PORT_PRINT); - bjnp_debug (LOG_DEBUG, + if (IN6_IS_ADDR_LOOPBACK(&(local_sa_copy.ipv6.sin6_addr))) { + /* not a valid interface */ + + bjnp_debug(LOG_DEBUG, "%s is not a valid IPv6 interface, skipping...\n", - if_name); - return -1; - } - else - { - dest_sa -> ipv6.sin6_family = AF_INET6; - dest_sa -> ipv6.sin6_port = htons(BJNP_PORT_PRINT); - inet_pton(AF_INET6, "ff02::1", dest_sa -> ipv6.sin6_addr.s6_addr); - if ( (socket = create_broadcast_socket( &local_sa_copy ) ) != -1) - { - bjnp_debug (LOG_DEBUG, "%s is IPv6 capable, sending broadcast, socket = %d\n", - if_name, socket); - } - else - { - bjnp_debug (LOG_DEBUG, "%s is IPv6 capable, but failed to create a socket.\n", - if_name); - return -1; + if_name); + return -1; + } else { + dest_sa -> ipv6.sin6_family = AF_INET6; + dest_sa -> ipv6.sin6_port = htons(BJNP_PORT_PRINT); + inet_pton(AF_INET6, "ff02::1", dest_sa -> ipv6.sin6_addr.s6_addr); + + if ((socket = create_broadcast_socket(&local_sa_copy)) != -1) { + bjnp_debug(LOG_DEBUG, "%s is IPv6 capable, sending broadcast, socket = %d\n", + if_name, socket); + } else { + bjnp_debug(LOG_DEBUG, "%s is IPv6 capable, but failed to create a socket.\n", + if_name); + return -1; + } } } - } - break; + break; #endif - default: - socket = -1; + default: + socket = -1; } - return socket; + + return socket; } static int -bjnp_send_broadcast (int sockfd, const http_addr_t * broadcast_addr, - bjnp_command_t cmd, int size) +bjnp_send_broadcast(int sockfd, const http_addr_t *broadcast_addr, + bjnp_command_t cmd, int size) { - int num_bytes; + int num_bytes; - /* set address to send packet to */ - /* usebroadcast address of interface */ + /* set address to send packet to */ + /* usebroadcast address of interface */ - if ((num_bytes = sendto (sockfd, &cmd, size, 0, - &(broadcast_addr->addr), - sa_size( broadcast_addr)) ) != size) - { - bjnp_debug (LOG_DEBUG, - "bjnp_send_broadcast: Socket: %d: sent only %x = %d bytes of packet, error = %s\n", - sockfd, num_bytes, num_bytes, strerror (errno)); - /* not allowed, skip this interface */ + if ((num_bytes = sendto(sockfd, &cmd, size, 0, + &(broadcast_addr->addr), + sa_size(*broadcast_addr))) != size) { + bjnp_debug(LOG_DEBUG, + "bjnp_send_broadcast: Socket: %d: sent only %x = %d bytes of packet, error = %s\n", + sockfd, num_bytes, num_bytes, strerror(errno)); + /* not allowed, skip this interface */ - return -1; + return -1; } - return sockfd; + + return sockfd; } -static void add_printer_address( http_addr_t *printer_sa, char *mac_address, int *no_printers, struct printer_list *printers ) +static void add_printer_address(http_addr_t *printer_sa, char *mac_address, + int *no_printers, struct printer_list *printers) { - char ip_addr[BJNP_HOST_MAX]; - int port; - int i; - bjnp_address_type_t host_type; - char host[BJNP_HOST_MAX]; - - - host_type = get_printer_host( printer_sa, host, &port); - - bjnp_debug (LOG_DEBUG, "add_printer_address(%s) %d\n", host, *no_printers ); - - /* Check if a device number is already allocated to any of the printer's addresses */ - for (i = 0; i < *no_printers; i++) - { - /* we check for mac_addresses as */ - /* an IPv6 host can have multiple adresses */ - - if ( strcmp( printers[i].mac_address, mac_address ) == 0 ) - { - if (host_type > printers[i].host_type) - { - /* This is a better address as it resolves to a FQDN or */ - /* it is a global address, so we do not rely on a scope */ - /* which could change when the number of IP-interfaces changes */ - memcpy(printers[i].addr, printer_sa, sa_size(printer_sa) ); - strcpy( printers[i].hostname, host); - printers[i].host_type = host_type; - bjnp_debug (LOG_DEBUG, "Printer at %s found before, but found better address!\n", - host); - } - else - { - bjnp_debug (LOG_DEBUG, "Printer at %s found before, not added!\n", - host); + char ip_addr[BJNP_HOST_MAX]; + int port; + char family[BJNP_FAMILY_MAX]; + int i; + bjnp_address_type_t host_type; + char host[BJNP_HOST_MAX]; + + + host_type = get_printer_host(*printer_sa, host, &port, family); + + bjnp_debug(LOG_DEBUG, "add_printer_address(%s) %d\n", host, *no_printers); + + /* Check if a device number is already allocated to any of the printer's addresses */ + for (i = 0; i < *no_printers; i++) { + /* we check for mac_addresses as */ + /* an IPv6 host can have multiple adresses */ + + if (strcmp(printers[i].mac_address, mac_address) == 0) { + if (host_type > printers[i].host_type) { + /* This is a better address as it resolves to a FQDN or */ + /* it is a global address, so we do not rely on a scope */ + /* which could change when the number of IP-interfaces changes */ + memcpy(printers[i].addr, printer_sa, sa_size(*printer_sa)); + strcpy(printers[i].hostname, host); + printers[i].host_type = host_type; + bjnp_debug(LOG_DEBUG, "Printer at %s found before, but found better address!\n", + host); + } else { + bjnp_debug(LOG_DEBUG, "Printer at %s found before, not added!\n", + host); } - return; + + return; } } - /* create a new device structure for this address */ - - if (*no_printers == BJNP_PRINTERS_MAX) - { - bjnp_debug (LOG_CRIT, - "Too many devices, ran out of device structures, can not add %s\n", - host); - return; + /* create a new device structure for this address */ + + if (*no_printers == BJNP_PRINTERS_MAX) { + bjnp_debug(LOG_CRIT, + "Too many devices, ran out of device structures, cannot add %s\n", + host); + return; } - printers[*no_printers].addr = malloc(sizeof(http_addr_t)); - memset(printers[*no_printers].addr, 0, sizeof(http_addr_t) ); - memcpy(printers[*no_printers].addr, printer_sa, sa_size(printer_sa)); - printers[*no_printers].host_type = host_type; - printers[*no_printers].port = port; - strcpy(printers[*no_printers].hostname, host); - strcpy(printers[*no_printers].mac_address, mac_address); - if (get_printer_id (printer_sa, printers[*no_printers].model, - printers[*no_printers].IEEE1284_id ) != 0) - { - bjnp_debug (LOG_CRIT, "Cannot read printer make & model: %s\n", host); - free(printers[*no_printers].addr); - return; + + printers[*no_printers].addr = malloc(sizeof(http_addr_t)); + memset(printers[*no_printers].addr, 0, sizeof(http_addr_t)); + memcpy(printers[*no_printers].addr, printer_sa, sa_size(*printer_sa)); + printers[*no_printers].host_type = host_type; + printers[*no_printers].port = port; + strcpy(printers[*no_printers].hostname, host); + strcpy(printers[*no_printers].mac_address, mac_address); + + if (get_printer_id(printer_sa, printers[*no_printers].model, + printers[*no_printers].IEEE1284_id) != 0) { + bjnp_debug(LOG_CRIT, "Cannot read printer make & model: %s\n", host); + free(printers[*no_printers].addr); + return; } - get_address_info( printer_sa, ip_addr, &port); - bjnp_debug (LOG_DEBUG, "Printer not yet in our list, added it: %s:%d\n", host, port); - (*no_printers)++; + + get_address_info(printer_sa, ip_addr, &port, family); + bjnp_debug(LOG_DEBUG, "Printer not yet in our list, added it: %s:%d(%s)\n", + host, port, family); + (*no_printers)++; } -static void add_printer( http_addr_t *printer_sa, bjnp_response_t *resp, - int *no_printers, struct printer_list *printers ) +static void add_printer(http_addr_t *printer_sa, bjnp_response_t *resp, + int *no_printers, struct printer_list *printers) { - char mac_address_string[BJNP_SERIAL_MAX]; - int i; + char mac_address_string[BJNP_SERIAL_MAX]; + int i; - /* create serial/mac_address string */ + /* create serial/mac_address string */ - u8tohex_string(resp -> udp_discover_response.mac_addr, mac_address_string, - sizeof(resp -> udp_discover_response.mac_addr) ); + u8tohex_string(resp -> udp_discover_response.mac_addr, mac_address_string, + sizeof(resp -> udp_discover_response.mac_addr)); - if (printer_sa->addr.sa_family == AF_INET) - { - add_printer_address( printer_sa, mac_address_string, no_printers, printers); + if (printer_sa->addr.sa_family == AF_INET) { + add_printer_address(printer_sa, mac_address_string, no_printers, printers); } - else - { - int no_addresses; - http_addr_t printer_addr; - - /* IPV6, we also need to try all adresses received in the discover response */ - - add_printer_address( printer_sa, mac_address_string, no_printers, printers); - no_addresses = resp -> udp_discover_response.addr_len >> 4; - memset(&printer_addr, 0, sizeof(printer_addr) ); - memcpy(&printer_addr, printer_sa, sa_size(printer_sa) ); - for (i = 0; i < no_addresses; i++ ) - { - memcpy(printer_addr.ipv6.sin6_addr.s6_addr, &(resp -> udp_discover_response.addresses.ipv6.ipv6_addr[i]), 16); - - /* we only add link-local address if the response came from a link-local aadress (done above) */ - - if ( ! IN6_IS_ADDR_LINKLOCAL( &(printer_addr.ipv6.sin6_addr) ) ) - { - /* address is already in network byte order */ - - add_printer_address(&printer_addr, mac_address_string, no_printers, printers ); - } - } + +#ifdef ENABLE_IPV6 + else { + int no_addresses; + http_addr_t printer_addr; + + /* IPV6, we also need to try all adresses received in the discover response */ + + add_printer_address(printer_sa, mac_address_string, no_printers, printers); + no_addresses = resp -> udp_discover_response.addr_len >> 4; + memset(&printer_addr, 0, sizeof(printer_addr)); + memcpy(&printer_addr, printer_sa, sa_size(*printer_sa)); + + for (i = 0; i < no_addresses; i++) { + memcpy(printer_addr.ipv6.sin6_addr.s6_addr, + &(resp -> udp_discover_response.addresses.ipv6.ipv6_addr[i]), 16); + + /* we only add link-local address if the response came from a */ + /* link-local aadress (done above) */ + + if (! IN6_IS_ADDR_LINKLOCAL(&(printer_addr.ipv6.sin6_addr))) { + /* address is already in network byte order */ + + add_printer_address(&printer_addr, mac_address_string, no_printers, printers); + } + } } + +#endif } -int bjnp_discover_printers ( struct printer_list *printers ) +int bjnp_discover_printers(struct printer_list *printers) { - int numbytes = 0; - bjnp_command_t cmd; - bjnp_response_t disc_resp; - int socket_fd[BJNP_SOCK_MAX]; - int no_sockets = 0; - int i; - int attempt; - int last_socketfd = 0; - fd_set fdset; - fd_set active_fdset; - struct timeval timeout; - int no_printers = 0; - http_addr_t broadcast_addr[BJNP_SOCK_MAX]; - http_addr_t printer_sa; - socklen_t socklen; - char host[BJNP_HOST_MAX]; - int port; - - clear_cmd(&cmd); - memset( broadcast_addr, 0, sizeof( broadcast_addr) ); - memset( &printer_sa, 0 ,sizeof( printer_sa ) ); - bjnp_debug (LOG_DEBUG, "sanei_bjnp_find_devices:\n"); - - for (i=0; i < BJNP_SOCK_MAX; i++) - { - socket_fd[i] = -1; + int numbytes = 0; + bjnp_command_t cmd; + bjnp_response_t disc_resp; + int socket_fd[BJNP_SOCK_MAX]; + int no_sockets = 0; + int i; + int attempt; + int last_socketfd = 0; + fd_set fdset; + fd_set active_fdset; + struct timeval timeout; + int no_printers = 0; + http_addr_t broadcast_addr[BJNP_SOCK_MAX]; + http_addr_t printer_sa; + socklen_t socklen; + char host[BJNP_HOST_MAX]; + int port; + char family[BJNP_FAMILY_MAX]; + + clear_cmd(&cmd); + memset(broadcast_addr, 0, sizeof(broadcast_addr)); + memset(&printer_sa, 0 , sizeof(printer_sa)); + bjnp_debug(LOG_DEBUG, "sanei_bjnp_find_devices:\n"); + + for (i = 0; i < BJNP_SOCK_MAX; i++) { + socket_fd[i] = -1; } - bjnp_debug - (LOG_DEBUG, - "Do auto detection of printers...\n"); - /* - * Send UDP DISCOVER to discover printers and return the list of printers found - */ + bjnp_debug + (LOG_DEBUG, + "Do auto detection of printers...\n"); - FD_ZERO (&fdset); - bjnp_set_command_header (&cmd, CMD_UDP_DISCOVER, 0, sizeof(cmd.udp_discover) ); + /* + * Send UDP DISCOVER to discover printers and return the list of printers found + */ - no_sockets = 0; + FD_ZERO(&fdset); + bjnp_defaults_set_command_header(&cmd, CMD_UDP_DISCOVER, sizeof(cmd.udp_discover)); + + no_sockets = 0; #ifdef HAVE_GETIFADDRS - { - struct ifaddrs *interfaces = NULL; - struct ifaddrs *interface; - getifaddrs (&interfaces); - - /* create a socket for each suitable interface */ - - interface = interfaces; - while ((no_sockets < BJNP_SOCK_MAX) && (interface != NULL)) - { - if ( ! (interface -> ifa_flags & IFF_POINTOPOINT) && - ( (socket_fd[no_sockets] = - prepare_socket( interface -> ifa_name, - (http_addr_t *) interface -> ifa_addr, - (http_addr_t *) interface -> ifa_broadaddr, - &broadcast_addr[no_sockets] ) ) != -1 ) ) - { - /* track highest used socket for later use in select */ - if (socket_fd[no_sockets] > last_socketfd) - { + { + struct ifaddrs *interfaces = NULL; + struct ifaddrs *interface; + getifaddrs(&interfaces); + + /* create a socket for each suitable interface */ + + interface = interfaces; + + while ((no_sockets < BJNP_SOCK_MAX) && (interface != NULL)) { + if (!(interface -> ifa_flags & IFF_POINTOPOINT) && + ((socket_fd[no_sockets] = + prepare_socket(interface -> ifa_name, + (http_addr_t *) interface -> ifa_addr, + (http_addr_t *) interface -> ifa_broadaddr, + &broadcast_addr[no_sockets])) != -1)) { + /* track highest used socket for later use in select */ + if (socket_fd[no_sockets] > last_socketfd) { + last_socketfd = socket_fd[no_sockets]; + } + + FD_SET(socket_fd[no_sockets], &fdset); + no_sockets++; + } + + interface = interface->ifa_next; + } + + freeifaddrs(interfaces); + } +#else + /* we have no easy way to find interfaces with their broadcast addresses. */ + /* use global broadcast and all-hosts instead */ + { + http_addr_t local; + http_addr_t bc_addr; + + memset(&local, 0, sizeof(local)); + local.ipv4.sin_family = AF_INET; + local.ipv4.sin_addr.s_addr = htonl(INADDR_ANY); + + bc_addr.ipv4.sin_family = AF_INET; + bc_addr.ipv4.sin_port = htons(BJNP_PORT_PRINT); + bc_addr.ipv4.sin_addr.s_addr = htonl(INADDR_BROADCAST); + + socket_fd[no_sockets] = prepare_socket("any_interface", + &local, + &bc_addr, + &broadcast_addr[no_sockets]); + + if (socket_fd[no_sockets] >= 0) { + FD_SET(socket_fd[no_sockets], &fdset); + + if (socket_fd[no_sockets] > last_socketfd) { last_socketfd = socket_fd[no_sockets]; - } - FD_SET (socket_fd[no_sockets], &fdset); + } + no_sockets++; - } - interface = interface->ifa_next; - } - freeifaddrs (interfaces); - } -#else - /* we have no easy way to find interfaces with their broadcast addresses. */ - /* use global broadcast and all-hosts instead */ - { - http_addr_t local; - http_addr_t bc_addr; - - memset( &local, 0, sizeof( local) ); - local.ipv4.sin_family = AF_INET; - local.ipv4.sin_addr.s_addr = htonl (INADDR_ANY); - - bc_addr.ipv4.sin_family = AF_INET; - bc_addr.ipv4.sin_port = htons(BJNP_PORT_PRINT); - bc_addr.ipv4.sin_addr.s_addr = htonl (INADDR_BROADCAST); - - socket_fd[no_sockets] = prepare_socket( "any_interface", - &local, - &bc_addr, - &broadcast_addr[no_sockets] ); - if (socket_fd[no_sockets] >= 0) - { - FD_SET (socket_fd[no_sockets], &fdset); - if (socket_fd[no_sockets] > last_socketfd) - { - last_socketfd = socket_fd[no_sockets]; - } - no_sockets++; - } + } + #ifdef ENABLE_IPV6 - local.ipv6.sin6_family = AF_INET6; - local.ipv6.sin6_addr = in6addr_any; - - socket_fd[no_sockets] = prepare_socket( "any_interface", - &local, - NULL, - &broadcast_addr[no_sockets] ); - if (socket_fd[no_sockets] >= 0) - { - FD_SET (socket_fd[no_sockets], &fdset); - if (socket_fd[no_sockets] > last_socketfd) - { - last_socketfd = socket_fd[no_sockets]; - } - no_sockets++; - } -#endif - } -#endif + local.ipv6.sin6_family = AF_INET6; + local.ipv6.sin6_addr = in6addr_any; - /* send BJNP_MAX_BROADCAST_ATTEMPTS broadcasts on each prepared socket */ - for (attempt = 0; attempt < BJNP_MAX_BROADCAST_ATTEMPTS; attempt++) - { - for ( i=0; i < no_sockets; i++) - { - bjnp_send_broadcast ( socket_fd[i], &broadcast_addr[i], cmd, sizeof (cmd.udp_discover)); - } - /* wait for some time between broadcast packets */ - usleep (BJNP_BROADCAST_INTERVAL * USLEEP_MS); + socket_fd[no_sockets] = prepare_socket("any_interface", + &local, + NULL, + &broadcast_addr[no_sockets]); + + if (socket_fd[no_sockets] >= 0) { + FD_SET(socket_fd[no_sockets], &fdset); + + if (socket_fd[no_sockets] > last_socketfd) { + last_socketfd = socket_fd[no_sockets]; + } + + no_sockets++; + } + +#endif /* ENABLE_IPV6 */ } +#endif /* HAVE_GETIFADDRS */ - /* wait for a UDP response */ + /* send BJNP_MAX_BROADCAST_ATTEMPTS broadcasts on each prepared socket */ + for (attempt = 0; attempt < BJNP_MAX_BROADCAST_ATTEMPTS; attempt++) { + for (i = 0; i < no_sockets; i++) { + bjnp_send_broadcast(socket_fd[i], &broadcast_addr[i], cmd, + sizeof(cmd.udp_discover)); + } - timeout.tv_sec = 0; - timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * USLEEP_MS; + /* wait for some time between broadcast packets */ + usleep(BJNP_BROADCAST_INTERVAL * USLEEP_MS); + } + /* wait for a UDP response */ - active_fdset = fdset; + timeout.tv_sec = 0; + timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * USLEEP_MS; - while (select (last_socketfd + 1, &active_fdset, NULL, NULL, &timeout) > 0) - { - bjnp_debug (LOG_DEBUG, "Select returned, time left %d.%d....\n", - (int) timeout.tv_sec, (int) timeout.tv_usec); - for (i = 0; i < no_sockets; i++) - { - if (FD_ISSET (socket_fd[i], &active_fdset)) - { - socklen = sizeof(printer_sa); - if ((numbytes = - recvfrom (socket_fd[i], &disc_resp, sizeof (disc_resp), 0, - &(printer_sa.addr), &socklen ) ) == -1) - { - bjnp_debug - (LOG_INFO, "find_devices: no data received, while socket is ready"); - break; - } - else - { - get_address_info( &printer_sa, host, &port); - bjnp_debug( LOG_DEBUG, "Response received from %s port %d\n", host, port); - bjnp_hexdump (LOG_DEBUG2, "Discover response:\n", &disc_resp, numbytes); - - /* check if something sensible is returned */ - if ( (numbytes < bjnp_header_size ) || - (strncmp ("BJNP", disc_resp.header.BJNP_id, 4) != 0)) - { - /* not a valid response, assume not a printer */ - - char bjnp_id[5]; - strncpy(bjnp_id, disc_resp.header.BJNP_id, 4); - bjnp_id[4] = '\0'; - bjnp_debug (LOG_INFO, - "Invalid discover response! Length = %d, Id = %s\n", - numbytes, bjnp_id ); - break; - } - if ( ! ((disc_resp.header.dev_type) & 0x80) ) - { - /* not a response, a discover command from somebody else or */ - /* a discover command that we generated */ - break; + + active_fdset = fdset; + + while (select(last_socketfd + 1, &active_fdset, NULL, NULL, &timeout) > 0) { + bjnp_debug(LOG_DEBUG, "Select returned, time left %d.%d....\n", + (int) timeout.tv_sec, (int) timeout.tv_usec); + + for (i = 0; i < no_sockets; i++) { + if (FD_ISSET(socket_fd[i], &active_fdset)) { + + socklen = sizeof(printer_sa); + + if ((numbytes = + recvfrom(socket_fd[i], &disc_resp, sizeof(disc_resp), 0, + &(printer_sa.addr), &socklen)) == -1) { + bjnp_debug + (LOG_INFO, "find_devices: no data received, while socket is ready"); + break; + } else { + /* process incoming packet */ + + get_address_info(&printer_sa, host, &port, family); + + bjnp_debug(LOG_DEBUG, "Response received from %s port %d(%s)\n", host, port, + family); + bjnp_hexdump(LOG_DEBUG2, "Discover response:\n", &disc_resp, numbytes); + + /* check if something sensible is returned */ + if ((numbytes < bjnp_header_size) || + (strncmp("BJNP", disc_resp.header.BJNP_id, 4) != 0)) { + /* not a valid response, assume not a printer */ + + char bjnp_id[5]; + strncpy(bjnp_id, disc_resp.header.BJNP_id, 4); + bjnp_id[4] = '\0'; + bjnp_debug(LOG_INFO, + "Invalid discover response! Length = %d, Id = %s\n", + numbytes, bjnp_id); + break; } - }; + if (!((disc_resp.header.dev_type) & 0x80)) { + /* not a response, a discover command from somebody else or */ + /* a discover command that we generated */ + break; + } + }; + + /* valid response, register printer */ + add_printer(&printer_sa, &disc_resp, &no_printers, printers); - add_printer( &printer_sa, &disc_resp, &no_printers, printers); + } + } - } - } - active_fdset = fdset; - timeout.tv_sec = 0; - timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * USLEEP_MS; + active_fdset = fdset; + timeout.tv_sec = 0; + timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * USLEEP_MS; } - bjnp_debug (LOG_DEBUG, "printer discovery finished...\n"); - for (i = 0; i < no_sockets; i++) - close (socket_fd[i]); + bjnp_debug(LOG_DEBUG, "printer discovery finished...\n"); + + for (i = 0; i < no_sockets; i++) { + close(socket_fd[i]); + } - return no_printers; + return no_printers; } |