plan9fox/sys/src/libip/readipifc.c
cinap_lenrek 0af11f97b5 libip: replace v4parsecidr() with new parseipandmask()
we want to accept V4 subnets in CIDR notation consistently which
means we need to interpret the mask in context of the IP address.
so parseipmask() now has an additional v4 flag argument which
offsets the prefixlength by 96 so a /24 will be interpreted
as a /120.

parseipandmask() is the new function which handles this automatically
depending on the ip address type.

v4parsecidr() is now obsolete.
2019-02-11 23:26:57 +01:00

199 lines
4.3 KiB
C

#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <ip.h>
static Ipifc**
_readoldipifc(char *buf, Ipifc **l, int index)
{
char *f[200];
int i, n;
Ipifc *ifc;
Iplifc *lifc, **ll;
/* allocate new interface */
*l = ifc = mallocz(sizeof(Ipifc), 1);
if(ifc == nil)
return l;
l = &ifc->next;
ifc->index = index;
n = tokenize(buf, f, nelem(f));
if(n < 2)
return l;
strncpy(ifc->dev, f[0], sizeof ifc->dev);
ifc->dev[sizeof(ifc->dev) - 1] = 0;
ifc->mtu = strtoul(f[1], nil, 10);
ll = &ifc->lifc;
for(i = 2; n-i >= 7; i += 7){
/* allocate new local address */
*ll = lifc = mallocz(sizeof(Iplifc), 1);
ll = &lifc->next;
parseipandmask(lifc->ip, lifc->mask, f[i], f[i+1]);
parseip(lifc->net, f[i+2]);
ifc->pktin = strtoul(f[i+3], nil, 10);
ifc->pktout = strtoul(f[i+4], nil, 10);
ifc->errin = strtoul(f[i+5], nil, 10);
ifc->errout = strtoul(f[i+6], nil, 10);
}
return l;
}
static char*
findfield(char *name, char **f, int n)
{
int i;
for(i = 0; i < n-1; i++)
if(strcmp(f[i], name) == 0)
return f[i+1];
return "";
}
static Ipifc**
_readipifc(char *file, Ipifc **l, int index)
{
int i, n, fd, lines;
char buf[4*1024];
char *line[32];
char *f[64];
Ipifc *ifc, **l0;
Iplifc *lifc, **ll;
/* read the file */
fd = open(file, OREAD);
if(fd < 0)
return l;
n = 0;
while((i = read(fd, buf+n, sizeof(buf)-1-n)) > 0 && n < sizeof(buf) - 1)
n += i;
buf[n] = 0;
close(fd);
if(strncmp(buf, "device", 6) != 0)
return _readoldipifc(buf, l, index);
/* ignore ifcs with no associated device */
if(strncmp(buf+6, " ", 2) == 0)
return l;
/* allocate new interface */
*l = ifc = mallocz(sizeof(Ipifc), 1);
if(ifc == nil)
return l;
l0 = l;
l = &ifc->next;
ifc->index = index;
lines = getfields(buf, line, nelem(line), 1, "\n");
/* pick off device specific info(first line) */
n = tokenize(line[0], f, nelem(f));
if(n%2 != 0)
goto lose;
strncpy(ifc->dev, findfield("device", f, n), sizeof(ifc->dev));
ifc->dev[sizeof(ifc->dev)-1] = 0;
if(ifc->dev[0] == 0){
lose:
free(ifc);
*l0 = nil;
return l;
}
ifc->mtu = strtoul(findfield("maxtu", f, n), nil, 10);
ifc->sendra6 = atoi(findfield("sendra", f, n));
ifc->recvra6 = atoi(findfield("recvra", f, n));
ifc->rp.mflag = atoi(findfield("mflag", f, n));
ifc->rp.oflag = atoi(findfield("oflag", f, n));
ifc->rp.maxraint = atoi(findfield("maxraint", f, n));
ifc->rp.minraint = atoi(findfield("minraint", f, n));
ifc->rp.linkmtu = atoi(findfield("linkmtu", f, n));
ifc->rp.reachtime = atoi(findfield("reachtime", f, n));
ifc->rp.rxmitra = atoi(findfield("rxmitra", f, n));
ifc->rp.ttl = atoi(findfield("ttl", f, n));
ifc->rp.routerlt = atoi(findfield("routerlt", f, n));
ifc->pktin = strtoul(findfield("pktin", f, n), nil, 10);
ifc->pktout = strtoul(findfield("pktout", f, n), nil, 10);
ifc->errin = strtoul(findfield("errin", f, n), nil, 10);
ifc->errout = strtoul(findfield("errout", f, n), nil, 10);
/* now read the addresses */
ll = &ifc->lifc;
for(i = 1; i < lines; i++){
n = tokenize(line[i], f, nelem(f));
if(n < 5)
break;
/* allocate new local address */
*ll = lifc = mallocz(sizeof(Iplifc), 1);
ll = &lifc->next;
parseipandmask(lifc->ip, lifc->mask, f[0], f[1]);
parseip(lifc->net, f[2]);
lifc->validlt = strtoul(f[3], nil, 10);
lifc->preflt = strtoul(f[4], nil, 10);
}
return l;
}
static void
_freeifc(Ipifc *ifc)
{
Ipifc *next;
Iplifc *lnext, *lifc;
if(ifc == nil)
return;
for(; ifc; ifc = next){
next = ifc->next;
for(lifc = ifc->lifc; lifc; lifc = lnext){
lnext = lifc->next;
free(lifc);
}
free(ifc);
}
}
Ipifc*
readipifc(char *net, Ipifc *ifc, int index)
{
int fd, i, n;
Dir *dir;
char directory[128];
char buf[128];
Ipifc **l;
_freeifc(ifc);
l = &ifc;
ifc = nil;
if(net == 0)
net = "/net";
snprint(directory, sizeof(directory), "%s/ipifc", net);
if(index >= 0){
snprint(buf, sizeof(buf), "%s/%d/status", directory, index);
_readipifc(buf, l, index);
} else {
fd = open(directory, OREAD);
if(fd < 0)
return nil;
n = dirreadall(fd, &dir);
close(fd);
for(i = 0; i < n; i++){
if(strcmp(dir[i].name, "clone") == 0)
continue;
if(strcmp(dir[i].name, "stats") == 0)
continue;
snprint(buf, sizeof(buf), "%s/%s/status", directory, dir[i].name);
l = _readipifc(buf, l, atoi(dir[i].name));
}
free(dir);
}
return ifc;
}