Remove remnants of classful behavior in route(8).

Curently route(8) treats some addresses as network addresses:

 RTA_DST: inet 10.0.0.0; RTA_NETMASK: inet 255.0.0.0; RTA_IFP: link ;
 RTM_GET: Report Metrics: len 240, pid: 0, seq 1, errno 0, flags:<UP,GATEWAY,STATIC>
 locks:  inits:
 sockaddrs: <DST,NETMASK,IFP>
   10.0.0.0 255.0.0.0 link#0

Note added `RTA_NETMASK` in the request.

Host address from the same network is ok:

route -nv get 10.0.0.1
 RTA_DST: inet 10.0.0.1
 RTA_IFP: link
 RTM_GET: Report Metrics: len 224, pid: 0, seq 1, errno 0, flags:<UP,GATEWAY,HOST,STATIC>
...
   route to: 10.0.0.1
destination: 10.0.0.0
       mask: 255.255.255.0

This change eliminates network auto-guessing part AND reading network from /etc/networks.

Reviewed By: rgrimes

Differential Revision: https://reviews.freebsd.org/D24401
This commit is contained in:
Alexander V. Chernikov 2021-01-16 23:06:32 +00:00
parent 0ec6c03c76
commit d28210b2c2

View file

@ -120,8 +120,7 @@ static int flushroutes_fib(int);
static int getaddr(int, char *, struct hostent **, int);
static int keyword(const char *);
#ifdef INET
static void inet_makenetandmask(u_long, struct sockaddr_in *,
struct sockaddr_in *, u_long);
static void inet_makemask(struct sockaddr_in *, u_long);
#endif
#ifdef INET6
static int inet6_makenetandmask(struct sockaddr_in6 *, const char *);
@ -1113,40 +1112,15 @@ newroute_fib(int fib, char *cmd, int flags)
#ifdef INET
static void
inet_makenetandmask(u_long net, struct sockaddr_in *sin,
struct sockaddr_in *sin_mask, u_long bits)
inet_makemask(struct sockaddr_in *sin_mask, u_long bits)
{
u_long mask = 0;
rtm_addrs |= RTA_NETMASK;
/*
* MSB of net should be meaningful. 0/0 is exception.
*/
if (net > 0)
while ((net & 0xff000000) == 0)
net <<= 8;
/*
* If no /xx was specified we must calculate the
* CIDR address.
*/
if ((bits == 0) && (net != 0)) {
u_long i, j;
for(i = 0, j = 0xff; i < 4; i++) {
if (net & j) {
break;
}
j <<= 8;
}
/* i holds the first non zero bit */
bits = 32 - (i*8);
}
if (bits != 0)
mask = 0xffffffff << (32 - bits);
sin->sin_addr.s_addr = htonl(net);
sin_mask->sin_addr.s_addr = htonl(mask);
sin_mask->sin_len = sizeof(struct sockaddr_in);
sin_mask->sin_family = AF_INET;
@ -1186,8 +1160,6 @@ getaddr(int idx, char *str, struct hostent **hpp, int nrflags)
#if defined(INET)
struct sockaddr_in *sin;
struct hostent *hp;
struct netent *np;
u_long val;
char *q;
#elif defined(INET6)
char *q;
@ -1314,34 +1286,21 @@ getaddr(int idx, char *str, struct hostent **hpp, int nrflags)
q = strchr(str,'/');
if (q != NULL && idx == RTAX_DST) {
/* A.B.C.D/NUM */
*q = '\0';
if ((val = inet_network(str)) != INADDR_NONE) {
inet_makenetandmask(val, sin,
(struct sockaddr_in *)&so[RTAX_NETMASK],
strtoul(q+1, 0, 0));
return (0);
}
*q = '/';
}
if ((idx != RTAX_DST || (nrflags & F_FORCENET) == 0) &&
inet_aton(str, &sin->sin_addr)) {
val = sin->sin_addr.s_addr;
if (idx != RTAX_DST || nrflags & F_FORCEHOST ||
inet_lnaof(sin->sin_addr) != INADDR_ANY)
return (1);
else {
val = ntohl(val);
goto netdone;
}
}
if (idx == RTAX_DST && (nrflags & F_FORCEHOST) == 0 &&
((val = inet_network(str)) != INADDR_NONE ||
((np = getnetbyname(str)) != NULL && (val = np->n_net) != 0))) {
netdone:
inet_makenetandmask(val, sin,
(struct sockaddr_in *)&so[RTAX_NETMASK], 0);
if (inet_aton(str, &sin->sin_addr) == 0)
errx(EX_NOHOST, "bad address: %s", str);
int masklen = strtol(q + 1, NULL, 10);
if (masklen < 0 || masklen > 32)
errx(EX_NOHOST, "bad mask length: %s", q + 1);
inet_makemask((struct sockaddr_in *)&so[RTAX_NETMASK],masklen);
return (0);
}
if (inet_aton(str, &sin->sin_addr) != 0)
return (1);
hp = gethostbyname(str);
if (hp != NULL) {
*hpp = hp;