M ip/devip.c => ip/devip.c +13 -3
@@ 16,6 16,7 @@ enum
Qarp= Qtopbase,
Qiproute,
Qiprouter,
+ Qipselftab,
Qlog,
Qprotodir, /* directory for a protocol */
@@ 107,7 108,9 @@ ip1gen(Chan *c, int i, Dir *dp)
{
Qid q;
char *p;
+ int prot;
+ prot = 0666;
switch(i) {
default:
return -1;
@@ 119,6 122,11 @@ ip1gen(Chan *c, int i, Dir *dp)
p = "iproute";
q = (Qid){QID(0, 0, Qiproute), 0};
break;
+ case Qipselftab:
+ p = "ipselftab";
+ prot = 0444;
+ q = (Qid){QID(0, 0, Qipselftab), 0};
+ break;
case Qiprouter:
p = "iprouter";
q = (Qid){QID(0, 0, Qiprouter), 0};
@@ 128,7 136,7 @@ ip1gen(Chan *c, int i, Dir *dp)
q = (Qid){QID(0, 0, Qlog), 0};
break;
}
- devdir(c, q, p, 0, network, 0666, dp);
+ devdir(c, q, p, 0, network, prot, dp);
return 1;
}
@@ 154,6 162,7 @@ ipgen(Chan *c, Dirtab*, int, int s, Dir *dp)
case Qlog:
case Qiproute:
case Qiprouter:
+ case Qipselftab:
return ip1gen(c, TYPE(c->qid), dp);
case Qprotodir:
if(s < fs.p[PROTO(c->qid)]->ac) {
@@ 295,6 304,7 @@ ipopen(Chan* c, int omode)
case Qremote:
case Qlocal:
case Qstats:
+ case Qipselftab:
if(omode != OREAD)
error(Eperm);
break;
@@ 464,8 474,8 @@ ipread(Chan *ch, void *a, long n, ulong offset)
return arpread(a, offset, n);
case Qiproute:
return routeread(a, offset, n);
- case Qiprouter:
- return iprouterread(a, n);
+ case Qipselftab:
+ return ipselftabread(a, offset, n);
case Qlog:
return netlogread(a, offset, n);
case Qctl:
M ip/ip.h => ip/ip.h +2 -0
@@ 340,6 340,7 @@ extern Route* v4lookup(uchar *a);
extern Route* v6lookup(uchar *a);
extern long routeread(char*, ulong, int);
extern long routewrite(Chan*, char*, int);
+extern void routetype(int, char*);
/*
* arp.c
@@ 432,6 433,7 @@ extern void ipifcremmulti(Conv *c, uchar *ma, uchar *ia);
extern void ipifcaddmulti(Conv *c, uchar *ma, uchar *ia);
extern char* ipifcrem(Ipifc *ifc, char **argv, int argc, int dolock);
extern char* ipifcadd(Ipifc *ifc, char **argv, int argc);
+extern long ipselftabread(char *a, ulong offset, int n);
/*
* ip.c
M ip/ipifc.c => ip/ipifc.c +36 -4
@@ 749,15 749,15 @@ remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a)
*l_self = link->selflink;
iplinkfree(link);
+ if(p->link != nil)
+ goto out;
+
/* remove from routing table */
if(isv4(a))
v4delroute(a+IPv4off, IPallbits+IPv4off);
else
v6delroute(a, IPallbits);
- if(p->link != nil)
- goto out;
-
/* no more links, remove from hash and free */
*l = p->next;
ipselffree(p);
@@ 783,12 783,44 @@ dumpselftab(void)
continue;
count = 0;
for(; p != nil && count++ < 6; p = p->next)
- print("(%i %d %lux)", p->a, p->type, p);
+ print("(%I %d %lux)", p->a, p->type, p);
print("\n");
}
qunlock(&selftab);
}
+static char *stformat = "%-32.32I %2.2d %4.4s\n";
+enum
+{
+ Nstformat= 41,
+};
+
+long
+ipselftabread(char *cp, ulong offset, int n)
+{
+ int i, m, nifc;
+ Ipself *p;
+ Iplink *link;
+ char state[8];
+
+ m = 0;
+ qlock(&selftab);
+ for(i = 0; i < NHASH && m < n; i++){
+ for(p = selftab.hash[i]; p != nil && m < n; p = p->next){
+ if(offset == 0){
+ nifc = 0;
+ for(link = p->link; link; link = link->selflink)
+ nifc++;
+ routetype(p->type, state);
+ m += snprint(cp + m, n - m, stformat, p->a, nifc, state);
+ }
+ offset -= Nstformat;
+ }
+ }
+ qunlock(&selftab);
+ return m;
+}
+
/*
* returns
M ip/iproute.c => ip/iproute.c +22 -17
@@ 544,6 544,27 @@ next: ;
return q;
}
+void
+routetype(int type, char *p)
+{
+ memset(p, ' ', 4);
+ p[4] = 0;
+ if(type & Rv4)
+ *p++ = '4';
+ else
+ *p++ = '6';
+ if(type & Rifc)
+ *p++ = 'i';
+ if(type & Runi)
+ *p++ = 'u';
+ else if(type & Rbcast)
+ *p++ = 'b';
+ else if(type & Rmulti)
+ *p++ = 'm';
+ if(type & Rptpt)
+ *p = 'p';
+}
+
enum
{
Rlinelen= 89,
@@ 555,7 576,6 @@ void
convroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc)
{
int i;
- char *p = t;
if(r->type & Rv4){
memmove(addr, v4prefix, IPv4off);
@@ 572,22 592,7 @@ convroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc)
memmove(gate, r->v6.gate, IPaddrlen);
}
- memset(t, ' ', 4);
- t[4] = 0;
- if(r->type & Rv4)
- *p++ = '4';
- else
- *p++ = '6';
- if(r->type & Rifc)
- *p++ = 'i';
- if(r->type & Runi)
- *p++ = 'u';
- else if(r->type & Rbcast)
- *p++ = 'b';
- else if(r->type & Rmulti)
- *p++ = 'm';
- if(r->type & Rptpt)
- *p = 'p';
+ routetype(r->type, t);
if(r->ifc)
*nifc = r->ifc->conv->x;
M port/devproc.c => port/devproc.c +39 -3
@@ 24,12 24,14 @@ enum
Qtext,
Qwait,
Qprofile,
+ Qfd,
};
#define STATSIZE (2*NAMELEN+12+9*12)
Dirtab procdir[] =
{
"ctl", {Qctl}, 0, 0000,
+ "fd", {Qfd}, 0, 0000,
"fpregs", {Qfpregs}, sizeof(FPsave), 0000,
"kregs", {Qkregs}, sizeof(Ureg), 0000,
"mem", {Qmem}, 0, 0000,
@@ 57,10 59,10 @@ char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata", "Map
* 32 bits of pid, for consistency checking
* If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
*/
-#define QSHIFT 4 /* location in qid of proc slot # */
+#define QSHIFT 5 /* location in qid of proc slot # */
-#define QID(q) (((q).path&0x0000000F)>>0)
-#define SLOT(q) ((((q).path&0x07FFFFFF0)>>QSHIFT)-1)
+#define QID(q) (((q).path&0x0000001F)>>0)
+#define SLOT(q) ((((q).path&0x07FFFFFE0)>>QSHIFT)-1)
#define PID(q) ((q).vers)
#define NOTEID(q) ((q).vers)
@@ 183,6 185,7 @@ procopen(Chan *c, int omode)
case Qkregs:
case Qsegment:
case Qprofile:
+ case Qfd:
if(omode != OREAD)
error(Eperm);
break;
@@ 242,6 245,37 @@ procwstat(Chan *c, char *db)
p->procmode = d.mode&0777;
}
+static int
+procfds(Fgrp *f, char *va, int count, long offset)
+{
+ Chan *c;
+ int n, i;
+
+ n = 0;
+ for(i = 0; i <= f->maxfd; i++) {
+ c = f->fd[i];
+ if(c == nil)
+ continue;
+ n += snprint(va+n, count-n, "%3d %.2s %.8lux.%.8d %8d ",
+ i,
+ &"r w rw"[(c->mode&3)<<1],
+ c->qid.path, c->qid.vers,
+ c->offset);
+ n += ptpath(c->path, va+n, count-n);
+ n += snprint(va+n, count-n, "\n");
+ if(offset > 0) {
+ offset -= n;
+ if(offset < 0) {
+ memmove(va, va+n+offset, -offset);
+ n = -offset;
+ }
+ else
+ n = 0;
+ }
+ }
+ return n;
+}
+
static void
procclose(Chan * c)
{
@@ 483,6 517,8 @@ procread(Chan *c, void *va, long n, ulong offset)
return a - (char*)va;
case Qnoteid:
return readnum(offset, va, n, p->noteid, NUMSIZE);
+ case Qfd:
+ return procfds(p->fgrp, va, n, offset);
}
error(Egreg);
return 0; /* not reached */