source: trunk/src/sh_portcheck.c@ 296

Last change on this file since 296 was 295, checked in by katerina, 14 years ago

Support for IPv6 (ticket #222).

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