source: trunk/src/sh_portcheck.c@ 408

Last change on this file since 408 was 405, checked in by katerina, 12 years ago

Fix for tickets #303, #304, #305. #306, and #307. Update version number.

  • 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#ifdef HAVE_RPC_RPC_H
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.