118316Swollman/* 218316Swollman * Copyright (c) 1983, 1993 318316Swollman * The Regents of the University of California. All rights reserved. 418316Swollman * 518316Swollman * Redistribution and use in source and binary forms, with or without 618316Swollman * modification, are permitted provided that the following conditions 718316Swollman * are met: 818316Swollman * 1. Redistributions of source code must retain the above copyright 918316Swollman * notice, this list of conditions and the following disclaimer. 1018316Swollman * 2. Redistributions in binary form must reproduce the above copyright 1118316Swollman * notice, this list of conditions and the following disclaimer in the 1218316Swollman * documentation and/or other materials provided with the distribution. 1318316Swollman * 4. Neither the name of the University nor the names of its contributors 1418316Swollman * may be used to endorse or promote products derived from this software 1518316Swollman * without specific prior written permission. 1618316Swollman * 1718316Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1818316Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1918316Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2018316Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2118316Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2218316Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2318316Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2418316Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2518316Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2618316Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2718316Swollman * SUCH DAMAGE. 2846303Smarkm * 2950476Speter * $FreeBSD$ 3018316Swollman */ 3118316Swollman 3218316Swollman#include "defs.h" 3318316Swollman#include "pathnames.h" 3420339Swollman#include <sys/stat.h> 3518316Swollman 36126250Sbms#ifdef __NetBSD__ 3746303Smarkm__RCSID("$NetBSD$"); 38126250Sbms#elif defined(__FreeBSD__) 39126250Sbms__RCSID("$FreeBSD$"); 40126250Sbms#else 41126250Sbms__RCSID("$Revision: 2.26 $"); 42126250Sbms#ident "$Revision: 2.26 $" 4346303Smarkm#endif 4446303Smarkm 4546303Smarkm 46190715Sphkstatic struct parm *parms; 4718316Swollmanstruct intnet *intnets; 4846303Smarkmstruct r1net *r1nets; 4919880Swollmanstruct tgate *tgates; 5018316Swollman 5118316Swollman 5218316Swollman/* use configured parameters 5318316Swollman */ 5418316Swollmanvoid 5518316Swollmanget_parms(struct interface *ifp) 5618316Swollman{ 5746303Smarkm static int warned_auth_in, warned_auth_out; 5818316Swollman struct parm *parmp; 5920339Swollman int i, num_passwds = 0; 6018316Swollman 6118316Swollman /* get all relevant parameters 6218316Swollman */ 6318316Swollman for (parmp = parms; parmp != 0; parmp = parmp->parm_next) { 6419880Swollman if (parmp->parm_name[0] == '\0' 6519880Swollman || !strcmp(ifp->int_name, parmp->parm_name) 6619880Swollman || (parmp->parm_name[0] == '\n' 6719880Swollman && on_net(ifp->int_addr, 6819880Swollman parmp->parm_net, parmp->parm_mask))) { 6919880Swollman 7019880Swollman /* This group of parameters is relevant, 7118316Swollman * so get its settings 7218316Swollman */ 7318316Swollman ifp->int_state |= parmp->parm_int_state; 7420339Swollman for (i = 0; i < MAX_AUTH_KEYS; i++) { 7520339Swollman if (parmp->parm_auth[0].type == RIP_AUTH_NONE 7620339Swollman || num_passwds >= MAX_AUTH_KEYS) 7720339Swollman break; 7846303Smarkm memcpy(&ifp->int_auth[num_passwds++], 7946303Smarkm &parmp->parm_auth[i], 8046303Smarkm sizeof(ifp->int_auth[0])); 8120339Swollman } 8218316Swollman if (parmp->parm_rdisc_pref != 0) 8318316Swollman ifp->int_rdisc_pref = parmp->parm_rdisc_pref; 8418316Swollman if (parmp->parm_rdisc_int != 0) 8518316Swollman ifp->int_rdisc_int = parmp->parm_rdisc_int; 86126250Sbms if (parmp->parm_adj_inmetric != 0) 87126250Sbms ifp->int_adj_inmetric = parmp->parm_adj_inmetric; 88126250Sbms if (parmp->parm_adj_outmetric != 0) 89126250Sbms ifp->int_adj_outmetric = parmp->parm_adj_outmetric; 9019880Swollman } 9118316Swollman } 9219880Swollman 9319880Swollman /* Set general defaults. 9419880Swollman * 9519880Swollman * Default poor-man's router discovery to a metric that will 9619880Swollman * be heard by old versions of `routed`. They ignored received 9719880Swollman * routes with metric 15. 9818316Swollman */ 9918316Swollman if ((ifp->int_state & IS_PM_RDISC) 10018316Swollman && ifp->int_d_metric == 0) 10119880Swollman ifp->int_d_metric = FAKE_METRIC; 10218316Swollman 10318316Swollman if (ifp->int_rdisc_int == 0) 10418316Swollman ifp->int_rdisc_int = DefMaxAdvertiseInterval; 10518316Swollman 10618316Swollman if (!(ifp->int_if_flags & IFF_MULTICAST) 10719880Swollman && !(ifp->int_state & IS_REMOTE)) 10818316Swollman ifp->int_state |= IS_BCAST_RDISC; 10918316Swollman 11018316Swollman if (ifp->int_if_flags & IFF_POINTOPOINT) { 11118316Swollman ifp->int_state |= IS_BCAST_RDISC; 11218316Swollman /* By default, point-to-point links should be passive 11318316Swollman * about router-discovery for the sake of demand-dialing. 11418316Swollman */ 11546303Smarkm if (0 == (ifp->int_state & GROUP_IS_SOL_OUT)) 11618316Swollman ifp->int_state |= IS_NO_SOL_OUT; 11746303Smarkm if (0 == (ifp->int_state & GROUP_IS_ADV_OUT)) 11818316Swollman ifp->int_state |= IS_NO_ADV_OUT; 11918316Swollman } 12018316Swollman 12118316Swollman if (0 != (ifp->int_state & (IS_PASSIVE | IS_REMOTE))) 12218316Swollman ifp->int_state |= IS_NO_RDISC; 12318316Swollman if (ifp->int_state & IS_PASSIVE) 12419880Swollman ifp->int_state |= IS_NO_RIP; 12519880Swollman 12619880Swollman if (!IS_RIP_IN_OFF(ifp->int_state) 12720339Swollman && ifp->int_auth[0].type != RIP_AUTH_NONE 12819880Swollman && !(ifp->int_state & IS_NO_RIPV1_IN) 12919880Swollman && !warned_auth_in) { 13019880Swollman msglog("Warning: RIPv1 input via %s" 13119880Swollman " will be accepted without authentication", 13219880Swollman ifp->int_name); 13319880Swollman warned_auth_in = 1; 13419880Swollman } 13519880Swollman if (!IS_RIP_OUT_OFF(ifp->int_state) 13620339Swollman && ifp->int_auth[0].type != RIP_AUTH_NONE 13720339Swollman && !(ifp->int_state & IS_NO_RIPV1_OUT)) { 13820339Swollman if (!warned_auth_out) { 13920339Swollman msglog("Warning: RIPv1 output via %s" 14020339Swollman " will be sent without authentication", 14120339Swollman ifp->int_name); 14220339Swollman warned_auth_out = 1; 14320339Swollman } 14419880Swollman } 14518316Swollman} 14618316Swollman 14718316Swollman 14818316Swollman/* Read a list of gateways from /etc/gateways and add them to our tables. 14918316Swollman * 15018316Swollman * This file contains a list of "remote" gateways. That is usually 15118316Swollman * a gateway which we cannot immediately determine if it is present or 15218316Swollman * not as we can do for those provided by directly connected hardware. 15318316Swollman * 15418316Swollman * If a gateway is marked "passive" in the file, then we assume it 15518316Swollman * does not understand RIP and assume it is always present. Those 15618316Swollman * not marked passive are treated as if they were directly connected 15718316Swollman * and assumed to be broken if they do not send us advertisements. 15818316Swollman * All remote interfaces are added to our list, and those not marked 15918316Swollman * passive are sent routing updates. 16018316Swollman * 16118316Swollman * A passive interface can also be local, hardware interface exempt 16218316Swollman * from RIP. 16318316Swollman */ 16418316Swollmanvoid 16518316Swollmangwkludge(void) 16618316Swollman{ 16718316Swollman FILE *fp; 16818316Swollman char *p, *lptr; 16946303Smarkm const char *cp; 17046303Smarkm char lbuf[200], net_host[5], dname[64+1+64+1]; 17146303Smarkm char gname[GNAME_LEN+1], qual[9]; 17218316Swollman struct interface *ifp; 17318316Swollman naddr dst, netmask, gate; 17446303Smarkm int metric, n, lnum; 17520339Swollman struct stat sb; 17618316Swollman u_int state; 17746303Smarkm const char *type; 17818316Swollman 17918316Swollman 18018316Swollman fp = fopen(_PATH_GATEWAYS, "r"); 18118316Swollman if (fp == 0) 18218316Swollman return; 18318316Swollman 18420339Swollman if (0 > fstat(fileno(fp), &sb)) { 18520339Swollman msglog("could not stat() "_PATH_GATEWAYS); 18620339Swollman (void)fclose(fp); 18720339Swollman return; 18820339Swollman } 18920339Swollman 19046303Smarkm for (lnum = 1; ; lnum++) { 191230045Skevlo if (fgets(lbuf, sizeof(lbuf), fp) == NULL) 19218316Swollman break; 19318316Swollman lptr = lbuf; 19418316Swollman while (*lptr == ' ') 19518316Swollman lptr++; 19646303Smarkm p = lptr+strlen(lptr)-1; 19746303Smarkm while (*p == '\n' 19846303Smarkm || (*p == ' ' && (p == lptr+1 || *(p-1) != '\\'))) 19946303Smarkm *p-- = '\0'; 20046303Smarkm if (*lptr == '\0' /* ignore null and comment lines */ 20118316Swollman || *lptr == '#') 20218316Swollman continue; 20318316Swollman 20418316Swollman /* notice newfangled parameter lines 20518316Swollman */ 20618316Swollman if (strncasecmp("net", lptr, 3) 20718316Swollman && strncasecmp("host", lptr, 4)) { 20846303Smarkm cp = parse_parms(lptr, 20946303Smarkm (sb.st_uid == 0 21046303Smarkm && !(sb.st_mode&(S_IRWXG|S_IRWXO)))); 21146303Smarkm if (cp != 0) 21246303Smarkm msglog("%s in line %d of "_PATH_GATEWAYS, 21346303Smarkm cp, lnum); 21418316Swollman continue; 21518316Swollman } 21618316Swollman 21718316Swollman/* {net | host} XX[/M] XX gateway XX metric DD [passive | external]\n */ 21819880Swollman qual[0] = '\0'; 21946303Smarkm /* the '64' here must be GNAME_LEN */ 22018316Swollman n = sscanf(lptr, "%4s %129[^ \t] gateway" 22119880Swollman " %64[^ / \t] metric %u %8s\n", 22218316Swollman net_host, dname, gname, &metric, qual); 22319880Swollman if (n != 4 && n != 5) { 22419880Swollman msglog("bad "_PATH_GATEWAYS" entry \"%s\"; %d values", 22519880Swollman lptr, n); 22618316Swollman continue; 22718316Swollman } 22819880Swollman if (metric >= HOPCNT_INFINITY) { 22918316Swollman msglog("bad metric in "_PATH_GATEWAYS" entry \"%s\"", 23018316Swollman lptr); 23118316Swollman continue; 23218316Swollman } 23319880Swollman if (!strcasecmp(net_host, "host")) { 23418316Swollman if (!gethost(dname, &dst)) { 23518316Swollman msglog("bad host \"%s\" in "_PATH_GATEWAYS 23618316Swollman " entry \"%s\"", dname, lptr); 23718316Swollman continue; 23818316Swollman } 23918316Swollman netmask = HOST_MASK; 24019880Swollman } else if (!strcasecmp(net_host, "net")) { 24118316Swollman if (!getnet(dname, &dst, &netmask)) { 24218316Swollman msglog("bad net \"%s\" in "_PATH_GATEWAYS 24318316Swollman " entry \"%s\"", dname, lptr); 24418316Swollman continue; 24518316Swollman } 24646303Smarkm if (dst == RIP_DEFAULT) { 24746303Smarkm msglog("bad net \"%s\" in "_PATH_GATEWAYS 24846303Smarkm " entry \"%s\"--cannot be default", 24946303Smarkm dname, lptr); 25046303Smarkm continue; 25146303Smarkm } 25290868Smike /* Turn network # into IP address. */ 25390868Smike dst = htonl(dst); 25418316Swollman } else { 25518316Swollman msglog("bad \"%s\" in "_PATH_GATEWAYS 25646303Smarkm " entry \"%s\"", net_host, lptr); 25718316Swollman continue; 25818316Swollman } 25918316Swollman 26018316Swollman if (!gethost(gname, &gate)) { 26118316Swollman msglog("bad gateway \"%s\" in "_PATH_GATEWAYS 26218316Swollman " entry \"%s\"", gname, lptr); 26318316Swollman continue; 26418316Swollman } 26518316Swollman 26619880Swollman if (!strcasecmp(qual, type = "passive")) { 26718316Swollman /* Passive entries are not placed in our tables, 26818316Swollman * only the kernel's, so we don't copy all of the 26918316Swollman * external routing information within a net. 27018316Swollman * Internal machines should use the default 27118316Swollman * route to a suitable gateway (like us). 27218316Swollman */ 27318316Swollman state = IS_REMOTE | IS_PASSIVE; 27418316Swollman if (metric == 0) 27518316Swollman metric = 1; 27618316Swollman 27719880Swollman } else if (!strcasecmp(qual, type = "external")) { 27818316Swollman /* External entries are handled by other means 27918316Swollman * such as EGP, and are placed only in the daemon 28018316Swollman * tables to prevent overriding them with something 28118316Swollman * else. 28218316Swollman */ 28319880Swollman strcpy(qual,"external"); 28418316Swollman state = IS_REMOTE | IS_PASSIVE | IS_EXTERNAL; 28518316Swollman if (metric == 0) 28618316Swollman metric = 1; 28718316Swollman 28819880Swollman } else if (!strcasecmp(qual, "active") 28919880Swollman || qual[0] == '\0') { 29018316Swollman if (metric != 0) { 29118316Swollman /* Entries that are neither "passive" nor 29218316Swollman * "external" are "remote" and must behave 29318316Swollman * like physical interfaces. If they are not 29418316Swollman * heard from regularly, they are deleted. 29518316Swollman */ 29618316Swollman state = IS_REMOTE; 29718316Swollman type = "remote"; 29818316Swollman } else { 29918316Swollman /* "remote" entries with a metric of 0 30018316Swollman * are aliases for our own interfaces 30118316Swollman */ 30219880Swollman state = IS_REMOTE | IS_PASSIVE | IS_ALIAS; 30318316Swollman type = "alias"; 30418316Swollman } 30518316Swollman 30618316Swollman } else { 30719880Swollman msglog("bad "_PATH_GATEWAYS" entry \"%s\";" 30819880Swollman " unknown type %s", lptr, qual); 30918316Swollman continue; 31018316Swollman } 31118316Swollman 31218316Swollman if (0 != (state & (IS_PASSIVE | IS_REMOTE))) 31318316Swollman state |= IS_NO_RDISC; 31418316Swollman if (state & IS_PASSIVE) 31519880Swollman state |= IS_NO_RIP; 31618316Swollman 317126250Sbms ifp = check_dup(gate,dst,netmask,state); 31818316Swollman if (ifp != 0) { 31919880Swollman msglog("duplicate "_PATH_GATEWAYS" entry \"%s\"",lptr); 32018316Swollman continue; 32118316Swollman } 32218316Swollman 32346303Smarkm ifp = (struct interface *)rtmalloc(sizeof(*ifp), "gwkludge()"); 32446303Smarkm memset(ifp, 0, sizeof(*ifp)); 32518316Swollman 32618316Swollman ifp->int_state = state; 32718316Swollman if (netmask == HOST_MASK) 32846303Smarkm ifp->int_if_flags = IFF_POINTOPOINT | IFF_UP; 32919880Swollman else 33046303Smarkm ifp->int_if_flags = IFF_UP; 33119880Swollman ifp->int_act_time = NEVER; 33219880Swollman ifp->int_addr = gate; 33318316Swollman ifp->int_dstaddr = dst; 33419880Swollman ifp->int_mask = netmask; 33519880Swollman ifp->int_ripv1_mask = netmask; 33619880Swollman ifp->int_std_mask = std_mask(gate); 33719880Swollman ifp->int_net = ntohl(dst); 33819880Swollman ifp->int_std_net = ifp->int_net & ifp->int_std_mask; 33919880Swollman ifp->int_std_addr = htonl(ifp->int_std_net); 34018316Swollman ifp->int_metric = metric; 34119880Swollman if (!(state & IS_EXTERNAL) 34219880Swollman && ifp->int_mask != ifp->int_std_mask) 34319880Swollman ifp->int_state |= IS_SUBNET; 34419880Swollman (void)sprintf(ifp->int_name, "%s(%s)", type, gname); 34518316Swollman ifp->int_index = -1; 34618316Swollman 34719880Swollman if_link(ifp); 34819880Swollman } 34919880Swollman 35019880Swollman /* After all of the parameter lines have been read, 35119880Swollman * apply them to any remote interfaces. 35219880Swollman */ 353190711Sphk LIST_FOREACH(ifp, &ifnet, int_list) { 35418316Swollman get_parms(ifp); 35518316Swollman 35619880Swollman tot_interfaces++; 35719880Swollman if (!IS_RIP_OFF(ifp->int_state)) 35819880Swollman rip_interfaces++; 35919880Swollman 36018316Swollman trace_if("Add", ifp); 36118316Swollman } 36220339Swollman 36320339Swollman (void)fclose(fp); 36418316Swollman} 36518316Swollman 36618316Swollman 36746303Smarkm/* like strtok(), but honoring backslash and not changing the source string 36818316Swollman */ 36920339Swollmanstatic int /* 0=ok, -1=bad */ 37046303Smarkmparse_quote(char **linep, /* look here */ 37146303Smarkm const char *delims, /* for these delimiters */ 37246303Smarkm char *delimp, /* 0 or put found delimiter here */ 37346303Smarkm char *buf, /* copy token to here */ 37446303Smarkm int lim) /* at most this many bytes */ 37519880Swollman{ 37646303Smarkm char c = '\0', *pc; 37746303Smarkm const char *p; 37819880Swollman 37919880Swollman 38019880Swollman pc = *linep; 38119880Swollman if (*pc == '\0') 38219880Swollman return -1; 38319880Swollman 38420339Swollman while (lim != 0) { 38519880Swollman c = *pc++; 38619880Swollman if (c == '\0') 38719880Swollman break; 38819880Swollman 38937815Sphk if (c == '\\' && *pc != '\0') { 39019880Swollman if ((c = *pc++) == 'n') { 39119880Swollman c = '\n'; 39219880Swollman } else if (c == 'r') { 39319880Swollman c = '\r'; 39419880Swollman } else if (c == 't') { 39519880Swollman c = '\t'; 39619880Swollman } else if (c == 'b') { 39719880Swollman c = '\b'; 39819880Swollman } else if (c >= '0' && c <= '7') { 39919880Swollman c -= '0'; 40019880Swollman if (*pc >= '0' && *pc <= '7') { 40119880Swollman c = (c<<3)+(*pc++ - '0'); 40219880Swollman if (*pc >= '0' && *pc <= '7') 40319880Swollman c = (c<<3)+(*pc++ - '0'); 40419880Swollman } 40519880Swollman } 40619880Swollman 40719880Swollman } else { 40819880Swollman for (p = delims; *p != '\0'; ++p) { 40919880Swollman if (*p == c) 41019880Swollman goto exit; 41119880Swollman } 41219880Swollman } 41319880Swollman 41419880Swollman *buf++ = c; 41519880Swollman --lim; 41619880Swollman } 41719880Swollmanexit: 41820339Swollman if (lim == 0) 41920339Swollman return -1; 42020339Swollman 42146303Smarkm *buf = '\0'; /* terminate copy of token */ 42219880Swollman if (delimp != 0) 42346303Smarkm *delimp = c; /* return delimiter */ 42446303Smarkm *linep = pc-1; /* say where we ended */ 42519880Swollman return 0; 42619880Swollman} 42719880Swollman 42819880Swollman 42919880Swollman/* Parse password timestamp 43019880Swollman */ 43119880Swollmanstatic char * 43219880Swollmanparse_ts(time_t *tp, 43319880Swollman char **valp, 43419880Swollman char *val0, 43519880Swollman char *delimp, 43619880Swollman char *buf, 43719880Swollman u_int bufsize) 43819880Swollman{ 43919880Swollman struct tm tm; 44046303Smarkm char *ptr; 44119880Swollman 44219880Swollman if (0 > parse_quote(valp, "| ,\n\r", delimp, 44319880Swollman buf,bufsize) 44419880Swollman || buf[bufsize-1] != '\0' 44519880Swollman || buf[bufsize-2] != '\0') { 44620339Swollman sprintf(buf,"bad timestamp %.25s", val0); 44719880Swollman return buf; 44819880Swollman } 44919880Swollman strcat(buf,"\n"); 45046303Smarkm memset(&tm, 0, sizeof(tm)); 45146303Smarkm ptr = strptime(buf, "%y/%m/%d@%H:%M\n", &tm); 45246303Smarkm if (ptr == NULL || *ptr != '\0') { 45346303Smarkm sprintf(buf,"bad timestamp %.25s", val0); 45446303Smarkm return buf; 45546303Smarkm } 45619880Swollman 45719880Swollman if ((*tp = mktime(&tm)) == -1) { 45820339Swollman sprintf(buf,"bad timestamp %.25s", val0); 45919880Swollman return buf; 46019880Swollman } 46119880Swollman 46219880Swollman return 0; 46319880Swollman} 46419880Swollman 46519880Swollman 46620339Swollman/* Get a password, key ID, and expiration date in the format 46720339Swollman * passwd|keyID|year/mon/day@hour:min|year/mon/day@hour:min 46819880Swollman */ 46946303Smarkmstatic const char * /* 0 or error message */ 47020339Swollmanget_passwd(char *tgt, 47120339Swollman char *val, 47220339Swollman struct parm *parmp, 47346303Smarkm u_int16_t type, 47420339Swollman int safe) /* 1=from secure file */ 47519880Swollman{ 47619880Swollman static char buf[80]; 47719880Swollman char *val0, *p, delim; 47820339Swollman struct auth k, *ap, *ap2; 47919880Swollman int i; 48019880Swollman u_long l; 48119880Swollman 482190718Sphk assert(val != NULL); 48320339Swollman if (!safe) 48446303Smarkm return "ignore unsafe password"; 48519880Swollman 48620339Swollman for (ap = parmp->parm_auth, i = 0; 48720339Swollman ap->type != RIP_AUTH_NONE; i++, ap++) { 48820339Swollman if (i >= MAX_AUTH_KEYS) 48920339Swollman return "too many passwords"; 49020339Swollman } 49119880Swollman 49246303Smarkm memset(&k, 0, sizeof(k)); 49320339Swollman k.type = type; 49420339Swollman k.end = -1-DAY; 49519880Swollman 49620339Swollman val0 = val; 49720339Swollman if (0 > parse_quote(&val, "| ,\n\r", &delim, 49820339Swollman (char *)k.key, sizeof(k.key))) 49920339Swollman return tgt; 50019880Swollman 50120339Swollman if (delim != '|') { 50220339Swollman if (type == RIP_AUTH_MD5) 50320339Swollman return "missing Keyid"; 50420339Swollman } else { 50519880Swollman val0 = ++val; 50620339Swollman buf[sizeof(buf)-1] = '\0'; 50719880Swollman if (0 > parse_quote(&val, "| ,\n\r", &delim, buf,sizeof(buf)) 50819880Swollman || buf[sizeof(buf)-1] != '\0' 50919880Swollman || (l = strtoul(buf,&p,0)) > 255 51019880Swollman || *p != '\0') { 51120339Swollman sprintf(buf,"bad KeyID \"%.20s\"", val0); 51219880Swollman return buf; 51319880Swollman } 51420339Swollman for (ap2 = parmp->parm_auth; ap2 < ap; ap2++) { 51520339Swollman if (ap2->keyid == l) { 51619880Swollman sprintf(buf,"duplicate KeyID \"%.20s\"", val0); 51719880Swollman return buf; 51819880Swollman } 51919880Swollman } 52020339Swollman k.keyid = (int)l; 52119880Swollman 52220339Swollman if (delim == '|') { 52320339Swollman val0 = ++val; 52420339Swollman if (0 != (p = parse_ts(&k.start,&val,val0,&delim, 52520339Swollman buf,sizeof(buf)))) 52620339Swollman return p; 52720339Swollman if (delim != '|') 52820339Swollman return "missing second timestamp"; 52920339Swollman val0 = ++val; 53020339Swollman if (0 != (p = parse_ts(&k.end,&val,val0,&delim, 53120339Swollman buf,sizeof(buf)))) 53220339Swollman return p; 53320339Swollman if ((u_long)k.start > (u_long)k.end) { 53420339Swollman sprintf(buf,"out of order timestamp %.30s", 53520339Swollman val0); 53620339Swollman return buf; 53720339Swollman } 53819880Swollman } 53919880Swollman } 54020339Swollman if (delim != '\0') 54120339Swollman return tgt; 54219880Swollman 54346303Smarkm memmove(ap, &k, sizeof(*ap)); 54420339Swollman return 0; 54519880Swollman} 54619880Swollman 54719880Swollman 54846303Smarkmstatic const char * 54946303Smarkmbad_str(const char *estr) 55046303Smarkm{ 55146303Smarkm static char buf[100+8]; 55246303Smarkm 55346303Smarkm sprintf(buf, "bad \"%.100s\"", estr); 55446303Smarkm return buf; 55546303Smarkm} 55646303Smarkm 55746303Smarkm 55819880Swollman/* Parse a set of parameters for an interface. 55919880Swollman */ 56046303Smarkmconst char * /* 0 or error message */ 56120339Swollmanparse_parms(char *line, 56220339Swollman int safe) /* 1=from secure file */ 56318316Swollman{ 56419880Swollman#define PARS(str) (!strcasecmp(tgt, str)) 56519880Swollman#define PARSEQ(str) (!strncasecmp(tgt, str"=", sizeof(str))) 56618316Swollman#define CKF(g,b) {if (0 != (parm.parm_int_state & ((g) & ~(b)))) break; \ 56718316Swollman parm.parm_int_state |= (b);} 56818316Swollman struct parm parm; 56918316Swollman struct intnet *intnetp; 57046303Smarkm struct r1net *r1netp; 57119880Swollman struct tgate *tg; 57219880Swollman naddr addr, mask; 57346303Smarkm char delim, *val0 = 0, *tgt, *val, *p; 57446303Smarkm const char *msg; 57546303Smarkm char buf[BUFSIZ], buf2[BUFSIZ]; 57646303Smarkm int i; 57718316Swollman 57818316Swollman 57946303Smarkm /* "subnet=x.y.z.u/mask[,metric]" must be alone on the line */ 58019880Swollman if (!strncasecmp(line, "subnet=", sizeof("subnet=")-1) 58135306Sphk && *(val = &line[sizeof("subnet=")-1]) != '\0') { 58246303Smarkm if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf))) 58346303Smarkm return bad_str(line); 58446303Smarkm intnetp = (struct intnet*)rtmalloc(sizeof(*intnetp), 58546303Smarkm "parse_parms subnet"); 58618316Swollman intnetp->intnet_metric = 1; 58746303Smarkm if (delim == ',') { 58846303Smarkm intnetp->intnet_metric = (int)strtol(val+1,&p,0); 58918316Swollman if (*p != '\0' 59018316Swollman || intnetp->intnet_metric <= 0 59118316Swollman || intnetp->intnet_metric >= HOPCNT_INFINITY) 59246303Smarkm return bad_str(line); 59318316Swollman } 59446303Smarkm if (!getnet(buf, &intnetp->intnet_addr, &intnetp->intnet_mask) 59518316Swollman || intnetp->intnet_mask == HOST_MASK 59618316Swollman || intnetp->intnet_addr == RIP_DEFAULT) { 59718316Swollman free(intnetp); 59846303Smarkm return bad_str(line); 59918316Swollman } 60090868Smike intnetp->intnet_addr = htonl(intnetp->intnet_addr); 60118316Swollman intnetp->intnet_next = intnets; 60218316Swollman intnets = intnetp; 60318316Swollman return 0; 60418316Swollman } 60518316Swollman 60646303Smarkm /* "ripv1_mask=x.y.z.u/mask1,mask2" must be alone on the line. 60746303Smarkm * This requires that x.y.z.u/mask1 be considered a subnet of 60846303Smarkm * x.y.z.u/mask2, as if x.y.z.u/mask2 were a class-full network. 60946303Smarkm */ 61046303Smarkm if (!strncasecmp(line, "ripv1_mask=", sizeof("ripv1_mask=")-1) 61146303Smarkm && *(val = &line[sizeof("ripv1_mask=")-1]) != '\0') { 61246303Smarkm if (0 > parse_quote(&val, ",", &delim, buf, sizeof(buf)) 61346303Smarkm || delim == '\0') 61446303Smarkm return bad_str(line); 61546303Smarkm if ((i = (int)strtol(val+1, &p, 0)) <= 0 61646303Smarkm || i > 32 || *p != '\0') 61746303Smarkm return bad_str(line); 61846303Smarkm r1netp = (struct r1net *)rtmalloc(sizeof(*r1netp), 61946303Smarkm "parse_parms ripv1_mask"); 62046303Smarkm r1netp->r1net_mask = HOST_MASK << (32-i); 62146303Smarkm if (!getnet(buf, &r1netp->r1net_net, &r1netp->r1net_match) 62246303Smarkm || r1netp->r1net_net == RIP_DEFAULT 62346303Smarkm || r1netp->r1net_mask > r1netp->r1net_match) { 62446303Smarkm free(r1netp); 62546303Smarkm return bad_str(line); 62646303Smarkm } 62746303Smarkm r1netp->r1net_next = r1nets; 62846303Smarkm r1nets = r1netp; 62946303Smarkm return 0; 63046303Smarkm } 63118316Swollman 63246303Smarkm memset(&parm, 0, sizeof(parm)); 63346303Smarkm 63419880Swollman for (;;) { 63519880Swollman tgt = line + strspn(line, " ,\n\r"); 63646303Smarkm if (*tgt == '\0' || *tgt == '#') 63719880Swollman break; 63846303Smarkm line = tgt+strcspn(tgt, "= #,\n\r"); 63919880Swollman delim = *line; 64019880Swollman if (delim == '=') { 64119880Swollman val0 = ++line; 64246303Smarkm if (0 > parse_quote(&line, " #,\n\r",&delim, 64319880Swollman buf,sizeof(buf))) 64446303Smarkm return bad_str(tgt); 645190718Sphk } else { 646190718Sphk val0 = NULL; 64719880Swollman } 64846303Smarkm if (delim != '\0') { 64946303Smarkm for (;;) { 65046303Smarkm *line = '\0'; 65146303Smarkm if (delim == '#') 65246303Smarkm break; 65346303Smarkm ++line; 65446303Smarkm if (delim != ' ' 65546303Smarkm || (delim = *line) != ' ') 65646303Smarkm break; 65746303Smarkm } 65846303Smarkm } 65919880Swollman 66019880Swollman if (PARSEQ("if")) { 66118316Swollman if (parm.parm_name[0] != '\0' 66246303Smarkm || strlen(buf) > IF_NAME_LEN) 66346303Smarkm return bad_str(tgt); 66419880Swollman strcpy(parm.parm_name, buf); 66518316Swollman 66619880Swollman } else if (PARSEQ("addr")) { 66719880Swollman /* This is a bad idea, because the address based 66819880Swollman * sets of parameters cannot be checked for 66919880Swollman * consistency with the interface name parameters. 67019880Swollman * The parm_net stuff is needed to allow several 67119880Swollman * -F settings. 67219880Swollman */ 67320339Swollman if (!getnet(val0, &addr, &mask) 67419880Swollman || parm.parm_name[0] != '\0') 67546303Smarkm return bad_str(tgt); 67619880Swollman parm.parm_net = addr; 67719880Swollman parm.parm_mask = mask; 67819880Swollman parm.parm_name[0] = '\n'; 67918316Swollman 68019880Swollman } else if (PARSEQ("passwd")) { 68120339Swollman /* since cleartext passwords are so weak allow 68220339Swollman * them anywhere 68320339Swollman */ 68446303Smarkm msg = get_passwd(tgt,val0,&parm,RIP_AUTH_PW,1); 68546303Smarkm if (msg) { 68620339Swollman *val0 = '\0'; 68746303Smarkm return bad_str(msg); 68820339Swollman } 68919880Swollman 69019880Swollman } else if (PARSEQ("md5_passwd")) { 69146303Smarkm msg = get_passwd(tgt,val0,&parm,RIP_AUTH_MD5,safe); 69246303Smarkm if (msg) { 69320339Swollman *val0 = '\0'; 69446303Smarkm return bad_str(msg); 69520339Swollman } 69619880Swollman 69718316Swollman } else if (PARS("no_ag")) { 69818316Swollman parm.parm_int_state |= (IS_NO_AG | IS_NO_SUPER_AG); 69918316Swollman 70018316Swollman } else if (PARS("no_super_ag")) { 70118316Swollman parm.parm_int_state |= IS_NO_SUPER_AG; 70218316Swollman 70394125Sasmodai } else if (PARS("no_rip_out")) { 70494125Sasmodai parm.parm_int_state |= IS_NO_RIP_OUT; 70594125Sasmodai 70618316Swollman } else if (PARS("no_ripv1_in")) { 70718316Swollman parm.parm_int_state |= IS_NO_RIPV1_IN; 70818316Swollman 70918316Swollman } else if (PARS("no_ripv2_in")) { 71018316Swollman parm.parm_int_state |= IS_NO_RIPV2_IN; 71118316Swollman 71218316Swollman } else if (PARS("ripv2_out")) { 71318316Swollman if (parm.parm_int_state & IS_NO_RIPV2_OUT) 71446303Smarkm return bad_str(tgt); 71518316Swollman parm.parm_int_state |= IS_NO_RIPV1_OUT; 71618316Swollman 71719880Swollman } else if (PARS("ripv2")) { 71819880Swollman if ((parm.parm_int_state & IS_NO_RIPV2_OUT) 71919880Swollman || (parm.parm_int_state & IS_NO_RIPV2_IN)) 72046303Smarkm return bad_str(tgt); 72119880Swollman parm.parm_int_state |= (IS_NO_RIPV1_IN 72219880Swollman | IS_NO_RIPV1_OUT); 72319880Swollman 72418316Swollman } else if (PARS("no_rip")) { 72519880Swollman CKF(IS_PM_RDISC, IS_NO_RIP); 72618316Swollman 72746303Smarkm } else if (PARS("no_rip_mcast")) { 72846303Smarkm parm.parm_int_state |= IS_NO_RIP_MCAST; 72946303Smarkm 73018316Swollman } else if (PARS("no_rdisc")) { 73146303Smarkm CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC); 73218316Swollman 73318316Swollman } else if (PARS("no_solicit")) { 73446303Smarkm CKF(GROUP_IS_SOL_OUT, IS_NO_SOL_OUT); 73518316Swollman 73618316Swollman } else if (PARS("send_solicit")) { 73746303Smarkm CKF(GROUP_IS_SOL_OUT, IS_SOL_OUT); 73818316Swollman 73918316Swollman } else if (PARS("no_rdisc_adv")) { 74046303Smarkm CKF(GROUP_IS_ADV_OUT, IS_NO_ADV_OUT); 74118316Swollman 74218316Swollman } else if (PARS("rdisc_adv")) { 74346303Smarkm CKF(GROUP_IS_ADV_OUT, IS_ADV_OUT); 74418316Swollman 74518316Swollman } else if (PARS("bcast_rdisc")) { 74618316Swollman parm.parm_int_state |= IS_BCAST_RDISC; 74718316Swollman 74818316Swollman } else if (PARS("passive")) { 74946303Smarkm CKF((GROUP_IS_SOL_OUT|GROUP_IS_ADV_OUT), IS_NO_RDISC); 750126250Sbms parm.parm_int_state |= IS_NO_RIP | IS_PASSIVE; 75118316Swollman 75219880Swollman } else if (PARSEQ("rdisc_pref")) { 75318316Swollman if (parm.parm_rdisc_pref != 0 75446303Smarkm || (parm.parm_rdisc_pref = (int)strtol(buf,&p,0), 75518316Swollman *p != '\0')) 75646303Smarkm return bad_str(tgt); 75718316Swollman 75818316Swollman } else if (PARS("pm_rdisc")) { 75919880Swollman if (IS_RIP_OUT_OFF(parm.parm_int_state)) 76046303Smarkm return bad_str(tgt); 76118316Swollman parm.parm_int_state |= IS_PM_RDISC; 76218316Swollman 76319880Swollman } else if (PARSEQ("rdisc_interval")) { 76418316Swollman if (parm.parm_rdisc_int != 0 76519880Swollman || (parm.parm_rdisc_int = (int)strtoul(buf,&p,0), 76618316Swollman *p != '\0') 76718316Swollman || parm.parm_rdisc_int < MinMaxAdvertiseInterval 76818316Swollman || parm.parm_rdisc_int > MaxMaxAdvertiseInterval) 76946303Smarkm return bad_str(tgt); 77018316Swollman 77119880Swollman } else if (PARSEQ("fake_default")) { 77218316Swollman if (parm.parm_d_metric != 0 77319880Swollman || IS_RIP_OUT_OFF(parm.parm_int_state) 774126250Sbms || (i = strtoul(buf,&p,0), *p != '\0') 775126250Sbms || i > HOPCNT_INFINITY-1) 77646303Smarkm return bad_str(tgt); 777126250Sbms parm.parm_d_metric = i; 77818316Swollman 779126250Sbms } else if (PARSEQ("adj_inmetric")) { 780126250Sbms if (parm.parm_adj_inmetric != 0 781126250Sbms || (i = strtoul(buf,&p,0), *p != '\0') 782126250Sbms || i > HOPCNT_INFINITY-1) 783126250Sbms return bad_str(tgt); 784126250Sbms parm.parm_adj_inmetric = i; 785126250Sbms 786126250Sbms } else if (PARSEQ("adj_outmetric")) { 787126250Sbms if (parm.parm_adj_outmetric != 0 788126250Sbms || (i = strtoul(buf,&p,0), *p != '\0') 789126250Sbms || i > HOPCNT_INFINITY-1) 790126250Sbms return bad_str(tgt); 791126250Sbms parm.parm_adj_outmetric = i; 792126250Sbms 79319880Swollman } else if (PARSEQ("trust_gateway")) { 79446303Smarkm /* look for trust_gateway=x.y.z|net/mask|...) */ 79546303Smarkm p = buf; 79646303Smarkm if (0 > parse_quote(&p, "|", &delim, 79746303Smarkm buf2, sizeof(buf2)) 79846303Smarkm || !gethost(buf2,&addr)) 79946303Smarkm return bad_str(tgt); 80046303Smarkm tg = (struct tgate *)rtmalloc(sizeof(*tg), 80146303Smarkm "parse_parms" 80246303Smarkm "trust_gateway"); 80346303Smarkm memset(tg, 0, sizeof(*tg)); 80446303Smarkm tg->tgate_addr = addr; 80546303Smarkm i = 0; 80646303Smarkm /* The default is to trust all routes. */ 80746303Smarkm while (delim == '|') { 80846303Smarkm p++; 80946303Smarkm if (i >= MAX_TGATE_NETS 81046303Smarkm || 0 > parse_quote(&p, "|", &delim, 81146303Smarkm buf2, sizeof(buf2)) 81246303Smarkm || !getnet(buf2, &tg->tgate_nets[i].net, 81346303Smarkm &tg->tgate_nets[i].mask) 81446303Smarkm || tg->tgate_nets[i].net == RIP_DEFAULT 81546303Smarkm || tg->tgate_nets[i].mask == 0) 81646303Smarkm return bad_str(tgt); 81746303Smarkm i++; 81846303Smarkm } 81919880Swollman tg->tgate_next = tgates; 82019880Swollman tgates = tg; 82119880Swollman parm.parm_int_state |= IS_DISTRUST; 82219880Swollman 82320339Swollman } else if (PARS("redirect_ok")) { 82420339Swollman parm.parm_int_state |= IS_REDIRECT_OK; 82520339Swollman 82618316Swollman } else { 82746303Smarkm return bad_str(tgt); /* error */ 82818316Swollman } 82918316Swollman } 83018316Swollman 83118316Swollman return check_parms(&parm); 83218316Swollman#undef PARS 83319880Swollman#undef PARSEQ 83418316Swollman} 83518316Swollman 83618316Swollman 83718316Swollman/* check for duplicate parameter specifications */ 83846303Smarkmconst char * /* 0 or error message */ 83918316Swollmancheck_parms(struct parm *new) 84018316Swollman{ 84120339Swollman struct parm *parmp, **parmpp; 84220339Swollman int i, num_passwds; 84318316Swollman 84418316Swollman /* set implicit values 84518316Swollman */ 84618316Swollman if (new->parm_int_state & IS_NO_ADV_IN) 84718316Swollman new->parm_int_state |= IS_NO_SOL_OUT; 84846303Smarkm if (new->parm_int_state & IS_NO_SOL_OUT) 84946303Smarkm new->parm_int_state |= IS_NO_ADV_IN; 85018316Swollman 85120339Swollman for (i = num_passwds = 0; i < MAX_AUTH_KEYS; i++) { 85220339Swollman if (new->parm_auth[i].type != RIP_AUTH_NONE) 85320339Swollman num_passwds++; 85420339Swollman } 85520339Swollman 85618316Swollman /* compare with existing sets of parameters 85718316Swollman */ 85820339Swollman for (parmpp = &parms; 85920339Swollman (parmp = *parmpp) != 0; 86020339Swollman parmpp = &parmp->parm_next) { 86118316Swollman if (strcmp(new->parm_name, parmp->parm_name)) 86218316Swollman continue; 86319880Swollman if (!on_net(htonl(parmp->parm_net), 86419880Swollman new->parm_net, new->parm_mask) 86519880Swollman && !on_net(htonl(new->parm_net), 86619880Swollman parmp->parm_net, parmp->parm_mask)) 86718316Swollman continue; 86818316Swollman 86920339Swollman for (i = 0; i < MAX_AUTH_KEYS; i++) { 87020339Swollman if (parmp->parm_auth[i].type != RIP_AUTH_NONE) 87120339Swollman num_passwds++; 87219880Swollman } 87320339Swollman if (num_passwds > MAX_AUTH_KEYS) 87420339Swollman return "too many conflicting passwords"; 87519880Swollman 87646303Smarkm if ((0 != (new->parm_int_state & GROUP_IS_SOL_OUT) 87746303Smarkm && 0 != (parmp->parm_int_state & GROUP_IS_SOL_OUT) 87819880Swollman && 0 != ((new->parm_int_state ^ parmp->parm_int_state) 879215702Sbrucec & GROUP_IS_SOL_OUT)) 88046303Smarkm || (0 != (new->parm_int_state & GROUP_IS_ADV_OUT) 88146303Smarkm && 0 != (parmp->parm_int_state & GROUP_IS_ADV_OUT) 88218316Swollman && 0 != ((new->parm_int_state ^ parmp->parm_int_state) 883215702Sbrucec & GROUP_IS_ADV_OUT)) 88418316Swollman || (new->parm_rdisc_pref != 0 88518316Swollman && parmp->parm_rdisc_pref != 0 88618316Swollman && new->parm_rdisc_pref != parmp->parm_rdisc_pref) 88718316Swollman || (new->parm_rdisc_int != 0 88818316Swollman && parmp->parm_rdisc_int != 0 88919880Swollman && new->parm_rdisc_int != parmp->parm_rdisc_int)) { 89019880Swollman return ("conflicting, duplicate router discovery" 89119880Swollman " parameters"); 89219880Swollman 89319880Swollman } 89419880Swollman 89519880Swollman if (new->parm_d_metric != 0 89619880Swollman && parmp->parm_d_metric != 0 89719880Swollman && new->parm_d_metric != parmp->parm_d_metric) { 89819880Swollman return ("conflicting, duplicate poor man's router" 89919880Swollman " discovery or fake default metric"); 90019880Swollman } 901126250Sbms 902126250Sbms if (new->parm_adj_inmetric != 0 903126250Sbms && parmp->parm_adj_inmetric != 0 904126250Sbms && new->parm_adj_inmetric != parmp->parm_adj_inmetric) { 905126250Sbms return ("conflicting interface input " 906126250Sbms "metric adjustments"); 907126250Sbms } 908126250Sbms 909126250Sbms if (new->parm_adj_outmetric != 0 910126250Sbms && parmp->parm_adj_outmetric != 0 911126250Sbms && new->parm_adj_outmetric != parmp->parm_adj_outmetric) { 912126250Sbms return ("conflicting interface output " 913126250Sbms "metric adjustments"); 914126250Sbms } 91518316Swollman } 91618316Swollman 917126250Sbms /* link new entry on the list so that when the entries are scanned, 91820339Swollman * they affect the result in the order the operator specified. 91920339Swollman */ 92037908Scharnier parmp = (struct parm*)rtmalloc(sizeof(*parmp), "check_parms"); 92146303Smarkm memcpy(parmp, new, sizeof(*parmp)); 92220339Swollman *parmpp = parmp; 92318316Swollman 92418316Swollman return 0; 92518316Swollman} 92618316Swollman 92718316Swollman 92818316Swollman/* get a network number as a name or a number, with an optional "/xx" 92918316Swollman * netmask. 93018316Swollman */ 93118316Swollmanint /* 0=bad */ 93218316Swollmangetnet(char *name, 93346303Smarkm naddr *netp, /* network in host byte order */ 93420339Swollman naddr *maskp) /* masks are always in host order */ 93518316Swollman{ 93618316Swollman int i; 93718316Swollman struct netent *np; 93820339Swollman naddr mask; /* in host byte order */ 93920339Swollman struct in_addr in; /* a network and so host byte order */ 94018316Swollman char hname[MAXHOSTNAMELEN+1]; 94118316Swollman char *mname, *p; 94218316Swollman 94318316Swollman 94418316Swollman /* Detect and separate "1.2.3.4/24" 94518316Swollman */ 94646303Smarkm if (0 != (mname = strrchr(name,'/'))) { 94718316Swollman i = (int)(mname - name); 94846303Smarkm if (i > (int)sizeof(hname)-1) /* name too long */ 94918316Swollman return 0; 95046303Smarkm memmove(hname, name, i); 95118316Swollman hname[i] = '\0'; 95218316Swollman mname++; 95318316Swollman name = hname; 95418316Swollman } 95518316Swollman 95618316Swollman np = getnetbyname(name); 95718316Swollman if (np != 0) { 95818316Swollman in.s_addr = (naddr)np->n_net; 95946303Smarkm if (0 == (in.s_addr & 0xff000000)) 96046303Smarkm in.s_addr <<= 8; 96146303Smarkm if (0 == (in.s_addr & 0xff000000)) 96246303Smarkm in.s_addr <<= 8; 96346303Smarkm if (0 == (in.s_addr & 0xff000000)) 96446303Smarkm in.s_addr <<= 8; 96518316Swollman } else if (inet_aton(name, &in) == 1) { 96690868Smike in.s_addr = ntohl(in.s_addr); 96719880Swollman } else if (!mname && !strcasecmp(name,"default")) { 96819880Swollman in.s_addr = RIP_DEFAULT; 96918316Swollman } else { 97018316Swollman return 0; 97118316Swollman } 97218316Swollman 97319880Swollman if (!mname) { 97418316Swollman /* we cannot use the interfaces here because we have not 97518316Swollman * looked at them yet. 97618316Swollman */ 97720339Swollman mask = std_mask(htonl(in.s_addr)); 97819880Swollman if ((~mask & in.s_addr) != 0) 97918316Swollman mask = HOST_MASK; 98018316Swollman } else { 98118316Swollman mask = (naddr)strtoul(mname, &p, 0); 98218316Swollman if (*p != '\0' || mask > 32) 98318316Swollman return 0; 98446303Smarkm if (mask != 0) 98546303Smarkm mask = HOST_MASK << (32-mask); 98618316Swollman } 98719880Swollman 98819880Swollman /* must have mask of 0 with default */ 98918316Swollman if (mask != 0 && in.s_addr == RIP_DEFAULT) 99018316Swollman return 0; 99119880Swollman /* no host bits allowed in a network number */ 99219880Swollman if ((~mask & in.s_addr) != 0) 99318316Swollman return 0; 99419880Swollman /* require non-zero network number */ 99519880Swollman if ((mask & in.s_addr) == 0 && in.s_addr != RIP_DEFAULT) 99619880Swollman return 0; 99719880Swollman if (in.s_addr>>24 == 0 && in.s_addr != RIP_DEFAULT) 99819880Swollman return 0; 99919880Swollman if (in.s_addr>>24 == 0xff) 100019880Swollman return 0; 100118316Swollman 100219880Swollman *netp = in.s_addr; 100318316Swollman *maskp = mask; 100418316Swollman return 1; 100518316Swollman} 100618316Swollman 100718316Swollman 100818316Swollmanint /* 0=bad */ 100918316Swollmangethost(char *name, 101018316Swollman naddr *addrp) 101118316Swollman{ 101218316Swollman struct hostent *hp; 101318316Swollman struct in_addr in; 101418316Swollman 101518316Swollman 101618316Swollman /* Try for a number first, even in IRIX where gethostbyname() 101718316Swollman * is smart. This avoids hitting the name server which 101818316Swollman * might be sick because routing is. 101918316Swollman */ 102018316Swollman if (inet_aton(name, &in) == 1) { 102119880Swollman /* get a good number, but check that it it makes some 102219880Swollman * sense. 102319880Swollman */ 102419880Swollman if (ntohl(in.s_addr)>>24 == 0 102519880Swollman || ntohl(in.s_addr)>>24 == 0xff) 102619880Swollman return 0; 102718316Swollman *addrp = in.s_addr; 102818316Swollman return 1; 102918316Swollman } 103018316Swollman 103118316Swollman hp = gethostbyname(name); 103218316Swollman if (hp) { 103346303Smarkm memcpy(addrp, hp->h_addr, sizeof(*addrp)); 103418316Swollman return 1; 103518316Swollman } 103618316Swollman 103718316Swollman return 0; 103818316Swollman} 1039