Added support for IPv6. Updated manpages. Patch from Julien BLACHE

<jb@jblache.org>.
merge-requests/1/head
Henning Geinitz 2003-03-30 19:07:18 +00:00
rodzic e1b27e1c18
commit 088281c4e1
11 zmienionych plików z 1467 dodań i 37 usunięć

Wyświetl plik

@ -2,6 +2,10 @@
* doc/descriptions/unsupported.desc: Added Medion MD 6228, Microtek * doc/descriptions/unsupported.desc: Added Medion MD 6228, Microtek
ScanPort 3000, and PIE Primefilm 1800u. ScanPort 3000, and PIE Primefilm 1800u.
* acinclude.m4 aclocal.m4 configure configure.in backend/net.c
backend/net.h doc/sane-net.man doc/saned.man frontend/saned.c
include/sane/config.h.in: Added support for IPv6. Updated
manpages. Patch from Julien BLACHE <jb@jblache.org>.
2003-03-28 Oliver Schirrmeister <oschirr@abm.de> 2003-03-28 Oliver Schirrmeister <oschirr@abm.de>

Wyświetl plik

@ -12,6 +12,7 @@ dnl JAPHAR_GREP_CFLAGS(flag, cmd_if_missing, cmd_if_present)
dnl SANE_LINKER_RPATH dnl SANE_LINKER_RPATH
dnl SANE_CHECK_U_TYPES dnl SANE_CHECK_U_TYPES
dnl SANE_CHECK_GPHOTO2 dnl SANE_CHECK_GPHOTO2
dnl SANE_CHECK_IPV6
dnl SANE_PROTOTYPES dnl SANE_PROTOTYPES
dnl AC_PROG_LIBTOOL dnl AC_PROG_LIBTOOL
dnl dnl
@ -344,6 +345,45 @@ AC_DEFUN([SANE_CHECK_GPHOTO2],
]) fi ]) fi
]) ])
#
# Check for AF_INET6, determines whether or not to enable IPv6 support
AC_DEFUN([SANE_CHECK_IPV6],
[
AC_MSG_CHECKING([whether to enable IPv6])
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 enable IPv6 (with IPv4) support
--disable-ipv6 disable IPv6 support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
ipv6=no
;;
*) AC_MSG_RESULT(yes)
AC_DEFINE([ENABLE_IPV6], 1, [Define to 1 if the system supports IPv6])
ipv6=yes
;;
esac ],
AC_TRY_COMPILE([
#define INET6
#include <sys/types.h>
#include <sys/socket.h> ], [
/* AF_INET6 available check */
if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
exit(1);
else
exit(0);
],
AC_MSG_RESULT(yes)
AC_DEFINE([ENABLE_IPV6], 1, [Define to 1 if the system supports IPv6])
ipv6=yes,
AC_MSG_RESULT(no)
ipv6=no,
AC_MSG_RESULT(no)
ipv6=no
))
])
# #
# Generate prototypes for functions not available on the system # Generate prototypes for functions not available on the system
AC_DEFUN([SANE_PROTOTYPES], AC_DEFUN([SANE_PROTOTYPES],

40
aclocal.m4 vendored
Wyświetl plik

@ -24,6 +24,7 @@ dnl JAPHAR_GREP_CFLAGS(flag, cmd_if_missing, cmd_if_present)
dnl SANE_LINKER_RPATH dnl SANE_LINKER_RPATH
dnl SANE_CHECK_U_TYPES dnl SANE_CHECK_U_TYPES
dnl SANE_CHECK_GPHOTO2 dnl SANE_CHECK_GPHOTO2
dnl SANE_CHECK_IPV6
dnl SANE_PROTOTYPES dnl SANE_PROTOTYPES
dnl AC_PROG_LIBTOOL dnl AC_PROG_LIBTOOL
dnl dnl
@ -356,6 +357,45 @@ AC_DEFUN([SANE_CHECK_GPHOTO2],
]) fi ]) fi
]) ])
#
# Check for AF_INET6, determines whether or not to enable IPv6 support
AC_DEFUN([SANE_CHECK_IPV6],
[
AC_MSG_CHECKING([whether to enable IPv6])
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 enable IPv6 (with IPv4) support
--disable-ipv6 disable IPv6 support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
ipv6=no
;;
*) AC_MSG_RESULT(yes)
AC_DEFINE([ENABLE_IPV6], 1, [Define to 1 if the system supports IPv6])
ipv6=yes
;;
esac ],
AC_TRY_COMPILE([
#define INET6
#include <sys/types.h>
#include <sys/socket.h> ], [
/* AF_INET6 available check */
if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
exit(1);
else
exit(0);
],
AC_MSG_RESULT(yes)
AC_DEFINE([ENABLE_IPV6], 1, [Define to 1 if the system supports IPv6])
ipv6=yes,
AC_MSG_RESULT(no)
ipv6=no,
AC_MSG_RESULT(no)
ipv6=no
))
])
# #
# Generate prototypes for functions not available on the system # Generate prototypes for functions not available on the system
AC_DEFUN([SANE_PROTOTYPES], AC_DEFUN([SANE_PROTOTYPES],

Wyświetl plik

@ -1,5 +1,8 @@
/* sane - Scanner Access Now Easy. /* sane - Scanner Access Now Easy.
Copyright (C) 1997 David Mosberger-Tang Copyright (C) 1997 David Mosberger-Tang
Copyright (C) 2003 Julien BLACHE <jb@jblache.org>
AF-independent code + IPv6
This file is part of the SANE package. This file is part of the SANE package.
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
@ -40,10 +43,6 @@
This file implements a SANE network-based meta backend. */ This file implements a SANE network-based meta backend. */
/* Please increase version number with every change
(don't forget to update net.desc) */
#define NET_VERSION "1.0.10"
#ifdef _AIX #ifdef _AIX
# include "../include/lalloca.h" /* MUST come first for AIX! */ # include "../include/lalloca.h" /* MUST come first for AIX! */
#endif #endif
@ -83,15 +82,34 @@
#include "../include/sane/sanei_config.h" #include "../include/sane/sanei_config.h"
#define NET_CONFIG_FILE "net.conf" #define NET_CONFIG_FILE "net.conf"
/* Please increase version number with every change
(don't forget to update net.desc) */
/* define the version string depending on which network code is used */
#if defined (HAVE_GETADDRINFO) && defined (HAVE_GETNAMEINFO)
# define NET_USES_AF_INDEP
# ifdef ENABLE_IPV6
# define NET_VERSION "1.0.11 (AF-indep+IPv6)"
# else
# define NET_VERSION "1.0.11 (AF-indep)"
# endif /* ENABLE_IPV6 */
#else
# undef ENABLE_IPV6
# define NET_VERSION "1.0.11"
#endif /* HAVE_GETADDRINFO && HAVE_GETNAMEINFO */
static SANE_Auth_Callback auth_callback; static SANE_Auth_Callback auth_callback;
static Net_Device *first_device; static Net_Device *first_device;
static Net_Scanner *first_handle; static Net_Scanner *first_handle;
static const SANE_Device **devlist; static const SANE_Device **devlist;
static int saned_port;
static int client_big_endian; /* 1 == big endian; 0 == little endian */ static int client_big_endian; /* 1 == big endian; 0 == little endian */
static int server_big_endian; /* 1 == big endian; 0 == little endian */ static int server_big_endian; /* 1 == big endian; 0 == little endian */
static int depth; /* bits per pixel */ static int depth; /* bits per pixel */
#ifndef NET_USES_AF_INDEP
static int saned_port;
#endif /* !NET_USES_AF_INDEP */
/* This variable is only needed, if the depth is 16bit/channel and /* This variable is only needed, if the depth is 16bit/channel and
client/server have different endianness. A value of -1 means, that there's client/server have different endianness. A value of -1 means, that there's
no hang over; otherwise the value has to be casted to SANE_Byte. hang_over no hang over; otherwise the value has to be casted to SANE_Byte. hang_over
@ -110,6 +128,99 @@ static int hang_over;
*/ */
static int left_over; static int left_over;
#ifdef NET_USES_AF_INDEP
static SANE_Status
add_device (const char *name, Net_Device ** ndp)
{
struct addrinfo hints;
struct addrinfo *res;
struct addrinfo *resp;
struct sockaddr_in *sin;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *sin6;
#endif /* ENABLE_IPV6 */
Net_Device *nd = NULL;
int error;
short sane_port = htons (6566);
DBG (1, "add_device: adding backend %s\n", name);
memset (&hints, 0, sizeof(hints));
# ifdef ENABLE_IPV6
hints.ai_family = PF_UNSPEC;
# else
hints.ai_family = PF_INET;
# endif /* ENABLE_IPV6 */
error = getaddrinfo (name, "sane", &hints, &res);
if (error)
{
error = getaddrinfo (name, NULL, &hints, &res);
if (error)
{
DBG (1, "add_device: error while getting address of host %s: %s\n",
name, gai_strerror (error));
return SANE_STATUS_IO_ERROR;
}
else
{
for (resp = res; resp != NULL; resp = resp->ai_next)
{
switch (resp->ai_family)
{
case AF_INET:
sin = (struct sockaddr_in *) resp->ai_addr;
sin->sin_port = sane_port;
break;
#ifdef ENABLE_IPV6
case AF_INET6:
sin6 = (struct sockaddr_in6 *) resp->ai_addr;
sin6->sin6_port = sane_port;
break;
#endif /* ENABLE_IPV6 */
}
}
}
}
nd = malloc (sizeof (Net_Device));
if (!nd)
{
DBG (1, "add_device: not enough memory for Net_Device struct\n");
freeaddrinfo (res);
return SANE_STATUS_NO_MEM;
}
memset (nd, 0, sizeof (Net_Device));
nd->name = strdup (name);
if (!nd->name)
{
DBG (1, "add_device: not enough memory to duplicate name\n");
free(nd);
return SANE_STATUS_NO_MEM;
}
nd->addr = res;
nd->ctl = -1;
nd->next = first_device;
first_device = nd;
if (ndp)
*ndp = nd;
DBG (2, "add_device: backend %s added\n", name);
return SANE_STATUS_GOOD;
}
#else /* !NET_USES_AF_INDEP */
static SANE_Status static SANE_Status
add_device (const char *name, Net_Device ** ndp) add_device (const char *name, Net_Device ** ndp)
{ {
@ -161,6 +272,69 @@ add_device (const char *name, Net_Device ** ndp)
DBG (2, "add_device: backend %s added\n", name); DBG (2, "add_device: backend %s added\n", name);
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
#endif /* NET_USES_AF_INDEP */
#ifdef NET_USES_AF_INDEP
static SANE_Status
connect_dev (Net_Device * dev)
{
struct addrinfo *addrp;
SANE_Word version_code;
SANE_Init_Reply reply;
SANE_Status status = SANE_STATUS_IO_ERROR;
SANE_Init_Req req;
SANE_Bool connected = SANE_FALSE;
#ifdef TCP_NODELAY
int on = 1;
int level = -1;
#endif
int i;
DBG (2, "connect_dev: trying to connect to %s\n", dev->name);
for (addrp = dev->addr, i = 0; (addrp != NULL) && (connected == SANE_FALSE); addrp = addrp->ai_next, i++)
{
# ifdef ENABLE_IPV6
if ((addrp->ai_family != AF_INET) && (addrp->ai_family != AF_INET6))
# else /* !ENABLE_IPV6 */
if (addrp->ai_family != AF_INET)
# endif /* ENABLE_IPV6 */
{
DBG (1, "connect_dev: [%d] don't know how to deal with addr family %d\n",
i, addrp->ai_family);
break;
}
dev->ctl = socket (addrp->ai_family, SOCK_STREAM, 0);
if (dev->ctl < 0)
{
DBG (1, "connect_dev: [%d] failed to obtain socket (%s)\n",
i, strerror (errno));
dev->ctl = -1;
break;
}
if (connect (dev->ctl, addrp->ai_addr, addrp->ai_addrlen) < 0)
{
DBG (1, "connect_dev: [%d] failed to connect (%s)\n", i, strerror (errno));
dev->ctl = -1;
break;
}
DBG (3, "connect_dev: [%d] connection succeeded (%s)\n", i, (addrp->ai_family == AF_INET6) ? "IPv6" : "IPv4");
dev->addr_used = addrp;
connected = SANE_TRUE;
}
if (connected != SANE_TRUE)
{
DBG (1, "connect_dev: couldn't connect to host (see messages above)\n");
return SANE_STATUS_IO_ERROR;
}
#else /* !NET_USES_AF_INDEP */
static SANE_Status static SANE_Status
connect_dev (Net_Device * dev) connect_dev (Net_Device * dev)
@ -202,6 +376,7 @@ connect_dev (Net_Device * dev)
return SANE_STATUS_IO_ERROR; return SANE_STATUS_IO_ERROR;
} }
DBG (3, "connect_dev: connection succeeded\n"); DBG (3, "connect_dev: connection succeeded\n");
#endif /* NET_USES_AF_INDEP */
#ifdef TCP_NODELAY #ifdef TCP_NODELAY
# ifdef SOL_TCP # ifdef SOL_TCP
@ -288,6 +463,7 @@ fail:
return status; return status;
} }
static SANE_Status static SANE_Status
fetch_options (Net_Scanner * s) fetch_options (Net_Scanner * s)
{ {
@ -444,13 +620,16 @@ SANE_Status
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
{ {
char device_name[PATH_MAX]; char device_name[PATH_MAX];
struct servent *serv;
const char *env; const char *env;
size_t len; size_t len;
FILE *fp; FILE *fp;
short ns = 0x1234; short ns = 0x1234;
unsigned char *p = (unsigned char *)(&ns); unsigned char *p = (unsigned char *)(&ns);
#ifndef NET_USES_AF_INDEP
struct servent *serv;
#endif /* !NET_USES_AF_INDEP */
DBG_INIT (); DBG_INIT ();
DBG (2, "sane_init: authorize = %p, version_code = %p\n", authorize, DBG (2, "sane_init: authorize = %p, version_code = %p\n", authorize,
@ -484,6 +663,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
DBG (3, "sane_init: Client has little endian byte order\n"); DBG (3, "sane_init: Client has little endian byte order\n");
} }
#ifndef NET_USES_AF_INDEP
DBG (2, "sane_init: determining sane service port\n"); DBG (2, "sane_init: determining sane service port\n");
serv = getservbyname ("sane", "tcp"); serv = getservbyname ("sane", "tcp");
@ -498,6 +678,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
DBG (1, "sane_init: could not find `sane' service (%s); using default " DBG (1, "sane_init: could not find `sane' service (%s); using default "
"port %d\n", strerror (errno), ntohs (saned_port)); "port %d\n", strerror (errno), ntohs (saned_port));
} }
#endif /* !NET_USES_AF_INDEP */
DBG (2, "sane_init: searching for config file\n"); DBG (2, "sane_init: searching for config file\n");
fp = sanei_config_open (NET_CONFIG_FILE); fp = sanei_config_open (NET_CONFIG_FILE);
@ -533,6 +714,30 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
next = copy; next = copy;
while ((host = strsep (&next, ":"))) while ((host = strsep (&next, ":")))
{ {
#ifdef ENABLE_IPV6
if (host[0] == '[')
{
/* skip '[' (host[0]) */
host++;
/* get the rest of the IPv6 addr (we're screwed if ] is missing)
* Is it worth checking for the matching ] ? Not for now. */
strsep (&next, "]");
/* add back the ":" that got removed by the strsep() */
host[strlen (host)] = ':';
/* host now holds the IPv6 address */
/* skip the ':' that could be after ] (avoids a call to strsep() */
if (next[0] == ':')
next++;
}
/*
* if the IPv6 is last in the list, the strsep() call in the while()
* will return a string with the first char being '\0'. Skip it.
*/
if (host[0] == '\0')
continue;
#endif /* ENABLE_IPV6 */
DBG (2, "sane_init: trying to add %s\n", host); DBG (2, "sane_init: trying to add %s\n", host);
add_device (host, 0); add_device (host, 0);
} }
@ -580,6 +785,12 @@ sane_exit (void)
} }
if (dev->name) if (dev->name)
free ((void *) dev->name); free ((void *) dev->name);
#ifdef NET_USES_AF_INDEP
if (dev->addr)
freeaddrinfo(dev->addr);
#endif /* NET_USES_AF_INDEP */
free (dev); free (dev);
} }
if (devlist) if (devlist)
@ -693,11 +904,23 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
{ {
SANE_Device *rdev; SANE_Device *rdev;
char *mem; char *mem;
#ifdef ENABLE_IPV6
SANE_Bool IPv6 = SANE_FALSE;
#endif /* ENABLE_IPV6 */
/* create a new device entry with a device name that is the /* create a new device entry with a device name that is the
sum of the backend name a colon and the backend's device sum of the backend name a colon and the backend's device
name: */ name: */
len = strlen (dev->name) + 1 + strlen (reply.device_list[i]->name); len = strlen (dev->name) + 1 + strlen (reply.device_list[i]->name);
#ifdef ENABLE_IPV6
if (strchr (dev->name, ':') != NULL)
{
len += 2;
IPv6 = SANE_TRUE;
}
#endif /* ENABLE_IPV6 */
mem = malloc (sizeof (*dev) + len + 1); mem = malloc (sizeof (*dev) + len + 1);
if (!mem) if (!mem)
{ {
@ -707,8 +930,22 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
&reply); &reply);
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} }
memset (mem, 0, sizeof (*dev) + len);
full_name = mem + sizeof (*dev); full_name = mem + sizeof (*dev);
strcpy (full_name, dev->name);
#ifdef ENABLE_IPV6
if (IPv6 == SANE_TRUE)
strcat (full_name, "[");
#endif /* ENABLE_IPV6 */
strcat (full_name, dev->name);
#ifdef ENABLE_IPV6
if (IPv6 == SANE_TRUE)
strcat (full_name, "]");
#endif /* ENABLE_IPV6 */
strcat (full_name, ":"); strcat (full_name, ":");
strcat (full_name, reply.device_list[i]->name); strcat (full_name, reply.device_list[i]->name);
DBG (3, "sane_get_devices: got %s\n", full_name); DBG (3, "sane_get_devices: got %s\n", full_name);
@ -723,11 +960,11 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
{ {
DBG (1, "sane_get_devices: not enough free memory\n"); DBG (1, "sane_get_devices: not enough free memory\n");
if (rdev->vendor) if (rdev->vendor)
free (rdev->vendor); free ((void *) rdev->vendor);
if (rdev->model) if (rdev->model)
free (rdev->model); free ((void *) rdev->model);
if (rdev->type) if (rdev->type)
free (rdev->type); free ((void *) rdev->type);
free (rdev); free (rdev);
sanei_w_free (&dev->wire, sanei_w_free (&dev->wire,
(WireCodecFunc) sanei_w_get_devices_reply, (WireCodecFunc) sanei_w_get_devices_reply,
@ -756,6 +993,10 @@ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
{ {
SANE_Open_Reply reply; SANE_Open_Reply reply;
const char *dev_name; const char *dev_name;
#ifdef ENABLE_IPV6
const char *tmp_name;
SANE_Bool v6addr = SANE_FALSE;
#endif /* ENABLE_IPV6 */
SANE_String nd_name; SANE_String nd_name;
SANE_Status status; SANE_Status status;
SANE_Word handle; SANE_Word handle;
@ -764,12 +1005,46 @@ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
int need_auth; int need_auth;
DBG (3, "sane_open(\"%s\")\n", full_name); DBG (3, "sane_open(\"%s\")\n", full_name);
#ifdef ENABLE_IPV6
/*
* Check whether a numerical IPv6 host was specified
* [2001:42:42::12] <== check for '[' as full_name[0]
* ex: [2001:42:42::12]:test:0 (syntax taken from Apache 2)
*/
if (full_name[0] == '[')
{
v6addr = SANE_TRUE;
tmp_name = strchr (full_name, ']');
if (!tmp_name)
{
DBG (1, "sane_open: incorrect host address: missing matching ']'\n");
return SANE_STATUS_INVAL;
}
}
else
tmp_name = full_name;
dev_name = strchr (tmp_name, ':');
#else /* !ENABLE_IPV6 */
dev_name = strchr (full_name, ':');
#endif /* ENABLE_IPV6 */
dev_name = strchr (full_name, ':');
if (dev_name) if (dev_name)
{ {
#ifdef strndupa #ifdef strndupa
# ifdef ENABLE_IPV6
if (v6addr == SANE_TRUE)
nd_name = strndupa (full_name + 1, dev_name - full_name - 2);
else
nd_name = strndupa (full_name, dev_name - full_name);
# else /* !ENABLE_IPV6 */
nd_name = strndupa (full_name, dev_name - full_name); nd_name = strndupa (full_name, dev_name - full_name);
# endif /* ENABLE_IPV6 */
if (!nd_name) if (!nd_name)
{ {
DBG (1, "sane_open: not enough free memory\n"); DBG (1, "sane_open: not enough free memory\n");
@ -778,14 +1053,41 @@ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
#else #else
char *tmp; char *tmp;
# ifdef ENABLE_IPV6
if (v6addr == SANE_TRUE)
tmp = alloca (dev_name - full_name - 2 + 1);
else
tmp = alloca (dev_name - full_name + 1);
# else /* !ENABLE_IPV6 */
tmp = alloca (dev_name - full_name + 1); tmp = alloca (dev_name - full_name + 1);
# endif /* ENABLE_IPV6 */
if (!tmp) if (!tmp)
{ {
DBG (1, "sane_open: not enough free memory\n"); DBG (1, "sane_open: not enough free memory\n");
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} }
# ifdef ENABLE_IPV6
if (v6addr == SANE_TRUE)
{
memcpy (tmp, full_name + 1, dev_name - full_name - 2);
tmp[dev_name - full_name - 2] = '\0';
}
else
{
memcpy (tmp, full_name, dev_name - full_name);
tmp[dev_name - full_name] = '\0';
}
# else /* !ENABLE_IPV6 */
memcpy (tmp, full_name, dev_name - full_name); memcpy (tmp, full_name, dev_name - full_name);
tmp[dev_name - full_name] = '\0'; tmp[dev_name - full_name] = '\0';
# endif /* ENABLE_IPV6 */
nd_name = tmp; nd_name = tmp;
#endif #endif
++dev_name; /* skip colon */ ++dev_name; /* skip colon */
@ -795,7 +1097,26 @@ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
/* if no colon interpret full_name as the host name; an empty /* if no colon interpret full_name as the host name; an empty
device name will cause us to open the first device of that device name will cause us to open the first device of that
host. */ host. */
#ifdef ENABLE_IPV6
if (v6addr == SANE_TRUE)
{
nd_name = alloca (strlen (full_name) - 2 + 1);
if (!nd_name)
{
DBG (1, "sane_open: not enough free memory\n");
return SANE_STATUS_NO_MEM;
}
memcpy (nd_name, full_name + 1, strlen (full_name) - 2);
nd_name[strlen (full_name) - 2] = '\0';
}
else
nd_name = (char *) full_name;
#else /* !ENABLE_IPV6 */
nd_name = (char *) full_name; nd_name = (char *) full_name;
#endif /* ENABLE_IPV6 */
dev_name = ""; dev_name = "";
} }
DBG (2, "sane_open: host = %s, device = %s\n", nd_name, dev_name); DBG (2, "sane_open: host = %s, device = %s\n", nd_name, dev_name);
@ -1136,6 +1457,146 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
return status; return status;
} }
#ifdef NET_USES_AF_INDEP
SANE_Status
sane_start (SANE_Handle handle)
{
Net_Scanner *s = handle;
SANE_Start_Reply reply;
struct sockaddr_in sin;
struct sockaddr *sa;
#ifdef ENABLE_IPV6
struct sockaddr_in6 sin6;
#endif /* ENABLE_IPV6 */
SANE_Status status;
int fd, need_auth;
socklen_t len;
u_int16_t port; /* Internet-specific */
DBG (3, "sane_start\n");
hang_over = -1;
left_over = -1;
if (s->data >= 0)
{
DBG (2, "sane_start: data pipe already exists\n");
return SANE_STATUS_INVAL;
}
/* Do this ahead of time so in case anything fails, we can
recover gracefully (without hanging our server). */
switch (s->hw->addr_used->ai_family)
{
case AF_INET:
len = sizeof (sin);
sa = (struct sockaddr *) &sin;
break;
#ifdef ENABLE_IPV6
case AF_INET6:
len = sizeof (sin6);
sa = (struct sockaddr *) &sin6;
break;
#endif /* ENABLE_IPV6 */
default:
DBG (1, "sane_start: unknown address family : %d\n",
s->hw->addr_used->ai_family);
return SANE_STATUS_INVAL;
}
if (getpeername (s->hw->ctl, sa, &len) < 0)
{
DBG (1, "sane_start: getpeername() failed (%s)\n", strerror (errno));
return SANE_STATUS_IO_ERROR;
}
fd = socket (s->hw->addr_used->ai_family, SOCK_STREAM, 0);
if (fd < 0)
{
DBG (1, "sane_start: socket() failed (%s)\n", strerror (errno));
return SANE_STATUS_IO_ERROR;
}
DBG (3, "sane_start: remote start\n");
sanei_w_call (&s->hw->wire, SANE_NET_START,
(WireCodecFunc) sanei_w_word, &s->handle,
(WireCodecFunc) sanei_w_start_reply, &reply);
do
{
status = reply.status;
port = reply.port;
if (reply.byte_order == 0x1234)
{
server_big_endian = 0;
DBG (1, "sane_start: server has little endian byte order\n");
}
else
{
server_big_endian = 1;
DBG (1, "sane_start: server has big endian byte order\n");
}
need_auth = (reply.resource_to_authorize != 0);
if (need_auth)
{
DBG (3, "sane_start: auth required\n");
do_authorization (s->hw, reply.resource_to_authorize);
sanei_w_free (&s->hw->wire,
(WireCodecFunc) sanei_w_start_reply, &reply);
sanei_w_set_dir (&s->hw->wire, WIRE_DECODE);
sanei_w_start_reply (&s->hw->wire, &reply);
continue;
}
sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_start_reply,
&reply);
if (need_auth && !s->hw->auth_active)
return SANE_STATUS_CANCELLED;
if (status != SANE_STATUS_GOOD)
{
DBG (1, "sane_start: remote start failed (%s)\n",
sane_strstatus (status));
close (fd);
return status;
}
}
while (need_auth);
DBG (3, "sane_start: remote start finished, data at port %hu\n", port);
switch (s->hw->addr_used->ai_family)
{
case AF_INET:
sin.sin_port = htons (port);
break;
#ifdef ENABLE_IPV6
case AF_INET6:
sin6.sin6_port = htons (port);
break;
#endif /* ENABLE_IPV6 */
}
if (connect (fd, sa, len) < 0)
{
DBG (1, "sane_start: connect() failed (%s)\n", strerror (errno));
close (fd);
return SANE_STATUS_IO_ERROR;
}
shutdown (fd, 1);
s->data = fd;
s->reclen_buf_offset = 0;
s->bytes_remaining = 0;
DBG (3, "sane_start: done (%s)\n", sane_strstatus (status));
return status;
}
#else /* !NET_USES_AF_INDEP */
SANE_Status SANE_Status
sane_start (SANE_Handle handle) sane_start (SANE_Handle handle)
{ {
@ -1240,6 +1701,8 @@ sane_start (SANE_Handle handle)
DBG (3, "sane_start: done (%s)\n", sane_strstatus (status)); DBG (3, "sane_start: done (%s)\n", sane_strstatus (status));
return status; return status;
} }
#endif /* NET_USES_AF_INDEP */
SANE_Status SANE_Status
sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,

Wyświetl plik

@ -1,5 +1,8 @@
/* sane - Scanner Access Now Easy. /* sane - Scanner Access Now Easy.
Copyright (C) 1997 David Mosberger-Tang Copyright (C) 1997 David Mosberger-Tang
Copyright (C) 2003 Julien BLACHE <jb@jblache.org>
AF-independent code + IPv6
This file is part of the SANE package. This file is part of the SANE package.
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
@ -44,12 +47,18 @@
#include <sys/socket.h> #include <sys/socket.h>
#include "../include/sane/sanei_wire.h" #include "../include/sane/sanei_wire.h"
#include "../include/sane/config.h"
typedef struct Net_Device typedef struct Net_Device
{ {
struct Net_Device *next; struct Net_Device *next;
const char *name; const char *name;
#if defined (HAVE_GETADDRINFO) && defined (HAVE_GETNAMEINFO)
struct addrinfo *addr;
struct addrinfo *addr_used;
#else
struct sockaddr addr; struct sockaddr addr;
#endif /* HAVE_GETADDRINFO && HAVE_GETNAMEINFO */
int ctl; /* socket descriptor (or -1) */ int ctl; /* socket descriptor (or -1) */
Wire wire; Wire wire;
int auth_active; int auth_active;

101
configure vendored
Wyświetl plik

@ -1011,6 +1011,8 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-warnings turn on tons of compiler warnings (GCC only) --enable-warnings turn on tons of compiler warnings (GCC only)
--enable-ipv6 enable IPv6 (with IPv4) support
--disable-ipv6 disable IPv6 support
--enable-static=PKGS build static libraries default=no --enable-static=PKGS build static libraries default=no
--enable-shared=PKGS build shared libraries default=yes --enable-shared=PKGS build shared libraries default=yes
--enable-fast-install=PKGS optimize for fast installation default=yes --enable-fast-install=PKGS optimize for fast installation default=yes
@ -8013,9 +8015,12 @@ rm -f conftest.mmap
for ac_func in atexit inet_addr inet_aton inet_ntoa ioperm mkdir \ for ac_func in atexit inet_addr inet_aton inet_ntoa ioperm mkdir \
scsireq_enter strftime strstr strtod \ scsireq_enter strftime strstr strtod \
cfmakeraw tcsendbreak strcasecmp strncasecmp _portaccess cfmakeraw tcsendbreak strcasecmp strncasecmp _portaccess \
getaddrinfo getnameinfo
do do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5 echo "$as_me:$LINENO: checking for $ac_func" >&5
@ -8298,6 +8303,90 @@ _ACEOF
fi fi
if test "$ac_cv_func_getnameinfo" = "yes" && test "$ac_cv_func_getaddrinfo" = "yes" ; then
echo "$as_me:$LINENO: checking whether to enable IPv6" >&5
echo $ECHO_N "checking whether to enable IPv6... $ECHO_C" >&6
# Check whether --enable-ipv6 or --disable-ipv6 was given.
if test "${enable_ipv6+set}" = set; then
enableval="$enable_ipv6"
case "$enableval" in
no)
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
ipv6=no
;;
*) echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
cat >>confdefs.h <<\_ACEOF
#define ENABLE_IPV6 1
_ACEOF
ipv6=yes
;;
esac
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#define INET6
#include <sys/types.h>
#include <sys/socket.h>
int
main ()
{
/* AF_INET6 available check */
if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
exit(1);
else
exit(0);
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6
cat >>confdefs.h <<\_ACEOF
#define ENABLE_IPV6 1
_ACEOF
ipv6=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6
ipv6=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi;
else
ipv6="no"
fi
# Check whether --enable-static or --disable-static was given. # Check whether --enable-static or --disable-static was given.
if test "${enable_static+set}" = set; then if test "${enable_static+set}" = set; then
@ -9475,7 +9564,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
case $host in case $host in
*-*-irix6*) *-*-irix6*)
# Find out which ABI we are using. # Find out which ABI we are using.
echo '#line 9478 "configure"' > conftest.$ac_ext echo '#line 9567 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5 (eval $ac_compile) 2>&5
ac_status=$? ac_status=$?
@ -10004,7 +10093,7 @@ chmod -w .
save_CFLAGS="$CFLAGS" save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
compiler_c_o=no compiler_c_o=no
if { (eval echo configure:10007: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then if { (eval echo configure:10096: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
# The compiler can only warn and ignore the option if not recognized # The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings # So say no if there are warnings
if test -s out/conftest.err; then if test -s out/conftest.err; then
@ -11836,7 +11925,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 11839 "configure" #line 11928 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@ -11934,7 +12023,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 11937 "configure" #line 12026 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@ -14026,6 +14115,8 @@ echo "Configuration: `eval eval echo ${sysconfdir}`"
echo "Libraries: `eval eval echo ${libdir}`" echo "Libraries: `eval eval echo ${libdir}`"
echo "Binaries: `eval eval echo ${bindir}` and `eval eval echo ${sbindir}`" echo "Binaries: `eval eval echo ${bindir}` and `eval eval echo ${sbindir}`"
echo "Manpages: `eval eval echo ${mandir}`" echo "Manpages: `eval eval echo ${mandir}`"
echo "Network parameters:"
echo "IPv6 support: `eval eval echo ${ipv6}`"
if test "$SANE_CONFIG_PATH" != "no" ; then if test "$SANE_CONFIG_PATH" != "no" ; then
SANE_INSTALLED_VERSION=`$SANE_CONFIG_PATH --version` SANE_INSTALLED_VERSION=`$SANE_CONFIG_PATH --version`

Wyświetl plik

@ -180,7 +180,8 @@ AC_FUNC_ALLOCA
AC_FUNC_MMAP AC_FUNC_MMAP
AC_CHECK_FUNCS(atexit inet_addr inet_aton inet_ntoa ioperm mkdir \ AC_CHECK_FUNCS(atexit inet_addr inet_aton inet_ntoa ioperm mkdir \
scsireq_enter strftime strstr strtod \ scsireq_enter strftime strstr strtod \
cfmakeraw tcsendbreak strcasecmp strncasecmp _portaccess) cfmakeraw tcsendbreak strcasecmp strncasecmp _portaccess \
getaddrinfo getnameinfo)
AC_REPLACE_FUNCS(getenv inet_ntop inet_pton isfdtype sigprocmask snprintf \ AC_REPLACE_FUNCS(getenv inet_ntop inet_pton isfdtype sigprocmask snprintf \
strdup strndup strsep usleep vsyslog) strdup strndup strsep usleep vsyslog)
SANE_PROTOTYPES SANE_PROTOTYPES
@ -208,6 +209,13 @@ if sparc64 -q > /dev/null 2>&1 ; then
AC_DEFINE(DISABLE_LINUX_SG_IO, 1, [Should we disable SCSI generic v3?]) AC_DEFINE(DISABLE_LINUX_SG_IO, 1, [Should we disable SCSI generic v3?])
fi fi
dnl check for IPv6 (can be overriden by --enable-ipv6)
if test "$ac_cv_func_getnameinfo" = "yes" && test "$ac_cv_func_getaddrinfo" = "yes" ; then
SANE_CHECK_IPV6
else
ipv6="no"
fi
dnl *********************************************************************** dnl ***********************************************************************
dnl initialize libtool dnl initialize libtool
dnl *********************************************************************** dnl ***********************************************************************
@ -433,6 +441,8 @@ echo "Configuration: `eval eval echo ${sysconfdir}`"
echo "Libraries: `eval eval echo ${libdir}`" echo "Libraries: `eval eval echo ${libdir}`"
echo "Binaries: `eval eval echo ${bindir}` and `eval eval echo ${sbindir}`" echo "Binaries: `eval eval echo ${bindir}` and `eval eval echo ${sbindir}`"
echo "Manpages: `eval eval echo ${mandir}`" echo "Manpages: `eval eval echo ${mandir}`"
echo "Network parameters:"
echo "IPv6 support: `eval eval echo ${ipv6}`"
if test "$SANE_CONFIG_PATH" != "no" ; then if test "$SANE_CONFIG_PATH" != "no" ; then
SANE_INSTALLED_VERSION=`$SANE_CONFIG_PATH --version` SANE_INSTALLED_VERSION=`$SANE_CONFIG_PATH --version`

Wyświetl plik

@ -20,7 +20,7 @@ This backend expects device names of the form:
.PP .PP
Where Where
.I host .I host
is the name of the (remote-) host and is the name (or IP address) of the (remote-) host and
.I device .I device
is the name of the device on this host that should be addressed. is the name of the device on this host that should be addressed.
If the device name does not contain a colon (:), then the entire string If the device name does not contain a colon (:), then the entire string
@ -28,35 +28,50 @@ is treated as the
.I device .I device
string for the default host. The default host is the host listed last string for the default host. The default host is the host listed last
in the configuration file (see below). in the configuration file (see below).
.PP
An IPv6 address can be specified enclosed in square brackets:
.PP
.RS
.IR [::1] : device
.RE
.SH CONFIGURATION .SH CONFIGURATION
The contents of the The contents of the
.IR net.conf . .IR net.conf
file is a list of host names that should be contacted for file is a list of host names (or IP addresses) that should be contacted for
scan requests. Empty lines and lines starting with a hash mark (#) are scan requests. Empty lines and lines starting with a hash mark (#) are
ignored. A sample configuration file is shown below: ignored. Note that IPv6 addresses in this file do not need to be enclosed
in square brackets. A sample configuration file is shown below:
.PP .PP
.RS .RS
scan-server.somedomain.firm scan-server.somedomain.firm
.br .br
192.168.0.1
.br
# this is a comment # this is a comment
.br .br
localhost localhost
.br
::1
.RE .RE
.PP .PP
The above list of host names can be extended at run-time using environment The above list of hosts can be extended at run-time using environment
variable variable
.BR SANE_NET_HOSTS . .BR SANE_NET_HOSTS .
This environment variable is a colon-separated list of hostnames that This environment variable is a colon-separated list of hostnames or IP
should be contacted in addition to the hosts mentioned in the addresses that should be contacted in addition to the hosts mentioned in
configuration file. For example, a user could set the environment the configuration file. For example, a user could set the environment
variable to the string: variable to the string:
.PP .PP
.RS .RS
new.scanner.com:scanner.univ.edu new.scanner.com:[::1]:192.168.0.2:scanner.univ.edu
.RE .RE
.PP .PP
To request that hosts To request that hosts
.I new.scanner.com .I new.scanner.com
,
.I [::1]
,
.I 192.168.0.2
and and
.I scanner.univ.edu .I scanner.univ.edu
are contacted in addition to the hosts listed above. are contacted in addition to the hosts listed above.
@ -65,7 +80,7 @@ For this backend to function properly, it is also necessary to define the
.B sane .B sane
service in service in
.IR /etc/services . .IR /etc/services .
At present, the The
.B sane .B sane
service should be defined using a line of the following form: service should be defined using a line of the following form:
.PP .PP
@ -103,7 +118,8 @@ to "/tmp/config:" would result in directories "tmp/config", ".", and
"@CONFIGDIR@" being searched (in this order). "@CONFIGDIR@" being searched (in this order).
.TP .TP
.B SANE_NET_HOSTS .B SANE_NET_HOSTS
A colon-separated list of host names to be contacted by this backend. A colon-separated list of host names or IP addresses to be contacted by this
backend.
.TP .TP
.B SANE_DEBUG_NET .B SANE_DEBUG_NET
If the library was compiled with debug support enabled, this If the library was compiled with debug support enabled, this

Wyświetl plik

@ -68,15 +68,22 @@ scan-client.somedomain.firm
# this is a comment # this is a comment
.br .br
192.168.0.1 192.168.0.1
.br
::1
.RE .RE
.PP .PP
The case of the host names does not matter, so AHost.COM is considered The case of the host names does not matter, so AHost.COM is considered
identical to ahost.com. identical to ahost.com. IPv6 addresses should always be specified in their
compressed form.
For For
.B saned .B saned
to work properly, it is also necessary to add a configuration line to to work properly, it is also necessary to add a configuration line to
.IR /etc/inetd.conf . .IR /etc/inetd.conf .
Note that your inetd must support IPv6 if you
want to connect to saned over IPv6 ; xinetd and openbsd-inetd are known to
support IPv6, check the documentation for your inetd daemon.
.PP
The configuration line normally looks like this: The configuration line normally looks like this:
.PP .PP
.RS .RS

Wyświetl plik

@ -1,6 +1,9 @@
/* sane - Scanner Access Now Easy. /* sane - Scanner Access Now Easy.
Copyright (C) 1997 Andreas Beck Copyright (C) 1997 Andreas Beck
Copyright (C) 2001, 2002 Henning Meier-Geinitz Copyright (C) 2001, 2002 Henning Meier-Geinitz
Copyright (C) 2003 Julien BLACHE <jb@jblache.org>
AF-independent + IPv6 code
This file is part of the SANE package. This file is part of the SANE package.
SANE is free software; you can redistribute it and/or modify it under SANE is free software; you can redistribute it and/or modify it under
@ -54,6 +57,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/poll.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -74,12 +78,26 @@
# define IN_LOOPBACK(addr) (addr == 0x7f000001L) # define IN_LOOPBACK(addr) (addr == 0x7f000001L)
#endif #endif
#ifdef ENABLE_IPV6
# define SANE_IN6_IS_ADDR_LOOPBACK(a) \
(((const uint32_t *) (a))[0] == 0 \
&& ((const uint32_t *) (a))[1] == 0 \
&& ((const uint32_t *) (a))[2] == 0 \
&& ((const uint32_t *) (a))[3] == htonl (1))
#endif /* ENABLE_IPV6 */
#ifndef MAXHOSTNAMELEN #ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN 120 # define MAXHOSTNAMELEN 120
#endif #endif
#define SANED_CONFIG_FILE "saned.conf" #define SANED_CONFIG_FILE "saned.conf"
#if defined(HAVE_GETADDRINFO) && defined (HAVE_GETNAMEINFO)
# define SANED_USES_AF_INDEP
#else
# undef ENABLE_IPV6
#endif /* HAVE_GETADDRINFO && HAVE_GETNAMEINFO */
typedef struct typedef struct
{ {
u_int inuse:1; /* is this handle in use? */ u_int inuse:1; /* is this handle in use? */
@ -107,8 +125,14 @@ byte_order;
it does is save a remote user some work by reducing the amount of it does is save a remote user some work by reducing the amount of
text s/he has to type when authentication is requested. */ text s/he has to type when authentication is requested. */
static const char *default_username = "saned-user"; static const char *default_username = "saned-user";
static char *remote_hostname; static char *remote_ip;
#ifdef SANED_USES_AF_INDEP
static struct sockaddr_storage remote_address;
static int remote_address_len;
#else
static struct in_addr remote_address; static struct in_addr remote_address;
#endif /* SANED_USES_AF_INDEP */
#ifndef _PATH_HEQUIV #ifndef _PATH_HEQUIV
# define _PATH_HEQUIV "/etc/hosts.equiv" # define _PATH_HEQUIV "/etc/hosts.equiv"
@ -371,6 +395,300 @@ decode_handle (Wire * w, const char *op)
} }
/* Access control */ /* Access control */
#ifdef SANED_USES_AF_INDEP
static SANE_Status
check_host (int fd)
{
struct sockaddr_in *sin = NULL;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *sin6;
#endif /* ENABLE_IPV6 */
struct addrinfo hints;
struct addrinfo *res;
struct addrinfo *resp;
int j, access_ok = 0;
int err;
char text_addr[64];
#ifdef ENABLE_IPV6
char *remote_ipv4 = NULL; /* in case we have an IPv4-mapped address (eg ::ffff:127.0.0.1) */
struct addrinfo *remote_ipv4_addr = NULL;
#endif /* ENABLE_IPV6 */
char config_line[1024];
char hostname[MAXHOSTNAMELEN];
#ifdef ENABLE_IPV6
SANE_Bool IPv4map = SANE_FALSE;
#endif /* ENABLE_IPV6 */
int len;
FILE *fp;
/* Get address of remote host */
remote_address_len = sizeof (remote_address);
if (getpeername (fd, (struct sockaddr *) &remote_address, (socklen_t *) &remote_address_len) < 0)
{
DBG (DBG_ERR, "check_host: getpeername failed: %s\n", strerror (errno));
remote_ip = strdup ("[error]");
return SANE_STATUS_INVAL;
}
err = getnameinfo ((struct sockaddr *) &remote_address, remote_address_len,
hostname, sizeof (hostname), NULL, 0, NI_NUMERICHOST);
if (err)
{
DBG (DBG_DBG, "check_host: getnameinfo failed: %s\n", gai_strerror(err));
remote_ip = strdup ("[error]");
return SANE_STATUS_INVAL;
}
else
remote_ip = strdup (hostname);
#ifdef ENABLE_IPV6
if (strncmp (remote_ip, "::ffff:", 7) == 0)
{
DBG (DBG_DBG, "check_host: detected an IPv4-mapped address\n");
remote_ipv4 = remote_ip + 7;
IPv4map = SANE_TRUE;
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = PF_INET;
err = getaddrinfo (remote_ipv4, NULL, &hints, &res);
if (err)
{
DBG (DBG_DBG, "check_host: getaddrinfo() failed: %s\n", gai_strerror (err));
IPv4map = SANE_FALSE; /* we failed, remote_ipv4_addr points to nothing */
}
else
{
remote_ipv4_addr = res;
sin = (struct sockaddr_in *)res->ai_addr;
}
}
#endif /* ENABLE_IPV6 */
DBG (DBG_WARN, "check_host: access by remote host: %s\n", remote_ip);
/* Always allow access from local host. Do it here to avoid DNS lookups
and reading saned.conf. */
#ifdef ENABLE_IPV6
if (IPv4map == SANE_TRUE)
{
if (IN_LOOPBACK (ntohl (sin->sin_addr.s_addr)))
{
DBG (DBG_MSG,
"check_host: remote host is IN_LOOPBACK: access granted\n");
freeaddrinfo (remote_ipv4_addr);
return SANE_STATUS_GOOD;
}
freeaddrinfo (remote_ipv4_addr);
}
#endif /* ENABLE_IPV6 */
sin = (struct sockaddr_in *) &remote_address;
#ifdef ENABLE_IPV6
sin6 = (struct sockaddr_in6 *) &remote_address;
#endif /* ENABLE_IPV6 */
switch (remote_address.ss_family)
{
case AF_INET:
if (IN_LOOPBACK (ntohl (sin->sin_addr.s_addr)))
{
DBG (DBG_MSG,
"check_host: remote host is IN_LOOPBACK: access granted\n");
return SANE_STATUS_GOOD;
}
break;
#ifdef ENABLE_IPV6
case AF_INET6:
if (SANE_IN6_IS_ADDR_LOOPBACK (sin6->sin6_addr.s6_addr))
{
DBG (DBG_MSG,
"check_host: remote host is IN6_LOOPBACK: access granted\n");
return SANE_STATUS_GOOD;
}
break;
#endif /* ENABLE_IPV6 */
default:
break;
}
DBG (DBG_DBG, "check_host: remote host is not IN_LOOPBACK"
#ifdef ENABLE_IPV6
" nor IN6_LOOPBACK"
#endif /* ENABLE_IPV6 */
"\n");
/* Get name of local host */
if (gethostname (hostname, sizeof (hostname)) < 0)
{
DBG (DBG_ERR, "check_host: gethostname failed: %s\n", strerror (errno));
return SANE_STATUS_INVAL;
}
DBG (DBG_DBG, "check_host: local hostname: %s\n", hostname);
/* Get local addresses */
memset (&hints, 0, sizeof (hints));
hints.ai_flags = AI_CANONNAME;
#ifdef ENABLE_IPV6
hints.ai_family = PF_UNSPEC;
#else
hints.ai_family = PF_INET;
#endif /* ENABLE_IPV6 */
err = getaddrinfo (hostname, NULL, &hints, &res);
if (err)
{
DBG (DBG_ERR, "check_host: getaddrinfo failed: %s\n",
gai_strerror (err));
return SANE_STATUS_INVAL;
}
else
{
for (resp = res; resp != NULL; resp = resp->ai_next)
{
DBG (DBG_DBG, "check_host: local hostname(s) (from DNS): %s\n",
resp->ai_canonname);
err = getnameinfo (resp->ai_addr, resp->ai_addrlen, text_addr,
sizeof (text_addr), NULL, 0, NI_NUMERICHOST);
if (err)
strncpy (text_addr, "[error]", 8);
#ifdef ENABLE_IPV6
if ((strcmp (text_addr, remote_ip) == 0) ||
((IPv4map == SANE_TRUE) && (strcmp (text_addr, remote_ipv4) == 0)))
#else
if (strcmp (text_addr, remote_ip) == 0)
#endif /* ENABLE_IPV6 */
{
DBG (DBG_MSG, "check_host: remote host has same addr as local: access granted\n");
freeaddrinfo (res);
return SANE_STATUS_GOOD;
}
}
freeaddrinfo (res);
DBG (DBG_DBG,
"check_host: remote host doesn't have same addr as local\n");
}
/* must be a remote host: check contents of PATH_NET_CONFIG or
/etc/hosts.equiv if former doesn't exist: */
for (j = 0; j < NELEMS (config_file_names); ++j)
{
DBG (DBG_DBG, "check_host: opening config file: %s\n",
config_file_names[j]);
if (config_file_names[j][0] == '/')
fp = fopen (config_file_names[j], "r");
else
fp = sanei_config_open (config_file_names[j]);
if (!fp)
{
DBG (DBG_MSG,
"check_host: can't open config file: %s (%s)\n",
config_file_names[j], strerror (errno));
continue;
}
while (!access_ok && sanei_config_read (config_line,
sizeof (config_line), fp))
{
DBG (DBG_DBG, "check_host: config file line: `%s'\n", config_line);
if (config_line[0] == '#') /* ignore line comments */
continue;
len = strlen (config_line);
if (!len)
continue; /* ignore empty lines */
if (strcmp (config_line, "+") == 0)
{
access_ok = 1;
DBG (DBG_DBG,
"check_host: access granted from any host (`+')\n");
}
/* compare remote_ip (remote IP address) to the config_line */
else if (strcmp (config_line, remote_ip) == 0)
{
access_ok = 1;
DBG (DBG_DBG,
"check_host: access granted from IP address %s\n", remote_ip);
}
#ifdef ENABLE_IPV6
else if ((IPv4map == SANE_TRUE) && (strcmp (config_line, remote_ipv4) == 0))
{
access_ok = 1;
DBG (DBG_DBG,
"check_host: access granted from IP address %s (IPv4-mapped)\n", remote_ip);
}
#endif /* ENABLE_IPV6 */
else
{
memset (&hints, 0, sizeof (hints));
hints.ai_flags = AI_CANONNAME;
#ifdef ENABLE_IPV6
hints.ai_family = PF_UNSPEC;
#else
hints.ai_family = PF_INET;
#endif /* ENABLE_IPV6 */
err = getaddrinfo (config_line, NULL, &hints, &res);
if (err)
{
DBG (DBG_DBG,
"check_host: getaddrinfo for `%s' failed: %s\n",
config_line, gai_strerror (err));
DBG (DBG_MSG, "check_host: entry isn't an IP address "
"and can't be found in DNS\n");
continue;
}
else
{
for (resp = res; resp != NULL; resp = resp->ai_next)
{
err = getnameinfo (resp->ai_addr, resp->ai_addrlen, text_addr,
sizeof (text_addr), NULL, 0, NI_NUMERICHOST);
if (err)
strncpy (text_addr, "[error]", 8);
DBG (DBG_MSG,
"check_host: DNS lookup returns IP address: %s\n",
text_addr);
#ifdef ENABLE_IPV6
if ((strcmp (text_addr, remote_ip) == 0) ||
((IPv4map == SANE_TRUE) && (strcmp (text_addr, remote_ipv4) == 0)))
#else
if (strcmp (text_addr, remote_ip) == 0)
#endif /* ENABLE_IPV6 */
access_ok = 1;
if (access_ok)
break;
}
freeaddrinfo (res);
}
}
}
}
fclose (fp);
if (access_ok)
return SANE_STATUS_GOOD;
return SANE_STATUS_ACCESS_DENIED;
}
#else /* !SANED_USES_AF_INDEP */
static SANE_Status static SANE_Status
check_host (int fd) check_host (int fd)
{ {
@ -391,12 +709,13 @@ check_host (int fd)
if (getpeername (fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0) if (getpeername (fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0)
{ {
DBG (DBG_ERR, "check_host: getpeername failed: %s\n", strerror (errno)); DBG (DBG_ERR, "check_host: getpeername failed: %s\n", strerror (errno));
remote_ip = strdup ("[error]");
return SANE_STATUS_INVAL; return SANE_STATUS_INVAL;
} }
r_hostname = inet_ntoa (sin.sin_addr); r_hostname = inet_ntoa (sin.sin_addr);
remote_hostname = strdup (r_hostname); remote_ip = strdup (r_hostname);
DBG (DBG_WARN, "check_host: access by remote host: %s\n", DBG (DBG_WARN, "check_host: access by remote host: %s\n",
remote_hostname); remote_ip);
/* Save remote address for check of control and data connections */ /* Save remote address for check of control and data connections */
memcpy (&remote_address, &sin.sin_addr, sizeof (remote_address)); memcpy (&remote_address, &sin.sin_addr, sizeof (remote_address));
@ -530,6 +849,8 @@ check_host (int fd)
return SANE_STATUS_ACCESS_DENIED; return SANE_STATUS_ACCESS_DENIED;
} }
#endif /* SANED_USES_AF_INDEP */
static int static int
init (Wire * w) init (Wire * w)
{ {
@ -543,9 +864,11 @@ init (Wire * w)
status = check_host (w->io.fd); status = check_host (w->io.fd);
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_WARN, "init: access by host %s denied\n", remote_hostname); DBG (DBG_WARN, "init: access by host %s denied\n", remote_ip);
return -1; return -1;
} }
else
DBG (DBG_MSG, "init: access granted\n");
sanei_w_set_dir (w, WIRE_DECODE); sanei_w_set_dir (w, WIRE_DECODE);
if (w->status) if (w->status)
@ -583,8 +906,8 @@ init (Wire * w)
reply.version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, reply.version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR,
SANEI_NET_PROTOCOL_VERSION); SANEI_NET_PROTOCOL_VERSION);
DBG (DBG_WARN, "init: access by %s@%s accepted\n", DBG (DBG_WARN, "init: access granted to %s@%s\n",
default_username, remote_hostname); default_username, remote_ip);
if (status == SANE_STATUS_GOOD) if (status == SANE_STATUS_GOOD)
{ {
@ -612,6 +935,108 @@ init (Wire * w)
return 0; return 0;
} }
#ifdef SANED_USES_AF_INDEP
static int
start_scan (Wire * w, int h, SANE_Start_Reply * reply)
{
struct sockaddr_storage ss;
struct sockaddr_in *sin;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *sin6;
#endif /* ENABLE_IPV6 */
SANE_Handle be_handle;
int fd, len;
be_handle = handle[h].handle;
len = sizeof (ss);
if (getsockname (w->io.fd, (struct sockaddr *) &ss, (socklen_t *) &len) < 0)
{
DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n",
strerror (errno));
reply->status = SANE_STATUS_IO_ERROR;
return -1;
}
fd = socket (ss.ss_family, SOCK_STREAM, 0);
if (fd < 0)
{
DBG (DBG_ERR, "start_scan: failed to obtain data socket (%s)\n",
strerror (errno));
reply->status = SANE_STATUS_IO_ERROR;
return -1;
}
switch (ss.ss_family)
{
case AF_INET:
sin = (struct sockaddr_in *) &ss;
sin->sin_port = 0;
break;
#ifdef ENABLE_IPV6
case AF_INET6:
sin6 = (struct sockaddr_in6 *) &ss;
sin6->sin6_port = 0;
break;
#endif /* ENABLE_IPV6 */
default:
break;
}
if (bind (fd, (struct sockaddr *) &ss, len) < 0)
{
DBG (DBG_ERR, "start_scan: failed to bind address (%s)\n",
strerror (errno));
reply->status = SANE_STATUS_IO_ERROR;
return -1;
}
if (listen (fd, 1) < 0)
{
DBG (DBG_ERR, "start_scan: failed to make socket listen (%s)\n",
strerror (errno));
reply->status = SANE_STATUS_IO_ERROR;
return -1;
}
if (getsockname (fd, (struct sockaddr *) &ss, (socklen_t *) &len) < 0)
{
DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n",
strerror (errno));
reply->status = SANE_STATUS_IO_ERROR;
return -1;
}
switch (ss.ss_family)
{
case AF_INET:
sin = (struct sockaddr_in *) &ss;
reply->port = ntohs (sin->sin_port);
break;
#ifdef ENABLE_IPV6
case AF_INET6:
sin6 = (struct sockaddr_in6 *) &ss;
reply->port = ntohs (sin6->sin6_port);
break;
#endif /* ENABLE_IPV6 */
default:
break;
}
DBG (DBG_MSG, "start_scan: using port %d for data\n", reply->port);
reply->status = sane_start (be_handle);
if (reply->status == SANE_STATUS_GOOD)
{
handle[h].scanning = 1;
handle[h].docancel = 0;
}
return fd;
}
#else /* !SANED_USES_AF_INDEP */
static int static int
start_scan (Wire * w, int h, SANE_Start_Reply * reply) start_scan (Wire * w, int h, SANE_Start_Reply * reply)
{ {
@ -677,6 +1102,7 @@ start_scan (Wire * w, int h, SANE_Start_Reply * reply)
return fd; return fd;
} }
#endif /* SANED_USES_AF_INDEP */
static int static int
store_reclen (SANE_Byte * buf, size_t buf_size, int i, size_t reclen) store_reclen (SANE_Byte * buf, size_t buf_size, int i, size_t reclen)
@ -958,7 +1384,7 @@ process_request (Wire * w)
} }
else else
{ {
DBG (DBG_MSG, "process_request: access to resource `%s' accepted\n", DBG (DBG_MSG, "process_request: access to resource `%s' granted\n",
resource); resource);
free (resource); free (resource);
memset (&reply, 0, sizeof (reply)); /* avoid leaking bits */ memset (&reply, 0, sizeof (reply)); /* avoid leaking bits */
@ -1089,6 +1515,51 @@ process_request (Wire * w)
sanei_w_reply (w, (WireCodecFunc) sanei_w_start_reply, &reply); sanei_w_reply (w, (WireCodecFunc) sanei_w_start_reply, &reply);
#ifdef SANED_USES_AF_INDEP
if (reply.status == SANE_STATUS_GOOD)
{
struct sockaddr_storage ss;
char text_addr[64];
int len;
int error;
DBG (DBG_MSG, "process_request: waiting for data connection\n");
data_fd = accept (fd, 0, 0);
close (fd);
/* Get address of remote host */
len = sizeof (ss);
if (getpeername (data_fd, (struct sockaddr *) &ss, (socklen_t *) &len) < 0)
{
DBG (DBG_ERR, "process_request: getpeername failed: %s\n",
strerror (errno));
return;
}
error = getnameinfo ((struct sockaddr *) &ss, len, text_addr,
sizeof (text_addr), NULL, 0, NI_NUMERICHOST);
if (error)
{
DBG (DBG_ERR, "process_request: getnameinfo failed: %s\n",
gai_strerror (error));
return;
}
DBG (DBG_MSG, "process_request: access to data port from %s\n",
text_addr);
if (strcmp (text_addr, remote_ip) != 0)
{
DBG (DBG_ERR, "process_request: however, only %s is authorized\n",
text_addr);
DBG (DBG_ERR, "process_request: configuration problem or attack?\n");
close (data_fd);
data_fd = -1;
quit (0);
}
#else /* !SANED_USES_AF_INDEP */
if (reply.status == SANE_STATUS_GOOD) if (reply.status == SANE_STATUS_GOOD)
{ {
struct sockaddr_in sin; struct sockaddr_in sin;
@ -1126,6 +1597,7 @@ process_request (Wire * w)
else else
DBG (DBG_MSG, "process_request: access to data port from %s\n", DBG (DBG_MSG, "process_request: access to data port from %s\n",
inet_ntoa (sin.sin_addr)); inet_ntoa (sin.sin_addr));
#endif /* SANED_USES_AF_INDEP */
if (data_fd < 0) if (data_fd < 0)
{ {
@ -1169,6 +1641,274 @@ process_request (Wire * w)
} }
} }
#ifdef SANED_USES_AF_INDEP
int
main (int argc, char *argv[])
{
int fd = -1;
int on = 1;
#ifdef TCP_NODELAY
int level = -1;
#endif
debug = DBG_WARN;
openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON);
prog_name = strrchr (argv[0], '/');
if (prog_name)
++prog_name;
else
prog_name = argv[0];
byte_order.w = 0;
byte_order.ch = 1;
sanei_w_init (&wire, sanei_codec_bin_init);
wire.io.read = read;
wire.io.write = write;
if (argc == 2 &&
(strncmp (argv[1], "-d", 2) == 0 || strncmp (argv[1], "-s", 2) == 0))
{
/* don't operate in daemon mode: wait for connection request: */
struct addrinfo *res;
struct addrinfo *resp;
struct addrinfo hints;
struct sockaddr_in *sin;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *sin6;
#endif /* ENABLE_IPV6 */
struct pollfd *fds = NULL;
struct pollfd *fdp = NULL;
int nfds;
int err;
int i;
short sane_port = htons (6566);
if (argv[1][2])
debug = atoi (argv[1] + 2);
if (strncmp (argv[1], "-d", 2) == 0)
log_to_syslog = SANE_FALSE;
DBG (DBG_WARN, "main: starting debug mode (level %d)\n", debug);
DBG (DBG_DBG,
"main: trying to get port for service `sane' (getaddrinfo)\n");
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
err = getaddrinfo (NULL, "sane", &hints, &res);
if (err)
{
/*
* You cannot pass (NULL, NULL, &hints, &res) to getaddrinfo,
* so request a good-old well known service, and change the port
* afterwards as a workaround
*/
err = getaddrinfo (NULL, "telnet", &hints, &res);
if (err)
{
DBG (DBG_ERR, "main: getaddrinfo() failed: %s\n", gai_strerror (err));
exit (1);
}
else
{
DBG (DBG_WARN, "main: \"sane\" service unknown on your host; you should add\n");
DBG (DBG_WARN, "main: sane 6566/tcp saned # SANE network scanner daemon\n");
DBG (DBG_WARN, "main: to your /etc/services file (or equivalent). Proceeding anyway.\n");
for (resp = res; resp != NULL; resp = resp->ai_next)
{
switch (resp->ai_family)
{
case AF_INET:
sin = (struct sockaddr_in *) resp->ai_addr;
sin->sin_port = sane_port;
break;
#ifdef ENABLE_IPV6
case AF_INET6:
sin6 = (struct sockaddr_in6 *) resp->ai_addr;
sin6->sin6_port = sane_port;
break;
#endif /* ENABLE_IPV6 */
}
}
}
}
for (resp = res, nfds = 0; resp != NULL; resp = resp->ai_next, nfds++)
;
fds = malloc (nfds * sizeof (struct pollfd));
if (fds == NULL)
{
DBG (DBG_ERR, "main: not enough memory for fds\n");
freeaddrinfo (res);
exit (1);
}
for (resp = res, i = 0, fdp = fds; resp != NULL; resp = resp->ai_next, i++, fdp++)
{
#ifdef ENABLE_IPV6
if ((resp->ai_family != AF_INET) && (resp->ai_family != AF_INET6))
#else
if (resp->ai_family != AF_INET)
#endif /* ENABLE_IPV6 */
{
fdp--;
nfds--;
continue;
}
DBG (DBG_DBG, "main: [%d] socket ()\n", i);
fd = socket (resp->ai_family, SOCK_STREAM, 0);
DBG (DBG_DBG, "main: [%d] setsockopt ()\n", i);
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
DBG (DBG_ERR, "main: [%d] failed to put socket in SO_REUSEADDR mode (%s)\n",
i, strerror (errno));
DBG (DBG_DBG, "main: [%d] bind ()\n", i);
if (bind (fd, resp->ai_addr, resp->ai_addrlen) < 0)
{
/*
* binding a socket may fail, eg if we already
* to the IPv6 addr returned by getaddrinfo (usually the first one),
* or if IPv6 isn't supported, but saned was built with IPv6 support
*/
DBG (DBG_ERR, "main: [%d] bind failed: %s\n", i, strerror (errno));
close (fd);
nfds--;
fdp--;
continue;
}
DBG (DBG_DBG, "main: [%d] listen ()\n", i);
if (listen (fd, 1) < 0)
{
DBG (DBG_ERR, "main: [%d] listen failed: %s\n", i, strerror (errno));
exit (1);
}
fdp->fd = fd;
fdp->events = POLLIN;
}
resp = NULL;
freeaddrinfo (res);
if (nfds <= 0)
{
DBG (DBG_ERR, "main: couldn't bind an address. Exiting.\n");
exit (1);
}
DBG (DBG_MSG, "main: waiting for control connection\n");
while (1)
{
if (poll (fds, nfds, -1) < 0)
{
if (errno == EINTR)
continue;
else
{
DBG (DBG_ERR, "main: poll failed: %s\n", strerror (errno));
free (fds);
exit (1);
}
}
for (i = 0, fdp = fds; i < nfds; i++, fdp++)
{
if (! (fdp->revents & POLLIN))
continue;
wire.io.fd = accept (fdp->fd, 0, 0);
if (wire.io.fd < 0)
{
DBG (DBG_ERR, "main: accept failed: %s", strerror (errno));
free (fds);
exit (1);
}
for (i = 0, fdp = fds; i < nfds; i++, fdp++)
close (fdp->fd);
free (fds);
break;
}
break;
}
}
else
/* use filedescriptor opened by inetd: */
#ifdef HAVE_OS2_H
/* under OS/2, the socket handle is passed as argument on the command
line; the socket handle is relative to IBM TCP/IP, so a call
to impsockethandle() is required to add it to the EMX runtime */
if (argc == 2)
{
wire.io.fd = _impsockhandle (atoi (argv[1]), 0);
if (wire.io.fd == -1)
perror ("impsockhandle");
}
else
#endif /* HAVE_OS2_H */
wire.io.fd = 1;
signal (SIGALRM, quit);
signal (SIGPIPE, quit);
#ifdef TCP_NODELAY
# ifdef SOL_TCP
level = SOL_TCP;
# else /* !SOL_TCP */
/* Look up the protocol level in the protocols database. */
{
struct protoent *p;
p = getprotobyname ("tcp");
if (p == 0)
{
DBG (DBG_WARN, "main: cannot look up `tcp' protocol number");
}
else
level = p->p_proto;
}
# endif /* SOL_TCP */
if (level == -1
|| setsockopt (wire.io.fd, level, TCP_NODELAY, &on, sizeof (on)))
DBG (DBG_WARN, "main: failed to put socket in TCP_NODELAY mode (%s)",
strerror (errno));
#endif /* !TCP_NODELAY */
/* define the version string depending on which network code is used */
#ifdef ENABLE_IPV6
DBG (DBG_WARN, "saned (AF-indep+IPv6) from %s ready\n", PACKAGE_STRING);
#else
DBG (DBG_WARN, "saned (AF-indep) from %s ready\n", PACKAGE_STRING);
#endif /* ENABLE_IPV6 */
if (init (&wire) < 0)
quit (0);
while (1)
{
reset_watchdog ();
process_request (&wire);
}
}
#else /* !SANED_USES_AF_INDEP */
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
@ -1287,7 +2027,7 @@ main (int argc, char *argv[])
p = getprotobyname ("tcp"); p = getprotobyname ("tcp");
if (p == 0) if (p == 0)
{ {
DBG (DBG_WARN, "main:: cannot look up `tcp' protocol number"); DBG (DBG_WARN, "main: cannot look up `tcp' protocol number");
} }
else else
level = p->p_proto; level = p->p_proto;
@ -1310,3 +2050,4 @@ main (int argc, char *argv[])
process_request (&wire); process_request (&wire);
} }
} }
#endif /* SANED_USES_AF_INDEP */

Wyświetl plik

@ -11,6 +11,9 @@
/* Should we disable SCSI generic v3? */ /* Should we disable SCSI generic v3? */
#undef DISABLE_LINUX_SG_IO #undef DISABLE_LINUX_SG_IO
/* Define to 1 if the system supports IPv6 */
#undef ENABLE_IPV6
/* Define to 1 if you have `alloca', as a function or macro. */ /* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA #undef HAVE_ALLOCA
@ -51,9 +54,15 @@
/* Define to 1 if you have the <fcntl.h> header file. */ /* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H #undef HAVE_FCNTL_H
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
/* Define to 1 if you have the `getenv' function. */ /* Define to 1 if you have the `getenv' function. */
#undef HAVE_GETENV #undef HAVE_GETENV
/* Define to 1 if you have the `getnameinfo' function. */
#undef HAVE_GETNAMEINFO
/* Define to 1 if you have the `getpagesize' function. */ /* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE #undef HAVE_GETPAGESIZE