source: trunk/src/sh_portcheck.c @ 498

Last change on this file since 498 was 498, checked in by katerina, 6 years ago

Fix for ticket #395 (Port check fails for some UDP daemons).

  • Property svn:executable set to *
File size: 54.9 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2006 Rainer Wichmann                                      */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20/***************************************************************************
21 *
22 * This file provides a module for samhain to check for open ports
23 * on the local machine.
24 *
25 */
26
27
28/* #define TEST_ONLY */
29#ifndef TEST_ONLY
30#include "config_xor.h"
31#endif
32
33#include <stdio.h>
34#include <string.h>
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#include <errno.h>
40#include <unistd.h>
41#include <fcntl.h>
42
43#define PORTCHK_VERSION "1.0"
44
45#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
46
47
48#define PORTMAP
49#ifdef  HAVE_RPC_RPC_H
50#include <rpc/rpc.h>
51#ifdef  HAVE_RPC_RPCENT_H
52#include <rpc/rpcent.h>
53#endif
54#include <rpc/pmap_clnt.h>
55#include <rpc/pmap_prot.h>
56#endif
57#include <netdb.h>
58
59/*
60 * struct pmaplist {
61 *      struct pmap     pml_map;
62 *      struct pmaplist *pml_next;
63 * };
64 */
65
66/* struct pmap {
67 *      long unsigned pm_prog;
68 *      long unsigned pm_vers;
69 *      long unsigned pm_prot;
70 *      long unsigned pm_port;
71 * };
72 */
73
74/* TIME_WAIT ? 60-240 seconds */
75
76#if !defined(TEST_ONLY)
77
78#define FIL__ _("sh_portcheck.c")
79#include "samhain.h"
80#include "sh_error.h"
81#include "sh_mem.h"
82#include "sh_calls.h"
83#include "sh_utils.h"
84#include "sh_modules.h"
85#define SH_NEED_GETHOSTBYXXX
86#include "sh_static.h"
87#include "sh_pthread.h"
88#include "sh_ipvx.h"
89
90/* the size of an interface string
91 */
92#define SH_INTERFACE_SIZE SH_IP_BUF
93
94#define SH_PORT_NOT 0
95#define SH_PORT_REQ 1
96#define SH_PORT_OPT 2
97#define SH_PORT_IGN 3
98#define SH_PORT_BLACKLIST 4
99
100static char * sh_port_type2str (int type)
101{
102  if (type == 0) return _("not");
103  if (type == 1) return _("req");
104  if (type == 2) return _("opt");
105  if (type == 3) return _("ign");
106  if (type == 4) return _("blc");
107  return _("???");
108}
109
110#define SH_PORT_MISS 0
111#define SH_PORT_ISOK 1
112#define SH_PORT_UNKN 2
113
114#define SH_PORT_NOREPT 0
115#define SH_PORT_REPORT 1
116
117#define SH_PROTO_TCP 0
118#define SH_PROTO_UDP 1
119#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
120
121struct sh_portentry {
122  int  port;
123  char interface[SH_INTERFACE_SIZE];
124  char * service;
125  char * error;
126  int  flag;    /* required or not */
127  int  status;  /* missing or not  */
128  struct sh_portentry * next;
129};
130
131static struct sh_portentry * portlist_tcp = NULL;
132static struct sh_portentry * portlist_udp = NULL;
133
134
135#define SH_PORTCHK_INTERVAL 300
136
137static int sh_portchk_check_udp = 1;
138static int sh_portchk_active    = 1;
139static int sh_portchk_interval  = SH_PORTCHK_INTERVAL;
140
141static int sh_portchk_minport = -1;
142static int sh_portchk_maxport = -1;
143
144struct sh_port {
145  int                  port;
146  struct sh_sockaddr * paddr;
147  struct sh_port     * next;
148};
149
150static struct sh_port * blacklist_tcp = NULL;
151static struct sh_port * blacklist_udp = NULL;
152
153SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
154
155static int sh_portchk_severity  = SH_ERR_SEVERE;
156
157extern char * sh_port2proc_query(int proto, struct sh_sockaddr * saddr, int sport,
158                                 unsigned long * pid, char * user, size_t userlen);
159extern int sh_port2proc_prepare();
160extern void sh_port2proc_finish();
161
162#endif
163
164/* Exported interface to add ignoreable ports as 'iface:portlist'
165 */
166static int sh_portchk_add_ignore (const char * str);
167
168/* Exported interface to add required ports as 'iface:portlist'
169 */
170static int sh_portchk_add_required (const char * str);
171
172/* Exported interface to add optional ports as 'iface:portlist'
173 */
174static int sh_portchk_add_optional (const char * str);
175
176/* Exported interface to add blacklisted ports as 'iface:portlist'
177 */
178static int sh_portchk_add_blacklist (const char * str);
179
180/* Exported interface to add an ethernet interface
181 */
182static int sh_portchk_add_interface (const char * str);
183
184/* verify whether port/interface is blacklisted (do not check)
185 */
186static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto);
187
188#ifndef TEST_ONLY
189
190static int sh_portchk_set_interval (const char * c)
191{
192  int retval = 0;
193  long val;
194
195  SL_ENTER(_("sh_portchk_set_interval"));
196  val = strtol (c, (char **)NULL, 10);
197  if (val <= 0)
198    {
199      SH_MUTEX_LOCK(mutex_thread_nolog);
200      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
201                       _("port check interval"), c);
202      SH_MUTEX_UNLOCK(mutex_thread_nolog);
203      retval = -1;
204    }
205  else
206    {
207      sh_portchk_interval = (time_t) val;
208    }
209  SL_RETURN(retval, _("sh_portchk_set_interval"));
210}
211
212static int sh_portchk_set_port_minmax (const char * c, int * setthis)
213{
214  int retval = 0;
215  long val;
216
217  SL_ENTER(_("sh_portchk_set_port_minmax"));
218  val = strtol (c, (char **)NULL, 10);
219  if (val < 0 || val > 65535)
220    {
221      SH_MUTEX_LOCK(mutex_thread_nolog);
222      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
223                       _("port check port minmax"), c);
224      SH_MUTEX_UNLOCK(mutex_thread_nolog);
225      retval = -1;
226    }
227  else
228    {
229      *setthis = (int) val;
230    }
231  SL_RETURN(retval, _("sh_portchk_set_port_minmax"));
232}
233
234
235static int sh_portchk_set_minport   (const char * str)
236{
237  return sh_portchk_set_port_minmax (str, &sh_portchk_minport);
238}
239
240static int sh_portchk_set_maxport   (const char * str)
241{
242  return sh_portchk_set_port_minmax (str, &sh_portchk_maxport);
243}
244
245static int sh_portchk_set_active   (const char * str)
246{
247  return sh_util_flagval(str, &sh_portchk_active);
248}
249
250static int sh_portchk_set_udp      (const char * str)
251{
252  return sh_util_flagval(str, &sh_portchk_check_udp);
253}
254
255static int sh_portchk_set_severity (const char * str)
256{
257  char tmp[32];
258  tmp[0] = '='; tmp[1] = '\0';
259  sl_strlcat (tmp, str, 32);
260  return sh_error_set_level (tmp, &sh_portchk_severity);
261}
262
263sh_rconf sh_portchk_table[] = {
264    {
265        N_("severityportcheck"),
266        sh_portchk_set_severity,
267    },
268    {
269        N_("portcheckrequired"),
270        sh_portchk_add_required,
271    },
272    {
273        N_("portcheckoptional"),
274        sh_portchk_add_optional,
275    },
276    {
277        N_("portcheckignore"),
278        sh_portchk_add_ignore,
279    },
280    {
281        N_("portcheckskip"),
282        sh_portchk_add_blacklist,
283    },
284    {
285        N_("portcheckactive"),
286        sh_portchk_set_active,
287    },
288    {
289        N_("portcheckinterface"),
290        sh_portchk_add_interface,
291    },
292    {
293        N_("portcheckinterval"),
294        sh_portchk_set_interval,
295    },
296    {
297        N_("portcheckminport"),
298        sh_portchk_set_minport,
299    },
300    {
301        N_("portcheckmaxport"),
302        sh_portchk_set_maxport,
303    },
304    {
305        N_("portcheckudp"),
306        sh_portchk_set_udp,
307    },
308    {
309        NULL,
310        NULL
311    }
312};
313
314#endif
315
316/* Interface to initialize port check
317 */
318int sh_portchk_init (struct mod_type * arg);
319
320/* Interface to reset port check
321 */
322int sh_portchk_reset (void);
323
324/* Interface to run port check
325 */
326int sh_portchk_check (void);
327
328
329static char * check_services (int port, int proto);
330
331#ifdef TEST_ONLY
332
333static int portchk_debug = 0; 
334#define SH_ALLOC       malloc
335#define SH_FREE        free
336#define sh_util_strdup strdup
337#define sl_strlcpy     strncpy
338#define _(a)           a
339
340#else
341
342static int portchk_debug = 0;
343
344#endif
345
346#ifdef  HAVE_RPC_RPC_H
347static char * sh_getrpcbynumber (int number, char * buf, size_t len)
348{
349  FILE * fp;
350
351  if (NULL != (fp = fopen(_("/etc/rpc"), "r")))
352    {
353      sh_string * s = sh_string_new(0);
354      while (0 < sh_string_read(s, fp, 1024))
355        {
356          char * p = sh_string_str(s);
357          while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
358          if (*p == '\0' || *p == '#') 
359            continue; /* skip comment */
360          else
361            {
362              size_t lengths[3];
363              unsigned int  fields = 3;
364              char * q             = sh_string_str(s);
365              char ** splits       = split_array_ws(q, &fields, lengths);
366
367              if (fields >= 2)
368                {
369                  int n = atoi(splits[1]);
370                  if (n == number)
371                    {
372                      sl_strlcpy(buf, splits[0], len);
373                      SH_FREE(splits);
374                      sh_string_destroy(&s);
375                      sl_fclose(FIL__, __LINE__, fp);
376                      return buf;
377                    }
378                }
379              SH_FREE(splits);
380            }
381        }
382      sh_string_destroy(&s);
383      sl_fclose(FIL__, __LINE__, fp);
384    }
385  return NULL;
386}
387#endif
388
389static char * sh_getservbyport (int port, const char * proto_in, char * buf, size_t len)
390{
391  FILE * fp;
392  char   proto[8];
393
394  sl_strlcpy(proto, proto_in, sizeof(proto));
395
396  if (NULL != (fp = fopen(_("/etc/services"), "r")))
397    {
398      sh_string * s = sh_string_new(0);
399      while (0 < sh_string_read(s, fp, 1024))
400        {
401          char * p = sh_string_str(s);
402          while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
403          if (*p == '\0' || *p == '#')
404            continue; /* skip comment */
405          else
406            {
407              size_t lengths[3];
408              unsigned int  fields = 3;
409              char * q             = sh_string_str(s);
410              char ** splits       = split_array_ws(q, &fields, lengths);
411
412              if (fields >= 2)
413                {
414                  char * end;
415                  long n = strtol(splits[1], &end, 10);
416                  if (n == port && end && (*end == '/' || *end == ','))
417                    {
418                      ++end;
419                      if (0 == strcmp(end, proto))
420                        {
421                          sl_strlcpy(buf, splits[0], len);
422                          SH_FREE(splits);
423                          sh_string_destroy(&s);
424                          sl_fclose(FIL__, __LINE__, fp);
425                          return buf;
426                        }
427                    }
428                }
429              SH_FREE(splits);
430            }
431        }
432      sh_string_destroy(&s);
433      sl_fclose(FIL__, __LINE__, fp);
434    }
435  return NULL;
436}
437
438static void sh_portchk_add_to_list (int proto, 
439                                    int port, struct sh_sockaddr * paddr, 
440                                    char * service,
441                                    int flag, int status)
442{
443  struct sh_portentry * new = SH_ALLOC (sizeof(struct sh_portentry));
444
445  new->port = port;
446  sh_ipvx_ntoa(new->interface, SH_INTERFACE_SIZE, paddr);
447  new->status = status;
448  new->flag   = flag;
449
450  new->error  = NULL;
451
452  if (portchk_debug)
453    fprintf(stderr, _("add to list: port %d/%s %d %d (%s) %s\n"),
454            port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"),
455            new->interface);
456
457  if (service)
458    new->service = sh_util_strdup (service);
459  else
460    new->service = NULL;
461  if (proto == IPPROTO_TCP)
462    {
463      new->next = portlist_tcp;
464      portlist_tcp = new;
465    }
466  else
467    {
468      new->next = portlist_udp;
469      portlist_udp = new;
470    }
471  return;
472}
473
474/* Reset the list by setting all entries to UNKN.
475 * In the next cycle we will check, and set found ports to ISOK.
476 * Thereafter, we check for entries that are still UNKN.
477 */
478static void sh_portchk_reset_lists (void)
479{
480  struct sh_portentry * portlist;
481
482  portlist = portlist_tcp;
483  while (portlist)
484    {
485      if (portlist->status != SH_PORT_MISS)
486        portlist->status = SH_PORT_UNKN;
487      portlist = portlist->next;
488    }
489  portlist = portlist_udp;
490  while (portlist)
491    {
492      if (portlist->status != SH_PORT_MISS)
493        portlist->status = SH_PORT_UNKN;
494      portlist = portlist->next;
495    }
496  return;
497}
498
499static struct sh_portentry * sh_portchk_kill_list (struct sh_portentry * head)
500{
501  if (head)
502    {
503      if (head->next)
504        sh_portchk_kill_list (head->next);
505
506      if (head->service)
507        SH_FREE(head->service);
508      SH_FREE(head);
509    }
510  return NULL;
511}
512 
513static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
514{
515  if (head)
516    {
517      if (head->next)
518        sh_portchk_kill_blacklist (head->next);
519
520      SH_FREE(head->paddr);
521      SH_FREE(head);
522    }
523  return NULL;
524}
525 
526/* These variables are not used anywhere. They only exist
527 * to assign &pre, &ptr to them, which keeps gcc from
528 * putting it into a register, and avoids the 'clobbered
529 * by longjmp' warning. And no, 'volatile' proved insufficient.
530 */
531void * sh_dummy_531_pre = NULL;
532void * sh_dummy_532_ptr = NULL;
533
534/* check the list of open ports for any that are marked as UNKN
535 */
536static void sh_portchk_check_list (struct sh_portentry ** head, 
537                                   int proto, int report)
538{
539  struct sh_portentry * ptr = *head;
540  struct sh_portentry * pre = *head;
541  char errbuf[256];
542
543  /* Take the address to keep gcc from putting them into registers.
544   * Avoids the 'clobbered by longjmp' warning.
545   */
546  sh_dummy_531_pre = (void*) &pre;
547  sh_dummy_532_ptr = (void*) &ptr;
548 
549  while (ptr)
550    {
551      if (portchk_debug && report)
552        fprintf(stderr, _("check list: port %d/%s %d %d\n"),
553                ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
554
555      if (ptr->status == SH_PORT_UNKN)
556        {
557          /* Don't report missing ports that are marked as optional
558           */
559          if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
560            {
561              snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
562                        ptr->interface, ptr->port, SH_PROTO_STR(proto), 
563                        ptr->service ? ptr->service : check_services(ptr->port, proto));
564#ifdef TEST_ONLY
565              if (report == SH_PORT_REPORT)
566                fprintf(stderr, _("%s\n"), errbuf);
567#else
568              if (report == SH_PORT_REPORT)
569                {
570                  SH_MUTEX_LOCK(mutex_thread_nolog);
571                  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
572                                  MSG_PORT_MISS, errbuf);
573                  SH_MUTEX_UNLOCK(mutex_thread_nolog);
574                }
575#endif
576            }
577
578          ptr->status = SH_PORT_MISS;
579
580          if ((ptr->flag != SH_PORT_REQ) && (ptr->flag != SH_PORT_OPT) && (ptr->flag != SH_PORT_IGN))
581            {
582              if (portchk_debug && report)
583                fprintf(stderr, _("removing: port %d/%s %d %d\n"),
584                        ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
585             
586              if (ptr == *head)
587                {
588                  *head = ptr->next;
589                  if (ptr->service)
590                    SH_FREE(ptr->service);
591                  SH_FREE(ptr);
592                  ptr = *head;
593                  pre = *head;
594                  continue;
595                }
596              else if (ptr->next == NULL)
597                {
598                  pre->next = NULL;
599                  if (ptr->service)
600                    SH_FREE(ptr->service);
601                  SH_FREE(ptr);
602                  return;
603                }
604              else
605                {
606                  pre->next = ptr->next;
607                  if (ptr->service)
608                    SH_FREE(ptr->service);
609                  SH_FREE(ptr);
610                  ptr = pre->next;
611                  continue;
612                }
613            }
614        }
615      pre = ptr;
616      ptr = ptr->next;
617    }
618
619  sh_dummy_532_ptr = NULL;
620  sh_dummy_531_pre = NULL;
621
622  return;
623}
624
625
626static struct sh_portentry * sh_portchk_get_from_list (int proto, int port, 
627                                                       struct sh_sockaddr * paddr, char * service)
628{
629  struct sh_portentry * portlist;
630  char str_addr[SH_IP_BUF];
631
632  if (proto == IPPROTO_TCP)
633    portlist = portlist_tcp;
634  else
635    portlist = portlist_udp;
636
637  sh_ipvx_ntoa(str_addr, sizeof(str_addr), paddr);
638
639  if (service)
640    {
641      while (portlist) 
642        {
643          if (portlist->service && 
644              0 == strcmp(service, portlist->service) &&
645              ( 0 == strcmp(portlist->interface, str_addr) ||
646                sh_ipvx_isany(paddr) ))
647            return portlist;
648          portlist = portlist->next;
649        }
650    }
651  else
652    {
653      while (portlist) 
654        {
655          if (port == portlist->port &&
656              (0 == strcmp(portlist->interface, str_addr)  ||
657               sh_ipvx_isany(paddr) ))
658            return portlist;
659          portlist = portlist->next;
660        }
661    }
662  return NULL;
663}
664     
665
666static void sh_portchk_cmp_to_list (int proto, int port, 
667                                    struct sh_sockaddr * paddr, char * service)
668{
669  struct sh_portentry * portent;
670  char errbuf[256];
671
672 
673  portent = sh_portchk_get_from_list (proto, port, paddr, service);
674
675  if (service)
676    {
677      if (!portent)
678        {
679          char * path;
680          unsigned long qpid;
681          char   user[USER_MAX];
682          char   saddr[SH_IP_BUF];
683
684          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
685
686          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
687                    saddr, port, SH_PROTO_STR(proto), service);
688
689          if (portchk_debug)
690            fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s)\n"), 
691                    saddr, port, SH_PROTO_STR(proto), service);
692
693#ifndef TEST_ONLY
694          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
695          SH_MUTEX_LOCK(mutex_thread_nolog);
696          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
697                          MSG_PORT_NEW, errbuf, path, qpid, user);
698          SH_MUTEX_UNLOCK(mutex_thread_nolog);
699          SH_FREE(path);
700#endif
701          /*
702           * was not there, thus it is not in 'required' or 'optional' list
703           */
704          sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
705        }
706      else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
707        {
708          char * path;
709          unsigned long qpid;
710          char   user[USER_MAX];
711          char   saddr[SH_IP_BUF];
712
713          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
714
715          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
716                    saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
717#ifdef TEST_ONLY
718          fprintf(stderr, _("service: %s\n"), errbuf);
719#else
720          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
721          SH_MUTEX_LOCK(mutex_thread_nolog);
722          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
723                          MSG_PORT_RESTART, errbuf, path, qpid, user);
724          SH_MUTEX_UNLOCK(mutex_thread_nolog);
725          SH_FREE(path);
726#endif
727
728          portent->status = SH_PORT_ISOK;
729        }
730      else if (port != portent->port && (-1) != portent->port)
731        {
732          char * path;
733          unsigned long qpid;
734          char   user[USER_MAX];
735          char   saddr[SH_IP_BUF];
736
737          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
738
739          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
740                    saddr, port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
741#ifdef TEST_ONLY
742          fprintf(stderr, _("service: %s\n"), errbuf);
743#else
744          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
745          SH_MUTEX_LOCK(mutex_thread_nolog);
746          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
747                          MSG_PORT_NEWPORT, errbuf, path, qpid, user);
748          SH_MUTEX_UNLOCK(mutex_thread_nolog);
749          SH_FREE(path);
750#endif
751          portent->port   = port;
752          portent->status = SH_PORT_ISOK;
753        }
754      else
755        {
756          portent->status = SH_PORT_ISOK;
757        }
758    }
759  else
760    {
761      if (!portent)
762        {
763          char * path;
764          unsigned long qpid;
765          char   user[USER_MAX];
766          char   saddr[SH_IP_BUF];
767
768          if (portchk_debug)
769            fprintf(stderr, _("call to  sh_ipvx_ntoa (port %d)\n"), port);
770 
771          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
772
773          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
774                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
775
776          if (portchk_debug)
777            fprintf(stderr, _("cmp_to_list: open port: %s:%d/%s (%s) check_services\n"), 
778                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
779
780#ifndef TEST_ONLY
781          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
782          SH_MUTEX_LOCK(mutex_thread_nolog);
783          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
784                          MSG_PORT_NEW, errbuf, path, qpid, user);
785          SH_MUTEX_UNLOCK(mutex_thread_nolog);
786          SH_FREE(path);
787#endif
788
789          /* was not there, thus it is not in 'required' or 'optional' list
790           */
791          sh_portchk_add_to_list (proto, port, paddr, service, SH_PORT_NOT, SH_PORT_ISOK);
792        }
793      else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
794        {
795          char * path;
796          unsigned long qpid;
797          char   user[USER_MAX];
798          char   saddr[SH_IP_BUF];
799
800          sh_ipvx_ntoa(saddr, sizeof(saddr), paddr);
801
802          snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
803                    saddr, port, SH_PROTO_STR(proto), check_services(port, proto));
804#ifdef TEST_ONLY
805          fprintf(stderr, _("port   : %s\n"), errbuf);
806#else
807          path = sh_port2proc_query(proto, paddr, port, &qpid, user, sizeof(user));
808          SH_MUTEX_LOCK(mutex_thread_nolog);
809          sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
810                          MSG_PORT_RESTART, errbuf, path, qpid, user);
811          SH_MUTEX_UNLOCK(mutex_thread_nolog);
812          SH_FREE(path);
813#endif
814
815          portent->status = SH_PORT_ISOK;
816        }
817      else
818        {
819          portent->status = SH_PORT_ISOK;
820        }
821    }
822
823  return;
824}
825
826                               
827/* Returns a static buffer containing the name of the service
828 * running on port <port> (from /etc/services)
829 * Returns NULL on failure
830 */
831static char * check_services (int port, int proto)
832{
833  static char buf[256];
834  char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
835
836  if (!service)
837    {
838      snprintf (buf, sizeof(buf), "%s",_("unknown"));
839    }
840  return buf;
841}
842
843/* Returns a static buffer containing the name of the service
844 * running on port <port> at <address> (from portmap daemon)
845 * Returns NULL on failure
846 */
847static char * check_rpc_list (int port, struct sockaddr_in * address, 
848                              unsigned long prot)
849{
850#if defined(HAVE_RPC_RPC_H) && defined(HAVE_PMAP_GETMAPS)
851  struct pmaplist * head;
852  char *r;
853  static char buf[256];
854
855  head = pmap_getmaps(address);
856
857  if (head) 
858    {
859      do /* while (head != NULL) */
860        {
861          if ((head->pml_map.pm_prot == prot) && 
862              (port == (int)head->pml_map.pm_port)) 
863            {
864              r = sh_getrpcbynumber((int)head->pml_map.pm_prog, 
865                                    buf, sizeof(buf));
866              if (r)
867                {
868                  return buf;
869                }
870              else
871                {
872                  snprintf (buf, sizeof(buf), "RPC_%lu",
873                            (unsigned long)head->pml_map.pm_prog);
874                  return buf;
875                }
876            }
877          head = head->pml_next;
878        }
879      while (head != NULL);
880    }
881#else
882  (void) port;
883  (void) address;
884  (void) prot;
885#endif
886  return NULL;
887}
888
889static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
890{
891  int                retval;
892  char             * p = NULL;
893  char               buf[8];
894#ifndef TEST_ONLY
895  char               errmsg[256];
896  int                nerr;
897#endif
898  char errbuf[SH_ERRBUF_SIZE];
899  char ipbuf[SH_IP_BUF];
900
901  sh_ipvx_set_port(paddr, port);
902
903  do {
904    retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
905  } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
906
907  if (retval == -1)
908    {
909#ifdef TEST_ONLY
910      if (portchk_debug)
911        perror(_("connect"));
912#else
913      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
914
915      nerr = errno;
916      sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
917                  port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
918      SH_MUTEX_LOCK(mutex_thread_nolog);
919      sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
920                      errmsg, _("connect"));
921      SH_MUTEX_UNLOCK(mutex_thread_nolog);
922#endif
923    }
924  else
925    {
926      do {
927        retval = send (fd, buf, 0, 0);
928      } while (retval < 0 && errno == EINTR);
929
930      if (retval == -1 && errno == ECONNREFUSED)
931        {
932          sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
933          if (portchk_debug)
934            fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
935                    port, ipbuf);
936        }
937      else 
938        {
939          /* Only the second send() may catch the error
940           */
941          do {
942            retval = send (fd, buf, 0, 0);
943          } while (retval < 0 && errno == EINTR);
944
945          if (retval == -1 && errno == ECONNREFUSED)
946            {
947              sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
948              if (portchk_debug)
949                fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
950                        port, ipbuf);
951            }
952          else if (retval != -1)
953            {
954              /* Try to get service name from portmap
955               */
956              if (paddr->ss_family == AF_INET)
957                {
958                  p = check_rpc_list (port, 
959                                      (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), 
960                                      IPPROTO_UDP);
961                }
962
963              sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
964             
965              /* If not an RPC service, try to get name from /etc/services
966               */
967              if (!p)
968                p = check_services(port, IPPROTO_UDP);
969             
970              if (portchk_debug)
971                {
972                  sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
973                  fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"), 
974                          port, ipbuf, p);
975                }
976             
977            }
978          else
979            {
980              if (portchk_debug)
981                {
982                  sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
983                  fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"), 
984                          port, ipbuf, errno);
985                }
986            }
987        }
988    }
989  sl_close_fd (FIL__, __LINE__, fd);
990  return 0;
991}
992
993static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
994{
995  int                retval;
996  int                flags;
997  char             * p = NULL;
998#ifndef TEST_ONLY
999  char               errmsg[256];
1000  int                nerr;
1001#endif
1002  char errbuf[SH_ERRBUF_SIZE];
1003  char ipbuf[SH_IP_BUF];
1004
1005  sh_ipvx_set_port(paddr, port);
1006
1007  do {
1008    retval = connect(fd, sh_ipvx_sockaddr_cast(paddr), SH_SSP_LEN(paddr));
1009  } while (retval < 0 && (errno == EINTR || errno == EINPROGRESS));
1010
1011  if (retval == -1 && errno == ECONNREFUSED)
1012    {
1013      if (portchk_debug)
1014        {
1015          sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1016          fprintf(stderr, _("check port_tcp: %5d on %15s closed\n"),
1017                  port, ipbuf);
1018        }
1019    }
1020  else if (retval == -1)
1021    {
1022#ifdef TEST_ONLY
1023      if (portchk_debug)
1024        perror(_("connect"));
1025#else
1026      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1027      nerr = errno;
1028      sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
1029                  port, ipbuf, sh_error_message(errno, errbuf, sizeof(errbuf)));
1030      SH_MUTEX_LOCK(mutex_thread_nolog);
1031      sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
1032                      errmsg, _("connect"));
1033      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1034#endif
1035    }
1036  else
1037    {
1038      /* Try to get service name from portmap
1039       */
1040      if (paddr->ss_family == AF_INET)
1041        {
1042          p = check_rpc_list (port, 
1043                              (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr), 
1044                              IPPROTO_TCP);
1045        }
1046
1047      sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
1048
1049      /* If not an RPC service, try to get name from /etc/services
1050       */
1051      if (!p)
1052        p = check_services(port, IPPROTO_TCP);
1053
1054      if (portchk_debug)
1055        {
1056          sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
1057          fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"), 
1058                  port, ipbuf, p);
1059        }
1060
1061#if !defined(O_NONBLOCK)
1062#if defined(O_NDELAY)
1063#define O_NONBLOCK  O_NDELAY
1064#else
1065#define O_NONBLOCK  0
1066#endif
1067#endif
1068
1069      /* prepare to close connection gracefully
1070       */
1071      if      (port == 22)  /* ssh */
1072        {
1073          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1074          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1075          retval = write (fd, _("SSH-2.0-Foobar"), 14);
1076          if (retval > 0) retval = write (fd, "\r\n", 2);
1077        }
1078      else if (port == 25)  /* smtp */
1079        {
1080          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1081          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1082          retval = write (fd, _("QUIT"), 4);
1083          if (retval > 0) retval = write (fd, "\r\n", 2);
1084        }
1085      else if (port == 79)  /* finger */
1086        {
1087          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1088          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1089          retval = write (fd, "\r\n", 2);
1090        }
1091      else if (port == 110) /* pop3 */
1092        {
1093          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1094          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1095          retval = write (fd, _("QUIT"), 4);
1096          if (retval > 0) retval = write (fd, "\r\n", 2);
1097        }
1098      else if (port == 143) /* imap */
1099        {
1100          flags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1101          retry_fcntl(FIL__, __LINE__, fd, F_SETFL, flags | O_NONBLOCK);
1102          retval = write (fd, _("A01 LOGOUT"), 10);
1103          if (retval > 0) retval = write (fd, "\r\n", 2);
1104        }
1105
1106      if (portchk_debug && retval < 0)
1107        fprintf(stderr, _("check port: error writing to port %5d\n"), 
1108                port);
1109     }
1110  sl_close_fd (FIL__, __LINE__, fd);
1111  return 0;
1112}
1113
1114/* typedef uint32_t in_addr_t;
1115 * struct in_addr
1116 * {
1117 * in_addr_t s_addr;
1118 * };
1119 */
1120
1121#define SH_IFACE_MAX 16
1122
1123struct portchk_interfaces {
1124  struct sh_sockaddr iface[SH_IFACE_MAX];
1125  int            used;
1126};
1127
1128static struct portchk_interfaces iface_list;
1129static int iface_initialized = 0;
1130
1131#ifdef TEST_ONLY
1132static char * portchk_hostname = NULL;
1133#else
1134static char * portchk_hostname = sh.host.name;
1135#endif
1136
1137static int sh_portchk_init_internal (void)
1138{
1139  volatile int     i, j; /* might be clobbered by ‘longjmp’ or ‘vfork’*/
1140  char errbuf[256];
1141#if defined(USE_IPVX)
1142  struct addrinfo hints;
1143  struct addrinfo *res;
1144#else
1145  struct hostent * hent;
1146#endif
1147  char ipbuf[SH_IP_BUF];
1148
1149  if (portchk_debug)
1150    fprintf(stderr, _("checking ports on: %s\n"), portchk_hostname ? portchk_hostname : _("NULL"));
1151
1152  if (!portchk_hostname)
1153    return -1;
1154
1155  if (sh_portchk_active == S_FALSE)
1156    return -1;
1157
1158  SH_MUTEX_LOCK(mutex_port_check);
1159  if (iface_initialized == 0)
1160    {
1161      iface_list.used   = 0;
1162      iface_initialized = 1;
1163    }
1164
1165#if !defined(USE_IPVX)
1166  SH_MUTEX_LOCK(mutex_resolv);
1167  hent = sh_gethostbyname(portchk_hostname);
1168  i = 0;
1169  while (hent && hent->h_addr_list[i] && (iface_list.used < SH_IFACE_MAX))
1170    {
1171      struct sockaddr_in sin;
1172      struct sh_sockaddr iface_tmp;
1173
1174      memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
1175      sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
1176
1177      for (j = 0; j < iface_list.used; ++j)
1178        {
1179          if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list.iface[j])))
1180            {
1181              goto next_iface;
1182            }
1183        }
1184
1185      sh_ipvx_save(&(iface_list.iface[iface_list.used]), 
1186                   AF_INET, (struct sockaddr *)&sin);
1187     
1188      if (portchk_debug)
1189        {
1190          char buf[256];
1191          sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list.iface[iface_list.used]));
1192          fprintf(stderr, _("added interface[%d]: %s\n"), i, buf); 
1193        }
1194      ++iface_list.used;
1195
1196    next_iface:
1197      ++i;
1198    }
1199  SH_MUTEX_UNLOCK(mutex_resolv);
1200#else
1201  memset(&hints, '\0', sizeof(hints));
1202  hints.ai_family = PF_UNSPEC;
1203  hints.ai_flags  = AI_ADDRCONFIG;
1204
1205  if (0 == getaddrinfo(portchk_hostname, NULL, &hints, &res))
1206    {
1207      struct addrinfo *p = res;
1208      struct sh_sockaddr iface_tmp;
1209
1210      while ((p != NULL) && (iface_list.used < SH_IFACE_MAX))
1211        {
1212          sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
1213
1214          for (j = 0; j < iface_list.used; ++j)
1215            {
1216              if (portchk_debug)
1217                {
1218                  char buf1[256], buf2[256];
1219                  sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list.iface[j]));
1220                  sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
1221                  fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2); 
1222                }
1223              if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list.iface[j])))
1224                {
1225                  if (portchk_debug) 
1226                    fprintf(stderr, _("skipping interface[%d]\n"), j);
1227                  goto next_iface;
1228                }
1229            }
1230          sh_ipvx_save(&(iface_list.iface[iface_list.used]), 
1231                       p->ai_family, p->ai_addr);
1232
1233          if (portchk_debug)
1234            {
1235              char buf[256];
1236              sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list.iface[iface_list.used]));
1237              fprintf(stderr, _("added interface[%d]: %s\n"), iface_list.used, buf); 
1238            }
1239
1240          ++iface_list.used;
1241
1242        next_iface:
1243          p = p->ai_next;
1244        }
1245      freeaddrinfo(res);
1246    } 
1247#endif
1248
1249  for (i = 0; i < iface_list.used; ++i)
1250    {
1251      sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list.iface[i]));
1252      sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
1253
1254      SH_MUTEX_LOCK(mutex_thread_nolog);
1255      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1256                      errbuf, _("sh_portchk_init"));
1257      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1258    }
1259  SH_MUTEX_UNLOCK(mutex_port_check);
1260
1261  return 0;
1262}
1263
1264int sh_portchk_init (struct mod_type * arg)
1265{
1266#ifndef HAVE_PTHREAD
1267  (void) arg;
1268#endif
1269
1270  if (sh_portchk_active == S_FALSE)
1271    return SH_MOD_FAILED;
1272  if (!portchk_hostname)
1273    return SH_MOD_FAILED;
1274
1275#ifdef HAVE_PTHREAD
1276  if (arg != NULL && arg->initval < 0 &&
1277      (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1278    {
1279      if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
1280        return SH_MOD_THREAD;
1281      else
1282        return SH_MOD_FAILED;
1283    }
1284  else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1285           (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1286    {
1287      return SH_MOD_THREAD;
1288    }
1289#endif
1290  return sh_portchk_init_internal();
1291}
1292
1293
1294
1295#if !defined(TEST_ONLY)
1296int sh_portchk_reconf (void)
1297{
1298  SH_MUTEX_LOCK(mutex_port_check);
1299  iface_initialized    = 0;
1300  sh_portchk_active    = 1;
1301  sh_portchk_check_udp = 1;
1302  sh_portchk_interval  = SH_PORTCHK_INTERVAL;
1303
1304  sh_portchk_minport = -1;
1305  sh_portchk_maxport = -1;
1306
1307  portlist_udp = sh_portchk_kill_list (portlist_udp);
1308  portlist_tcp = sh_portchk_kill_list (portlist_tcp);
1309
1310  blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
1311  blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
1312  sh_port2proc_finish();
1313
1314  SH_MUTEX_UNLOCK(mutex_port_check);
1315  return 0;
1316}
1317
1318int sh_portchk_cleanup (void)
1319{
1320  return sh_portchk_reconf ();
1321}
1322
1323int sh_portchk_timer (time_t tcurrent) 
1324{
1325  static time_t lastcheck = 0;
1326
1327  SL_ENTER(_("sh_portchk_timer"));
1328  if ((time_t) (tcurrent - lastcheck) >= sh_portchk_interval)
1329    {
1330      lastcheck  = tcurrent;
1331      SL_RETURN((-1), _("sh_portchk_timer"));
1332    }
1333  SL_RETURN(0, _("sh_portchk_timer"));
1334}
1335#endif
1336
1337static int check_port_generic (int port, int domain, int type, int protocol)
1338{
1339  volatile int     i    =  0;
1340  int              sock = -1;
1341  int              flag =  1; /* non-zero to enable an option */
1342  struct sh_sockaddr   paddr;
1343  char errbuf[SH_ERRBUF_SIZE];
1344
1345  /* Check all interfaces for this host
1346   */
1347  while (i < iface_list.used)
1348    {
1349      memcpy(&paddr, &(iface_list.iface[i]), sizeof(paddr));
1350
1351      if (paddr.ss_family != domain)
1352        {
1353          ++i;
1354          continue;
1355        }
1356
1357      if (0 != sh_portchk_is_blacklisted(port, &paddr, protocol))
1358        {
1359          ++i; 
1360          continue;
1361        }
1362
1363      if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
1364        {
1365          ++i;
1366#ifdef TEST_ONLY
1367          if (portchk_debug)
1368            perror(_("socket"));
1369#else
1370
1371#ifndef EPROTONOSUPPORT
1372#define EPROTONOSUPPORT 0
1373#endif
1374#ifndef EAFNOSUPPORT
1375#define EAFNOSUPPORT    0
1376#endif
1377          if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1378            {
1379              SH_MUTEX_LOCK(mutex_thread_nolog);
1380              sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1381                              sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1382              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1383            }
1384#endif
1385          continue;
1386        }
1387      if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1388                      (void *) &flag, sizeof(flag)) < 0 )
1389        {
1390          ++i;
1391#ifdef TEST_ONLY
1392          if (portchk_debug)
1393            perror(_("setsockopt"));
1394#else
1395          SH_MUTEX_LOCK(mutex_thread_nolog);
1396          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1397                          sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1398          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1399#endif
1400          continue;
1401        }
1402
1403
1404      if (protocol == IPPROTO_TCP)
1405        check_port_tcp_internal(sock, port, &paddr);
1406      else
1407        check_port_udp_internal(sock, port, &paddr);
1408
1409      ++i;
1410    }
1411
1412  return 0;
1413}
1414
1415
1416
1417static int check_port_udp (int port, int domain)
1418{
1419  return check_port_generic(port, domain, SOCK_DGRAM, IPPROTO_UDP);
1420}
1421
1422static int check_port_tcp (int port, int domain)
1423{
1424  return check_port_generic(port, domain, SOCK_STREAM, IPPROTO_TCP);
1425}
1426
1427
1428static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg, 
1429                                          int domain, int type, int protocol)
1430{
1431  /*
1432  int min_port = 1024;
1433  int max_port = 65535;
1434  */
1435
1436  volatile int port; /*  might be clobbered by ‘longjmp’ or ‘vfork’*/
1437  volatile int max_port = max_port_arg;
1438  int retval;
1439  int sock   = -1;
1440#if 0
1441  int flag   = 1; /* non-zero to enable an option */
1442#endif
1443  struct sockaddr_in  addr4;
1444  struct sockaddr_in6 addr6;
1445
1446  int addrlen4      = sizeof(addr4);
1447  int addrlen6      = sizeof(addr6);
1448
1449  struct in6_addr anyaddr = IN6ADDR_ANY_INIT; 
1450
1451  char errbuf[SH_ERRBUF_SIZE];
1452
1453  if (min_port == -1)
1454     min_port = 0;
1455  if (max_port == -1)
1456    max_port = 65535;
1457
1458  if (portchk_debug)
1459    fprintf(stderr, _("scan_ports_generic %d-%d %s %s\n"), 
1460            min_port, max_port, (domain == AF_INET6) ? _("AF_INET6") : _("AF_INET"),
1461            (protocol == IPPROTO_TCP) ? _("tcp") : _("udp"));
1462           
1463  for (port = min_port; port <= max_port; ++port) 
1464    {
1465      if ((sock = socket(domain, type, protocol)) < 0 )
1466        {
1467#ifdef TEST_ONLY
1468          if (portchk_debug)
1469            perror(_("socket"));
1470#else
1471#ifndef EPROTONOSUPPORT
1472#define EPROTONOSUPPORT 0
1473#endif
1474#ifndef EAFNOSUPPORT
1475#define EAFNOSUPPORT    0
1476#endif
1477          if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT)
1478            {
1479              SH_MUTEX_LOCK(mutex_thread_nolog);
1480              sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1481                              sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
1482              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1483            }
1484#endif
1485          continue;
1486        }
1487
1488#if 0
1489      if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1490                      (void *) &flag, sizeof(flag)) < 0 )
1491        {
1492#ifdef TEST_ONLY
1493          if (portchk_debug)
1494            perror(_("setsockopt"));
1495#else
1496          SH_MUTEX_LOCK(mutex_thread_nolog);
1497          sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
1498                          sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
1499          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1500#endif
1501          continue;
1502        }
1503#endif
1504
1505      if (domain == AF_INET)
1506        {
1507          addr4.sin_family      = AF_INET;
1508          addr4.sin_port        = htons(port);
1509          addr4.sin_addr.s_addr = INADDR_ANY;
1510          retval = bind (sock, (struct sockaddr *) &addr4, addrlen4);
1511        }
1512      else
1513        {
1514          addr6.sin6_family       = AF_INET6;
1515          addr6.sin6_port         = htons(port);
1516          memcpy(&(addr6.sin6_addr.s6_addr), &anyaddr, sizeof(anyaddr));
1517          retval = bind (sock, (struct sockaddr *) &addr6, addrlen6);
1518        }
1519
1520      if (retval == 0)
1521        {
1522          /* we can bind the port, thus it is unused
1523           */
1524          sl_close_fd (FIL__, __LINE__, sock);
1525        }
1526      else
1527        {
1528          if (errno == EINVAL || errno == EADDRINUSE)
1529            {
1530              /* try to connect to the port
1531               */
1532              if (protocol == IPPROTO_TCP)
1533                check_port_tcp(port, domain);
1534              else
1535                check_port_udp(port, domain);
1536            }
1537          else
1538            {
1539#ifdef TEST_ONLY
1540              if (portchk_debug)
1541                perror(_("bind"));
1542#else
1543              SH_MUTEX_LOCK(mutex_thread_nolog);
1544              sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
1545                              sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
1546              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1547#endif
1548            }
1549          sl_close_fd (FIL__, __LINE__, sock);
1550        }
1551    }
1552  return 0;
1553}
1554
1555static int sh_portchk_scan_ports_tcp (int min_port, int max_port)
1556{
1557#if defined(USE_IPVX)
1558  sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6, 
1559                                 SOCK_STREAM, IPPROTO_TCP);
1560#endif
1561  return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET, 
1562                                        SOCK_STREAM, IPPROTO_TCP);
1563}
1564 
1565static int sh_portchk_scan_ports_udp (int min_port, int max_port)
1566{
1567#if defined(USE_IPVX)
1568  sh_portchk_scan_ports_generic (min_port, max_port, AF_INET6, 
1569                                 SOCK_DGRAM, IPPROTO_UDP);
1570#endif
1571  return sh_portchk_scan_ports_generic (min_port, max_port, AF_INET,
1572                                        SOCK_DGRAM, IPPROTO_UDP);
1573}
1574
1575/* Subroutine to add an interface
1576 */
1577void * sh_dummy_1564_str    = NULL; /* fix clobbered by.. warning */
1578
1579static int sh_portchk_add_interface (const char * str)
1580{
1581  struct sh_sockaddr saddr;
1582  char errbuf[256];
1583  char buf[64];
1584
1585  sh_dummy_1564_str    = (void*) &str;
1586
1587  if (iface_initialized == 0)
1588    {
1589      iface_list.used   = 0;
1590      iface_initialized = 1;
1591    }
1592
1593  do {
1594
1595    while (*str == ',' || *str == ' ' || *str == '\t') ++str;
1596
1597    if (*str)
1598      {
1599        char ipbuf[SH_IP_BUF];
1600        unsigned int i = 0;
1601        while (*str && i < (sizeof(buf)-1) && 
1602               *str != ',' && *str != ' ' && *str != '\t')
1603          {
1604            buf[i] = *str; ++str; ++i;
1605          }
1606        buf[i] = '\0';
1607
1608        if (0 == sh_ipvx_aton(buf, &saddr))
1609          return -1;
1610
1611        if (iface_list.used == SH_IFACE_MAX)
1612          return -1;
1613
1614        sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
1615        sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), ipbuf);
1616        SH_MUTEX_LOCK(mutex_thread_nolog);
1617        sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1618                        errbuf, _("sh_portchk_add_interface"));
1619        SH_MUTEX_UNLOCK(mutex_thread_nolog);
1620       
1621        memcpy (&(iface_list.iface[iface_list.used]), &(saddr), sizeof(saddr));
1622        ++iface_list.used;
1623      }
1624  } while (*str);
1625
1626  sh_dummy_1564_str = NULL;
1627  return 0;
1628}
1629
1630/* verify whether port/interface is blacklisted (do not check)
1631 */
1632static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr, 
1633                                     int proto)
1634{
1635  struct sh_port * head;
1636
1637  if (proto == IPPROTO_TCP)
1638    head = blacklist_tcp;
1639  else
1640    head = blacklist_udp;
1641
1642  while (head)
1643    {
1644      if (head->port == port)
1645        {
1646          if (sh_ipvx_isany(head->paddr) || 
1647              0 == sh_ipvx_cmp(head->paddr, saddr))
1648            return 1;
1649          else
1650            return 0;
1651        }
1652      head = head->next;
1653    }
1654  return 0;
1655}
1656
1657
1658static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
1659{
1660  struct sh_port * black;
1661  struct sh_port * head;
1662
1663  if (proto == IPPROTO_TCP)
1664    head = blacklist_tcp;
1665  else
1666    head = blacklist_udp;
1667
1668  black = head;
1669
1670  while (black)
1671    {
1672      if (black->port == port && 
1673          0 == sh_ipvx_cmp(head->paddr, saddr))
1674        return -1;
1675      black = black->next;
1676    }
1677
1678  black = SH_ALLOC (sizeof(struct sh_port));
1679  black->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
1680  black->port  = port;
1681  memcpy(black->paddr, saddr, sizeof(struct sh_sockaddr));
1682  black->next  = head;
1683
1684  if (proto == IPPROTO_TCP)
1685    blacklist_tcp = black;
1686  else
1687    blacklist_udp = black;
1688
1689  if (portchk_debug)
1690    {
1691      int checkit = sh_portchk_is_blacklisted(port, saddr, proto);
1692      fprintf(stderr, _("port blacklisted: %d %s\n"), port, 
1693              (checkit == 1) ? _("ok") : _("fail"));
1694    }
1695  return 0;
1696}
1697 
1698 
1699/* Subroutine to add a required or optional port/service
1700 */
1701static int sh_portchk_add_required_port_generic (char * service, 
1702                                                 char * interface, int type)
1703{
1704  char buf[256] = { '\0' };
1705  int proto;
1706  char * p;
1707  char * endptr;
1708  unsigned long int  port;
1709  struct sh_sockaddr   saddr;
1710  struct sh_portentry * portent;
1711
1712  if (0 == sh_ipvx_aton(interface, &saddr))
1713    return -1;
1714
1715  sl_strlcpy (buf, service, sizeof(buf));
1716
1717  p = strchr(buf, '/');
1718  if (!p)
1719    return -1;
1720  if (0 == strcmp(p, _("/tcp")))
1721    proto = IPPROTO_TCP;
1722  else if  (0 == strcmp(p, _("/udp")))
1723    proto = IPPROTO_UDP;
1724  else
1725    return -1;
1726
1727  *p = '\0';
1728  port = strtoul(buf, &endptr, 0);
1729
1730  if (portchk_debug)
1731    {
1732      char buf[SH_IP_BUF];
1733      sh_ipvx_ntoa(buf, sizeof(buf), &saddr);
1734      fprintf(stderr, _("add_port_generic: %s (%s) %d %s (%s)\n"),
1735              interface, buf, (int) port, (proto == IPPROTO_TCP) ? _("tcp") : _("udp"),
1736              sh_port_type2str(type));
1737    }
1738
1739  /* Blacklisted ports
1740   */
1741  if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
1742    return (sh_portchk_blacklist(port, &saddr, proto));
1743
1744  if (*endptr != '\0')
1745    { 
1746      portent = sh_portchk_get_from_list (proto, -1, &saddr, buf);
1747      if (!portent)
1748        {
1749          if (portchk_debug)
1750            fprintf(stderr, _("add_required_port %d\n"), (int) port);
1751          sh_portchk_add_to_list (proto,   -1, &saddr,  buf, type, SH_PORT_UNKN);
1752        }
1753      else
1754        {
1755#ifdef TEST_ONLY
1756          fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
1757#else
1758          SH_MUTEX_LOCK(mutex_thread_nolog);
1759          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1760                          _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
1761          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1762#endif
1763          return -1;
1764        }
1765    }
1766  else if (port <= 65535)
1767    {
1768      portent = sh_portchk_get_from_list (proto, port, &saddr, NULL);
1769      if (!portent)
1770        {
1771          if (portchk_debug)
1772            fprintf(stderr, _("add_required_port: open port: %d/%s\n"), 
1773                    (int) port, SH_PROTO_STR(proto));
1774          sh_portchk_add_to_list (proto, port, &saddr, NULL, type, SH_PORT_UNKN);
1775        }
1776      else
1777        {
1778#ifdef TEST_ONLY
1779          fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
1780#else
1781          SH_MUTEX_LOCK(mutex_thread_nolog);
1782          sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1783                          _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
1784          SH_MUTEX_UNLOCK(mutex_thread_nolog);
1785#endif
1786          return -1;
1787        }
1788    }
1789  else
1790    return -1;
1791
1792  return 0;
1793}
1794
1795/* Internal interface to add required or optional ports as 'iface:portlist'
1796 */
1797static int sh_portchk_add_required_generic (const char * str, int type)
1798{
1799  size_t ll = 0;
1800  int    status;
1801
1802  char * interface = NULL;
1803  char * list;
1804  char * p;
1805#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1806  char * saveptr;
1807#endif
1808
1809  if (!str)
1810    return -1;
1811
1812  if (strchr(str, ':'))
1813    {
1814      char *last = strrchr(str, ':');
1815      if (last != NULL)
1816        {
1817          size_t tolast = (last - str);
1818          interface = SH_ALLOC(tolast+1);
1819          sl_strlcpy(interface, str, tolast+1);
1820          interface[tolast] = '\0';
1821
1822          ll = tolast;
1823
1824          while (str[ll] == ':' || str[ll] == ' ' || str[ll] == '\t')
1825            ++ll;
1826        }
1827    }
1828  else
1829    {
1830      interface = SH_ALLOC(8);
1831      sl_strlcpy(interface, _("0.0.0.0"), 8);
1832      interface[7] = '\0';
1833      while (str[ll] == ' ' || str[ll] == '\t')
1834        ++ll;     
1835    }
1836
1837  if (!interface)
1838    return -1;
1839
1840  if (str[ll] == '\0')
1841    {
1842      SH_FREE(interface);
1843      return -1;
1844    }
1845
1846  if (portchk_debug)
1847    fprintf(stderr, "add ports for interface: %s (%s)\n", interface, sh_port_type2str(type));
1848
1849  list = sh_util_strdup(&str[ll]);
1850#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1851  p    = strtok_r (list, " ,\t", &saveptr);
1852#else
1853  p    = strtok (list, " ,\t");
1854#endif
1855  if (!p)
1856    {
1857      SH_FREE(interface);
1858      SH_FREE(list);
1859      return -1;
1860    }
1861  while (p)
1862    {
1863      status = sh_portchk_add_required_port_generic (p, interface, type);
1864
1865      if (-1 == status)
1866        {
1867          SH_FREE(interface);
1868          SH_FREE(list);
1869          return -1;
1870        }
1871#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1872      p    = strtok_r (NULL, " ,\t", &saveptr);
1873#else
1874      p    = strtok (NULL, " ,\t");
1875#endif
1876    }
1877  SH_FREE(interface);
1878  SH_FREE(list);
1879  return 0;
1880}
1881
1882/* User interface to add required ports as 'iface:portlist'
1883 */
1884static int sh_portchk_add_required (const char * str)
1885{
1886  return sh_portchk_add_required_generic (str, SH_PORT_REQ); 
1887}
1888
1889/* User interface to add optional ports as 'iface:portlist'
1890 */
1891static int sh_portchk_add_optional (const char * str)
1892{
1893  return sh_portchk_add_required_generic (str, SH_PORT_OPT); 
1894}
1895
1896/* User interface to add ignoreable ports as 'iface:portlist'
1897 */
1898static int sh_portchk_add_ignore (const char * str)
1899{
1900  return sh_portchk_add_required_generic (str, SH_PORT_IGN); 
1901}
1902
1903/* User interface to add ports that should not be checked as 'iface:portlist'
1904 */
1905static int sh_portchk_add_blacklist (const char * str)
1906{
1907  return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST); 
1908}
1909
1910/* Interface to run port check
1911 */
1912int sh_portchk_check ()
1913{
1914  volatile int min_port;
1915  static int noprivports = 0;
1916
1917  SH_MUTEX_LOCK(mutex_port_check);
1918
1919  min_port = (sh_portchk_minport == -1) ? 0 : sh_portchk_minport;
1920
1921  if (sh_portchk_active != S_FALSE)
1922    {
1923      SH_MUTEX_LOCK(mutex_thread_nolog);
1924      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1925                      _("Checking for open ports"),
1926                      _("sh_portchk_check"));
1927      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1928
1929      sh_portchk_reset_lists();
1930      if ((0 != geteuid()) && (min_port < 1024))
1931        {
1932          min_port = 1024;
1933          if (noprivports == 0)
1934            {
1935#ifdef TEST_ONLY
1936              fprintf(stderr, "** WARNING not scanning ports < 1024\n");
1937#else
1938              SH_MUTEX_LOCK(mutex_thread_nolog);
1939              sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1940                              _("not scanning ports below 1024"), 
1941                              _("sh_portchk_check"));
1942              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1943#endif
1944              noprivports = 1;
1945            }
1946        }
1947
1948      sh_port2proc_prepare();
1949
1950      if (sh_portchk_check_udp == 1)
1951        sh_portchk_scan_ports_udp(min_port, sh_portchk_maxport);
1952      sh_portchk_scan_ports_tcp(min_port, sh_portchk_maxport);
1953
1954
1955      sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
1956      if (sh_portchk_check_udp == 1)
1957        sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
1958
1959    }
1960  SH_MUTEX_UNLOCK(mutex_port_check);
1961  return 0;
1962}
1963#endif
1964
1965#ifdef SH_CUTEST
1966#include "CuTest.h"
1967
1968void Test_portcheck_lists (CuTest *tc)
1969{
1970#if defined(SH_USE_PORTCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
1971  struct sh_sockaddr    haddr_local;
1972  struct sh_portentry * portent;
1973  char   buf[256];
1974  char * p;
1975
1976#ifdef HAVE_RPC_RPC_H
1977  p = sh_getrpcbynumber(0, buf, sizeof(buf));
1978  CuAssertTrue(tc, p == NULL);
1979
1980  p = sh_getrpcbynumber(100000, buf, sizeof(buf));
1981  CuAssertPtrNotNull(tc, p);
1982  CuAssertTrue(tc, (0 == strcmp(p, "portmapper") || 0 == strcmp(p, "rpcbind")));
1983  CuAssertTrue(tc, (0 == strcmp(buf, "portmapper") || 0 == strcmp(p, "rpcbind")));
1984
1985  p = sh_getrpcbynumber(100007, buf, sizeof(buf));
1986  CuAssertPtrNotNull(tc, p);
1987  CuAssertTrue(tc, 0 == strcmp(p, "ypbind"));
1988  CuAssertTrue(tc, 0 == strcmp(buf, "ypbind"));
1989#endif
1990
1991  p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
1992  CuAssertTrue(tc, p == NULL);
1993
1994#if !defined(HOST_IS_CYGWIN)
1995  p = sh_getservbyport(22, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf));
1996  CuAssertPtrNotNull(tc, p);
1997  CuAssertTrue(tc, 0 == strcmp(p, "ssh"));
1998  CuAssertTrue(tc, 0 == strcmp(buf, "ssh"));
1999#endif
2000
2001  p = sh_getservbyport(13, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
2002  CuAssertPtrNotNull(tc, p);
2003  CuAssertTrue(tc, 0 == strcmp(p, "daytime"));
2004  CuAssertTrue(tc, 0 == strcmp(buf, "daytime"));
2005
2006  CuAssertTrue(tc, 0 != sh_ipvx_aton("127.0.0.1", &haddr_local));
2007
2008  sh_portchk_add_to_list (IPPROTO_TCP,  8000, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2009
2010  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, NULL);
2011  CuAssertPtrNotNull(tc, portent);
2012
2013  CuAssertTrue(tc, portent->port == 8000);
2014  CuAssertTrue(tc, 0 == strcmp("127.0.0.1", portent->interface));
2015  CuAssertTrue(tc, portent->status == SH_PORT_UNKN);
2016  CuAssertTrue(tc, portent->flag == SH_PORT_NOT);
2017
2018  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2019
2020  CuAssertTrue(tc, NULL == portlist_tcp);
2021
2022  sh_portchk_add_to_list (IPPROTO_TCP,  8000, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2023  sh_portchk_add_to_list (IPPROTO_TCP,  8001, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2024  sh_portchk_add_to_list (IPPROTO_TCP,  8002, &haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
2025  sh_portchk_add_to_list (IPPROTO_TCP,  8003, &haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
2026  sh_portchk_add_to_list (IPPROTO_TCP,  8004, &haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
2027  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
2028  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
2029  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
2030  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
2031  sh_portchk_add_to_list (IPPROTO_TCP,    -1, &haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
2032
2033  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
2034
2035  CuAssertPtrNotNull(tc, portlist_tcp);
2036
2037  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, NULL);
2038  CuAssertPtrNotNull(tc, portent);
2039
2040  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8001, &haddr_local, NULL);
2041  CuAssertTrue(tc, NULL == portent);
2042
2043  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8002, &haddr_local, NULL);
2044  CuAssertPtrNotNull(tc, portent);
2045
2046  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8003, &haddr_local, NULL);
2047  CuAssertTrue(tc, NULL == portent);
2048
2049  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8004, &haddr_local, NULL);
2050  CuAssertPtrNotNull(tc, portent);
2051
2052  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo1");
2053  CuAssertTrue(tc, NULL == portent);
2054
2055  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo2");
2056  CuAssertPtrNotNull(tc, portent);
2057  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
2058
2059  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo3");
2060  CuAssertTrue(tc, NULL == portent);
2061
2062  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo4");
2063  CuAssertPtrNotNull(tc, portent);
2064  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
2065
2066  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, &haddr_local, "foo5");
2067  CuAssertPtrNotNull(tc, portent);
2068  CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
2069
2070  CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2071  CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_TCP));
2072  CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_TCP));
2073  CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_TCP));
2074  CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2075  CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, &haddr_local, IPPROTO_UDP));
2076  CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, &haddr_local, IPPROTO_UDP));
2077  CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, &haddr_local, IPPROTO_UDP));
2078
2079  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_UDP));
2080  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_UDP));
2081  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_UDP));
2082  CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_UDP));
2083
2084  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, &haddr_local, IPPROTO_TCP));
2085  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, &haddr_local, IPPROTO_TCP));
2086  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, &haddr_local, IPPROTO_TCP));
2087  CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, &haddr_local, IPPROTO_TCP));
2088#else
2089  (void) tc; /* fix compiler warning */
2090#endif
2091  return;
2092}
2093#endif
2094
2095#ifdef TEST_ONLY
2096
2097void usage (char * pname)
2098{
2099  printf ("%s [-r|--required interface:portlist][-o|--optional interface:portlist][--no-udp][-d|--debug] hostname\n\n", pname);
2100  printf ("   Check local host for open ports; Version %s\n\n", PORTCHK_VERSION);
2101  printf ("   Interface: Numeric address for an interface, e.g. 127.0.0.1\n");
2102  printf ("   Portlist:  List of ports or services, e.g. 22/tcp,nfs/udp,nlockmgr/udp\n");
2103  printf ("     required -> must be open\n");
2104  printf ("     optional ->  may be open or closed\n");
2105  printf ("   RPC services must be specified with service **name**, others with **port number**\n\n");
2106  printf ("   Example:\n");
2107  printf ("      %s --required 192.168.1.2:22/tcp,nfs/udp,nlockmgr/udp\n\n", pname);
2108  return;
2109}
2110
2111int main(int argc, char *argv[])
2112{
2113  char * pname = argv[0];
2114
2115
2116  /*
2117  test_lists();
2118
2119  portlist_tcp = sh_portchk_kill_list (portlist_tcp);
2120  portlist_udp = sh_portchk_kill_list (portlist_udp);
2121  */
2122
2123  /* sh_portchk_add_required ("127.0.0.1 : nlockmgr/tcp, 5308/tcp, nfs/tcp"); */
2124
2125  while (argc > 1 && argv[1][0] == '-')
2126    {
2127      if (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h"))
2128        {
2129          usage(pname);
2130          exit (0);
2131        }
2132      else if (0 == strcmp(argv[1], "--required") || 0 == strcmp(argv[1], "-r"))
2133        {
2134          if (argc < 3)
2135            {
2136              usage(pname);
2137              exit (1);
2138            }
2139          sh_portchk_add_required (argv[2]);
2140          --argc; ++argv;
2141        }
2142      else if (0 == strcmp(argv[1], "--optional") || 0 == strcmp(argv[1], "-o"))
2143        {
2144          if (argc < 3)
2145            {
2146              usage(pname);
2147              exit (1);
2148            }
2149          sh_portchk_add_optional (argv[2]);
2150          --argc; ++argv;
2151        }
2152      else if (0 == strcmp(argv[1], "--no-udp"))
2153        {
2154          sh_portchk_check_udp = 0;
2155        }
2156      else if (0 == strcmp(argv[1], "--debug") || 0 == strcmp(argv[1], "-d"))
2157        {
2158          portchk_debug = 1;
2159        }
2160      else
2161        {
2162          usage(pname);
2163          exit (1);
2164        }
2165      --argc; ++argv;
2166    }
2167
2168  if (argc < 2)
2169    {
2170      usage(pname);
2171      exit (1);
2172    }
2173
2174  portchk_hostname = argv[1];
2175     
2176  if (0 != sh_portchk_init ())
2177    {
2178      usage(pname);
2179      exit (1);
2180    }
2181
2182  sh_portchk_check();
2183
2184  return 0;
2185}
2186#endif
Note: See TracBrowser for help on using the repository browser.