144743Smarkm /* 244743Smarkm * tcpdchk - examine all tcpd access control rules and inetd.conf entries 344743Smarkm * 444743Smarkm * Usage: tcpdchk [-a] [-d] [-i inet_conf] [-v] 544743Smarkm * 644743Smarkm * -a: complain about implicit "allow" at end of rule. 744743Smarkm * 844743Smarkm * -d: rules in current directory. 944743Smarkm * 1044743Smarkm * -i: location of inetd.conf file. 1144743Smarkm * 1244743Smarkm * -v: show all rules. 1344743Smarkm * 1444743Smarkm * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 1551495Ssheldonh * 1651495Ssheldonh * $FreeBSD$ 1744743Smarkm */ 1844743Smarkm 1944743Smarkm#ifndef lint 2044743Smarkmstatic char sccsid[] = "@(#) tcpdchk.c 1.8 97/02/12 02:13:25"; 2144743Smarkm#endif 2244743Smarkm 2344743Smarkm/* System libraries. */ 2444743Smarkm 2544743Smarkm#include <sys/types.h> 2644743Smarkm#include <sys/stat.h> 2756977Sshin#ifdef INET6 2856977Sshin#include <sys/socket.h> 2956977Sshin#endif 3044743Smarkm#include <netinet/in.h> 3144743Smarkm#include <arpa/inet.h> 3244743Smarkm#include <stdio.h> 3344743Smarkm#include <syslog.h> 3444743Smarkm#include <setjmp.h> 3544743Smarkm#include <errno.h> 3644743Smarkm#include <netdb.h> 3744743Smarkm#include <string.h> 3844743Smarkm 3944743Smarkmextern int errno; 4044743Smarkmextern void exit(); 4144743Smarkmextern int optind; 4244743Smarkmextern char *optarg; 4344743Smarkm 4444743Smarkm#ifndef INADDR_NONE 4544743Smarkm#define INADDR_NONE (-1) /* XXX should be 0xffffffff */ 4644743Smarkm#endif 4744743Smarkm 4844743Smarkm#ifndef S_ISDIR 4944743Smarkm#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 5044743Smarkm#endif 5144743Smarkm 5244743Smarkm/* Application-specific. */ 5344743Smarkm 5444743Smarkm#include "tcpd.h" 5544743Smarkm#include "inetcf.h" 5644743Smarkm#include "scaffold.h" 5744743Smarkm 5844743Smarkm /* 5944743Smarkm * Stolen from hosts_access.c... 6044743Smarkm */ 6144743Smarkmstatic char sep[] = ", \t\n"; 6244743Smarkm 6344743Smarkm#define BUFLEN 2048 6444743Smarkm 6544743Smarkmint resident = 0; 6644743Smarkmint hosts_access_verbose = 0; 6744743Smarkmchar *hosts_allow_table = HOSTS_ALLOW; 6844743Smarkmchar *hosts_deny_table = HOSTS_DENY; 6944743Smarkmextern jmp_buf tcpd_buf; 7044743Smarkm 7144743Smarkm /* 7244743Smarkm * Local stuff. 7344743Smarkm */ 7444743Smarkmstatic void usage(); 7544743Smarkmstatic void parse_table(); 7644743Smarkmstatic void print_list(); 7744743Smarkmstatic void check_daemon_list(); 7844743Smarkmstatic void check_client_list(); 7944743Smarkmstatic void check_daemon(); 8044743Smarkmstatic void check_user(); 8144743Smarkmstatic int check_host(); 8244743Smarkmstatic int reserved_name(); 8344743Smarkm 8444743Smarkm#define PERMIT 1 8544743Smarkm#define DENY 0 8644743Smarkm 8744743Smarkm#define YES 1 8844743Smarkm#define NO 0 8944743Smarkm 9044743Smarkmstatic int defl_verdict; 9144743Smarkmstatic char *myname; 9244743Smarkmstatic int allow_check; 9344743Smarkmstatic char *inetcf; 9444743Smarkm 9544743Smarkmint main(argc, argv) 9644743Smarkmint argc; 9744743Smarkmchar **argv; 9844743Smarkm{ 9944743Smarkm struct request_info request; 10044743Smarkm struct stat st; 10144743Smarkm int c; 10244743Smarkm 10344743Smarkm myname = argv[0]; 10444743Smarkm 10544743Smarkm /* 10644743Smarkm * Parse the JCL. 10744743Smarkm */ 10844743Smarkm while ((c = getopt(argc, argv, "adi:v")) != EOF) { 10944743Smarkm switch (c) { 11044743Smarkm case 'a': 11144743Smarkm allow_check = 1; 11244743Smarkm break; 11344743Smarkm case 'd': 11444743Smarkm hosts_allow_table = "hosts.allow"; 11544743Smarkm hosts_deny_table = "hosts.deny"; 11644743Smarkm break; 11744743Smarkm case 'i': 11844743Smarkm inetcf = optarg; 11944743Smarkm break; 12044743Smarkm case 'v': 12144743Smarkm hosts_access_verbose++; 12244743Smarkm break; 12344743Smarkm default: 12444743Smarkm usage(); 12544743Smarkm /* NOTREACHED */ 12644743Smarkm } 12744743Smarkm } 12844743Smarkm if (argc != optind) 12944743Smarkm usage(); 13044743Smarkm 13144743Smarkm /* 13244743Smarkm * When confusion really strikes... 13344743Smarkm */ 13444743Smarkm if (check_path(REAL_DAEMON_DIR, &st) < 0) { 13544743Smarkm tcpd_warn("REAL_DAEMON_DIR %s: %m", REAL_DAEMON_DIR); 13644743Smarkm } else if (!S_ISDIR(st.st_mode)) { 13744743Smarkm tcpd_warn("REAL_DAEMON_DIR %s is not a directory", REAL_DAEMON_DIR); 13844743Smarkm } 13944743Smarkm 14044743Smarkm /* 14144743Smarkm * Process the inet configuration file (or its moral equivalent). This 14244743Smarkm * information is used later to find references in hosts.allow/deny to 14344743Smarkm * unwrapped services, and other possible problems. 14444743Smarkm */ 14544743Smarkm inetcf = inet_cfg(inetcf); 14644743Smarkm if (hosts_access_verbose) 14744743Smarkm printf("Using network configuration file: %s\n", inetcf); 14844743Smarkm 14944743Smarkm /* 15044743Smarkm * These are not run from inetd but may have built-in access control. 15144743Smarkm */ 15244743Smarkm inet_set("portmap", WR_NOT); 15344743Smarkm inet_set("rpcbind", WR_NOT); 15444743Smarkm 15544743Smarkm /* 15644743Smarkm * Check accessibility of access control files. 15744743Smarkm */ 15844743Smarkm (void) check_path(hosts_allow_table, &st); 15944743Smarkm (void) check_path(hosts_deny_table, &st); 16044743Smarkm 16144743Smarkm /* 16244743Smarkm * Fake up an arbitrary service request. 16344743Smarkm */ 16444743Smarkm request_init(&request, 16544743Smarkm RQ_DAEMON, "daemon_name", 16644743Smarkm RQ_SERVER_NAME, "server_hostname", 16744743Smarkm RQ_SERVER_ADDR, "server_addr", 16844743Smarkm RQ_USER, "user_name", 16944743Smarkm RQ_CLIENT_NAME, "client_hostname", 17044743Smarkm RQ_CLIENT_ADDR, "client_addr", 17144743Smarkm RQ_FILE, 1, 17244743Smarkm 0); 17344743Smarkm 17444743Smarkm /* 17544743Smarkm * Examine all access-control rules. 17644743Smarkm */ 17744743Smarkm defl_verdict = PERMIT; 17844743Smarkm parse_table(hosts_allow_table, &request); 17944743Smarkm defl_verdict = DENY; 18044743Smarkm parse_table(hosts_deny_table, &request); 18144743Smarkm return (0); 18244743Smarkm} 18344743Smarkm 18444743Smarkm/* usage - explain */ 18544743Smarkm 18644743Smarkmstatic void usage() 18744743Smarkm{ 18844743Smarkm fprintf(stderr, "usage: %s [-a] [-d] [-i inet_conf] [-v]\n", myname); 18944743Smarkm fprintf(stderr, " -a: report rules with implicit \"ALLOW\" at end\n"); 19044743Smarkm fprintf(stderr, " -d: use allow/deny files in current directory\n"); 19144743Smarkm fprintf(stderr, " -i: location of inetd.conf file\n"); 19244743Smarkm fprintf(stderr, " -v: list all rules\n"); 19344743Smarkm exit(1); 19444743Smarkm} 19544743Smarkm 19644743Smarkm/* parse_table - like table_match(), but examines _all_ entries */ 19744743Smarkm 19844743Smarkmstatic void parse_table(table, request) 19944743Smarkmchar *table; 20044743Smarkmstruct request_info *request; 20144743Smarkm{ 20244743Smarkm FILE *fp; 20344743Smarkm int real_verdict; 20444743Smarkm char sv_list[BUFLEN]; /* becomes list of daemons */ 20544743Smarkm char *cl_list; /* becomes list of requests */ 20644743Smarkm char *sh_cmd; /* becomes optional shell command */ 20744743Smarkm char buf[BUFSIZ]; 20844743Smarkm int verdict; 20944743Smarkm struct tcpd_context saved_context; 21044743Smarkm 21144743Smarkm saved_context = tcpd_context; /* stupid compilers */ 21244743Smarkm 21344743Smarkm if (fp = fopen(table, "r")) { 21444743Smarkm tcpd_context.file = table; 21544743Smarkm tcpd_context.line = 0; 21644743Smarkm while (xgets(sv_list, sizeof(sv_list), fp)) { 21744743Smarkm if (sv_list[strlen(sv_list) - 1] != '\n') { 21844743Smarkm tcpd_warn("missing newline or line too long"); 21944743Smarkm continue; 22044743Smarkm } 22144743Smarkm if (sv_list[0] == '#' || sv_list[strspn(sv_list, " \t\r\n")] == 0) 22244743Smarkm continue; 22344743Smarkm if ((cl_list = split_at(sv_list, ':')) == 0) { 22444743Smarkm tcpd_warn("missing \":\" separator"); 22544743Smarkm continue; 22644743Smarkm } 22744743Smarkm sh_cmd = split_at(cl_list, ':'); 22844743Smarkm 22944743Smarkm if (hosts_access_verbose) 23044743Smarkm printf("\n>>> Rule %s line %d:\n", 23144743Smarkm tcpd_context.file, tcpd_context.line); 23244743Smarkm 23344743Smarkm if (hosts_access_verbose) 23444743Smarkm print_list("daemons: ", sv_list); 23544743Smarkm check_daemon_list(sv_list); 23644743Smarkm 23744743Smarkm if (hosts_access_verbose) 23844743Smarkm print_list("clients: ", cl_list); 23944743Smarkm check_client_list(cl_list); 24044743Smarkm 24144743Smarkm#ifdef PROCESS_OPTIONS 24244743Smarkm real_verdict = defl_verdict; 24344743Smarkm if (sh_cmd) { 24444743Smarkm verdict = setjmp(tcpd_buf); 24544743Smarkm if (verdict != 0) { 24644743Smarkm real_verdict = (verdict == AC_PERMIT); 24744743Smarkm } else { 24844743Smarkm dry_run = 1; 24944743Smarkm process_options(sh_cmd, request); 25044743Smarkm if (dry_run == 1 && real_verdict && allow_check) 25144743Smarkm tcpd_warn("implicit \"allow\" at end of rule"); 25244743Smarkm } 25344743Smarkm } else if (defl_verdict && allow_check) { 25444743Smarkm tcpd_warn("implicit \"allow\" at end of rule"); 25544743Smarkm } 25644743Smarkm if (hosts_access_verbose) 25744743Smarkm printf("access: %s\n", real_verdict ? "granted" : "denied"); 25844743Smarkm#else 25944743Smarkm if (sh_cmd) 26044743Smarkm shell_cmd(percent_x(buf, sizeof(buf), sh_cmd, request)); 26144743Smarkm if (hosts_access_verbose) 26244743Smarkm printf("access: %s\n", defl_verdict ? "granted" : "denied"); 26344743Smarkm#endif 26444743Smarkm } 26544743Smarkm (void) fclose(fp); 26644743Smarkm } else if (errno != ENOENT) { 26744743Smarkm tcpd_warn("cannot open %s: %m", table); 26844743Smarkm } 26944743Smarkm tcpd_context = saved_context; 27044743Smarkm} 27144743Smarkm 27244743Smarkm/* print_list - pretty-print a list */ 27344743Smarkm 27444743Smarkmstatic void print_list(title, list) 27544743Smarkmchar *title; 27644743Smarkmchar *list; 27744743Smarkm{ 27844743Smarkm char buf[BUFLEN]; 27944743Smarkm char *cp; 28044743Smarkm char *next; 28144743Smarkm 28244743Smarkm fputs(title, stdout); 28344743Smarkm strcpy(buf, list); 28444743Smarkm 28544743Smarkm for (cp = strtok(buf, sep); cp != 0; cp = next) { 28644743Smarkm fputs(cp, stdout); 28744743Smarkm next = strtok((char *) 0, sep); 28844743Smarkm if (next != 0) 28944743Smarkm fputs(" ", stdout); 29044743Smarkm } 29144743Smarkm fputs("\n", stdout); 29244743Smarkm} 29344743Smarkm 29444743Smarkm/* check_daemon_list - criticize daemon list */ 29544743Smarkm 29644743Smarkmstatic void check_daemon_list(list) 29744743Smarkmchar *list; 29844743Smarkm{ 29944743Smarkm char buf[BUFLEN]; 30044743Smarkm char *cp; 30144743Smarkm char *host; 30244743Smarkm int daemons = 0; 30344743Smarkm 30444743Smarkm strcpy(buf, list); 30544743Smarkm 30644743Smarkm for (cp = strtok(buf, sep); cp != 0; cp = strtok((char *) 0, sep)) { 30744743Smarkm if (STR_EQ(cp, "EXCEPT")) { 30844743Smarkm daemons = 0; 30944743Smarkm } else { 31044743Smarkm daemons++; 31144743Smarkm if ((host = split_at(cp + 1, '@')) != 0 && check_host(host) > 1) { 31244743Smarkm tcpd_warn("host %s has more than one address", host); 31344743Smarkm tcpd_warn("(consider using an address instead)"); 31444743Smarkm } 31544743Smarkm check_daemon(cp); 31644743Smarkm } 31744743Smarkm } 31844743Smarkm if (daemons == 0) 31944743Smarkm tcpd_warn("daemon list is empty or ends in EXCEPT"); 32044743Smarkm} 32144743Smarkm 32244743Smarkm/* check_client_list - criticize client list */ 32344743Smarkm 32444743Smarkmstatic void check_client_list(list) 32544743Smarkmchar *list; 32644743Smarkm{ 32744743Smarkm char buf[BUFLEN]; 32844743Smarkm char *cp; 32944743Smarkm char *host; 33044743Smarkm int clients = 0; 33144743Smarkm 33244743Smarkm strcpy(buf, list); 33344743Smarkm 33444743Smarkm for (cp = strtok(buf, sep); cp != 0; cp = strtok((char *) 0, sep)) { 33544743Smarkm if (STR_EQ(cp, "EXCEPT")) { 33644743Smarkm clients = 0; 33744743Smarkm } else { 33844743Smarkm clients++; 33944743Smarkm if (host = split_at(cp + 1, '@')) { /* user@host */ 34044743Smarkm check_user(cp); 34144743Smarkm check_host(host); 34244743Smarkm } else { 34344743Smarkm check_host(cp); 34444743Smarkm } 34544743Smarkm } 34644743Smarkm } 34744743Smarkm if (clients == 0) 34844743Smarkm tcpd_warn("client list is empty or ends in EXCEPT"); 34944743Smarkm} 35044743Smarkm 35144743Smarkm/* check_daemon - criticize daemon pattern */ 35244743Smarkm 35344743Smarkmstatic void check_daemon(pat) 35444743Smarkmchar *pat; 35544743Smarkm{ 35644743Smarkm if (pat[0] == '@') { 35744743Smarkm tcpd_warn("%s: daemon name begins with \"@\"", pat); 35851495Ssheldonh } else if (pat[0] == '/') { 35951495Ssheldonh tcpd_warn("%s: daemon name begins with \"/\"", pat); 36044743Smarkm } else if (pat[0] == '.') { 36144743Smarkm tcpd_warn("%s: daemon name begins with dot", pat); 36244743Smarkm } else if (pat[strlen(pat) - 1] == '.') { 36344743Smarkm tcpd_warn("%s: daemon name ends in dot", pat); 36444743Smarkm } else if (STR_EQ(pat, "ALL") || STR_EQ(pat, unknown)) { 36544743Smarkm /* void */ ; 36644743Smarkm } else if (STR_EQ(pat, "FAIL")) { /* obsolete */ 36744743Smarkm tcpd_warn("FAIL is no longer recognized"); 36844743Smarkm tcpd_warn("(use EXCEPT or DENY instead)"); 36944743Smarkm } else if (reserved_name(pat)) { 37044743Smarkm tcpd_warn("%s: daemon name may be reserved word", pat); 37144743Smarkm } else { 37244743Smarkm switch (inet_get(pat)) { 37344743Smarkm case WR_UNKNOWN: 37444743Smarkm tcpd_warn("%s: no such process name in %s", pat, inetcf); 37544743Smarkm inet_set(pat, WR_YES); /* shut up next time */ 37644743Smarkm break; 37744743Smarkm case WR_NOT: 37844743Smarkm tcpd_warn("%s: service possibly not wrapped", pat); 37944743Smarkm inet_set(pat, WR_YES); 38044743Smarkm break; 38144743Smarkm } 38244743Smarkm } 38344743Smarkm} 38444743Smarkm 38544743Smarkm/* check_user - criticize user pattern */ 38644743Smarkm 38744743Smarkmstatic void check_user(pat) 38844743Smarkmchar *pat; 38944743Smarkm{ 39044743Smarkm if (pat[0] == '@') { /* @netgroup */ 39144743Smarkm tcpd_warn("%s: user name begins with \"@\"", pat); 39251495Ssheldonh } else if (pat[0] == '/') { 39351495Ssheldonh tcpd_warn("%s: user name begins with \"/\"", pat); 39444743Smarkm } else if (pat[0] == '.') { 39544743Smarkm tcpd_warn("%s: user name begins with dot", pat); 39644743Smarkm } else if (pat[strlen(pat) - 1] == '.') { 39744743Smarkm tcpd_warn("%s: user name ends in dot", pat); 39844743Smarkm } else if (STR_EQ(pat, "ALL") || STR_EQ(pat, unknown) 39944743Smarkm || STR_EQ(pat, "KNOWN")) { 40044743Smarkm /* void */ ; 40144743Smarkm } else if (STR_EQ(pat, "FAIL")) { /* obsolete */ 40244743Smarkm tcpd_warn("FAIL is no longer recognized"); 40344743Smarkm tcpd_warn("(use EXCEPT or DENY instead)"); 40444743Smarkm } else if (reserved_name(pat)) { 40544743Smarkm tcpd_warn("%s: user name may be reserved word", pat); 40644743Smarkm } 40744743Smarkm} 40844743Smarkm 40956977Sshin#ifdef INET6 41056977Sshinstatic int is_inet6_addr(pat) 41156977Sshin char *pat; 41256977Sshin{ 41363158Sume struct addrinfo hints, *res; 41456977Sshin int len, ret; 41556977Sshin char ch; 41656977Sshin 41756977Sshin if (*pat != '[') 41856977Sshin return (0); 41956977Sshin len = strlen(pat); 42056977Sshin if ((ch = pat[len - 1]) != ']') 42156977Sshin return (0); 42256977Sshin pat[len - 1] = '\0'; 42363158Sume memset(&hints, 0, sizeof(hints)); 42463158Sume hints.ai_family = AF_INET6; 42563158Sume hints.ai_socktype = SOCK_STREAM; 42663158Sume hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 42763158Sume if ((ret = getaddrinfo(pat + 1, NULL, &hints, &res)) == 0) 42863158Sume freeaddrinfo(res); 42956977Sshin pat[len - 1] = ch; 43063158Sume return (ret == 0); 43156977Sshin} 43256977Sshin#endif 43356977Sshin 43444743Smarkm/* check_host - criticize host pattern */ 43544743Smarkm 43644743Smarkmstatic int check_host(pat) 43744743Smarkmchar *pat; 43844743Smarkm{ 43951495Ssheldonh char buf[BUFSIZ]; 44044743Smarkm char *mask; 44144743Smarkm int addr_count = 1; 44251495Ssheldonh FILE *fp; 44351495Ssheldonh struct tcpd_context saved_context; 44451495Ssheldonh char *cp; 44551495Ssheldonh char *wsp = " \t\r\n"; 44644743Smarkm 44744743Smarkm if (pat[0] == '@') { /* @netgroup */ 44844743Smarkm#ifdef NO_NETGRENT 44944743Smarkm /* SCO has no *netgrent() support */ 45044743Smarkm#else 45144743Smarkm#ifdef NETGROUP 45244743Smarkm char *machinep; 45344743Smarkm char *userp; 45444743Smarkm char *domainp; 45544743Smarkm 45644743Smarkm setnetgrent(pat + 1); 45744743Smarkm if (getnetgrent(&machinep, &userp, &domainp) == 0) 45844743Smarkm tcpd_warn("%s: unknown or empty netgroup", pat + 1); 45944743Smarkm endnetgrent(); 46044743Smarkm#else 46144743Smarkm tcpd_warn("netgroup support disabled"); 46244743Smarkm#endif 46344743Smarkm#endif 46451495Ssheldonh } else if (pat[0] == '/') { /* /path/name */ 46551495Ssheldonh if ((fp = fopen(pat, "r")) != 0) { 46651495Ssheldonh saved_context = tcpd_context; 46751495Ssheldonh tcpd_context.file = pat; 46851495Ssheldonh tcpd_context.line = 0; 46951495Ssheldonh while (fgets(buf, sizeof(buf), fp)) { 47051495Ssheldonh tcpd_context.line++; 47151495Ssheldonh for (cp = strtok(buf, wsp); cp; cp = strtok((char *) 0, wsp)) 47251495Ssheldonh check_host(cp); 47351495Ssheldonh } 47451495Ssheldonh tcpd_context = saved_context; 47551495Ssheldonh fclose(fp); 47651495Ssheldonh } else if (errno != ENOENT) { 47751495Ssheldonh tcpd_warn("open %s: %m", pat); 47851495Ssheldonh } 47944743Smarkm } else if (mask = split_at(pat, '/')) { /* network/netmask */ 48056977Sshin#ifdef INET6 48156977Sshin int mask_len; 48256977Sshin 48356977Sshin if ((dot_quad_addr(pat) == INADDR_NONE 48456977Sshin || dot_quad_addr(mask) == INADDR_NONE) 48556977Sshin && (!is_inet6_addr(pat) 48656977Sshin || ((mask_len = atoi(mask)) < 0 || mask_len > 128))) 48756977Sshin#else 48844743Smarkm if (dot_quad_addr(pat) == INADDR_NONE 48944743Smarkm || dot_quad_addr(mask) == INADDR_NONE) 49056977Sshin#endif 49144743Smarkm tcpd_warn("%s/%s: bad net/mask pattern", pat, mask); 49244743Smarkm } else if (STR_EQ(pat, "FAIL")) { /* obsolete */ 49344743Smarkm tcpd_warn("FAIL is no longer recognized"); 49444743Smarkm tcpd_warn("(use EXCEPT or DENY instead)"); 49544743Smarkm } else if (reserved_name(pat)) { /* other reserved */ 49644743Smarkm /* void */ ; 49756977Sshin#ifdef INET6 49856977Sshin } else if (is_inet6_addr(pat)) { /* IPv6 address */ 49956977Sshin addr_count = 1; 50056977Sshin#endif 50144743Smarkm } else if (NOT_INADDR(pat)) { /* internet name */ 50244743Smarkm if (pat[strlen(pat) - 1] == '.') { 50344743Smarkm tcpd_warn("%s: domain or host name ends in dot", pat); 50444743Smarkm } else if (pat[0] != '.') { 50544743Smarkm addr_count = check_dns(pat); 50644743Smarkm } 50744743Smarkm } else { /* numeric form */ 50844743Smarkm if (STR_EQ(pat, "0.0.0.0") || STR_EQ(pat, "255.255.255.255")) { 50944743Smarkm /* void */ ; 51044743Smarkm } else if (pat[0] == '.') { 51144743Smarkm tcpd_warn("%s: network number begins with dot", pat); 51244743Smarkm } else if (pat[strlen(pat) - 1] != '.') { 51344743Smarkm check_dns(pat); 51444743Smarkm } 51544743Smarkm } 51644743Smarkm return (addr_count); 51744743Smarkm} 51844743Smarkm 51944743Smarkm/* reserved_name - determine if name is reserved */ 52044743Smarkm 52144743Smarkmstatic int reserved_name(pat) 52244743Smarkmchar *pat; 52344743Smarkm{ 52444743Smarkm return (STR_EQ(pat, unknown) 52544743Smarkm || STR_EQ(pat, "KNOWN") 52644743Smarkm || STR_EQ(pat, paranoid) 52744743Smarkm || STR_EQ(pat, "ALL") 52844743Smarkm || STR_EQ(pat, "LOCAL")); 52944743Smarkm} 530