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