• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 1997 Andreas Beck
3    Copyright (C) 2001 - 2004 Henning Meier-Geinitz
4    Copyright (C) 2003, 2008 Julien BLACHE <jb@jblache.org>
5        AF-independent + IPv6 code, standalone mode
6 
7    This file is part of the SANE package.
8 
9    SANE is free software; you can redistribute it and/or modify it under
10    the terms of the GNU General Public License as published by the Free
11    Software Foundation; either version 2 of the License, or (at your
12    option) any later version.
13 
14    SANE is distributed in the hope that it will be useful, but WITHOUT
15    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17    for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with sane; see the file COPYING.
21    If not, see <https://www.gnu.org/licenses/>.
22 
23    The SANE network daemon.  This is the counterpart to the NET
24    backend.
25 */
26 
27 #ifdef _AIX
28 # include "../include/lalloca.h"		/* MUST come first for AIX! */
29 #endif
30 
31 #include "../include/sane/config.h"
32 #include "../include/lalloca.h"
33 #include <sys/types.h>
34 
35 #if defined(HAVE_GETADDRINFO) && defined (HAVE_GETNAMEINFO)
36 # define SANED_USES_AF_INDEP
37 # ifdef HAS_SS_FAMILY
38 #  define SS_FAMILY(ss) ss.ss_family
39 # elif defined(HAS___SS_FAMILY)
40 #  define SS_FAMILY(ss) ss.__ss_family
41 # else /* fallback to the old, IPv4-only code */
42 #  undef SANED_USES_AF_INDEP
43 #  undef ENABLE_IPV6
44 # endif
45 #else
46 # undef ENABLE_IPV6
47 #endif /* HAVE_GETADDRINFO && HAVE_GETNAMEINFO */
48 
49 #include <assert.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <netdb.h>
53 #include <signal.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <stdint.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <time.h>
60 #include <unistd.h>
61 #include <limits.h>
62 #ifdef HAVE_LIBC_H
63 # include <libc.h>		/* NeXTStep/OpenStep */
64 #endif
65 
66 #ifdef HAVE_SYS_SELECT_H
67 # include <sys/select.h>
68 #endif
69 
70 #include <netinet/in.h>
71 
72 #include <stdarg.h>
73 
74 #include <sys/param.h>
75 #include <sys/socket.h>
76 
77 #include <sys/time.h>
78 #include <sys/types.h>
79 #include <arpa/inet.h>
80 
81 #include <sys/wait.h>
82 
83 #include <pwd.h>
84 #include <grp.h>
85 
86 #include "lgetopt.h"
87 
88 #if defined(HAVE_POLL_H) && defined(HAVE_POLL)
89 # include <poll.h>
90 #else
91 /*
92  * This replacement poll() using select() is only designed to cover
93  * our needs in run_standalone(). It should probably be extended...
94  */
95 struct pollfd
96 {
97   int fd;
98   short events;
99   short revents;
100 };
101 
102 #define POLLIN 0x0001
103 #define POLLERR 0x0002
104 
105 int
106 poll (struct pollfd *ufds, unsigned int nfds, int timeout);
107 
108 int
poll(struct pollfd * ufds,unsigned int nfds,int timeout)109 poll (struct pollfd *ufds, unsigned int nfds, int timeout)
110 {
111   struct pollfd *fdp;
112 
113   fd_set rfds;
114   fd_set efds;
115   struct timeval tv;
116   int maxfd = 0;
117   unsigned int i;
118   int ret;
119 
120   tv.tv_sec = timeout / 1000;
121   tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;
122 
123   FD_ZERO (&rfds);
124   FD_ZERO (&efds);
125 
126   for (i = 0, fdp = ufds; i < nfds; i++, fdp++)
127     {
128       fdp->revents = 0;
129 
130       if (fdp->events & POLLIN)
131 	FD_SET (fdp->fd, &rfds);
132 
133       FD_SET (fdp->fd, &efds);
134 
135       maxfd = (fdp->fd > maxfd) ? fdp->fd : maxfd;
136     }
137 
138   maxfd++;
139 
140   ret = select (maxfd, &rfds, NULL, &efds, &tv);
141 
142   if (ret < 0)
143     return ret;
144 
145   for (i = 0, fdp = ufds; i < nfds; i++, fdp++)
146     {
147       if (fdp->events & POLLIN)
148 	if (FD_ISSET (fdp->fd, &rfds))
149 	  fdp->revents |= POLLIN;
150 
151       if (FD_ISSET (fdp->fd, &efds))
152 	fdp->revents |= POLLERR;
153     }
154 
155   return ret;
156 }
157 #endif /* HAVE_SYS_POLL_H && HAVE_POLL */
158 
159 #if WITH_AVAHI
160 # include <avahi-client/client.h>
161 # include <avahi-client/publish.h>
162 
163 # include <avahi-common/alternative.h>
164 # include <avahi-common/simple-watch.h>
165 # include <avahi-common/malloc.h>
166 # include <avahi-common/error.h>
167 
168 # define SANED_SERVICE_DNS "_sane-port._tcp"
169 # define SANED_NAME "saned"
170 
171 pid_t avahi_pid = -1;
172 
173 char *avahi_svc_name;
174 
175 static AvahiClient *avahi_client = NULL;
176 static AvahiSimplePoll *avahi_poll = NULL;
177 static AvahiEntryGroup *avahi_group = NULL;
178 #endif /* WITH_AVAHI */
179 
180 #ifdef HAVE_SYSTEMD
181 #include <systemd/sd-daemon.h>
182 #endif
183 
184 
185 #include "../include/sane/sane.h"
186 #include "../include/sane/sanei.h"
187 #include "../include/sane/sanei_net.h"
188 #include "../include/sane/sanei_codec_bin.h"
189 #include "../include/sane/sanei_config.h"
190 
191 #include "../include/sane/sanei_auth.h"
192 
193 #ifndef EXIT_SUCCESS
194 # define EXIT_SUCCESS   0
195 #endif
196 
197 #ifndef IN_LOOPBACK
198 # define IN_LOOPBACK(addr) (addr == 0x7f000001L)
199 #endif
200 
201 #ifdef ENABLE_IPV6
202 # ifndef IN6_IS_ADDR_LOOPBACK
203 # define IN6_IS_ADDR_LOOPBACK(a) \
204         (((const uint32_t *) (a))[0] == 0                                   \
205          && ((const uint32_t *) (a))[1] == 0                                \
206          && ((const uint32_t *) (a))[2] == 0                                \
207          && ((const uint32_t *) (a))[3] == htonl (1))
208 # endif
209 # ifndef IN6_IS_ADDR_V4MAPPED
210 # define IN6_IS_ADDR_V4MAPPED(a) \
211 ((((const uint32_t *) (a))[0] == 0)                                 \
212  && (((const uint32_t *) (a))[1] == 0)                              \
213  && (((const uint32_t *) (a))[2] == htonl (0xffff)))
214 # endif
215 #endif /* ENABLE_IPV6 */
216 
217 #ifndef MAXHOSTNAMELEN
218 # define MAXHOSTNAMELEN 120
219 #endif
220 
221 #ifndef PATH_MAX
222 # define PATH_MAX 1024
223 #endif
224 
225 struct saned_child {
226   pid_t pid;
227   struct saned_child *next;
228 };
229 struct saned_child *children;
230 int numchildren;
231 
232 #define SANED_CONFIG_FILE "saned.conf"
233 #define SANED_PID_FILE    "/var/run/saned.pid"
234 
235 #define SANED_SERVICE_NAME   "sane-port"
236 #define SANED_SERVICE_PORT   6566
237 #define SANED_SERVICE_PORT_S "6566"
238 
239 typedef struct
240 {
241   u_int inuse:1;		/* is this handle in use? */
242   u_int scanning:1;		/* are we scanning? */
243   u_int docancel:1;		/* cancel the current scan */
244   SANE_Handle handle;		/* backends handle */
245 }
246 Handle;
247 
248 static SANE_Net_Procedure_Number current_request;
249 static const char *prog_name;
250 static int can_authorize;
251 static Wire wire;
252 static int num_handles;
253 static int debug;
254 static int run_mode;
255 static int run_foreground;
256 static int run_once;
257 static int data_connect_timeout = 4000;
258 static Handle *handle;
259 static char *bind_addr;
260 static short bind_port = -1;
261 static size_t buffer_size = (1 * 1024 * 1024);
262 static union
263 {
264   int w;
265   u_char ch;
266 }
267 byte_order;
268 
269 /* The default-user name.  This is not used to imply any rights.  All
270    it does is save a remote user some work by reducing the amount of
271    text s/he has to type when authentication is requested.  */
272 static const char *default_username = "saned-user";
273 static char *remote_ip;
274 
275 /* data port range */
276 static in_port_t data_port_lo;
277 static in_port_t data_port_hi;
278 
279 #ifdef SANED_USES_AF_INDEP
280 static union {
281   struct sockaddr_storage ss;
282   struct sockaddr sa;
283   struct sockaddr_in sin;
284 #ifdef ENABLE_IPV6
285   struct sockaddr_in6 sin6;
286 #endif
287 } remote_address;
288 static int remote_address_len;
289 #else
290 static struct in_addr remote_address;
291 #endif /* SANED_USES_AF_INDEP */
292 
293 #ifndef _PATH_HEQUIV
294 # define _PATH_HEQUIV   "/etc/hosts.equiv"
295 #endif
296 
297 static const char *config_file_names[] = {
298   _PATH_HEQUIV, SANED_CONFIG_FILE
299 };
300 
301 static SANE_Bool log_to_syslog = SANE_TRUE;
302 
303 /* forward declarations: */
304 static int process_request (Wire * w);
305 
306 #define SANED_RUN_INETD  0
307 #define SANED_RUN_ALONE  1
308 
309 #define DBG_ERR  1
310 #define DBG_WARN 2
311 #define DBG_MSG  3
312 #define DBG_INFO 4
313 #define DBG_DBG  5
314 
315 #define DBG	saned_debug_call
316 
317 static void
saned_debug_call(int level,const char * fmt,...)318 saned_debug_call (int level, const char *fmt, ...)
319 {
320 #ifndef NDEBUG
321   va_list ap;
322   va_start (ap, fmt);
323   if (debug >= level)
324     {
325       if (log_to_syslog)
326 	{
327 	  /* print to syslog */
328 	  vsyslog (LOG_DEBUG, fmt, ap);
329 	}
330       else
331 	{
332 	  /* print to stderr */
333 	  fprintf (stderr, "[saned] ");
334 	  vfprintf (stderr, fmt, ap);
335 	}
336     }
337   va_end (ap);
338 #endif
339 }
340 
341 
342 static void
reset_watchdog(void)343 reset_watchdog (void)
344 {
345   if (!debug)
346     alarm (3600);
347 }
348 
349 static void
auth_callback(SANE_String_Const res,SANE_Char * username,SANE_Char * password)350 auth_callback (SANE_String_Const res,
351 	       SANE_Char *username,
352 	       SANE_Char *password)
353 {
354   SANE_Net_Procedure_Number procnum;
355   SANE_Authorization_Req req;
356   SANE_Word word, ack = 0;
357 
358   memset (username, 0, SANE_MAX_USERNAME_LEN);
359   memset (password, 0, SANE_MAX_PASSWORD_LEN);
360 
361   if (!can_authorize)
362     {
363       DBG (DBG_WARN,
364 	   "auth_callback: called during non-authorizable RPC (resource=%s)\n",
365 	   res);
366       return;
367     }
368 
369   if (wire.status)
370     {
371       DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
372       return;
373     }
374 
375   switch (current_request)
376     {
377     case SANE_NET_OPEN:
378       {
379 	SANE_Open_Reply reply;
380 
381 	memset (&reply, 0, sizeof (reply));
382 	reply.resource_to_authorize = (char *) res;
383 	sanei_w_reply (&wire, (WireCodecFunc) sanei_w_open_reply, &reply);
384       }
385       break;
386 
387     case SANE_NET_CONTROL_OPTION:
388       {
389 	SANE_Control_Option_Reply reply;
390 
391 	memset (&reply, 0, sizeof (reply));
392 	reply.resource_to_authorize = (char *) res;
393 	sanei_w_reply (&wire,
394 		       (WireCodecFunc) sanei_w_control_option_reply, &reply);
395       }
396       break;
397 
398     case SANE_NET_START:
399       {
400 	SANE_Start_Reply reply;
401 
402 	memset (&reply, 0, sizeof (reply));
403 	reply.resource_to_authorize = (char *) res;
404 	sanei_w_reply (&wire, (WireCodecFunc) sanei_w_start_reply, &reply);
405       }
406       break;
407 
408     default:
409       DBG (DBG_WARN,
410 	   "auth_callback: called for unexpected request %d (resource=%s)\n",
411 	   current_request, res);
412       break;
413     }
414 
415   if (wire.status)
416     {
417       DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
418       return;
419     }
420 
421   reset_watchdog ();
422 
423   sanei_w_set_dir (&wire, WIRE_DECODE);
424   sanei_w_word (&wire, &word);
425 
426   if (wire.status)
427     {
428       DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
429       return;
430     }
431 
432   procnum = word;
433   if (procnum != SANE_NET_AUTHORIZE)
434     {
435       DBG (DBG_WARN,
436 	   "auth_callback: bad procedure number %d "
437 	   "(expected: %d, resource=%s)\n", procnum, SANE_NET_AUTHORIZE,
438 	   res);
439       return;
440     }
441 
442   sanei_w_authorization_req (&wire, &req);
443   if (wire.status)
444     {
445       DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
446       return;
447     }
448 
449   if (req.username)
450     strcpy (username, req.username);
451   if (req.password)
452     strcpy (password, req.password);
453   if (!req.resource || strcmp (req.resource, res) != 0)
454     {
455       DBG (DBG_MSG,
456 	   "auth_callback: got auth for resource %s (expected resource=%s)\n",
457 	   res, req.resource);
458     }
459   sanei_w_free (&wire, (WireCodecFunc) sanei_w_authorization_req, &req);
460   sanei_w_reply (&wire, (WireCodecFunc) sanei_w_word, &ack);
461 }
462 
463 static void
quit(int signum)464 quit (int signum)
465 {
466   static int running = 0;
467   int i;
468 
469   if (signum)
470     DBG (DBG_ERR, "quit: received signal %d\n", signum);
471 
472   if (running)
473     {
474       DBG (DBG_ERR, "quit: already active, returning\n");
475       return;
476     }
477   running = 1;
478 
479   for (i = 0; i < num_handles; ++i)
480     if (handle[i].inuse)
481       sane_close (handle[i].handle);
482 
483   sane_exit ();
484   sanei_w_exit (&wire);
485   if (handle)
486     free (handle);
487   DBG (DBG_WARN, "quit: exiting\n");
488   if (log_to_syslog)
489     closelog ();
490   exit (EXIT_SUCCESS);		/* This is a nowait-daemon. */
491 }
492 
493 static SANE_Word
get_free_handle(void)494 get_free_handle (void)
495 {
496 # define ALLOC_INCREMENT        16
497   static int h, last_handle_checked = -1;
498 
499   if (num_handles > 0)
500     {
501       h = last_handle_checked + 1;
502       do
503 	{
504 	  if (h >= num_handles)
505 	    h = 0;
506 	  if (!handle[h].inuse)
507 	    {
508 	      last_handle_checked = h;
509 	      memset (handle + h, 0, sizeof (handle[0]));
510 	      handle[h].inuse = 1;
511 	      return h;
512 	    }
513 	  ++h;
514 	}
515       while (h != last_handle_checked);
516     }
517 
518   /* we're out of handles---alloc some more: */
519   last_handle_checked = num_handles - 1;
520   num_handles += ALLOC_INCREMENT;
521   if (handle)
522     handle = realloc (handle, num_handles * sizeof (handle[0]));
523   else
524     handle = malloc (num_handles * sizeof (handle[0]));
525   if (!handle)
526     return -1;
527   memset (handle + last_handle_checked + 1, 0,
528 	  ALLOC_INCREMENT * sizeof (handle[0]));
529   return get_free_handle ();
530 # undef ALLOC_INCREMENT
531 }
532 
533 static void
close_handle(int h)534 close_handle (int h)
535 {
536   if (h >= 0 && handle[h].inuse)
537     {
538       sane_close (handle[h].handle);
539       handle[h].inuse = 0;
540     }
541 }
542 
543 static SANE_Word
decode_handle(Wire * w,const char * op)544 decode_handle (Wire * w, const char *op)
545 {
546   SANE_Word h;
547 
548   sanei_w_word (w, &h);
549   if (w->status || (unsigned) h >= (unsigned) num_handles || !handle[h].inuse)
550     {
551       DBG (DBG_ERR,
552 	   "decode_handle: %s: error while decoding handle argument "
553 	   "(h=%d, %s)\n", op, h, strerror (w->status));
554       return -1;
555     }
556   return h;
557 }
558 
559 
560 
561 /* Convert a number of bits to an 8-bit bitmask */
562 static unsigned int cidrtomask[9] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0,
563 				      0xF8, 0xFC, 0xFE, 0xFF };
564 
565 #ifdef SANED_USES_AF_INDEP
566 static SANE_Bool
check_v4_in_range(struct sockaddr_in * sin,char * base_ip,char * netmask)567 check_v4_in_range (struct sockaddr_in *sin, char *base_ip, char *netmask)
568 {
569   int cidr;
570   int i, err;
571   char *end;
572   uint32_t mask;
573   struct sockaddr_in *base;
574   struct addrinfo hints;
575   struct addrinfo *res;
576   SANE_Bool ret = SANE_FALSE;
577 
578   cidr = -1;
579   cidr = strtol (netmask, &end, 10);
580 
581   /* Sanity check on the cidr value */
582   if ((cidr < 0) || (cidr > 32) || (end == netmask))
583     {
584       DBG (DBG_ERR, "check_v4_in_range: invalid CIDR value (%s) !\n", netmask);
585       return SANE_FALSE;
586     }
587 
588   mask = 0;
589   cidr -= 8;
590 
591   /* Build a bitmask out of the CIDR value */
592   for (i = 3; cidr >= 0; i--)
593     {
594       mask |= (0xff << (8 * i));
595       cidr -= 8;
596     }
597 
598   if (cidr < 0)
599     mask |= (cidrtomask[cidr + 8] << (8 * i));
600 
601   mask = htonl (mask);
602 
603   /* get a sockaddr_in representing the base IP address */
604   memset (&hints, 0, sizeof (struct addrinfo));
605   hints.ai_flags = AI_NUMERICHOST;
606   hints.ai_family = PF_INET;
607 
608   err = getaddrinfo (base_ip, NULL, &hints, &res);
609   if (err)
610     {
611       DBG (DBG_DBG, "check_v4_in_range: getaddrinfo() failed: %s\n", gai_strerror (err));
612       return SANE_FALSE;
613     }
614 
615   base = (struct sockaddr_in *) res->ai_addr;
616 
617   /*
618    * Check that the address belongs to the specified subnet, using the bitmask.
619    * The address is represented by a 32bit integer.
620    */
621   if ((base->sin_addr.s_addr & mask) == (sin->sin_addr.s_addr & mask))
622     ret = SANE_TRUE;
623 
624   freeaddrinfo (res);
625 
626   return ret;
627 }
628 
629 
630 # ifdef ENABLE_IPV6
631 
632 static SANE_Bool
check_v6_in_range(struct sockaddr_in6 * sin6,char * base_ip,char * netmask)633 check_v6_in_range (struct sockaddr_in6 *sin6, char *base_ip, char *netmask)
634 {
635   int cidr;
636   int i, err;
637   unsigned int mask[16];
638   char *end;
639   struct sockaddr_in6 *base;
640   struct addrinfo hints;
641   struct addrinfo *res;
642   SANE_Bool ret = SANE_TRUE;
643 
644   cidr = -1;
645   cidr = strtol (netmask, &end, 10);
646 
647   /* Sanity check on the cidr value */
648   if ((cidr < 0) || (cidr > 128) || (end == netmask))
649     {
650       DBG (DBG_ERR, "check_v6_in_range: invalid CIDR value (%s) !\n", netmask);
651       return SANE_FALSE;
652     }
653 
654   memset (mask, 0, (16 * sizeof (unsigned int)));
655   cidr -= 8;
656 
657   /* Build a bitmask out of the CIDR value */
658   for (i = 0; cidr >= 0; i++)
659     {
660       mask[i] = 0xff;
661       cidr -= 8;
662     }
663 
664   if (cidr < 0)
665     mask[i] = cidrtomask[cidr + 8];
666 
667   /* get a sockaddr_in6 representing the base IP address */
668   memset (&hints, 0, sizeof (struct addrinfo));
669   hints.ai_flags = AI_NUMERICHOST;
670   hints.ai_family = PF_INET6;
671 
672   err = getaddrinfo (base_ip, NULL, &hints, &res);
673   if (err)
674     {
675       DBG (DBG_DBG, "check_v6_in_range: getaddrinfo() failed: %s\n", gai_strerror (err));
676       return SANE_FALSE;
677     }
678 
679   base = (struct sockaddr_in6 *) res->ai_addr;
680 
681   /*
682    * Check that the address belongs to the specified subnet.
683    * The address is reprensented by an array of 16 8bit integers.
684    */
685   for (i = 0; i < 16; i++)
686     {
687       if ((base->sin6_addr.s6_addr[i] & mask[i]) != (sin6->sin6_addr.s6_addr[i] & mask[i]))
688 	{
689 	  ret = SANE_FALSE;
690 	  break;
691 	}
692     }
693 
694   freeaddrinfo (res);
695 
696   return ret;
697 }
698 # endif /* ENABLE_IPV6 */
699 #else /* !SANED_USES_AF_INDEP */
700 static SANE_Bool
check_v4_in_range(struct in_addr * inaddr,struct in_addr * base,char * netmask)701 check_v4_in_range (struct in_addr *inaddr, struct in_addr *base, char *netmask)
702 {
703   int cidr;
704   int i;
705   char *end;
706   uint32_t mask;
707   SANE_Bool ret = SANE_FALSE;
708 
709   cidr = -1;
710   cidr = strtol (netmask, &end, 10);
711 
712   /* sanity check on the cidr value */
713   if ((cidr < 0) || (cidr > 32) || (end == netmask))
714     {
715       DBG (DBG_ERR, "check_v4_in_range: invalid CIDR value (%s) !\n", netmask);
716       return SANE_FALSE;
717     }
718 
719   mask = 0;
720   cidr -= 8;
721 
722   /* Build a bitmask out of the CIDR value */
723   for (i = 3; cidr >= 0; i--)
724     {
725       mask |= (0xff << (8 * i));
726       cidr -= 8;
727     }
728 
729   if (cidr < 0)
730     mask |= (cidrtomask[cidr + 8] << (8 * i));
731 
732   mask = htonl (mask);
733 
734   /*
735    * Check that the address belongs to the specified subnet, using the bitmask.
736    * The address is represented by a 32bit integer.
737    */
738   if ((base->s_addr & mask) == (inaddr->s_addr & mask))
739     ret = SANE_TRUE;
740 
741   return ret;
742 }
743 #endif /* SANED_USES_AF_INDEP */
744 
745 
746 
747 /* Access control */
748 #ifdef SANED_USES_AF_INDEP
749 static SANE_Status
check_host(int fd)750 check_host (int fd)
751 {
752   struct sockaddr_in *sin = NULL;
753 #ifdef ENABLE_IPV6
754   struct sockaddr_in6 *sin6;
755 #endif /* ENABLE_IPV6 */
756   struct addrinfo hints;
757   struct addrinfo *res;
758   struct addrinfo *resp;
759   int j, access_ok = 0;
760   int err;
761   char text_addr[64];
762 #ifdef ENABLE_IPV6
763   SANE_Bool IPv4map = SANE_FALSE;
764   char *remote_ipv4 = NULL; /* in case we have an IPv4-mapped address (eg ::ffff:127.0.0.1) */
765   char *tmp;
766   struct addrinfo *remote_ipv4_addr = NULL;
767 #endif /* ENABLE_IPV6 */
768   char config_line_buf[1024];
769   char *config_line;
770   char *netmask;
771   char hostname[MAXHOSTNAMELEN];
772 
773   int len;
774   FILE *fp;
775 
776   /* Get address of remote host */
777   remote_address_len = sizeof (remote_address.ss);
778   if (getpeername (fd, &remote_address.sa, (socklen_t *) &remote_address_len) < 0)
779     {
780       DBG (DBG_ERR, "check_host: getpeername failed: %s\n", strerror (errno));
781       remote_ip = strdup ("[error]");
782       return SANE_STATUS_INVAL;
783     }
784 
785   err = getnameinfo (&remote_address.sa, remote_address_len,
786 		     hostname, sizeof (hostname), NULL, 0, NI_NUMERICHOST);
787   if (err)
788     {
789       DBG (DBG_DBG, "check_host: getnameinfo failed: %s\n", gai_strerror(err));
790       remote_ip = strdup ("[error]");
791       return SANE_STATUS_INVAL;
792     }
793   else
794     remote_ip = strdup (hostname);
795 
796 #ifdef ENABLE_IPV6
797   sin6 = &remote_address.sin6;
798 
799   if (IN6_IS_ADDR_V4MAPPED ((struct in6_addr *)sin6->sin6_addr.s6_addr))
800     {
801       DBG (DBG_DBG, "check_host: detected an IPv4-mapped address\n");
802       remote_ipv4 = remote_ip + 7;
803       IPv4map = SANE_TRUE;
804 
805       memset (&hints, 0, sizeof (struct addrinfo));
806       hints.ai_flags = AI_NUMERICHOST;
807       hints.ai_family = PF_INET;
808 
809       err = getaddrinfo (remote_ipv4, NULL, &hints, &res);
810       if (err)
811 	{
812 	  DBG (DBG_DBG, "check_host: getaddrinfo() failed: %s\n", gai_strerror (err));
813 	  IPv4map = SANE_FALSE; /* we failed, remote_ipv4_addr points to nothing */
814 	}
815       else
816 	{
817 	  remote_ipv4_addr = res;
818 	  sin = (struct sockaddr_in *)res->ai_addr;
819 	}
820     }
821 #endif /* ENABLE_IPV6 */
822 
823   DBG (DBG_WARN, "check_host: access by remote host: %s\n", remote_ip);
824 
825   /* Always allow access from local host. Do it here to avoid DNS lookups
826      and reading saned.conf. */
827 
828 #ifdef ENABLE_IPV6
829   if (IPv4map == SANE_TRUE)
830     {
831       if (IN_LOOPBACK (ntohl (sin->sin_addr.s_addr)))
832 	{
833 	  DBG (DBG_MSG,
834 	       "check_host: remote host is IN_LOOPBACK: access granted\n");
835 	  freeaddrinfo (remote_ipv4_addr);
836 	  return SANE_STATUS_GOOD;
837 	}
838       freeaddrinfo (remote_ipv4_addr);
839     }
840 #endif /* ENABLE_IPV6 */
841 
842   sin = &remote_address.sin;
843 
844   switch (SS_FAMILY(remote_address.ss))
845     {
846       case AF_INET:
847 	if (IN_LOOPBACK (ntohl (sin->sin_addr.s_addr)))
848 	  {
849 	    DBG (DBG_MSG,
850 		 "check_host: remote host is IN_LOOPBACK: access granted\n");
851 	    return SANE_STATUS_GOOD;
852 	  }
853 	break;
854 #ifdef ENABLE_IPV6
855       case AF_INET6:
856 	if (IN6_IS_ADDR_LOOPBACK ((struct in6_addr *)sin6->sin6_addr.s6_addr))
857 	  {
858 	    DBG (DBG_MSG,
859 		 "check_host: remote host is IN6_LOOPBACK: access granted\n");
860 	    return SANE_STATUS_GOOD;
861 	  }
862 	break;
863 #endif /* ENABLE_IPV6 */
864       default:
865 	break;
866     }
867 
868   DBG (DBG_DBG, "check_host: remote host is not IN_LOOPBACK"
869 #ifdef ENABLE_IPV6
870        " nor IN6_LOOPBACK"
871 #endif /* ENABLE_IPV6 */
872        "\n");
873 
874 
875   /* Get name of local host */
876   if (gethostname (hostname, sizeof (hostname)) < 0)
877     {
878       DBG (DBG_ERR, "check_host: gethostname failed: %s\n", strerror (errno));
879       return SANE_STATUS_INVAL;
880     }
881   DBG (DBG_DBG, "check_host: local hostname: %s\n", hostname);
882 
883   /* Get local addresses */
884   memset (&hints, 0, sizeof (hints));
885   hints.ai_flags = AI_CANONNAME;
886 #ifdef ENABLE_IPV6
887   hints.ai_family = PF_UNSPEC;
888 #else
889   hints.ai_family = PF_INET;
890 #endif /* ENABLE_IPV6 */
891 
892   err = getaddrinfo (hostname, NULL, &hints, &res);
893   if (err)
894     {
895       DBG (DBG_ERR, "check_host: getaddrinfo for local hostname failed: %s\n",
896 	   gai_strerror (err));
897 
898       /* Proceed even if the local hostname does not resolve */
899       if (err != EAI_NONAME)
900 	return SANE_STATUS_INVAL;
901     }
902   else
903     {
904       for (resp = res; resp != NULL; resp = resp->ai_next)
905 	{
906 	  DBG (DBG_DBG, "check_host: local hostname(s) (from DNS): %s\n",
907 	       resp->ai_canonname);
908 
909 	  err = getnameinfo (resp->ai_addr, resp->ai_addrlen, text_addr,
910 			     sizeof (text_addr), NULL, 0, NI_NUMERICHOST);
911 	  if (err)
912 		strncpy (text_addr, "[error]", 8);
913 
914 #ifdef ENABLE_IPV6
915 	  if ((strcasecmp (text_addr, remote_ip) == 0) ||
916 	      ((IPv4map == SANE_TRUE) && (strcmp (text_addr, remote_ipv4) == 0)))
917 #else
918 	  if (strcmp (text_addr, remote_ip) == 0)
919 #endif /* ENABLE_IPV6 */
920 	    {
921 	      DBG (DBG_MSG, "check_host: remote host has same addr as local: access granted\n");
922 
923 	      freeaddrinfo (res);
924 	      res = NULL;
925 
926 	      return SANE_STATUS_GOOD;
927 	    }
928 	}
929 
930       freeaddrinfo (res);
931       res = NULL;
932 
933       DBG (DBG_DBG,
934 	   "check_host: remote host doesn't have same addr as local\n");
935     }
936 
937   /* must be a remote host: check contents of PATH_NET_CONFIG or
938      /etc/hosts.equiv if former doesn't exist: */
939   for (j = 0; j < NELEMS (config_file_names); ++j)
940     {
941       DBG (DBG_DBG, "check_host: opening config file: %s\n",
942 	   config_file_names[j]);
943       if (config_file_names[j][0] == '/')
944 	fp = fopen (config_file_names[j], "r");
945       else
946 	fp = sanei_config_open (config_file_names[j]);
947       if (!fp)
948 	{
949 	  DBG (DBG_MSG,
950 	       "check_host: can't open config file: %s (%s)\n",
951 	       config_file_names[j], strerror (errno));
952 	  continue;
953 	}
954 
955       while (!access_ok && sanei_config_read (config_line_buf,
956 					      sizeof (config_line_buf), fp))
957 	{
958 	  config_line = config_line_buf; /* from now on, use a pointer */
959 	  DBG (DBG_DBG, "check_host: config file line: `%s'\n", config_line);
960 	  if (config_line[0] == '#')
961 	    continue;           /* ignore comments */
962 
963 	  if (strchr (config_line, '='))
964 	    continue;           /* ignore lines with an = sign */
965 
966 	  len = strlen (config_line);
967 	  if (!len)
968 	    continue;		/* ignore empty lines */
969 
970 	  /* look for a subnet specification */
971 	  netmask = strchr (config_line, '/');
972 	  if (netmask != NULL)
973 	    {
974 	      *netmask = '\0';
975 	      netmask++;
976 	      DBG (DBG_DBG, "check_host: subnet with base IP = %s, CIDR netmask = %s\n",
977 		   config_line, netmask);
978 	    }
979 
980 #ifdef ENABLE_IPV6
981 	  /* IPv6 addresses are enclosed in [] */
982 	  if (*config_line == '[')
983 	    {
984 	      config_line++;
985 	      tmp = strchr (config_line, ']');
986 	      if (tmp == NULL)
987 		{
988 		  DBG (DBG_ERR,
989 		       "check_host: malformed IPv6 address in config file, skipping: [%s\n",
990 		       config_line);
991 		  continue;
992 		}
993 	      *tmp = '\0';
994 	    }
995 #endif /* ENABLE_IPV6 */
996 
997 	  if (strcmp (config_line, "+") == 0)
998 	    {
999 	      access_ok = 1;
1000 	      DBG (DBG_DBG,
1001 		   "check_host: access granted from any host (`+')\n");
1002 	    }
1003 	  /* compare remote_ip (remote IP address) to the config_line */
1004 	  else if (strcasecmp (config_line, remote_ip) == 0)
1005 	    {
1006 	      access_ok = 1;
1007 	      DBG (DBG_DBG,
1008 		   "check_host: access granted from IP address %s\n", remote_ip);
1009 	    }
1010 #ifdef ENABLE_IPV6
1011 	  else if ((IPv4map == SANE_TRUE) && (strcmp (config_line, remote_ipv4) == 0))
1012 	    {
1013 	      access_ok = 1;
1014 	      DBG (DBG_DBG,
1015 		   "check_host: access granted from IP address %s (IPv4-mapped)\n", remote_ip);
1016 	    }
1017 	  /* handle IP ranges, take care of the IPv4map stuff */
1018 	  else if (netmask != NULL)
1019 	    {
1020 	      if (strchr (config_line, ':') != NULL) /* is a v6 address */
1021 		{
1022 		  if (SS_FAMILY(remote_address.ss) == AF_INET6)
1023 		    {
1024 		      if (check_v6_in_range (sin6, config_line, netmask))
1025 			{
1026 			  access_ok = 1;
1027 			  DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet [%s]/%s)\n",
1028 			       remote_ip, config_line, netmask);
1029 			}
1030 		    }
1031 		}
1032 	      else /* is a v4 address */
1033 		{
1034 		  if (IPv4map == SANE_TRUE)
1035 		    {
1036 		      /* get a sockaddr_in representing the v4-mapped IP address */
1037 		      memset (&hints, 0, sizeof (struct addrinfo));
1038 		      hints.ai_flags = AI_NUMERICHOST;
1039 		      hints.ai_family = PF_INET;
1040 
1041 		      err = getaddrinfo (remote_ipv4, NULL, &hints, &res);
1042 		      if (err)
1043 			DBG (DBG_DBG, "check_host: getaddrinfo() failed: %s\n", gai_strerror (err));
1044 		      else
1045 			sin = (struct sockaddr_in *)res->ai_addr;
1046 		    }
1047 
1048 		  if ((SS_FAMILY(remote_address.ss) == AF_INET) ||
1049 		      (IPv4map == SANE_TRUE))
1050 		    {
1051 
1052 		      if (check_v4_in_range (sin, config_line, netmask))
1053 			{
1054 			  DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet %s/%s)\n",
1055 			       ((IPv4map == SANE_TRUE) ? remote_ipv4 : remote_ip), config_line, netmask);
1056 			  access_ok = 1;
1057 			}
1058 		      else
1059 			{
1060 			  /* restore the old sin pointer */
1061 			  sin = &remote_address.sin;
1062 			}
1063 
1064 		      if (res != NULL)
1065 			{
1066 			  freeaddrinfo (res);
1067 			  res = NULL;
1068 			}
1069 		    }
1070 		}
1071 	    }
1072 #else /* !ENABLE_IPV6 */
1073 	  /* handle IP ranges */
1074 	  else if (netmask != NULL)
1075 	    {
1076 	      if (check_v4_in_range (sin, config_line, netmask))
1077 		{
1078 		  access_ok = 1;
1079 		  DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet %s/%s)\n",
1080 		       remote_ip, config_line, netmask);
1081 		}
1082 	    }
1083 #endif /* ENABLE_IPV6 */
1084 	  else
1085 	    {
1086 	      memset (&hints, 0, sizeof (hints));
1087 	      hints.ai_flags = AI_CANONNAME;
1088 #ifdef ENABLE_IPV6
1089 	      hints.ai_family = PF_UNSPEC;
1090 #else
1091 	      hints.ai_family = PF_INET;
1092 #endif /* ENABLE_IPV6 */
1093 
1094 	      err = getaddrinfo (config_line, NULL, &hints, &res);
1095 	      if (err)
1096 		{
1097 		  DBG (DBG_DBG,
1098 		       "check_host: getaddrinfo for `%s' failed: %s\n",
1099 		       config_line, gai_strerror (err));
1100 		  DBG (DBG_MSG, "check_host: entry isn't an IP address "
1101 		       "and can't be found in DNS\n");
1102 		  continue;
1103 		}
1104 	      else
1105 		{
1106 		  for (resp = res; resp != NULL; resp = resp->ai_next)
1107 		    {
1108 		      err = getnameinfo (resp->ai_addr, resp->ai_addrlen, text_addr,
1109 					 sizeof (text_addr), NULL, 0, NI_NUMERICHOST);
1110 		      if (err)
1111 			strncpy (text_addr, "[error]", 8);
1112 
1113 		      DBG (DBG_MSG,
1114 			   "check_host: DNS lookup returns IP address: %s\n",
1115 			   text_addr);
1116 
1117 #ifdef ENABLE_IPV6
1118 		      if ((strcasecmp (text_addr, remote_ip) == 0) ||
1119 			  ((IPv4map == SANE_TRUE) && (strcmp (text_addr, remote_ipv4) == 0)))
1120 #else
1121 		      if (strcmp (text_addr, remote_ip) == 0)
1122 #endif /* ENABLE_IPV6 */
1123 			access_ok = 1;
1124 
1125 		      if (access_ok)
1126 			break;
1127 		    }
1128 		  freeaddrinfo (res);
1129 		  res = NULL;
1130 		}
1131 	    }
1132 	}
1133       fclose (fp);
1134     }
1135 
1136   if (access_ok)
1137     return SANE_STATUS_GOOD;
1138 
1139   return SANE_STATUS_ACCESS_DENIED;
1140 }
1141 
1142 #else /* !SANED_USES_AF_INDEP */
1143 
1144 static SANE_Status
check_host(int fd)1145 check_host (int fd)
1146 {
1147   struct sockaddr_in sin;
1148   int j, access_ok = 0;
1149   struct hostent *he;
1150   char text_addr[64];
1151   char config_line_buf[1024];
1152   char *config_line;
1153   char *netmask;
1154   char hostname[MAXHOSTNAMELEN];
1155   char *r_hostname;
1156   static struct in_addr config_line_address;
1157 
1158   int len;
1159   FILE *fp;
1160 
1161   /* Get address of remote host */
1162   len = sizeof (sin);
1163   if (getpeername (fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0)
1164     {
1165       DBG (DBG_ERR, "check_host: getpeername failed: %s\n", strerror (errno));
1166       remote_ip = strdup ("[error]");
1167       return SANE_STATUS_INVAL;
1168     }
1169   r_hostname = inet_ntoa (sin.sin_addr);
1170   remote_ip = strdup (r_hostname);
1171   DBG (DBG_WARN, "check_host: access by remote host: %s\n",
1172        remote_ip);
1173   /* Save remote address for check of control and data connections */
1174   memcpy (&remote_address, &sin.sin_addr, sizeof (remote_address));
1175 
1176   /* Always allow access from local host. Do it here to avoid DNS lookups
1177      and reading saned.conf. */
1178   if (IN_LOOPBACK (ntohl (sin.sin_addr.s_addr)))
1179     {
1180       DBG (DBG_MSG,
1181 	   "check_host: remote host is IN_LOOPBACK: access accepted\n");
1182       return SANE_STATUS_GOOD;
1183     }
1184   DBG (DBG_DBG, "check_host: remote host is not IN_LOOPBACK\n");
1185 
1186   /* Get name of local host */
1187   if (gethostname (hostname, sizeof (hostname)) < 0)
1188     {
1189       DBG (DBG_ERR, "check_host: gethostname failed: %s\n", strerror (errno));
1190       return SANE_STATUS_INVAL;
1191     }
1192   DBG (DBG_DBG, "check_host: local hostname: %s\n", hostname);
1193 
1194   /* Get local address */
1195   he = gethostbyname (hostname);
1196 
1197   if (!he)
1198     {
1199       DBG (DBG_ERR, "check_host: gethostbyname for local hostname failed: %s\n",
1200 	   hstrerror (h_errno));
1201 
1202       /* Proceed even if the local hostname doesn't resolve */
1203       if (h_errno != HOST_NOT_FOUND)
1204 	return SANE_STATUS_INVAL;
1205     }
1206   else
1207     {
1208       DBG (DBG_DBG, "check_host: local hostname (from DNS): %s\n",
1209 	   he->h_name);
1210 
1211       if ((he->h_length == 4) || (he->h_addrtype == AF_INET))
1212 	{
1213 	  if (!inet_ntop (he->h_addrtype, he->h_addr_list[0], text_addr,
1214 			  sizeof (text_addr)))
1215 	    strcpy (text_addr, "[error]");
1216 	  DBG (DBG_DBG, "check_host: local host address (from DNS): %s\n",
1217 	       text_addr);
1218 	  if (memcmp (he->h_addr_list[0], &remote_address.s_addr, 4) == 0)
1219 	    {
1220 	      DBG (DBG_MSG,
1221 		   "check_host: remote host has same addr as local: "
1222 		   "access accepted\n");
1223 	      return SANE_STATUS_GOOD;
1224 	    }
1225 	}
1226       else
1227 	{
1228 	  DBG (DBG_ERR, "check_host: can't get local address "
1229 	       "(only IPv4 is supported)\n");
1230 	}
1231 
1232       DBG (DBG_DBG,
1233 	   "check_host: remote host doesn't have same addr as local\n");
1234     }
1235 
1236   /* must be a remote host: check contents of PATH_NET_CONFIG or
1237      /etc/hosts.equiv if former doesn't exist: */
1238   for (j = 0; j < NELEMS (config_file_names); ++j)
1239     {
1240       DBG (DBG_DBG, "check_host: opening config file: %s\n",
1241 	   config_file_names[j]);
1242       if (config_file_names[j][0] == '/')
1243 	fp = fopen (config_file_names[j], "r");
1244       else
1245 	fp = sanei_config_open (config_file_names[j]);
1246       if (!fp)
1247 	{
1248 	  DBG (DBG_MSG,
1249 	       "check_host: can't open config file: %s (%s)\n",
1250 	       config_file_names[j], strerror (errno));
1251 	  continue;
1252 	}
1253 
1254       while (!access_ok && sanei_config_read (config_line_buf,
1255 					      sizeof (config_line_buf), fp))
1256 	{
1257 	  config_line = config_line_buf; /* from now on, use a pointer */
1258 	  DBG (DBG_DBG, "check_host: config file line: `%s'\n", config_line);
1259 	  if (config_line[0] == '#')
1260 	    continue;           /* ignore comments */
1261 
1262 	  if (strchr (config_line, '='))
1263 	    continue;           /* ignore lines with an = sign */
1264 
1265 	  len = strlen (config_line);
1266 	  if (!len)
1267 	    continue;		/* ignore empty lines */
1268 
1269 	  /* look for a subnet specification */
1270 	  netmask = strchr (config_line, '/');
1271 	  if (netmask != NULL)
1272 	    {
1273 	      *netmask = '\0';
1274 	      netmask++;
1275 	      DBG (DBG_DBG, "check_host: subnet with base IP = %s, CIDR netmask = %s\n",
1276 		   config_line, netmask);
1277 	    }
1278 
1279 	  if (strcmp (config_line, "+") == 0)
1280 	    {
1281 	      access_ok = 1;
1282 	      DBG (DBG_DBG,
1283 		   "check_host: access accepted from any host (`+')\n");
1284 	    }
1285 	  else
1286 	    {
1287 	      if (inet_pton (AF_INET, config_line, &config_line_address) > 0)
1288 		{
1289 		  if (memcmp (&remote_address.s_addr,
1290 			      &config_line_address.s_addr, 4) == 0)
1291 		    access_ok = 1;
1292 		  else if (netmask != NULL)
1293 		    {
1294 		      if (check_v4_in_range (&remote_address, &config_line_address, netmask))
1295 			{
1296 			  access_ok = 1;
1297 			  DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet %s/%s)\n",
1298 			       remote_ip, config_line, netmask);
1299 			}
1300 		    }
1301 		}
1302 	      else
1303 		{
1304 		  DBG (DBG_DBG,
1305 		       "check_host: inet_pton for `%s' failed\n",
1306 		       config_line);
1307 		  he = gethostbyname (config_line);
1308 		  if (!he)
1309 		    {
1310 		      DBG (DBG_DBG,
1311 			   "check_host: gethostbyname for `%s' failed: %s\n",
1312 			   config_line, hstrerror (h_errno));
1313 		      DBG (DBG_MSG, "check_host: entry isn't an IP address "
1314 			   "and can't be found in DNS\n");
1315 		      continue;
1316 		    }
1317 		  if (!inet_ntop (he->h_addrtype, he->h_addr_list[0],
1318 				  text_addr, sizeof (text_addr)))
1319 		    strcpy (text_addr, "[error]");
1320 		  DBG (DBG_MSG,
1321 		       "check_host: DNS lookup returns IP address: %s\n",
1322 		       text_addr);
1323 		  if (memcmp (&remote_address.s_addr,
1324 			      he->h_addr_list[0], 4) == 0)
1325 		    access_ok = 1;
1326 		}
1327 	    }
1328 	}
1329       fclose (fp);
1330       if (access_ok)
1331 	return SANE_STATUS_GOOD;
1332     }
1333   return SANE_STATUS_ACCESS_DENIED;
1334 }
1335 
1336 #endif /* SANED_USES_AF_INDEP */
1337 
1338 static int
init(Wire * w)1339 init (Wire * w)
1340 {
1341   SANE_Word word, be_version_code;
1342   SANE_Init_Reply reply;
1343   SANE_Status status;
1344   SANE_Init_Req req;
1345 
1346   reset_watchdog ();
1347 
1348   status = check_host (w->io.fd);
1349   if (status != SANE_STATUS_GOOD)
1350     {
1351       DBG (DBG_WARN, "init: access by host %s denied\n", remote_ip);
1352       return -1;
1353     }
1354   else
1355     DBG (DBG_MSG, "init: access granted\n");
1356 
1357   sanei_w_set_dir (w, WIRE_DECODE);
1358   if (w->status)
1359     {
1360       DBG (DBG_ERR, "init: bad status after sanei_w_set_dir: %d\n", w->status);
1361       return -1;
1362     }
1363 
1364   sanei_w_word (w, &word);	/* decode procedure number */
1365   if (w->status || word != SANE_NET_INIT)
1366     {
1367       DBG (DBG_ERR, "init: bad status=%d or procnum=%d\n",
1368 	   w->status, word);
1369       return -1;
1370     }
1371 
1372   sanei_w_init_req (w, &req);
1373   if (w->status)
1374     {
1375       DBG (DBG_ERR, "init: bad status after sanei_w_init_req: %d\n", w->status);
1376       return -1;
1377     }
1378 
1379   w->version = SANEI_NET_PROTOCOL_VERSION;
1380   if (req.username)
1381     default_username = strdup (req.username);
1382 
1383   sanei_w_free (w, (WireCodecFunc) sanei_w_init_req, &req);
1384   if (w->status)
1385     {
1386       DBG (DBG_ERR, "init: bad status after sanei_w_free: %d\n", w->status);
1387       return -1;
1388     }
1389 
1390   reply.version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR,
1391 					  SANEI_NET_PROTOCOL_VERSION);
1392 
1393   DBG (DBG_WARN, "init: access granted to %s@%s\n",
1394        default_username, remote_ip);
1395 
1396   if (status == SANE_STATUS_GOOD)
1397     {
1398       status = sane_init (&be_version_code, auth_callback);
1399       if (status != SANE_STATUS_GOOD)
1400 	DBG (DBG_ERR, "init: failed to initialize backend (%s)\n",
1401 	     sane_strstatus (status));
1402 
1403       if (SANE_VERSION_MAJOR (be_version_code) != V_MAJOR)
1404 	{
1405 	  DBG (DBG_ERR,
1406 	       "init: unexpected backend major version %d (expected %d)\n",
1407 	       SANE_VERSION_MAJOR (be_version_code), V_MAJOR);
1408 	  status = SANE_STATUS_INVAL;
1409 	}
1410     }
1411   reply.status = status;
1412   if (status != SANE_STATUS_GOOD)
1413     reply.version_code = 0;
1414   sanei_w_reply (w, (WireCodecFunc) sanei_w_init_reply, &reply);
1415 
1416   if (w->status || status != SANE_STATUS_GOOD)
1417     return -1;
1418 
1419   return 0;
1420 }
1421 
1422 #ifdef SANED_USES_AF_INDEP
1423 static int
start_scan(Wire * w,int h,SANE_Start_Reply * reply)1424 start_scan (Wire * w, int h, SANE_Start_Reply * reply)
1425 {
1426   union {
1427     struct sockaddr_storage ss;
1428     struct sockaddr sa;
1429     struct sockaddr_in sin;
1430 #ifdef ENABLE_IPV6
1431     struct sockaddr_in6 sin6;
1432 #endif /* ENABLE_IPV6 */
1433   } data_addr;
1434   struct sockaddr_in *sin;
1435 #ifdef ENABLE_IPV6
1436   struct sockaddr_in6 *sin6;
1437 #endif /* ENABLE_IPV6 */
1438   SANE_Handle be_handle;
1439   int fd, len;
1440   in_port_t data_port;
1441   int ret = -1;
1442 
1443   be_handle = handle[h].handle;
1444 
1445   len = sizeof (data_addr.ss);
1446   if (getsockname (w->io.fd, &data_addr.sa, (socklen_t *) &len) < 0)
1447     {
1448       DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n",
1449 	   strerror (errno));
1450       reply->status = SANE_STATUS_IO_ERROR;
1451       return -1;
1452     }
1453 
1454   fd = socket (SS_FAMILY(data_addr.ss), SOCK_STREAM, 0);
1455   if (fd < 0)
1456     {
1457       DBG (DBG_ERR, "start_scan: failed to obtain data socket (%s)\n",
1458 	   strerror (errno));
1459       reply->status = SANE_STATUS_IO_ERROR;
1460       return -1;
1461     }
1462 
1463   switch (SS_FAMILY(data_addr.ss))
1464     {
1465       case AF_INET:
1466 	sin = &data_addr.sin;
1467 	break;
1468 #ifdef ENABLE_IPV6
1469       case AF_INET6:
1470 	sin6 = &data_addr.sin6;
1471 	break;
1472 #endif /* ENABLE_IPV6 */
1473       default:
1474 	break;
1475     }
1476 
1477   /* Try to bind a port between data_port_lo and data_port_hi for the data connection */
1478   for (data_port = data_port_lo; data_port <= data_port_hi; data_port++)
1479     {
1480       switch (SS_FAMILY(data_addr.ss))
1481         {
1482           case AF_INET:
1483             sin->sin_port = htons(data_port);
1484             break;
1485 #ifdef ENABLE_IPV6
1486           case AF_INET6:
1487             sin6->sin6_port = htons(data_port);
1488             break;
1489 #endif /* ENABLE_IPV6 */
1490           default:
1491             break;
1492        }
1493 
1494       DBG (DBG_INFO, "start_scan: trying to bind data port %d\n", data_port);
1495 
1496       ret = bind (fd, &data_addr.sa, len);
1497       if (ret == 0)
1498         break;
1499     }
1500 
1501   if (ret < 0)
1502     {
1503       DBG (DBG_ERR, "start_scan: failed to bind address (%s)\n",
1504 	   strerror (errno));
1505       reply->status = SANE_STATUS_IO_ERROR;
1506       return -1;
1507     }
1508 
1509   if (listen (fd, 1) < 0)
1510     {
1511       DBG (DBG_ERR, "start_scan: failed to make socket listen (%s)\n",
1512 	   strerror (errno));
1513       reply->status = SANE_STATUS_IO_ERROR;
1514       return -1;
1515     }
1516 
1517   if (getsockname (fd, &data_addr.sa, (socklen_t *) &len) < 0)
1518     {
1519       DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n",
1520 	   strerror (errno));
1521       reply->status = SANE_STATUS_IO_ERROR;
1522       return -1;
1523     }
1524 
1525   switch (SS_FAMILY(data_addr.ss))
1526     {
1527       case AF_INET:
1528 	sin = &data_addr.sin;
1529 	reply->port = ntohs (sin->sin_port);
1530 	break;
1531 #ifdef ENABLE_IPV6
1532       case AF_INET6:
1533 	sin6 = &data_addr.sin6;
1534 	reply->port = ntohs (sin6->sin6_port);
1535 	break;
1536 #endif /* ENABLE_IPV6 */
1537       default:
1538 	break;
1539     }
1540 
1541   DBG (DBG_MSG, "start_scan: using port %d for data\n", reply->port);
1542 
1543   reply->status = sane_start (be_handle);
1544   if (reply->status == SANE_STATUS_GOOD)
1545     {
1546       handle[h].scanning = 1;
1547       handle[h].docancel = 0;
1548     }
1549 
1550   return fd;
1551 }
1552 
1553 #else /* !SANED_USES_AF_INDEP */
1554 
1555 static int
start_scan(Wire * w,int h,SANE_Start_Reply * reply)1556 start_scan (Wire * w, int h, SANE_Start_Reply * reply)
1557 {
1558   struct sockaddr_in sin;
1559   SANE_Handle be_handle;
1560   int fd, len;
1561   in_port_t data_port;
1562   int ret;
1563 
1564   be_handle = handle[h].handle;
1565 
1566   len = sizeof (sin);
1567   if (getsockname (w->io.fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0)
1568     {
1569       DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n",
1570 	   strerror (errno));
1571       reply->status = SANE_STATUS_IO_ERROR;
1572       return -1;
1573     }
1574 
1575   fd = socket (AF_INET, SOCK_STREAM, 0);
1576   if (fd < 0)
1577     {
1578       DBG (DBG_ERR, "start_scan: failed to obtain data socket (%s)\n",
1579 	   strerror (errno));
1580       reply->status = SANE_STATUS_IO_ERROR;
1581       return -1;
1582     }
1583 
1584   /* Try to bind a port between data_port_lo and data_port_hi for the data connection */
1585   for (data_port = data_port_lo; data_port <= data_port_hi; data_port++)
1586     {
1587       sin.sin_port = htons(data_port);
1588 
1589       DBG(DBG_INFO, "start_scan: trying to bind data port %d\n", data_port);
1590 
1591       ret = bind (fd, (struct sockaddr *) &sin, len);
1592       if (ret == 0)
1593         break;
1594     }
1595 
1596   if (ret < 0)
1597     {
1598       DBG (DBG_ERR, "start_scan: failed to bind address (%s)\n",
1599 	   strerror (errno));
1600       reply->status = SANE_STATUS_IO_ERROR;
1601       return -1;
1602     }
1603 
1604   if (listen (fd, 1) < 0)
1605     {
1606       DBG (DBG_ERR, "start_scan: failed to make socket listen (%s)\n",
1607 	   strerror (errno));
1608       reply->status = SANE_STATUS_IO_ERROR;
1609       return -1;
1610     }
1611 
1612   if (getsockname (fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0)
1613     {
1614       DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n",
1615 	   strerror (errno));
1616       reply->status = SANE_STATUS_IO_ERROR;
1617       return -1;
1618     }
1619 
1620   reply->port = ntohs (sin.sin_port);
1621 
1622   DBG (DBG_MSG, "start_scan: using port %d for data\n", reply->port);
1623 
1624   reply->status = sane_start (be_handle);
1625   if (reply->status == SANE_STATUS_GOOD)
1626     {
1627       handle[h].scanning = 1;
1628       handle[h].docancel = 0;
1629     }
1630 
1631   return fd;
1632 }
1633 #endif /* SANED_USES_AF_INDEP */
1634 
1635 static int
store_reclen(SANE_Byte * buf,size_t buf_size,int i,size_t reclen)1636 store_reclen (SANE_Byte * buf, size_t buf_size, int i, size_t reclen)
1637 {
1638   buf[i++] = (reclen >> 24) & 0xff;
1639   if (i >= (int) buf_size)
1640     i = 0;
1641   buf[i++] = (reclen >> 16) & 0xff;
1642   if (i >= (int) buf_size)
1643     i = 0;
1644   buf[i++] = (reclen >> 8) & 0xff;
1645   if (i >= (int) buf_size)
1646     i = 0;
1647   buf[i++] = (reclen >> 0) & 0xff;
1648   if (i >= (int) buf_size)
1649     i = 0;
1650   return i;
1651 }
1652 
1653 static void
do_scan(Wire * w,int h,int data_fd)1654 do_scan (Wire * w, int h, int data_fd)
1655 {
1656   int num_fds, be_fd = -1, reader, bytes_in_buf, status_dirty = 0;
1657   size_t writer;
1658   SANE_Handle be_handle = handle[h].handle;
1659   struct timeval tv, *timeout = 0;
1660   fd_set rd_set, rd_mask, wr_set, wr_mask;
1661   SANE_Byte *buf = NULL;
1662   SANE_Status status;
1663   ssize_t nwritten;
1664   SANE_Int length;
1665   size_t nbytes;
1666 
1667   DBG (3, "do_scan: start\n");
1668 
1669   /*
1670    * Allocate the read buffer.
1671    *
1672    */
1673   buf = malloc (buffer_size);
1674   if (!buf)
1675     {
1676       status = SANE_STATUS_NO_MEM;
1677       DBG (DBG_ERR, "do_scan: failed to allocate read buffer (%zu bytes)\n",
1678            buffer_size);
1679     }
1680   else
1681     {
1682       FD_ZERO(&rd_mask);
1683       FD_SET(w->io.fd, &rd_mask);
1684       num_fds = w->io.fd + 1;
1685 
1686       FD_ZERO(&wr_mask);
1687       FD_SET(data_fd, &wr_mask);
1688       if (data_fd >= num_fds)
1689         num_fds = data_fd + 1;
1690 
1691       sane_set_io_mode (be_handle, SANE_TRUE);
1692       if (sane_get_select_fd (be_handle, &be_fd) == SANE_STATUS_GOOD)
1693         {
1694           FD_SET(be_fd, &rd_mask);
1695           if (be_fd >= num_fds)
1696             num_fds = be_fd + 1;
1697         }
1698       else
1699         {
1700           memset (&tv, 0, sizeof(tv));
1701           timeout = &tv;
1702         }
1703 
1704       status = SANE_STATUS_GOOD;
1705       reader = writer = bytes_in_buf = 0;
1706       do
1707         {
1708           rd_set = rd_mask;
1709           wr_set = wr_mask;
1710           if (select (num_fds, &rd_set, &wr_set, 0, timeout) < 0)
1711             {
1712               if (be_fd >= 0 && errno == EBADF)
1713                 {
1714                   /* This normally happens when a backend closes a select
1715                    filedescriptor when reaching the end of file.  So
1716                    pass back this status to the client: */
1717                   FD_CLR(be_fd, &rd_mask);
1718                   be_fd = -1;
1719                   /* only set status_dirty if EOF hasn't been already detected */
1720                   if (status == SANE_STATUS_GOOD)
1721                     status_dirty = 1;
1722                   status = SANE_STATUS_EOF;
1723                   DBG (DBG_INFO, "do_scan: select_fd was closed --> EOF\n");
1724                   continue;
1725                 }
1726               else
1727                 {
1728                   status = SANE_STATUS_IO_ERROR;
1729                   DBG (DBG_ERR, "do_scan: select failed (%s)\n",
1730                        strerror (errno));
1731                   break;
1732                 }
1733             }
1734 
1735           if (bytes_in_buf)
1736             {
1737               if (FD_ISSET(data_fd, &wr_set))
1738                 {
1739                   if (bytes_in_buf > 0)
1740                     {
1741                       /* write more input data */
1742                       nbytes = bytes_in_buf;
1743                       if (writer + nbytes > buffer_size)
1744                         nbytes = buffer_size - writer;
1745                       DBG (DBG_INFO,
1746                            "do_scan: trying to write %d bytes to client\n",
1747                            nbytes);
1748                       nwritten = write (data_fd, buf + writer, nbytes);
1749                       DBG (DBG_INFO, "do_scan: wrote %ld bytes to client\n",
1750                            nwritten);
1751                       if (nwritten < 0)
1752                         {
1753                           DBG (DBG_ERR, "do_scan: write failed (%s)\n",
1754                                strerror (errno));
1755                           status = SANE_STATUS_CANCELLED;
1756                           handle[h].docancel = 1;
1757                           break;
1758                         }
1759                       bytes_in_buf -= (size_t) nwritten;
1760                       writer += (size_t) nwritten;
1761                       if (writer == buffer_size)
1762                         writer = 0;
1763                     }
1764                 }
1765             }
1766           else if (status == SANE_STATUS_GOOD
1767               && (timeout || FD_ISSET(be_fd, &rd_set)))
1768             {
1769               int i;
1770 
1771               /* get more input data */
1772 
1773               /* reserve 4 bytes to store the length of the data record: */
1774               i = reader;
1775               reader += 4;
1776               if (reader >= (int) buffer_size)
1777                 reader -= buffer_size;
1778 
1779               assert(bytes_in_buf == 0);
1780               nbytes = buffer_size - 4;
1781               if (reader + nbytes > buffer_size)
1782                 nbytes = buffer_size - reader;
1783 
1784               DBG (DBG_INFO, "do_scan: trying to read %d bytes from scanner\n",
1785                    nbytes);
1786               status = sane_read (be_handle, buf + reader, nbytes, &length);
1787               DBG (DBG_INFO, "do_scan: read %d bytes from scanner\n", length);
1788 
1789               reset_watchdog ();
1790 
1791               reader += length;
1792               if (reader >= (int) buffer_size)
1793                 reader = 0;
1794               bytes_in_buf += length + 4;
1795 
1796               if (status != SANE_STATUS_GOOD)
1797                 {
1798                   reader = i; /* restore reader index */
1799                   status_dirty = 1;
1800                   DBG (DBG_MSG, "do_scan: status = `%s'\n",
1801                        sane_strstatus (status));
1802                 }
1803               else
1804                 store_reclen (buf, buffer_size, i, length);
1805             }
1806 
1807           if (status_dirty && buffer_size - bytes_in_buf >= 5)
1808             {
1809               status_dirty = 0;
1810               reader = store_reclen (buf, buffer_size, reader, 0xffffffff);
1811               buf[reader] = status;
1812               bytes_in_buf += 5;
1813               DBG (DBG_MSG, "do_scan: statuscode `%s' was added to buffer\n",
1814                    sane_strstatus (status));
1815             }
1816 
1817           if (FD_ISSET(w->io.fd, &rd_set))
1818             {
1819               DBG (DBG_MSG, "do_scan: processing RPC request on fd %d\n",
1820                    w->io.fd);
1821               if (process_request (w) < 0)
1822                 handle[h].docancel = 1;
1823 
1824               if (handle[h].docancel)
1825                 break;
1826             }
1827         }
1828       while (status == SANE_STATUS_GOOD || bytes_in_buf > 0 || status_dirty);
1829       DBG (DBG_MSG, "do_scan: done, status=%s\n", sane_strstatus (status));
1830 
1831       free (buf);
1832       buf = NULL;
1833     }
1834 
1835   if (handle[h].docancel)
1836     sane_cancel (handle[h].handle);
1837 
1838   handle[h].docancel = 0;
1839   handle[h].scanning = 0;
1840 }
1841 
1842 static int
process_request(Wire * w)1843 process_request (Wire * w)
1844 {
1845   SANE_Handle be_handle;
1846   SANE_Word h, word;
1847   int i;
1848 
1849   DBG (DBG_DBG, "process_request: waiting for request\n");
1850   sanei_w_set_dir (w, WIRE_DECODE);
1851   sanei_w_word (w, &word);	/* decode procedure number */
1852 
1853   if (w->status)
1854     {
1855       DBG (DBG_ERR,
1856 	   "process_request: bad status %d\n", w->status);
1857       return -1;
1858     }
1859 
1860   current_request = word;
1861 
1862   DBG (DBG_MSG, "process_request: got request %d\n", current_request);
1863 
1864   switch (current_request)
1865     {
1866     case SANE_NET_GET_DEVICES:
1867       {
1868 	SANE_Get_Devices_Reply reply;
1869 
1870 	reply.status =
1871 	  sane_get_devices ((const SANE_Device ***) &reply.device_list,
1872 			    SANE_TRUE);
1873 	sanei_w_reply (w, (WireCodecFunc) sanei_w_get_devices_reply, &reply);
1874       }
1875       break;
1876 
1877     case SANE_NET_OPEN:
1878       {
1879 	SANE_Open_Reply reply;
1880 	SANE_Handle be_handle;
1881 	SANE_String name, resource;
1882 
1883 	sanei_w_string (w, &name);
1884 	if (w->status)
1885 	  {
1886 	    DBG (DBG_ERR,
1887 		 "process_request: (open) error while decoding args (%s)\n",
1888 		 strerror (w->status));
1889 	    return 1;
1890 	  }
1891 
1892 	if (!name)
1893 	  {
1894 	    DBG (DBG_ERR, "process_request: (open) device_name == NULL\n");
1895 	    reply.status = SANE_STATUS_INVAL;
1896 	    sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply);
1897 	    return 1;
1898 	  }
1899 
1900 	can_authorize = 1;
1901 
1902 	resource = strdup (name);
1903 
1904 	if (strlen(resource) == 0) {
1905 
1906 	  const SANE_Device **device_list;
1907 
1908 	  DBG(DBG_DBG, "process_request: (open) strlen(resource) == 0\n");
1909 	  free (resource);
1910 
1911 	  if ((i = sane_get_devices (&device_list, SANE_TRUE)) !=
1912 	      SANE_STATUS_GOOD)
1913 	    {
1914 	      DBG(DBG_ERR, "process_request: (open) sane_get_devices failed\n");
1915 	      memset (&reply, 0, sizeof (reply));
1916 	      reply.status = i;
1917 	      sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply);
1918 	      break;
1919 	    }
1920 
1921 	  if ((device_list == NULL) || (device_list[0] == NULL))
1922 	    {
1923 	      DBG(DBG_ERR, "process_request: (open) device_list[0] == 0\n");
1924 	      memset (&reply, 0, sizeof (reply));
1925 	      reply.status = SANE_STATUS_INVAL;
1926 	      sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply);
1927 	      break;
1928 	    }
1929 
1930 	  resource = strdup (device_list[0]->name);
1931 	}
1932 
1933 	if (strchr (resource, ':'))
1934 	  *(strchr (resource, ':')) = 0;
1935 
1936 	if (sanei_authorize (resource, "saned", auth_callback) !=
1937 	    SANE_STATUS_GOOD)
1938 	  {
1939 	    DBG (DBG_ERR, "process_request: access to resource `%s' denied\n",
1940 		 resource);
1941 	    free (resource);
1942 	    memset (&reply, 0, sizeof (reply));	/* avoid leaking bits */
1943 	    reply.status = SANE_STATUS_ACCESS_DENIED;
1944 	  }
1945 	else
1946 	  {
1947 	    DBG (DBG_MSG, "process_request: access to resource `%s' granted\n",
1948 		 resource);
1949 	    free (resource);
1950 	    memset (&reply, 0, sizeof (reply));	/* avoid leaking bits */
1951 	    reply.status = sane_open (name, &be_handle);
1952 	    DBG (DBG_MSG, "process_request: sane_open returned: %s\n",
1953 		 sane_strstatus (reply.status));
1954 	  }
1955 
1956 	if (reply.status == SANE_STATUS_GOOD)
1957 	  {
1958 	    h = get_free_handle ();
1959 	    if (h < 0)
1960 	      reply.status = SANE_STATUS_NO_MEM;
1961 	    else
1962 	      {
1963 		handle[h].handle = be_handle;
1964 		reply.handle = h;
1965 	      }
1966 	  }
1967 
1968 	can_authorize = 0;
1969 
1970 	sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply);
1971 	sanei_w_free (w, (WireCodecFunc) sanei_w_string, &name);
1972       }
1973       break;
1974 
1975     case SANE_NET_CLOSE:
1976       {
1977 	SANE_Word ack = 0;
1978 
1979 	h = decode_handle (w, "close");
1980 	close_handle (h);
1981 	sanei_w_reply (w, (WireCodecFunc) sanei_w_word, &ack);
1982       }
1983       break;
1984 
1985     case SANE_NET_GET_OPTION_DESCRIPTORS:
1986       {
1987 	SANE_Option_Descriptor_Array opt;
1988 
1989 	h = decode_handle (w, "get_option_descriptors");
1990 	if (h < 0)
1991 	  return 1;
1992 	be_handle = handle[h].handle;
1993 	sane_control_option (be_handle, 0, SANE_ACTION_GET_VALUE,
1994 			     &opt.num_options, 0);
1995 
1996 	opt.desc = malloc (opt.num_options * sizeof (opt.desc[0]));
1997 	for (i = 0; i < opt.num_options; ++i)
1998 	  opt.desc[i] = (SANE_Option_Descriptor *)
1999 	    sane_get_option_descriptor (be_handle, i);
2000 
2001 	sanei_w_reply (w,(WireCodecFunc) sanei_w_option_descriptor_array,
2002 		       &opt);
2003 
2004 	free (opt.desc);
2005       }
2006       break;
2007 
2008     case SANE_NET_CONTROL_OPTION:
2009       {
2010 	SANE_Control_Option_Req req;
2011 	SANE_Control_Option_Reply reply;
2012 
2013 	sanei_w_control_option_req (w, &req);
2014 	if (w->status || (unsigned) req.handle >= (unsigned) num_handles
2015 	    || !handle[req.handle].inuse)
2016 	  {
2017 	    DBG (DBG_ERR,
2018 		 "process_request: (control_option) "
2019 		 "error while decoding args h=%d (%s)\n"
2020 		 , req.handle, strerror (w->status));
2021 	    return 1;
2022 	  }
2023 
2024         /* Addresses CVE-2017-6318 (#315576, Debian BTS #853804) */
2025         /* This is done here (rather than in sanei/sanei_wire.c where
2026          * it should be done) to minimize scope of impact and amount
2027          * of code change.
2028          */
2029         if (w->direction == WIRE_DECODE
2030             && req.value_type == SANE_TYPE_STRING
2031             && req.action     == SANE_ACTION_GET_VALUE)
2032           {
2033             if (req.value)
2034               {
2035                 /* FIXME: If req.value contains embedded NUL
2036                  *        characters, this is wrong but we do not have
2037                  *        access to the amount of memory allocated in
2038                  *        sanei/sanei_wire.c at this point.
2039                  */
2040                 w->allocated_memory -= (1 + strlen (req.value));
2041                 free (req.value);
2042               }
2043             req.value = malloc (req.value_size);
2044             if (!req.value)
2045               {
2046                 w->status = ENOMEM;
2047                 DBG (DBG_ERR,
2048                      "process_request: (control_option) "
2049                      "h=%d (%s)\n", req.handle, strerror (w->status));
2050                 return 1;
2051               }
2052             memset (req.value, 0, req.value_size);
2053             w->allocated_memory += req.value_size;
2054           }
2055 
2056 	can_authorize = 1;
2057 
2058 	memset (&reply, 0, sizeof (reply));	/* avoid leaking bits */
2059 	be_handle = handle[req.handle].handle;
2060 	reply.status = sane_control_option (be_handle, req.option,
2061 					    req.action, req.value,
2062 					    &reply.info);
2063 	reply.value_type = req.value_type;
2064 	reply.value_size = req.value_size;
2065 	reply.value = req.value;
2066 
2067 	can_authorize = 0;
2068 
2069 	sanei_w_reply (w, (WireCodecFunc) sanei_w_control_option_reply,
2070 		       &reply);
2071 	sanei_w_free (w, (WireCodecFunc) sanei_w_control_option_req, &req);
2072       }
2073       break;
2074 
2075     case SANE_NET_GET_PARAMETERS:
2076       {
2077 	SANE_Get_Parameters_Reply reply;
2078 
2079 	h = decode_handle (w, "get_parameters");
2080 	if (h < 0)
2081 	  return 1;
2082 	be_handle = handle[h].handle;
2083 
2084 	reply.status = sane_get_parameters (be_handle, &reply.params);
2085 
2086 	sanei_w_reply (w, (WireCodecFunc) sanei_w_get_parameters_reply,
2087 		       &reply);
2088       }
2089       break;
2090 
2091     case SANE_NET_START:
2092       {
2093 	SANE_Start_Reply reply;
2094 	int fd = -1, data_fd = -1;
2095 
2096 	h = decode_handle (w, "start");
2097 	if (h < 0)
2098 	  return 1;
2099 
2100 	memset (&reply, 0, sizeof (reply));	/* avoid leaking bits */
2101 	reply.byte_order = SANE_NET_LITTLE_ENDIAN;
2102 	if (byte_order.w != 1)
2103 	  reply.byte_order = SANE_NET_BIG_ENDIAN;
2104 
2105 	if (handle[h].scanning)
2106 	  reply.status = SANE_STATUS_DEVICE_BUSY;
2107 	else
2108 	  fd = start_scan (w, h, &reply);
2109 
2110 	sanei_w_reply (w, (WireCodecFunc) sanei_w_start_reply, &reply);
2111 
2112 #ifdef SANED_USES_AF_INDEP
2113 	if (reply.status == SANE_STATUS_GOOD)
2114 	  {
2115 	    struct sockaddr_storage ss;
2116 	    char text_addr[64];
2117 	    int len;
2118 	    int error;
2119 	    struct pollfd fds[1];
2120 	    int ret;
2121 
2122 	    fds->fd = fd;
2123 	    fds->events = POLLIN;
2124 
2125 	    DBG (DBG_MSG, "process_request: waiting 4s for data connection\n");
2126 	    if(data_connect_timeout)
2127 	      {
2128 	        while (1)
2129 	          {
2130 	            ret = poll (fds, 1, data_connect_timeout);
2131 	            if (ret < 0)
2132 	              {
2133 	                if (errno == EINTR)
2134 	                  continue;
2135 	                else
2136 	                  {
2137 	                    DBG (DBG_ERR, "run_standalone: poll failed: %s\n",
2138 	                         strerror (errno));
2139 	                  }
2140 	                break;
2141 	              }
2142 	            break;
2143 	          }
2144 	      }
2145 	    else
2146 	      ret = 0;
2147 	    if(ret >= 0)
2148 	      data_fd = accept (fd, 0, 0);
2149 	    close (fd);
2150 
2151 	    /* Get address of remote host */
2152 	    len = sizeof (ss);
2153 	    if (getpeername (data_fd, (struct sockaddr *) &ss, (socklen_t *) &len) < 0)
2154 	      {
2155 		DBG (DBG_ERR, "process_request: getpeername failed: %s\n",
2156 		     strerror (errno));
2157 		return 1;
2158 	      }
2159 
2160 	    error = getnameinfo ((struct sockaddr *) &ss, len, text_addr,
2161 				 sizeof (text_addr), NULL, 0, NI_NUMERICHOST);
2162 	    if (error)
2163 	      {
2164 		DBG (DBG_ERR, "process_request: getnameinfo failed: %s\n",
2165 		     gai_strerror (error));
2166 		return 1;
2167 	      }
2168 
2169 	    DBG (DBG_MSG, "process_request: access to data port from %s\n",
2170 		 text_addr);
2171 
2172 	    if (strcmp (text_addr, remote_ip) != 0)
2173 	      {
2174 		DBG (DBG_ERR, "process_request: however, only %s is authorized\n",
2175 		     text_addr);
2176 		DBG (DBG_ERR, "process_request: configuration problem or attack?\n");
2177 		close (data_fd);
2178 		data_fd = -1;
2179 		return -1;
2180 	      }
2181 
2182 #else /* !SANED_USES_AF_INDEP */
2183 
2184 	if (reply.status == SANE_STATUS_GOOD)
2185 	  {
2186 	    struct sockaddr_in sin;
2187 	    int len;
2188 	    int ret;
2189 	    struct pollfd fds[1];
2190 
2191 	    fds->fd = fd;
2192 	    fds->events = POLLIN;
2193 
2194 	    DBG (DBG_MSG, "process_request: waiting for data connection\n");
2195 	    if(data_connect_timeout)
2196 	      {
2197 	        while (1)
2198 	         {
2199 	           ret = poll (fds, 1, data_connect_timeout);
2200 	           if (ret < 0)
2201 	             {
2202 	               if (errno == EINTR)
2203 	                 continue;
2204 	               else
2205 	                 {
2206 	                   DBG (DBG_ERR, "run_standalone: poll failed: %s\n", strerror (errno));
2207 	                 }
2208 	               break;
2209 	             }
2210 	           break;
2211 	         }
2212 	      }
2213 	    else
2214 	      ret = 0;
2215 	    if(ret >= 0)
2216 	      data_fd = accept (fd, 0, 0);
2217 
2218 	    close (fd);
2219 
2220 	    /* Get address of remote host */
2221 	    len = sizeof (sin);
2222 	    if (getpeername (data_fd, (struct sockaddr *) &sin,
2223 			     (socklen_t *) &len) < 0)
2224 	      {
2225 		DBG (DBG_ERR, "process_request: getpeername failed: %s\n",
2226 		     strerror (errno));
2227 		return 1;
2228 	      }
2229 
2230 	    if (memcmp (&remote_address, &sin.sin_addr,
2231 			sizeof (remote_address)) != 0)
2232 	      {
2233 		DBG (DBG_ERR,
2234 		     "process_request: access to data port from %s\n",
2235 		     inet_ntoa (sin.sin_addr));
2236 		DBG (DBG_ERR,
2237 		     "process_request: however, only %s is authorized\n",
2238 		     inet_ntoa (remote_address));
2239 		DBG (DBG_ERR,
2240 		     "process_request: configuration problem or attack?\n");
2241 		close (data_fd);
2242 		data_fd = -1;
2243 		return -1;
2244 	      }
2245 	    else
2246 	      DBG (DBG_MSG, "process_request: access to data port from %s\n",
2247 		   inet_ntoa (sin.sin_addr));
2248 #endif /* SANED_USES_AF_INDEP */
2249 
2250 	    if (data_fd < 0)
2251 	      {
2252 		sane_cancel (handle[h].handle);
2253 		handle[h].scanning = 0;
2254 		handle[h].docancel = 0;
2255 		DBG (DBG_ERR, "process_request: accept failed! (%s)\n",
2256 		     strerror (errno));
2257 		return 1;
2258 	      }
2259 	    fcntl (data_fd, F_SETFL, O_NONBLOCK);      /* set non-blocking */
2260 	    shutdown (data_fd, SHUT_RD);
2261 	    do_scan (w, h, data_fd);
2262 	    close (data_fd);
2263 	  }
2264       }
2265       break;
2266 
2267     case SANE_NET_CANCEL:
2268       {
2269 	SANE_Word ack = 0;
2270 
2271 	h = decode_handle (w, "cancel");
2272 	if (h >= 0)
2273 	  {
2274 	    sane_cancel (handle[h].handle);
2275 	    handle[h].docancel = 1;
2276 	  }
2277 	sanei_w_reply (w, (WireCodecFunc) sanei_w_word, &ack);
2278       }
2279       break;
2280 
2281     case SANE_NET_EXIT:
2282       return -1;
2283       break;
2284 
2285     case SANE_NET_INIT:
2286     case SANE_NET_AUTHORIZE:
2287     default:
2288       DBG (DBG_ERR,
2289 	   "process_request: received unexpected procedure number %d\n",
2290 	   current_request);
2291       return -1;
2292     }
2293 
2294   return 0;
2295 }
2296 
2297 
2298 static int
2299 wait_child (pid_t pid, int *status, int options)
2300 {
2301   struct saned_child *c;
2302   struct saned_child *p = NULL;
2303   int ret;
2304 
2305   ret = waitpid(pid, status, options);
2306 
2307   if (ret <= 0)
2308     return ret;
2309 
2310 #if WITH_AVAHI
2311   if ((avahi_pid > 0) && (ret == avahi_pid))
2312     {
2313       avahi_pid = -1;
2314       numchildren--;
2315       return ret;
2316     }
2317 #endif /* WITH_AVAHI */
2318 
2319   for (c = children; (c != NULL) && (c->next != NULL); p = c, c = c->next)
2320     {
2321       if (c->pid == ret)
2322 	{
2323 	  if (c == children)
2324 	    children = c->next;
2325 	  else if (p != NULL)
2326 	    p->next = c->next;
2327 
2328 	  free(c);
2329 
2330 	  numchildren--;
2331 
2332 	  break;
2333 	}
2334     }
2335 
2336   return ret;
2337 }
2338 
2339 static int
2340 add_child (pid_t pid)
2341 {
2342   struct saned_child *c;
2343 
2344   c = (struct saned_child *) malloc (sizeof(struct saned_child));
2345 
2346   if (c == NULL)
2347     {
2348       DBG (DBG_ERR, "add_child: out of memory\n");
2349       return -1;
2350     }
2351 
2352   c->pid = pid;
2353   c->next = children;
2354 
2355   children = c;
2356 
2357   return 0;
2358 }
2359 
2360 
2361 static void
2362 handle_connection (int fd)
2363 {
2364 #ifdef TCP_NODELAY
2365   int on = 1;
2366   int level = -1;
2367 #endif
2368 
2369   DBG (DBG_DBG, "handle_connection: processing client connection\n");
2370 
2371   wire.io.fd = fd;
2372 
2373   signal (SIGALRM, quit);
2374   signal (SIGPIPE, quit);
2375 
2376 #ifdef TCP_NODELAY
2377 # ifdef SOL_TCP
2378   level = SOL_TCP;
2379 # else /* !SOL_TCP */
2380   /* Look up the protocol level in the protocols database. */
2381   {
2382     struct protoent *p;
2383     p = getprotobyname ("tcp");
2384     if (p == 0)
2385       {
2386 	DBG (DBG_WARN, "handle_connection: cannot look up `tcp' protocol number");
2387       }
2388     else
2389       level = p->p_proto;
2390   }
2391 # endif	/* SOL_TCP */
2392   if (level == -1
2393       || setsockopt (wire.io.fd, level, TCP_NODELAY, &on, sizeof (on)))
2394     DBG (DBG_WARN, "handle_connection: failed to put socket in TCP_NODELAY mode (%s)",
2395 	 strerror (errno));
2396 #endif /* !TCP_NODELAY */
2397 
2398   if (init (&wire) < 0)
2399     return;
2400 
2401   while (1)
2402     {
2403       reset_watchdog ();
2404       if (process_request (&wire) < 0)
2405 	break;
2406     }
2407 }
2408 
2409 static void
2410 handle_client (int fd)
2411 {
2412   pid_t pid;
2413   int i;
2414 
2415   DBG (DBG_DBG, "handle_client: spawning child process\n");
2416 
2417   pid = fork ();
2418   if (pid == 0)
2419     {
2420       /* child */
2421       if (log_to_syslog)
2422 	closelog();
2423 
2424       for (i = 3; i < fd; i++)
2425 	close(i);
2426 
2427       if (log_to_syslog)
2428 	openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON);
2429 
2430       handle_connection (fd);
2431       quit (0);
2432     }
2433   else if (pid > 0)
2434     {
2435       /* parent */
2436       add_child (pid);
2437       close(fd);
2438     }
2439   else
2440     {
2441       /* FAILED */
2442       DBG (DBG_ERR, "handle_client: fork() failed: %s\n", strerror (errno));
2443       close(fd);
2444     }
2445 }
2446 
2447 static void
2448 bail_out (int error)
2449 {
2450   DBG (DBG_ERR, "%sbailing out, waiting for children...\n", (error) ? "FATAL ERROR; " : "");
2451 
2452 #if WITH_AVAHI
2453   if (avahi_pid > 0)
2454     kill (avahi_pid, SIGTERM);
2455 #endif /* WITH_AVAHI */
2456 
2457   while (numchildren > 0)
2458     wait_child (-1, NULL, 0);
2459 
2460   DBG (DBG_ERR, "bail_out: all children exited\n");
2461 
2462   exit ((error) ? 1 : 0);
2463 }
2464 
2465 void
2466 sig_int_term_handler (int signum);
2467 
2468 void
2469 sig_int_term_handler (int signum)
2470 {
2471   /* unused */
2472   (void) signum;
2473 
2474   signal (SIGINT, NULL);
2475   signal (SIGTERM, NULL);
2476 
2477   bail_out (0);
2478 }
2479 
2480 
2481 #if WITH_AVAHI
2482 static void
2483 saned_avahi (struct pollfd *fds, int nfds);
2484 
2485 static void
2486 saned_create_avahi_services (AvahiClient *c);
2487 
2488 static void
2489 saned_avahi_callback (AvahiClient *c, AvahiClientState state, void *userdata);
2490 
2491 static void
2492 saned_avahi_group_callback (AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata);
2493 
2494 
2495 static void
2496 saned_avahi (struct pollfd *fds, int nfds)
2497 {
2498   struct pollfd *fdp = NULL;
2499   int error;
2500 
2501   avahi_pid = fork ();
2502 
2503   if (avahi_pid > 0)
2504     {
2505       numchildren++;
2506       return;
2507     }
2508   else if (avahi_pid < 0)
2509     {
2510       DBG (DBG_ERR, "saned_avahi: could not spawn Avahi process: %s\n", strerror (errno));
2511       return;
2512     }
2513 
2514   signal (SIGINT, NULL);
2515   signal (SIGTERM, NULL);
2516 
2517   /* Close network fds */
2518   for (fdp = fds; nfds > 0; nfds--, fdp++)
2519     close (fdp->fd);
2520 
2521   free(fds);
2522 
2523   avahi_svc_name = avahi_strdup(SANED_NAME);
2524 
2525   avahi_poll = avahi_simple_poll_new ();
2526   if (avahi_poll == NULL)
2527     {
2528       DBG (DBG_ERR, "saned_avahi: failed to create simple poll object\n");
2529       goto fail;
2530     }
2531 
2532   avahi_client = avahi_client_new (avahi_simple_poll_get (avahi_poll), AVAHI_CLIENT_NO_FAIL, saned_avahi_callback, NULL, &error);
2533   if (avahi_client == NULL)
2534     {
2535       DBG (DBG_ERR, "saned_avahi: failed to create client: %s\n", avahi_strerror (error));
2536       goto fail;
2537     }
2538 
2539   avahi_simple_poll_loop (avahi_poll);
2540 
2541   DBG (DBG_INFO, "saned_avahi: poll loop exited\n");
2542 
2543   exit(EXIT_SUCCESS);
2544 
2545   /* NOT REACHED */
2546   return;
2547 
2548  fail:
2549   if (avahi_client)
2550     avahi_client_free (avahi_client);
2551 
2552   if (avahi_poll)
2553     avahi_simple_poll_free (avahi_poll);
2554 
2555   avahi_free (avahi_svc_name);
2556 
2557   exit(EXIT_FAILURE);
2558 }
2559 
2560 static void
2561 saned_avahi_group_callback (AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata)
2562 {
2563   char *n;
2564 
2565   /* unused */
2566   (void) userdata;
2567 
2568   if ((!g) || (g != avahi_group))
2569     return;
2570 
2571   switch (state)
2572     {
2573       case AVAHI_ENTRY_GROUP_ESTABLISHED:
2574 	/* The entry group has been established successfully */
2575 	DBG (DBG_INFO, "saned_avahi_group_callback: service '%s' successfully established\n", avahi_svc_name);
2576 	break;
2577 
2578       case AVAHI_ENTRY_GROUP_COLLISION:
2579 	/* A service name collision with a remote service
2580 	 * happened. Let's pick a new name */
2581 	n = avahi_alternative_service_name (avahi_svc_name);
2582 	avahi_free (avahi_svc_name);
2583 	avahi_svc_name = n;
2584 
2585 	DBG (DBG_WARN, "saned_avahi_group_callback: service name collision, renaming service to '%s'\n", avahi_svc_name);
2586 
2587 	/* And recreate the services */
2588 	saned_create_avahi_services (avahi_entry_group_get_client (g));
2589 	break;
2590 
2591       case AVAHI_ENTRY_GROUP_FAILURE :
2592 	DBG (DBG_ERR, "saned_avahi_group_callback: entry group failure: %s\n", avahi_strerror (avahi_client_errno (avahi_entry_group_get_client (g))));
2593 
2594 	/* Some kind of failure happened while we were registering our services */
2595 	avahi_simple_poll_quit (avahi_poll);
2596 	break;
2597 
2598       case AVAHI_ENTRY_GROUP_UNCOMMITED:
2599       case AVAHI_ENTRY_GROUP_REGISTERING:
2600 	break;
2601     }
2602 }
2603 
2604 static void
2605 saned_create_avahi_services (AvahiClient *c)
2606 {
2607   char *n;
2608   char txt[32];
2609   AvahiProtocol proto;
2610   int ret;
2611 
2612   if (!c)
2613     return;
2614 
2615   if (!avahi_group)
2616     {
2617       avahi_group = avahi_entry_group_new (c, saned_avahi_group_callback, NULL);
2618       if (avahi_group == NULL)
2619 	{
2620 	  DBG (DBG_ERR, "saned_create_avahi_services: avahi_entry_group_new() failed: %s\n", avahi_strerror (avahi_client_errno (c)));
2621 	  goto fail;
2622 	}
2623     }
2624 
2625   if (avahi_entry_group_is_empty (avahi_group))
2626     {
2627       DBG (DBG_INFO, "saned_create_avahi_services: adding service '%s'\n", avahi_svc_name);
2628 
2629       snprintf(txt, sizeof (txt), "protovers=%x", SANE_VERSION_CODE (V_MAJOR, V_MINOR, SANEI_NET_PROTOCOL_VERSION));
2630 
2631 #ifdef ENABLE_IPV6
2632       proto = AVAHI_PROTO_UNSPEC;
2633 #else
2634       proto = AVAHI_PROTO_INET;
2635 #endif /* ENABLE_IPV6 */
2636 
2637       ret = avahi_entry_group_add_service (avahi_group, AVAHI_IF_UNSPEC, proto, 0, avahi_svc_name, SANED_SERVICE_DNS, NULL, NULL, SANED_SERVICE_PORT, txt, NULL);
2638       if (ret < 0)
2639 	{
2640 	  if (ret == AVAHI_ERR_COLLISION)
2641 	    {
2642 	      n = avahi_alternative_service_name (avahi_svc_name);
2643 	      avahi_free (avahi_svc_name);
2644 	      avahi_svc_name = n;
2645 
2646 	      DBG (DBG_WARN, "saned_create_avahi_services: service name collision, renaming service to '%s'\n", avahi_svc_name);
2647 
2648 	      avahi_entry_group_reset (avahi_group);
2649 
2650 	      saned_create_avahi_services (c);
2651 
2652 	      return;
2653 	    }
2654 
2655 	  DBG (DBG_ERR, "saned_create_avahi_services: failed to add %s service: %s\n", SANED_SERVICE_DNS, avahi_strerror (ret));
2656 	  goto fail;
2657 	}
2658 
2659       /* Tell the server to register the service */
2660       ret = avahi_entry_group_commit (avahi_group);
2661       if (ret < 0)
2662 	{
2663 	  DBG (DBG_ERR, "saned_create_avahi_services: failed to commit entry group: %s\n", avahi_strerror (ret));
2664 	  goto fail;
2665 	}
2666     }
2667 
2668   return;
2669 
2670  fail:
2671   avahi_simple_poll_quit (avahi_poll);
2672 }
2673 
2674 static void
2675 saned_avahi_callback (AvahiClient *c, AvahiClientState state, void *userdata)
2676 {
2677   int error;
2678 
2679   /* unused */
2680   (void) userdata;
2681 
2682   if (!c)
2683     return;
2684 
2685   switch (state)
2686     {
2687       case AVAHI_CLIENT_CONNECTING:
2688 	DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_CONNECTING\n");
2689 	break;
2690 
2691       case AVAHI_CLIENT_S_RUNNING:
2692 	DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_S_RUNNING\n");
2693 	saned_create_avahi_services (c);
2694 	break;
2695 
2696       case AVAHI_CLIENT_S_COLLISION:
2697 	DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_S_COLLISION\n");
2698 	if (avahi_group)
2699 	  avahi_entry_group_reset (avahi_group);
2700 	break;
2701 
2702       case AVAHI_CLIENT_S_REGISTERING:
2703 	DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_S_REGISTERING\n");
2704 	if (avahi_group)
2705 	  avahi_entry_group_reset (avahi_group);
2706 	break;
2707 
2708       case AVAHI_CLIENT_FAILURE:
2709 	DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_FAILURE\n");
2710 
2711 	error = avahi_client_errno (c);
2712 	if (error == AVAHI_ERR_DISCONNECTED)
2713 	  {
2714 	    DBG (DBG_INFO, "saned_avahi_callback: AVAHI_ERR_DISCONNECTED\n");
2715 
2716 	    /* Server disappeared - try to reconnect */
2717             avahi_client_free (avahi_client);
2718             avahi_client = NULL;
2719 	    avahi_group = NULL;
2720 
2721 	    avahi_client = avahi_client_new (avahi_simple_poll_get (avahi_poll), AVAHI_CLIENT_NO_FAIL, saned_avahi_callback, NULL, &error);
2722 	    if (avahi_client == NULL)
2723 	      {
2724 		DBG (DBG_ERR, "saned_avahi_callback: failed to create client: %s\n", avahi_strerror (error));
2725 		avahi_simple_poll_quit (avahi_poll);
2726 	      }
2727 	  }
2728 	else
2729 	  {
2730 	    /* Another error happened - game over */
2731 	    DBG (DBG_ERR, "saned_avahi_callback: client failure: %s\n", avahi_strerror (error));
2732 	    avahi_simple_poll_quit (avahi_poll);
2733 	  }
2734 	break;
2735     }
2736 }
2737 #endif /* WITH_AVAHI */
2738 
2739 
2740 static void
2741 read_config (void)
2742 {
2743   char config_line[PATH_MAX];
2744   const char *optval;
2745   char *endval;
2746   long val;
2747   FILE *fp;
2748   int len;
2749 
2750   DBG (DBG_INFO, "read_config: searching for config file\n");
2751   fp = sanei_config_open (SANED_CONFIG_FILE);
2752   if (fp)
2753     {
2754       while (sanei_config_read (config_line, sizeof (config_line), fp))
2755         {
2756           if (config_line[0] == '#')
2757             continue;           /* ignore line comments */
2758 
2759 	  optval = strchr (config_line, '=');
2760 	  if (optval == NULL)
2761 	    continue;           /* only interested in options, skip hosts */
2762 
2763           len = strlen (config_line);
2764           if (!len)
2765             continue;           /* ignore empty lines */
2766 
2767           /*
2768            * Check for saned options.
2769            * Anything that isn't an option is a client.
2770            */
2771           if (strstr(config_line, "data_portrange") != NULL)
2772             {
2773               optval = sanei_config_skip_whitespace (++optval);
2774               if ((optval != NULL) && (*optval != '\0'))
2775                 {
2776 		  val = strtol (optval, &endval, 10);
2777 		  if (optval == endval)
2778 		    {
2779 		      DBG (DBG_ERR, "read_config: invalid value for data_portrange\n");
2780 		      continue;
2781 		    }
2782 		  else if ((val < 0) || (val > 65535))
2783 		    {
2784 		      DBG (DBG_ERR, "read_config: data_portrange start port is invalid\n");
2785 		      continue;
2786 		    }
2787 
2788 		  optval = strchr (endval, '-');
2789 		  if (optval == NULL)
2790 		    {
2791 		      DBG (DBG_ERR, "read_config: no end port value for data_portrange\n");
2792 		      continue;
2793 		    }
2794 
2795 		  optval = sanei_config_skip_whitespace (++optval);
2796 
2797 		  data_port_lo = val;
2798 
2799 		  val = strtol (optval, &endval, 10);
2800 		  if (optval == endval)
2801 		    {
2802 		      DBG (DBG_ERR, "read_config: invalid value for data_portrange\n");
2803 		      data_port_lo = 0;
2804 		      continue;
2805 		    }
2806 		  else if ((val < 0) || (val > 65535))
2807 		    {
2808 		      DBG (DBG_ERR, "read_config: data_portrange end port is invalid\n");
2809 		      data_port_lo = 0;
2810 		      continue;
2811 		    }
2812 		  else if (val < data_port_lo)
2813 		    {
2814 		      DBG (DBG_ERR, "read_config: data_portrange end port is less than start port\n");
2815 		      data_port_lo = 0;
2816 		      continue;
2817 		    }
2818 
2819 		  data_port_hi = val;
2820 
2821                   DBG (DBG_INFO, "read_config: data port range: %d - %d\n", data_port_lo, data_port_hi);
2822                 }
2823             }
2824             else if(strstr(config_line, "data_connect_timeout") != NULL)
2825             {
2826               optval = sanei_config_skip_whitespace (++optval);
2827               if ((optval != NULL) && (*optval != '\0'))
2828               {
2829                 val = strtol (optval, &endval, 10);
2830                 if (optval == endval)
2831                 {
2832                   DBG (DBG_ERR, "read_config: invalid value for data_connect_timeout\n");
2833                   continue;
2834                 }
2835                 else if ((val < 0) || (val > 65535))
2836                 {
2837                   DBG (DBG_ERR, "read_config: data_connect_timeout is invalid\n");
2838                   continue;
2839                 }
2840                 data_connect_timeout = val;
2841                 DBG (DBG_INFO, "read_config: data connect timeout: %d\n", data_connect_timeout);
2842               }
2843             }
2844         }
2845       fclose (fp);
2846       DBG (DBG_INFO, "read_config: done reading config\n");
2847     }
2848   else
2849     DBG (DBG_ERR, "read_config: could not open config file (%s): %s\n",
2850 	 SANED_CONFIG_FILE, strerror (errno));
2851 }
2852 
2853 
2854 #ifdef SANED_USES_AF_INDEP
2855 static void
2856 do_bindings_family (int family, int *nfds, struct pollfd **fds, struct addrinfo *res)
2857 {
2858   struct addrinfo *resp;
2859   struct pollfd *fdp;
2860   short sane_port;
2861   int fd = -1;
2862   int on = 1;
2863   int i;
2864 
2865   sane_port = bind_port;
2866   fdp = *fds;
2867 
2868   for (resp = res, i = 0; resp != NULL; resp = resp->ai_next, i++)
2869     {
2870       /* We're not interested */
2871       if (resp->ai_family != family)
2872 	continue;
2873 
2874       if (resp->ai_family == AF_INET)
2875 	{
2876           if (sane_port != -1)
2877 	      ((struct sockaddr_in *) resp->ai_addr)->sin_port = htons(sane_port);
2878           else
2879 	      sane_port = ntohs(((struct sockaddr_in *) resp->ai_addr)->sin_port);
2880 	}
2881 #ifdef ENABLE_IPV6
2882       else if (resp->ai_family == AF_INET6)
2883 	{
2884           if (sane_port != -1)
2885               ((struct sockaddr_in6 *) resp->ai_addr)->sin6_port = htons(sane_port);
2886           else
2887               sane_port = ntohs (((struct sockaddr_in6 *) resp->ai_addr)->sin6_port);
2888 	}
2889 #endif /* ENABLE_IPV6 */
2890       else
2891 	continue;
2892 
2893       DBG (DBG_DBG, "do_bindings: [%d] socket () using IPv%d\n", i, (family == AF_INET) ? 4 : 6);
2894       if ((fd = socket (resp->ai_family, SOCK_STREAM, 0)) < 0)
2895 	{
2896 	  DBG (DBG_ERR, "do_bindings: [%d] socket failed: %s\n", i, strerror (errno));
2897 
2898 	  continue;
2899 	}
2900 
2901       DBG (DBG_DBG, "do_bindings: [%d] setsockopt ()\n", i);
2902       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
2903 	DBG (DBG_ERR, "do_bindings: [%d] failed to put socket in SO_REUSEADDR mode (%s)\n", i, strerror (errno));
2904 
2905 
2906       DBG (DBG_DBG, "do_bindings: [%d] bind () to port %d\n", i, sane_port);
2907       if (bind (fd, resp->ai_addr, resp->ai_addrlen) < 0)
2908 	{
2909 	  /*
2910 	   * Binding a socket may fail with EADDRINUSE if we already bound
2911 	   * to an IPv6 addr returned by getaddrinfo (usually the first ones)
2912 	   * and we're trying to bind to an IPv4 addr now.
2913 	   * It can also fail because we're trying to bind an IPv6 socket and IPv6
2914 	   * is not functional on this machine.
2915 	   * In any case, a bind() call returning an error is not necessarily fatal.
2916 	   */
2917 	  DBG (DBG_WARN, "do_bindings: [%d] bind failed: %s\n", i, strerror (errno));
2918 
2919 	  close (fd);
2920 
2921 	  continue;
2922 	}
2923 
2924       DBG (DBG_DBG, "do_bindings: [%d] listen ()\n", i);
2925       if (listen (fd, 1) < 0)
2926 	{
2927 	  DBG (DBG_ERR, "do_bindings: [%d] listen failed: %s\n", i, strerror (errno));
2928 
2929 	  close (fd);
2930 
2931 	  continue;
2932 	}
2933 
2934       if (sane_port == 0)
2935 	{
2936 	  /* sane was asked to bind to an ephemeral port, log it */
2937 	  socklen_t len = sizeof (*resp->ai_addr);
2938 	  if (getsockname(fd, resp->ai_addr, &len) != -1)
2939 	    {
2940 	      if (resp->ai_family == AF_INET)
2941 		{
2942 		  DBG (DBG_INFO, "do_bindings: [%d] selected ephemeral port: %d\n", i, ntohs(((struct sockaddr_in *) resp->ai_addr)->sin_port));
2943 		}
2944 
2945 #ifdef ENABLE_IPV6
2946 	      if (resp->ai_family == AF_INET6)
2947 		{
2948 		  DBG (DBG_INFO, "do_bindings: [%d] selected ephemeral port: %d\n", i, ntohs(((struct sockaddr_in6 *) resp->ai_addr)->sin6_port));
2949 		}
2950 
2951 #endif /* ENABLE_IPV6 */
2952 
2953 	    }
2954 	}
2955 
2956       fdp->fd = fd;
2957       fdp->events = POLLIN;
2958 
2959       (*nfds)++;
2960       fdp++;
2961     }
2962 
2963   *fds = fdp;
2964 }
2965 
2966 static void
2967 do_bindings (int *nfds, struct pollfd **fds)
2968 {
2969   struct addrinfo *res;
2970   struct addrinfo *resp;
2971   struct addrinfo hints;
2972   struct pollfd *fdp;
2973   int err;
2974 
2975   DBG (DBG_DBG, "do_bindings: trying to get port for service \"%s\" (getaddrinfo)\n", SANED_SERVICE_NAME);
2976 
2977   memset (&hints, 0, sizeof (struct addrinfo));
2978 
2979   hints.ai_family = PF_UNSPEC;
2980   hints.ai_flags = AI_PASSIVE;
2981   hints.ai_socktype = SOCK_STREAM;
2982 
2983   err = getaddrinfo (bind_addr, SANED_SERVICE_NAME, &hints, &res);
2984   if (err)
2985     {
2986       DBG (DBG_WARN, "do_bindings: \" %s \" service unknown on your host; you should add\n", SANED_SERVICE_NAME);
2987       DBG (DBG_WARN, "do_bindings:      %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT);
2988       DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n");
2989       err = getaddrinfo (bind_addr, SANED_SERVICE_PORT_S, &hints, &res);
2990       if (err)
2991 	{
2992 	  DBG (DBG_ERR, "do_bindings: getaddrinfo() failed even with numeric port: %s\n", gai_strerror (err));
2993 	  bail_out (1);
2994 	}
2995     }
2996 
2997   for (resp = res, *nfds = 0; resp != NULL; resp = resp->ai_next, (*nfds)++)
2998     ;
2999 
3000   *fds = malloc (*nfds * sizeof (struct pollfd));
3001 
3002   if (fds == NULL)
3003     {
3004       DBG (DBG_ERR, "do_bindings: not enough memory for fds\n");
3005       freeaddrinfo (res);
3006       bail_out (1);
3007     }
3008 
3009   fdp = *fds;
3010   *nfds = 0;
3011 
3012   /* bind IPv6 first, IPv4 second */
3013 #ifdef ENABLE_IPV6
3014   do_bindings_family (AF_INET6, nfds, &fdp, res);
3015 #endif
3016   do_bindings_family (AF_INET, nfds, &fdp, res);
3017 
3018   resp = NULL;
3019   freeaddrinfo (res);
3020 
3021   if (*nfds <= 0)
3022     {
3023       DBG (DBG_ERR, "do_bindings: couldn't bind an address. Exiting.\n");
3024       bail_out (1);
3025     }
3026 }
3027 
3028 #else /* !SANED_USES_AF_INDEP */
3029 
3030 static void
3031 do_bindings (int *nfds, struct pollfd **fds)
3032 {
3033   struct sockaddr_in sin;
3034   struct servent *serv;
3035   short port;
3036   int fd = -1;
3037   int on = 1;
3038 
3039   DBG (DBG_DBG, "do_bindings: trying to get port for service \"%s\" (getservbyname)\n", SANED_SERVICE_NAME);
3040   serv = getservbyname (SANED_SERVICE_NAME, "tcp");
3041 
3042   if (serv)
3043     {
3044       port = serv->s_port;
3045       DBG (DBG_MSG, "do_bindings: port is %d\n", ntohs (port));
3046     }
3047   else
3048     {
3049       port = htons (SANED_SERVICE_PORT);
3050       DBG (DBG_WARN, "do_bindings: \"%s\" service unknown on your host; you should add\n", SANED_SERVICE_NAME);
3051       DBG (DBG_WARN, "do_bindings:      %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT);
3052       DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n");
3053     }
3054 
3055   *nfds = 1;
3056   *fds = malloc (*nfds * sizeof (struct pollfd));
3057 
3058   if (fds == NULL)
3059     {
3060       DBG (DBG_ERR, "do_bindings: not enough memory for fds\n");
3061       bail_out (1);
3062     }
3063 
3064   memset (&sin, 0, sizeof (sin));
3065 
3066   sin.sin_family = AF_INET;
3067   if(bind_addr)
3068     sin.sin_addr.s_addr = inet_addr(bind_addr);
3069   else
3070     sin.sin_addr.s_addr = INADDR_ANY;
3071   sin.sin_port = port;
3072 
3073   DBG (DBG_DBG, "do_bindings: socket ()\n");
3074   fd = socket (AF_INET, SOCK_STREAM, 0);
3075 
3076   DBG (DBG_DBG, "do_bindings: setsockopt ()\n");
3077   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
3078     DBG (DBG_ERR, "do_bindings: failed to put socket in SO_REUSEADDR mode (%s)", strerror (errno));
3079 
3080   DBG (DBG_DBG, "do_bindings: bind ()\n");
3081   if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)
3082     {
3083       DBG (DBG_ERR, "do_bindings: bind failed: %s", strerror (errno));
3084       bail_out (1);
3085     }
3086 
3087   DBG (DBG_DBG, "do_bindings: listen ()\n");
3088   if (listen (fd, 1) < 0)
3089     {
3090       DBG (DBG_ERR, "do_bindings: listen failed: %s", strerror (errno));
3091       bail_out (1);
3092     }
3093 
3094   (*fds)->fd = fd;
3095   (*fds)->events = POLLIN;
3096 }
3097 
3098 #endif /* SANED_USES_AF_INDEP */
3099 
3100 
3101 static void
3102 runas_user (char *user)
3103 {
3104   uid_t runas_uid = 0;
3105   gid_t runas_gid = 0;
3106   struct passwd *pwent;
3107   gid_t *grplist = NULL;
3108   struct group *grp;
3109   int ngroups = 0;
3110   int ret;
3111 
3112   pwent = getpwnam(user);
3113 
3114   if (pwent == NULL)
3115     {
3116       DBG (DBG_ERR, "FATAL ERROR: user %s not found on system\n", user);
3117       bail_out (1);
3118     }
3119 
3120   runas_uid = pwent->pw_uid;
3121   runas_gid = pwent->pw_gid;
3122 
3123   /* Get group list for runas_uid */
3124   grplist = (gid_t *)malloc(sizeof(gid_t));
3125 
3126   if (grplist == NULL)
3127     {
3128       DBG (DBG_ERR, "FATAL ERROR: cannot allocate memory for group list\n");
3129 
3130       exit (1);
3131     }
3132 
3133   ngroups = 1;
3134   grplist[0] = runas_gid;
3135 
3136   setgrent();
3137   while ((grp = getgrent()) != NULL)
3138     {
3139       int i = 0;
3140 
3141       /* Already added current group */
3142       if (grp->gr_gid == runas_gid)
3143 	continue;
3144 
3145       while (grp->gr_mem[i])
3146 	{
3147 	  if (strcmp(grp->gr_mem[i], user) == 0)
3148 	    {
3149 	      int need_to_add = 1, j;
3150 
3151 	      /* Make sure its not already in list */
3152 	      for (j = 0; j < ngroups; j++)
3153 		{
3154 		  if (grp->gr_gid == grplist[i])
3155 		    need_to_add = 0;
3156 		}
3157 	      if (need_to_add)
3158 		{
3159 		  grplist = (gid_t *)realloc(grplist,
3160 					     sizeof(gid_t)*ngroups+1);
3161 		  if (grplist == NULL)
3162 		    {
3163 		      DBG (DBG_ERR, "FATAL ERROR: cannot reallocate memory for group list\n");
3164 
3165 		      exit (1);
3166 		    }
3167 		  grplist[ngroups++] = grp->gr_gid;
3168 		}
3169 	    }
3170 	  i++;
3171 	}
3172     }
3173   endgrent();
3174 
3175   /* Drop privileges if requested */
3176   if (runas_uid > 0)
3177     {
3178       ret = setgroups(ngroups, grplist);
3179       if (ret < 0)
3180 	{
3181 	  DBG (DBG_ERR, "FATAL ERROR: could not set group list: %s\n", strerror(errno));
3182 
3183 	  exit (1);
3184 	}
3185 
3186       free(grplist);
3187 
3188       ret = setegid (runas_gid);
3189       if (ret < 0)
3190 	{
3191 	  DBG (DBG_ERR, "FATAL ERROR: setegid to gid %d failed: %s\n", runas_gid, strerror (errno));
3192 
3193 	  exit (1);
3194 	}
3195 
3196       ret = seteuid (runas_uid);
3197       if (ret < 0)
3198 	{
3199 	  DBG (DBG_ERR, "FATAL ERROR: seteuid to uid %d failed: %s\n", runas_uid, strerror (errno));
3200 
3201 	  exit (1);
3202 	}
3203 
3204       DBG (DBG_WARN, "Dropped privileges to uid %d gid %d\n", runas_uid, runas_gid);
3205     }
3206 }
3207 
3208 
3209 static void
3210 run_standalone (char *user)
3211 {
3212   struct pollfd *fds = NULL;
3213   struct pollfd *fdp = NULL;
3214   int nfds;
3215   int fd = -1;
3216   int i;
3217   int ret;
3218 
3219   FILE *pidfile;
3220 
3221   do_bindings (&nfds, &fds);
3222 
3223   if (run_foreground == SANE_FALSE)
3224     {
3225       DBG (DBG_MSG, "run_standalone: daemonizing now\n");
3226 
3227       fd = open ("/dev/null", O_RDWR);
3228       if (fd < 0)
3229 	{
3230 	  DBG (DBG_ERR, "FATAL ERROR: cannot open /dev/null: %s\n", strerror (errno));
3231 	  exit (1);
3232 	}
3233 
3234       ret = fork ();
3235       if (ret > 0)
3236 	{
3237 	  _exit (0);
3238 	}
3239       else if (ret < 0)
3240 	{
3241 	  DBG (DBG_ERR, "FATAL ERROR: fork failed: %s\n", strerror (errno));
3242 	  exit (1);
3243 	}
3244 
3245       DBG (DBG_WARN, "Now daemonized\n");
3246 
3247       /* Write out PID file */
3248       pidfile = fopen (SANED_PID_FILE, "w");
3249       if (pidfile)
3250 	{
3251 	  fprintf (pidfile, "%d", getpid());
3252 	  fclose (pidfile);
3253 	}
3254       else
3255 	DBG (DBG_ERR, "Could not write PID file: %s\n", strerror (errno));
3256 
3257       chdir ("/");
3258 
3259       dup2 (fd, STDIN_FILENO);
3260       dup2 (fd, STDOUT_FILENO);
3261       dup2 (fd, STDERR_FILENO);
3262 
3263       close (fd);
3264 
3265       setsid ();
3266 
3267       signal(SIGINT, sig_int_term_handler);
3268       signal(SIGTERM, sig_int_term_handler);
3269     }
3270 
3271   if (user)
3272     runas_user(user);
3273 
3274 #if WITH_AVAHI
3275   DBG (DBG_INFO, "run_standalone: spawning Avahi process\n");
3276   saned_avahi (fds, nfds);
3277 
3278   /* NOT REACHED (Avahi process) */
3279 #endif /* WITH_AVAHI */
3280 
3281   DBG (DBG_MSG, "run_standalone: waiting for control connection\n");
3282 
3283   while (1)
3284     {
3285       ret = poll (fds, nfds, 500);
3286       if (ret < 0)
3287 	{
3288 	  if (errno == EINTR)
3289 	    continue;
3290 	  else
3291 	    {
3292 	      DBG (DBG_ERR, "run_standalone: poll failed: %s\n", strerror (errno));
3293 	      free (fds);
3294 	      bail_out (1);
3295 	    }
3296 	}
3297 
3298       /* Wait for children */
3299       while (wait_child (-1, NULL, WNOHANG) > 0)
3300 	;
3301 
3302       if (ret == 0)
3303 	continue;
3304 
3305       for (i = 0, fdp = fds; i < nfds; i++, fdp++)
3306 	{
3307 	  /* Error on an fd */
3308 	  if (fdp->revents & (POLLERR | POLLHUP | POLLNVAL))
3309 	    {
3310 	      for (i = 0, fdp = fds; i < nfds; i++, fdp++)
3311 		close (fdp->fd);
3312 
3313 	      free (fds);
3314 
3315 	      DBG (DBG_WARN, "run_standalone: invalid fd in set, attempting to re-bind\n");
3316 
3317 	      /* Reopen sockets */
3318 	      do_bindings (&nfds, &fds);
3319 
3320 	      break;
3321 	    }
3322 	  else if (! (fdp->revents & POLLIN))
3323 	    continue;
3324 
3325 	  fd = accept (fdp->fd, 0, 0);
3326 	  if (fd < 0)
3327 	    {
3328 	      DBG (DBG_ERR, "run_standalone: accept failed: %s", strerror (errno));
3329 	      continue;
3330 	    }
3331 
3332 	  handle_client (fd);
3333 
3334 	  if (run_once == SANE_TRUE)
3335 	    break; /* We have handled the only connection we're going to handle */
3336 	}
3337 
3338       if (run_once == SANE_TRUE)
3339 	break;
3340     }
3341 
3342   for (i = 0, fdp = fds; i < nfds; i++, fdp++)
3343     close (fdp->fd);
3344 
3345   free (fds);
3346 }
3347 
3348 
3349 static void
3350 run_inetd (char __sane_unused__ *sock)
3351 {
3352 
3353   int fd = -1;
3354 
3355 #ifdef HAVE_SYSTEMD
3356   int n;
3357 
3358   n = sd_listen_fds(0);
3359 
3360   if (n > 1)
3361     {
3362       DBG (DBG_ERR, "run_inetd: Too many file descriptors (sockets) received from systemd!\n");
3363       return;
3364     }
3365 
3366   if (n == 1)
3367     {
3368     fd = SD_LISTEN_FDS_START + 0;
3369     DBG (DBG_INFO, "run_inetd: Using systemd socket %d!\n", fd);
3370     }
3371 #endif
3372 
3373   if (fd == -1)
3374     {
3375       int dave_null;
3376 
3377       /* Some backends really can't keep their dirty fingers off
3378        * stdin/stdout/stderr; we work around them here so they don't
3379        * mess up the network dialog and crash the remote net backend
3380        * by messing with the inetd socket.
3381        * For systemd this not an issue as systemd uses fd >= 3 for the
3382        * socket and can even redirect stdout and stderr to syslog.
3383        * We can even use this to get the debug logging
3384        */
3385       do
3386         {
3387           /* get new fd for the inetd socket */
3388           fd = dup (1);
3389 
3390           if (fd == -1)
3391       	    {
3392               DBG (DBG_ERR, "run_inetd: duplicating fd failed: %s", strerror (errno));
3393               return;
3394             }
3395         }
3396       while (fd < 3);
3397 
3398       /* Our good'ole friend Dave Null to the rescue */
3399       dave_null = open ("/dev/null", O_RDWR);
3400       if (dave_null < 0)
3401         {
3402           DBG (DBG_ERR, "run_inetd: could not open /dev/null: %s", strerror (errno));
3403           return;
3404         }
3405 
3406       close (STDIN_FILENO);
3407       close (STDOUT_FILENO);
3408       close (STDERR_FILENO);
3409 
3410       dup2 (dave_null, STDIN_FILENO);
3411       dup2 (dave_null, STDOUT_FILENO);
3412       dup2 (dave_null, STDERR_FILENO);
3413 
3414       close (dave_null);
3415     }
3416 #ifdef HAVE_OS2_H
3417   /* under OS/2, the socket handle is passed as argument on the command
3418      line; the socket handle is relative to IBM TCP/IP, so a call
3419      to impsockethandle() is required to add it to the EMX runtime */
3420   if (sock)
3421     {
3422       fd = _impsockhandle (atoi (sock), 0);
3423       if (fd == -1)
3424 	perror ("impsockhandle");
3425     }
3426 #endif /* HAVE_OS2_H */
3427 
3428   handle_connection(fd);
3429 }
3430 
3431 static void usage(char *me, int err)
3432 {
3433   fprintf (stderr,
3434        "Usage: %s [OPTIONS]\n\n"
3435        " Options:\n\n"
3436        "  -a, --alone[=user]	        equal to `-l -D -u user'\n"
3437        "  -l, --listen		        run in standalone mode (listen for connection)\n"
3438        "  -u, --user=user	        run as `user'\n"
3439        "  -D, --daemonize	        run in background\n"
3440        "  -o, --once		        exit after first client disconnects\n"
3441        "  -d, --debug=level	        set debug level `level' (default is 2)\n"
3442        "  -e, --stderr		        output to stderr\n"
3443        "  -b, --bind=addr	        bind address `addr' (default all interfaces)\n"
3444        "  -p, --port=port               bind port `port` (default sane-port or 6566)\n"
3445        "  -B, --buffer-size=size        set size of read buffer in KB (default: 1024)\n"
3446        "  -h, --help		        show this help message and exit\n", me);
3447 
3448   exit(err);
3449 }
3450 
3451 static int debug;
3452 
3453 static struct option long_options[] =
3454 {
3455 /* These options set a flag. */
3456   {"help",              no_argument,            0, 'h'},
3457   {"alone",             optional_argument,      0, 'a'},
3458   {"listen",            no_argument,            0, 'l'},
3459   {"user",              required_argument,      0, 'u'},
3460   {"daemonize",         no_argument,            0, 'D'},
3461   {"once",              no_argument,            0, 'o'},
3462   {"debug",             required_argument,      0, 'd'},
3463   {"stderr",            no_argument,            0, 'e'},
3464   {"bind",              required_argument,      0, 'b'},
3465   {"port",              required_argument,      0, 'p'},
3466   {"buffer-size",       required_argument,      0, 'B'},
3467   {0,                   0,                      0,  0 }
3468 };
3469 
3470 int
3471 main (int argc, char *argv[])
3472 {
3473   char options[64] = "";
3474   char *user = NULL;
3475   char *sock = NULL;
3476   int c;
3477   int long_index = 0;
3478 
3479   debug = DBG_WARN;
3480 
3481   prog_name = strrchr (argv[0], '/');
3482   if (prog_name)
3483     ++prog_name;
3484   else
3485     prog_name = argv[0];
3486 
3487   numchildren = 0;
3488   run_mode = SANED_RUN_INETD;
3489   run_foreground = SANE_TRUE;
3490   run_once = SANE_FALSE;
3491 
3492   while((c = getopt_long(argc, argv,"ha::lu:Dod:eb:p:B:", long_options, &long_index )) != -1)
3493     {
3494       switch(c) {
3495       case 'a':
3496 	run_mode = SANED_RUN_ALONE;
3497 	run_foreground = SANE_FALSE;
3498 	if (optarg)
3499 	  user = optarg;
3500 	break;
3501       case 'l':
3502 	run_mode = SANED_RUN_ALONE;
3503 	break;
3504       case 'u':
3505 	user = optarg;
3506 	break;
3507       case 'D':
3508 	run_foreground = SANE_FALSE;
3509 	break;
3510       case 'o':
3511 	run_once = SANE_TRUE;
3512 	break;
3513       case 'd':
3514 	debug = atoi(optarg);
3515 	break;
3516       case 'e':
3517 	log_to_syslog = SANE_FALSE;
3518 	break;
3519       case 'b':
3520 	bind_addr = optarg;
3521 	break;
3522       case 'p':
3523         bind_port = atoi(optarg);
3524         break;
3525       case 'B':
3526         {
3527           int buffer_arg = atoi(optarg);
3528 
3529           if ((buffer_arg < 0) || ((size_t)buffer_arg > (SIZE_MAX / 1024)))
3530             {
3531               DBG (
3532                   DBG_ERR,
3533                   "saned: specified buffer size in KB is invalid. Default of %zuKB will be substituted.\n",
3534                   buffer_size / 1024);
3535             }
3536           else
3537             {
3538               buffer_size = 1024 * (size_t)buffer_arg;
3539             }
3540           break;
3541         }
3542       case 'h':
3543 	usage(argv[0], EXIT_SUCCESS);
3544 	break;
3545       default:
3546 	usage(argv[0], EXIT_FAILURE);
3547 	break;
3548       }
3549     }
3550 
3551   if (log_to_syslog)
3552     openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON);
3553 
3554   read_config ();
3555 
3556   byte_order.w = 0;
3557   byte_order.ch = 1;
3558 
3559   sanei_w_init (&wire, sanei_codec_bin_init);
3560   wire.io.read = read;
3561   wire.io.write = write;
3562 
3563 #ifdef SANED_USES_AF_INDEP
3564   strcat(options, "AF-indep");
3565 # ifdef ENABLE_IPV6
3566   strcat(options, "+IPv6");
3567 #endif
3568 #else
3569   strcat(options, "IPv4 only");
3570 #endif
3571 #ifdef HAVE_SYSTEMD
3572   if (sd_listen_fds(0) > 0)
3573     {
3574       strcat(options, "+systemd");
3575     }
3576 #endif
3577 
3578   if (strlen(options) > 0)
3579     {
3580       DBG (DBG_WARN, "saned (%s) from %s starting up\n", options, PACKAGE_STRING);
3581     }
3582   else
3583     {
3584       DBG (DBG_WARN, "saned from %s ready\n", PACKAGE_STRING);
3585     }
3586 
3587   if (run_mode == SANED_RUN_ALONE)
3588     {
3589       run_standalone(user);
3590     }
3591   else
3592     {
3593 #ifdef HAVE_OS2_H
3594       if (argc == 2)
3595 	sock = argv[1];
3596 #endif
3597       run_inetd(sock);
3598     }
3599 
3600   DBG (DBG_WARN, "saned exiting\n");
3601 
3602   return 0;
3603 }
3604