diff options
Diffstat (limited to 'src/libip/readipifc.c')
-rw-r--r-- | src/libip/readipifc.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/libip/readipifc.c b/src/libip/readipifc.c new file mode 100644 index 00000000..b28b3b0c --- /dev/null +++ b/src/libip/readipifc.c @@ -0,0 +1,194 @@ +#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; + + parseip(lifc->ip, f[i]); + parseipmask(lifc->mask, 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; + 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); + + /* allocate new interface */ + *l = ifc = mallocz(sizeof(Ipifc), 1); + if(ifc == nil) + return 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)); + strncpy(ifc->dev, findfield("device", f, n), sizeof(ifc->dev)); + ifc->dev[sizeof(ifc->dev)-1] = 0; + if(ifc->dev[0] == 0){ + free(ifc); + return l; + } + ifc->mtu = strtoul(findfield("maxmtu", 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; + + parseip(lifc->ip, f[0]); + parseipmask(lifc->mask, 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; +} |