The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ip/ipmux.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * IP packet filter
    3  */
    4 #include "u.h"
    5 #include "../port/lib.h"
    6 #include "mem.h"
    7 #include "dat.h"
    8 #include "fns.h"
    9 #include "../port/error.h"
   10 
   11 #include "ip.h"
   12 #include "ipv6.h"
   13 
   14 typedef struct Ipmuxrock  Ipmuxrock;
   15 typedef struct Ipmux      Ipmux;
   16 
   17 typedef struct Myip4hdr Myip4hdr;
   18 struct Myip4hdr
   19 {
   20         uchar   vihl;           /* Version and header length */
   21         uchar   tos;            /* Type of service */
   22         uchar   length[2];      /* packet length */
   23         uchar   id[2];          /* ip->identification */
   24         uchar   frag[2];        /* Fragment information */
   25         uchar   ttl;            /* Time to live */
   26         uchar   proto;          /* Protocol */
   27         uchar   cksum[2];       /* Header checksum */
   28         uchar   src[4];         /* IP source */
   29         uchar   dst[4];         /* IP destination */
   30 
   31         uchar   data[1];        /* start of data */
   32 };
   33 Myip4hdr *ipoff = 0;
   34 
   35 enum
   36 {
   37         Tproto,
   38         Tdata,
   39         Tiph,
   40         Tdst,
   41         Tsrc,
   42         Tifc,
   43 
   44         Cother = 0,
   45         Cbyte,          /* single byte */
   46         Cmbyte,         /* single byte with mask */
   47         Cshort,         /* single short */
   48         Cmshort,        /* single short with mask */
   49         Clong,          /* single long */
   50         Cmlong,         /* single long with mask */
   51         Cifc,
   52         Cmifc,
   53 };
   54 
   55 char *ftname[] = 
   56 {
   57 [Tproto]        "proto",
   58 [Tdata]         "data",
   59 [Tiph]          "iph",
   60 [Tdst]          "dst",
   61 [Tsrc]          "src",
   62 [Tifc]          "ifc",
   63 };
   64 
   65 /*
   66  *  a node in the decision tree
   67  */
   68 struct Ipmux
   69 {
   70         Ipmux   *yes;
   71         Ipmux   *no;
   72         uchar   type;           /* type of field(Txxxx) */
   73         uchar   ctype;          /* tupe of comparison(Cxxxx) */
   74         uchar   len;            /* length in bytes of item to compare */
   75         uchar   n;              /* number of items val points to */
   76         short   off;            /* offset of comparison */
   77         short   eoff;           /* end offset of comparison */
   78         uchar   skiphdr;        /* should offset start after ipheader */
   79         uchar   *val;
   80         uchar   *mask;
   81         uchar   *e;             /* val+n*len*/
   82 
   83         int     ref;            /* so we can garbage collect */
   84         Conv    *conv;
   85 };
   86 
   87 /*
   88  *  someplace to hold per conversation data
   89  */
   90 struct Ipmuxrock
   91 {
   92         Ipmux   *chain;
   93 };
   94 
   95 static int      ipmuxsprint(Ipmux*, int, char*, int);
   96 static void     ipmuxkick(void *x);
   97 
   98 static char*
   99 skipwhite(char *p)
  100 {
  101         while(*p == ' ' || *p == '\t')
  102                 p++;
  103         return p;
  104 }
  105 
  106 static char*
  107 follows(char *p, char c)
  108 {
  109         char *f;
  110 
  111         f = strchr(p, c);
  112         if(f == nil)
  113                 return nil;
  114         *f++ = 0;
  115         f = skipwhite(f);
  116         if(*f == 0)
  117                 return nil;
  118         return f;
  119 }
  120 
  121 static Ipmux*
  122 parseop(char **pp)
  123 {
  124         char *p = *pp;
  125         int type, off, end, len;
  126         Ipmux *f;
  127 
  128         p = skipwhite(p);
  129         if(strncmp(p, "dst", 3) == 0){
  130                 type = Tdst;
  131                 off = (ulong)(ipoff->dst);
  132                 len = IPv4addrlen;
  133                 p += 3;
  134         }
  135         else if(strncmp(p, "src", 3) == 0){
  136                 type = Tsrc;
  137                 off = (ulong)(ipoff->src);
  138                 len = IPv4addrlen;
  139                 p += 3;
  140         }
  141         else if(strncmp(p, "ifc", 3) == 0){
  142                 type = Tifc;
  143                 off = -IPv4addrlen;
  144                 len = IPv4addrlen;
  145                 p += 3;
  146         }
  147         else if(strncmp(p, "proto", 5) == 0){
  148                 type = Tproto;
  149                 off = (ulong)&(ipoff->proto);
  150                 len = 1;
  151                 p += 5;
  152         }
  153         else if(strncmp(p, "data", 4) == 0 || strncmp(p, "iph", 3) == 0){
  154                 if(strncmp(p, "data", 4) == 0) {
  155                         type = Tdata;
  156                         p += 4;
  157                 }
  158                 else {
  159                         type = Tiph;
  160                         p += 3;
  161                 }
  162                 p = skipwhite(p);
  163                 if(*p != '[')
  164                         return nil;
  165                 p++;
  166                 off = strtoul(p, &p, 0);
  167                 if(off < 0 || off > (64-IP4HDR))
  168                         return nil;
  169                 p = skipwhite(p);
  170                 if(*p != ':')
  171                         end = off;
  172                 else {
  173                         p++;
  174                         p = skipwhite(p);
  175                         end = strtoul(p, &p, 0);
  176                         if(end < off)
  177                                 return nil;
  178                         p = skipwhite(p);
  179                 }
  180                 if(*p != ']')
  181                         return nil;
  182                 p++;
  183                 len = end - off + 1;
  184         }
  185         else
  186                 return nil;
  187 
  188         f = smalloc(sizeof(*f));
  189         f->type = type;
  190         f->len = len;
  191         f->off = off;
  192         f->val = nil;
  193         f->mask = nil;
  194         f->n = 1;
  195         f->ref = 1;
  196         if(type == Tdata)
  197                 f->skiphdr = 1;
  198         else
  199                 f->skiphdr = 0;
  200 
  201         return f;       
  202 }
  203 
  204 static int
  205 htoi(char x)
  206 {
  207         if(x >= '' && x <= '9')
  208                 x -= '';
  209         else if(x >= 'a' && x <= 'f')
  210                 x -= 'a' - 10;
  211         else if(x >= 'A' && x <= 'F')
  212                 x -= 'A' - 10;
  213         else
  214                 x = 0;
  215         return x;
  216 }
  217 
  218 static int
  219 hextoi(char *p)
  220 {
  221         return (htoi(p[0])<<4) | htoi(p[1]);
  222 }
  223 
  224 static void
  225 parseval(uchar *v, char *p, int len)
  226 {
  227         while(*p && len-- > 0){
  228                 *v++ = hextoi(p);
  229                 p += 2;
  230         }
  231 }
  232 
  233 static Ipmux*
  234 parsemux(char *p)
  235 {
  236         int n, nomask;
  237         Ipmux *f;
  238         char *val;
  239         char *mask;
  240         char *vals[20];
  241         uchar *v;
  242 
  243         /* parse operand */
  244         f = parseop(&p);
  245         if(f == nil)
  246                 return nil;
  247 
  248         /* find value */
  249         val = follows(p, '=');
  250         if(val == nil)
  251                 goto parseerror;
  252 
  253         /* parse mask */
  254         mask = follows(p, '&');
  255         if(mask != nil){
  256                 switch(f->type){
  257                 case Tsrc:
  258                 case Tdst:
  259                 case Tifc:
  260                         f->mask = smalloc(f->len);
  261                         v4parseip(f->mask, mask);
  262                         break;
  263                 case Tdata:
  264                 case Tiph:
  265                         f->mask = smalloc(f->len);
  266                         parseval(f->mask, mask, f->len);
  267                         break;
  268                 default:
  269                         goto parseerror;
  270                 }
  271                 nomask = 0;
  272         } else {
  273                 nomask = 1;
  274                 f->mask = smalloc(f->len);
  275                 memset(f->mask, 0xff, f->len);
  276         }
  277 
  278         /* parse vals */
  279         f->n = getfields(val, vals, sizeof(vals)/sizeof(char*), 1, "|");
  280         if(f->n == 0)
  281                 goto parseerror;
  282         f->val = smalloc(f->n*f->len);
  283         v = f->val;
  284         for(n = 0; n < f->n; n++){
  285                 switch(f->type){
  286                 case Tsrc:
  287                 case Tdst:
  288                 case Tifc:
  289                         v4parseip(v, vals[n]);
  290                         break;
  291                 case Tproto:
  292                 case Tdata:
  293                 case Tiph:
  294                         parseval(v, vals[n], f->len);
  295                         break;
  296                 }
  297                 v += f->len;
  298         }
  299 
  300         f->eoff = f->off + f->len;
  301         f->e = f->val + f->n*f->len;
  302         f->ctype = Cother;
  303         if(f->n == 1){
  304                 switch(f->len){
  305                 case 1:
  306                         f->ctype = nomask ? Cbyte : Cmbyte;
  307                         break;
  308                 case 2:
  309                         f->ctype = nomask ? Cshort : Cmshort;
  310                         break;
  311                 case 4:
  312                         if(f->type == Tifc)
  313                                 f->ctype = nomask ? Cifc : Cmifc;
  314                         else
  315                                 f->ctype = nomask ? Clong : Cmlong;
  316                         break;
  317                 }
  318         }
  319         return f;
  320 
  321 parseerror:
  322         if(f->mask)
  323                 free(f->mask);
  324         if(f->val)
  325                 free(f->val);
  326         free(f);
  327         return nil;
  328 }
  329 
  330 /*
  331  *  Compare relative ordering of two ipmuxs.  This doesn't compare the
  332  *  values, just the fields being looked at.  
  333  *
  334  *  returns:    <0 if a is a more specific match
  335  *               0 if a and b are matching on the same fields
  336  *              >0 if b is a more specific match
  337  */
  338 static int
  339 ipmuxcmp(Ipmux *a, Ipmux *b)
  340 {
  341         int n;
  342 
  343         /* compare types, lesser ones are more important */
  344         n = a->type - b->type;
  345         if(n != 0)
  346                 return n;
  347 
  348         /* compare offsets, call earlier ones more specific */
  349         n = (a->off+((int)a->skiphdr)*(ulong)ipoff->data) - 
  350                 (b->off+((int)b->skiphdr)*(ulong)ipoff->data);
  351         if(n != 0)
  352                 return n;
  353 
  354         /* compare match lengths, longer ones are more specific */
  355         n = b->len - a->len;
  356         if(n != 0)
  357                 return n;
  358 
  359         /*
  360          *  if we get here we have two entries matching
  361          *  the same bytes of the record.  Now check
  362          *  the mask for equality.  Longer masks are
  363          *  more specific.
  364          */
  365         if(a->mask != nil && b->mask == nil)
  366                 return -1;
  367         if(a->mask == nil && b->mask != nil)
  368                 return 1;
  369         if(a->mask != nil && b->mask != nil){
  370                 n = memcmp(b->mask, a->mask, a->len);
  371                 if(n != 0)
  372                         return n;
  373         }
  374         return 0;
  375 }
  376 
  377 /*
  378  *  Compare the values of two ipmuxs.  We're assuming that ipmuxcmp
  379  *  returned 0 comparing them.
  380  */
  381 static int
  382 ipmuxvalcmp(Ipmux *a, Ipmux *b)
  383 {
  384         int n;
  385 
  386         n = b->len*b->n - a->len*a->n;
  387         if(n != 0)
  388                 return n;
  389         return memcmp(a->val, b->val, a->len*a->n);
  390 } 
  391 
  392 /*
  393  *  add onto an existing ipmux chain in the canonical comparison
  394  *  order
  395  */
  396 static void
  397 ipmuxchain(Ipmux **l, Ipmux *f)
  398 {
  399         for(; *l; l = &(*l)->yes)
  400                 if(ipmuxcmp(f, *l) < 0)
  401                         break;
  402         f->yes = *l;
  403         *l = f;
  404 }
  405 
  406 /*
  407  *  copy a tree
  408  */
  409 static Ipmux*
  410 ipmuxcopy(Ipmux *f)
  411 {
  412         Ipmux *nf;
  413 
  414         if(f == nil)
  415                 return nil;
  416         nf = smalloc(sizeof *nf);
  417         *nf = *f;
  418         nf->no = ipmuxcopy(f->no);
  419         nf->yes = ipmuxcopy(f->yes);
  420         nf->val = smalloc(f->n*f->len);
  421         nf->e = nf->val + f->len*f->n;
  422         memmove(nf->val, f->val, f->n*f->len);
  423         return nf;
  424 }
  425 
  426 static void
  427 ipmuxfree(Ipmux *f)
  428 {
  429         if(f->val != nil)
  430                 free(f->val);
  431         free(f);
  432 }
  433 
  434 static void
  435 ipmuxtreefree(Ipmux *f)
  436 {
  437         if(f == nil)
  438                 return;
  439         if(f->no != nil)
  440                 ipmuxfree(f->no);
  441         if(f->yes != nil)
  442                 ipmuxfree(f->yes);
  443         ipmuxfree(f);
  444 }
  445 
  446 /*
  447  *  merge two trees
  448  */
  449 static Ipmux*
  450 ipmuxmerge(Ipmux *a, Ipmux *b)
  451 {
  452         int n;
  453         Ipmux *f;
  454 
  455         if(a == nil)
  456                 return b;
  457         if(b == nil)
  458                 return a;
  459         n = ipmuxcmp(a, b);
  460         if(n < 0){
  461                 f = ipmuxcopy(b);
  462                 a->yes = ipmuxmerge(a->yes, b);
  463                 a->no = ipmuxmerge(a->no, f);
  464                 return a;
  465         }
  466         if(n > 0){
  467                 f = ipmuxcopy(a);
  468                 b->yes = ipmuxmerge(b->yes, a);
  469                 b->no = ipmuxmerge(b->no, f);
  470                 return b;
  471         }
  472         if(ipmuxvalcmp(a, b) == 0){
  473                 a->yes = ipmuxmerge(a->yes, b->yes);
  474                 a->no = ipmuxmerge(a->no, b->no);
  475                 a->ref++;
  476                 ipmuxfree(b);
  477                 return a;
  478         }
  479         a->no = ipmuxmerge(a->no, b);
  480         return a;
  481 }
  482 
  483 /*
  484  *  remove a chain from a demux tree.  This is like merging accept that
  485  *  we remove instead of insert.
  486  */
  487 static int
  488 ipmuxremove(Ipmux **l, Ipmux *f)
  489 {
  490         int n, rv;
  491         Ipmux *ft;
  492 
  493         if(f == nil)
  494                 return 0;               /* we've removed it all */
  495         if(*l == nil)
  496                 return -1;
  497 
  498         ft = *l;
  499         n = ipmuxcmp(ft, f);
  500         if(n < 0){
  501                 /* *l is maching an earlier field, descend both paths */
  502                 rv = ipmuxremove(&ft->yes, f);
  503                 rv += ipmuxremove(&ft->no, f);
  504                 return rv;
  505         }
  506         if(n > 0){
  507                 /* f represents an earlier field than *l, this should be impossible */
  508                 return -1;
  509         }
  510 
  511         /* if we get here f and *l are comparing the same fields */
  512         if(ipmuxvalcmp(ft, f) != 0){
  513                 /* different values mean mutually exclusive */
  514                 return ipmuxremove(&ft->no, f);
  515         }
  516 
  517         /* we found a match */
  518         if(--(ft->ref) == 0){
  519                 /*
  520                  *  a dead node implies the whole yes side is also dead.
  521                  *  since our chain is constrained to be on that side,
  522                  *  we're done.
  523                  */
  524                 ipmuxtreefree(ft->yes);
  525                 *l = ft->no;
  526                 ipmuxfree(ft);
  527                 return 0;
  528         }
  529 
  530         /*
  531          *  free the rest of the chain.  it is constrained to match the
  532          *  yes side.
  533          */
  534         return ipmuxremove(&ft->yes, f->yes);
  535 }
  536 
  537 /*
  538  *  connection request is a semi separated list of filters
  539  *  e.g. proto=17;data[0:4]=11aa22bb;ifc=135.104.9.2&255.255.255.0
  540  *
  541  *  there's no protection against overlapping specs.
  542  */
  543 static char*
  544 ipmuxconnect(Conv *c, char **argv, int argc)
  545 {
  546         int i, n;
  547         char *field[10];
  548         Ipmux *mux, *chain;
  549         Ipmuxrock *r;
  550         Fs *f;
  551 
  552         f = c->p->f;
  553 
  554         if(argc != 2)
  555                 return Ebadarg;
  556 
  557         n = getfields(argv[1], field, nelem(field), 1, ";");
  558         if(n <= 0)
  559                 return Ebadarg;
  560 
  561         chain = nil;
  562         mux = nil;
  563         for(i = 0; i < n; i++){
  564                 mux = parsemux(field[i]);
  565                 if(mux == nil){
  566                         ipmuxtreefree(chain);
  567                         return Ebadarg;
  568                 }
  569                 ipmuxchain(&chain, mux);
  570         }
  571         if(chain == nil)
  572                 return Ebadarg;
  573         mux->conv = c;
  574 
  575         /* save a copy of the chain so we can later remove it */
  576         mux = ipmuxcopy(chain);
  577         r = (Ipmuxrock*)(c->ptcl);
  578         r->chain = chain;
  579 
  580         /* add the chain to the protocol demultiplexor tree */
  581         wlock(f);
  582         f->ipmux->priv = ipmuxmerge(f->ipmux->priv, mux);
  583         wunlock(f);
  584 
  585         Fsconnected(c, nil);
  586         return nil;
  587 }
  588 
  589 static int
  590 ipmuxstate(Conv *c, char *state, int n)
  591 {
  592         Ipmuxrock *r;
  593         
  594         r = (Ipmuxrock*)(c->ptcl);
  595         return ipmuxsprint(r->chain, 0, state, n);
  596 }
  597 
  598 static void
  599 ipmuxcreate(Conv *c)
  600 {
  601         Ipmuxrock *r;
  602 
  603         c->rq = qopen(64*1024, Qmsg, 0, c);
  604         c->wq = qopen(64*1024, Qkick, ipmuxkick, c);
  605         r = (Ipmuxrock*)(c->ptcl);
  606         r->chain = nil;
  607 }
  608 
  609 static char*
  610 ipmuxannounce(Conv*, char**, int)
  611 {
  612         return "ipmux does not support announce";
  613 }
  614 
  615 static void
  616 ipmuxclose(Conv *c)
  617 {
  618         Ipmuxrock *r;
  619         Fs *f = c->p->f;
  620 
  621         r = (Ipmuxrock*)(c->ptcl);
  622 
  623         qclose(c->rq);
  624         qclose(c->wq);
  625         qclose(c->eq);
  626         ipmove(c->laddr, IPnoaddr);
  627         ipmove(c->raddr, IPnoaddr);
  628         c->lport = 0;
  629         c->rport = 0;
  630 
  631         wlock(f);
  632         ipmuxremove(&(c->p->priv), r->chain);
  633         wunlock(f);
  634         ipmuxtreefree(r->chain);
  635         r->chain = nil;
  636 }
  637 
  638 /*
  639  *  takes a fully formed ip packet and just passes it down
  640  *  the stack
  641  */
  642 static void
  643 ipmuxkick(void *x)
  644 {
  645         Conv *c = x;
  646         Block *bp;
  647 
  648         bp = qget(c->wq);
  649         if(bp != nil) {
  650                 Myip4hdr *ih4 = (Myip4hdr*)(bp->rp);
  651 
  652                 if((ih4->vihl & 0xF0) != IP_VER6)
  653                         ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil);
  654                 else
  655                         ipoput6(c->p->f, bp, 0, ((Ip6hdr*)ih4)->ttl, 0, nil);
  656         }
  657 }
  658 
  659 static void
  660 ipmuxiput(Proto *p, Ipifc *ifc, Block *bp)
  661 {
  662         int len, hl;
  663         Fs *f = p->f;
  664         uchar *m, *h, *v, *e, *ve, *hp;
  665         Conv *c;
  666         Ipmux *mux;
  667         Myip4hdr *ip;
  668         Ip6hdr *ip6;
  669 
  670         ip = (Myip4hdr*)bp->rp;
  671         hl = (ip->vihl&0x0F)<<2;
  672 
  673         if(p->priv == nil)
  674                 goto nomatch;
  675 
  676         h = bp->rp;
  677         len = BLEN(bp);
  678 
  679         /* run the v4 filter */
  680         rlock(f);
  681         c = nil;
  682         mux = f->ipmux->priv;
  683         while(mux != nil){
  684                 if(mux->eoff > len){
  685                         mux = mux->no;
  686                         continue;
  687                 }
  688                 hp = h + mux->off + ((int)mux->skiphdr)*hl;
  689                 switch(mux->ctype){
  690                 case Cbyte:
  691                         if(*mux->val == *hp)
  692                                 goto yes;
  693                         break;
  694                 case Cmbyte:
  695                         if((*hp & *mux->mask) == *mux->val)
  696                                 goto yes;
  697                         break;
  698                 case Cshort:
  699                         if(*((ushort*)mux->val) == *(ushort*)hp)
  700                                 goto yes;
  701                         break;
  702                 case Cmshort:
  703                         if((*(ushort*)hp & (*((ushort*)mux->mask))) == *((ushort*)mux->val))
  704                                 goto yes;
  705                         break;
  706                 case Clong:
  707                         if(*((ulong*)mux->val) == *(ulong*)hp)
  708                                 goto yes;
  709                         break;
  710                 case Cmlong:
  711                         if((*(ulong*)hp & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
  712                                 goto yes;
  713                         break;
  714                 case Cifc:
  715                         if(*((ulong*)mux->val) == *(ulong*)(ifc->lifc->local + IPv4off))
  716                                 goto yes;
  717                         break;
  718                 case Cmifc:
  719                         if((*(ulong*)(ifc->lifc->local + IPv4off) & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
  720                                 goto yes;
  721                         break;
  722                 default:
  723                         v = mux->val;
  724                         for(e = mux->e; v < e; v = ve){
  725                                 m = mux->mask;
  726                                 hp = h + mux->off;
  727                                 for(ve = v + mux->len; v < ve; v++){
  728                                         if((*hp++ & *m++) != *v)
  729                                                 break;
  730                                 }
  731                                 if(v == ve)
  732                                         goto yes;
  733                         }
  734                 }
  735                 mux = mux->no;
  736                 continue;
  737 yes:
  738                 if(mux->conv != nil)
  739                         c = mux->conv;
  740                 mux = mux->yes;
  741         }
  742         runlock(f);
  743 
  744         if(c != nil){
  745                 /* tack on interface address */
  746                 bp = padblock(bp, IPaddrlen);
  747                 ipmove(bp->rp, ifc->lifc->local);
  748                 bp = concatblock(bp);
  749                 if(bp != nil)
  750                         if(qpass(c->rq, bp) < 0)
  751                                 print("Q");
  752                 return;
  753         }
  754 
  755 nomatch:
  756         /* doesn't match any filter, hand it to the specific protocol handler */
  757         ip = (Myip4hdr*)bp->rp;
  758         if((ip->vihl & 0xF0) == IP_VER4) {
  759                 p = f->t2p[ip->proto];
  760         } else {
  761                 ip6 = (Ip6hdr*)bp->rp;
  762                 p = f->t2p[ip6->proto];
  763         }
  764         if(p && p->rcv)
  765                 (*p->rcv)(p, ifc, bp);
  766         else
  767                 freeblist(bp);
  768         return;
  769 }
  770 
  771 static int
  772 ipmuxsprint(Ipmux *mux, int level, char *buf, int len)
  773 {
  774         int i, j, n;
  775         uchar *v;
  776 
  777         n = 0;
  778         for(i = 0; i < level; i++)
  779                 n += snprint(buf+n, len-n, " ");
  780         if(mux == nil){
  781                 n += snprint(buf+n, len-n, "\n");
  782                 return n;
  783         }
  784         n += snprint(buf+n, len-n, "h[%d:%d]&", 
  785                mux->off+((int)mux->skiphdr)*((int)ipoff->data), 
  786                mux->off+(((int)mux->skiphdr)*((int)ipoff->data))+mux->len-1);
  787         for(i = 0; i < mux->len; i++)
  788                 n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);
  789         n += snprint(buf+n, len-n, "=");
  790         v = mux->val;
  791         for(j = 0; j < mux->n; j++){
  792                 for(i = 0; i < mux->len; i++)
  793                         n += snprint(buf+n, len - n, "%2.2ux", *v++);
  794                 n += snprint(buf+n, len-n, "|");
  795         }
  796         n += snprint(buf+n, len-n, "\n");
  797         level++;
  798         n += ipmuxsprint(mux->no, level, buf+n, len-n);
  799         n += ipmuxsprint(mux->yes, level, buf+n, len-n);
  800         return n;
  801 }
  802 
  803 static int
  804 ipmuxstats(Proto *p, char *buf, int len)
  805 {
  806         int n;
  807         Fs *f = p->f;
  808 
  809         rlock(f);
  810         n = ipmuxsprint(p->priv, 0, buf, len);
  811         runlock(f);
  812 
  813         return n;
  814 }
  815 
  816 void
  817 ipmuxinit(Fs *f)
  818 {
  819         Proto *ipmux;
  820 
  821         ipmux = smalloc(sizeof(Proto));
  822         ipmux->priv = nil;
  823         ipmux->name = "ipmux";
  824         ipmux->connect = ipmuxconnect;
  825         ipmux->announce = ipmuxannounce;
  826         ipmux->state = ipmuxstate;
  827         ipmux->create = ipmuxcreate;
  828         ipmux->close = ipmuxclose;
  829         ipmux->rcv = ipmuxiput;
  830         ipmux->ctl = nil;
  831         ipmux->advise = nil;
  832         ipmux->stats = ipmuxstats;
  833         ipmux->ipproto = -1;
  834         ipmux->nc = 64;
  835         ipmux->ptclsize = sizeof(Ipmuxrock);
  836 
  837         f->ipmux = ipmux;                       /* hack for Fsrcvpcol */
  838 
  839         Fsproto(f, ipmux);
  840 }

Cache object: 5078873cfb938352295e6e77c968d2a2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.