0af11f97b5
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.
199 lines
4.3 KiB
C
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;
|
|
}
|