netlog.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       netlog.c (3969B)
       ---
            1 #include        "u.h"
            2 #include        "lib.h"
            3 #include        "mem.h"
            4 #include        "dat.h"
            5 #include        "fns.h"
            6 #include        "error.h"
            7 #include        "ip/ip.h"
            8 
            9 enum {
           10         Nlog                = 16*1024,
           11 };
           12 
           13 /*
           14  *  action log
           15  */
           16 struct Netlog {
           17         Lock        lk;
           18         int        opens;
           19         char*        buf;
           20         char        *end;
           21         char        *rptr;
           22         int        len;
           23 
           24         int        logmask;                        /* mask of things to debug */
           25         uchar        iponly[IPaddrlen];                /* ip address to print debugging for */
           26         int        iponlyset;
           27 
           28         QLock        qlock;
           29         Rendez        rendez;
           30 };
           31 
           32 typedef struct Netlogflag {
           33         char*        name;
           34         int        mask;
           35 } Netlogflag;
           36 
           37 static Netlogflag flags[] =
           38 {
           39         { "ppp",        Logppp, },
           40         { "ip",                Logip, },
           41         { "fs",                Logfs, },
           42         { "tcp",        Logtcp, },
           43         { "icmp",        Logicmp, },
           44         { "udp",        Logudp, },
           45         { "compress",        Logcompress, },
           46         { "gre",        Loggre, },
           47         { "tcpwin",        Logtcp|Logtcpwin, },
           48         { "tcprxmt",        Logtcp|Logtcprxmt, },
           49         { "udpmsg",        Logudp|Logudpmsg, },
           50         { "ipmsg",        Logip|Logipmsg, },
           51         { "esp",        Logesp, },
           52         { nil,                0, },
           53 };
           54 
           55 char Ebadnetctl[] = "too few arguments for netlog control message";
           56 
           57 enum
           58 {
           59         CMset,
           60         CMclear,
           61         CMonly,
           62 };
           63 
           64 static
           65 Cmdtab routecmd[] = {
           66         CMset,                "set",                0,
           67         CMclear,        "clear",        0,
           68         CMonly,                "only",                0,
           69 };
           70 
           71 void
           72 netloginit(Fs *f)
           73 {
           74         f->alog = smalloc(sizeof(Netlog));
           75 }
           76 
           77 void
           78 netlogopen(Fs *f)
           79 {
           80         LOCK(f->alog);
           81         if(waserror()){
           82                 UNLOCK(f->alog);
           83                 nexterror();
           84         }
           85         if(f->alog->opens == 0){
           86                 if(f->alog->buf == nil)
           87                         f->alog->buf = malloc(Nlog);
           88                 f->alog->rptr = f->alog->buf;
           89                 f->alog->end = f->alog->buf + Nlog;
           90         }
           91         f->alog->opens++;
           92         UNLOCK(f->alog);
           93         poperror();
           94 }
           95 
           96 void
           97 netlogclose(Fs *f)
           98 {
           99         LOCK(f->alog);
          100         if(waserror()){
          101                 UNLOCK(f->alog);
          102                 nexterror();
          103         }
          104         f->alog->opens--;
          105         if(f->alog->opens == 0){
          106                 free(f->alog->buf);
          107                 f->alog->buf = nil;
          108         }
          109         UNLOCK(f->alog);
          110         poperror();
          111 }
          112 
          113 static int
          114 netlogready(void *a)
          115 {
          116         Fs *f = a;
          117 
          118         return f->alog->len;
          119 }
          120 
          121 long
          122 netlogread(Fs *f, void *a, ulong _, long n)
          123 {
          124         int i, d;
          125         char *p, *rptr;
          126 
          127         QLOCK(f->alog);
          128         if(waserror()){
          129                 QUNLOCK(f->alog);
          130                 nexterror();
          131         }
          132 
          133         for(;;){
          134                 LOCK(f->alog);
          135                 if(f->alog->len){
          136                         if(n > f->alog->len)
          137                                 n = f->alog->len;
          138                         d = 0;
          139                         rptr = f->alog->rptr;
          140                         f->alog->rptr += n;
          141                         if(f->alog->rptr >= f->alog->end){
          142                                 d = f->alog->rptr - f->alog->end;
          143                                 f->alog->rptr = f->alog->buf + d;
          144                         }
          145                         f->alog->len -= n;
          146                         UNLOCK(f->alog);
          147 
          148                         i = n-d;
          149                         p = a;
          150                         memmove(p, rptr, i);
          151                         memmove(p+i, f->alog->buf, d);
          152                         break;
          153                 }
          154                 else
          155                         UNLOCK(f->alog);
          156 
          157                 sleep(&f->alog->rendez, netlogready, f);
          158         }
          159 
          160         QUNLOCK(f->alog);
          161         poperror();
          162 
          163         return n;
          164 }
          165 
          166 void
          167 netlogctl(Fs *f, char* s, int n)
          168 {
          169         int i, set;
          170         Netlogflag *fp;
          171         Cmdbuf *cb;
          172         Cmdtab *ct;
          173 
          174         cb = parsecmd(s, n);
          175         if(waserror()){
          176                 free(cb);
          177                 nexterror();
          178         }
          179 
          180         if(cb->nf < 2)
          181                 error(Ebadnetctl);
          182 
          183         ct = lookupcmd(cb, routecmd, nelem(routecmd));
          184 
          185         set = 1;
          186 
          187         switch(ct->index){
          188         case CMset:
          189                 set = 1;
          190                 break;
          191 
          192         case CMclear:
          193                 set = 0;
          194                 break;
          195 
          196         case CMonly:
          197                 parseip(f->alog->iponly, cb->f[1]);
          198                 if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
          199                         f->alog->iponlyset = 0;
          200                 else
          201                         f->alog->iponlyset = 1;
          202                 free(cb);
          203                 return;
          204 
          205         default:
          206                 cmderror(cb, "unknown ip control message");
          207         }
          208 
          209         for(i = 1; i < cb->nf; i++){
          210                 for(fp = flags; fp->name; fp++)
          211                         if(strcmp(fp->name, cb->f[i]) == 0)
          212                                 break;
          213                 if(fp->name == nil)
          214                         continue;
          215                 if(set)
          216                         f->alog->logmask |= fp->mask;
          217                 else
          218                         f->alog->logmask &= ~fp->mask;
          219         }
          220 
          221         free(cb);
          222         poperror();
          223 }
          224 
          225 void
          226 netlog(Fs *f, int mask, char *fmt, ...)
          227 {
          228         char buf[128], *t, *fp;
          229         int i, n;
          230         va_list arg;
          231 
          232         if(!(f->alog->logmask & mask))
          233                 return;
          234 
          235         if(f->alog->opens == 0)
          236                 return;
          237 
          238         va_start(arg, fmt);
          239         n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
          240         va_end(arg);
          241 
          242         LOCK(f->alog);
          243         i = f->alog->len + n - Nlog;
          244         if(i > 0){
          245                 f->alog->len -= i;
          246                 f->alog->rptr += i;
          247                 if(f->alog->rptr >= f->alog->end)
          248                         f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
          249         }
          250         t = f->alog->rptr + f->alog->len;
          251         fp = buf;
          252         f->alog->len += n;
          253         while(n-- > 0){
          254                 if(t >= f->alog->end)
          255                         t = f->alog->buf + (t - f->alog->end);
          256                 *t++ = *fp++;
          257         }
          258         UNLOCK(f->alog);
          259 
          260         wakeup(&f->alog->rendez);
          261 }