source: trunk/src/sh_portcheck.c @ 452

Last change on this file since 452 was 439, checked in by katerina, 8 years ago

Fix for ticket #343 (Static compile with port check fails)

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