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/port/netif.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "../port/error.h"
    7 #include        "../port/netif.h"
    8 
    9 static int netown(Netfile*, char*, int);
   10 static int openfile(Netif*, int);
   11 static char* matchtoken(char*, char*);
   12 static char* netmulti(Netif*, Netfile*, uchar*, int);
   13 static int parseaddr(uchar*, char*, int);
   14 
   15 /*
   16  *  set up a new network interface
   17  */
   18 void
   19 netifinit(Netif *nif, char *name, int nfile, ulong limit)
   20 {
   21         strncpy(nif->name, name, KNAMELEN-1);
   22         nif->name[KNAMELEN-1] = 0;
   23         nif->nfile = nfile;
   24         nif->f = xalloc(nfile*sizeof(Netfile*));
   25         if (nif->f == nil)
   26                 panic("netifinit: no memory");
   27         memset(nif->f, 0, nfile*sizeof(Netfile*));
   28         nif->limit = limit;
   29 }
   30 
   31 /*
   32  *  generate a 3 level directory
   33  */
   34 static int
   35 netifgen(Chan *c, char*, Dirtab *vp, int, int i, Dir *dp)
   36 {
   37         Qid q;
   38         Netif *nif = (Netif*)vp;
   39         Netfile *f;
   40         int t;
   41         int perm;
   42         char *o;
   43 
   44         q.type = QTFILE;
   45         q.vers = 0;
   46 
   47         /* top level directory contains the name of the network */
   48         if(c->qid.path == 0){
   49                 switch(i){
   50                 case DEVDOTDOT:
   51                         q.path = 0;
   52                         q.type = QTDIR;
   53                         devdir(c, q, ".", 0, eve, 0555, dp);
   54                         break;
   55                 case 0:
   56                         q.path = N2ndqid;
   57                         q.type = QTDIR;
   58                         strcpy(up->genbuf, nif->name);
   59                         devdir(c, q, up->genbuf, 0, eve, 0555, dp);
   60                         break;
   61                 default:
   62                         return -1;
   63                 }
   64                 return 1;
   65         }
   66 
   67         /* second level contains clone plus all the conversations */
   68         t = NETTYPE(c->qid.path);
   69         if(t == N2ndqid || t == Ncloneqid || t == Naddrqid){
   70                 switch(i) {
   71                 case DEVDOTDOT:
   72                         q.type = QTDIR;
   73                         q.path = 0;
   74                         devdir(c, q, ".", 0, eve, DMDIR|0555, dp);
   75                         break;
   76                 case 0:
   77                         q.path = Ncloneqid;
   78                         devdir(c, q, "clone", 0, eve, 0666, dp);
   79                         break;
   80                 case 1:
   81                         q.path = Naddrqid;
   82                         devdir(c, q, "addr", 0, eve, 0666, dp);
   83                         break;
   84                 case 2:
   85                         q.path = Nstatqid;
   86                         devdir(c, q, "stats", 0, eve, 0444, dp);
   87                         break;
   88                 case 3:
   89                         q.path = Nifstatqid;
   90                         devdir(c, q, "ifstats", 0, eve, 0444, dp);
   91                         break;
   92                 default:
   93                         i -= 4;
   94                         if(i >= nif->nfile)
   95                                 return -1;
   96                         if(nif->f[i] == 0)
   97                                 return 0;
   98                         q.type = QTDIR;
   99                         q.path = NETQID(i, N3rdqid);
  100                         sprint(up->genbuf, "%d", i);
  101                         devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp);
  102                         break;
  103                 }
  104                 return 1;
  105         }
  106 
  107         /* third level */
  108         f = nif->f[NETID(c->qid.path)];
  109         if(f == 0)
  110                 return 0;
  111         if(*f->owner){
  112                 o = f->owner;
  113                 perm = f->mode;
  114         } else {
  115                 o = eve;
  116                 perm = 0666;
  117         }
  118         switch(i){
  119         case DEVDOTDOT:
  120                 q.type = QTDIR;
  121                 q.path = N2ndqid;
  122                 strcpy(up->genbuf, nif->name);
  123                 devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp);
  124                 break;
  125         case 0:
  126                 q.path = NETQID(NETID(c->qid.path), Ndataqid);
  127                 devdir(c, q, "data", 0, o, perm, dp);
  128                 break;
  129         case 1:
  130                 q.path = NETQID(NETID(c->qid.path), Nctlqid);
  131                 devdir(c, q, "ctl", 0, o, perm, dp);
  132                 break;
  133         case 2:
  134                 q.path = NETQID(NETID(c->qid.path), Nstatqid);
  135                 devdir(c, q, "stats", 0, eve, 0444, dp);
  136                 break;
  137         case 3:
  138                 q.path = NETQID(NETID(c->qid.path), Ntypeqid);
  139                 devdir(c, q, "type", 0, eve, 0444, dp);
  140                 break;
  141         case 4:
  142                 q.path = NETQID(NETID(c->qid.path), Nifstatqid);
  143                 devdir(c, q, "ifstats", 0, eve, 0444, dp);
  144                 break;
  145         default:
  146                 return -1;
  147         }
  148         return 1;
  149 }
  150 
  151 Walkqid*
  152 netifwalk(Netif *nif, Chan *c, Chan *nc, char **name, int nname)
  153 {
  154         return devwalk(c, nc, name, nname, (Dirtab *)nif, 0, netifgen);
  155 }
  156 
  157 Chan*
  158 netifopen(Netif *nif, Chan *c, int omode)
  159 {
  160         int id;
  161         Netfile *f;
  162 
  163         id = 0;
  164         if(c->qid.type & QTDIR){
  165                 if(omode != OREAD)
  166                         error(Eperm);
  167         } else {
  168                 switch(NETTYPE(c->qid.path)){
  169                 case Ndataqid:
  170                 case Nctlqid:
  171                         id = NETID(c->qid.path);
  172                         openfile(nif, id);
  173                         break;
  174                 case Ncloneqid:
  175                         id = openfile(nif, -1);
  176                         c->qid.path = NETQID(id, Nctlqid);
  177                         break;
  178                 default:
  179                         if(omode != OREAD)
  180                                 error(Ebadarg);
  181                 }
  182                 switch(NETTYPE(c->qid.path)){
  183                 case Ndataqid:
  184                 case Nctlqid:
  185                         f = nif->f[id];
  186                         if(netown(f, up->user, omode&7) < 0)
  187                                 error(Eperm);
  188                         break;
  189                 }
  190         }
  191         c->mode = openmode(omode);
  192         c->flag |= COPEN;
  193         c->offset = 0;
  194         c->iounit = qiomaxatomic;
  195         return c;
  196 }
  197 
  198 long
  199 netifread(Netif *nif, Chan *c, void *a, long n, ulong offset)
  200 {
  201         int i, j;
  202         Netfile *f;
  203         char *p;
  204 
  205         if(c->qid.type&QTDIR)
  206                 return devdirread(c, a, n, (Dirtab*)nif, 0, netifgen);
  207 
  208         switch(NETTYPE(c->qid.path)){
  209         case Ndataqid:
  210                 f = nif->f[NETID(c->qid.path)];
  211                 return qread(f->in, a, n);
  212         case Nctlqid:
  213                 return readnum(offset, a, n, NETID(c->qid.path), NUMSIZE);
  214         case Nstatqid:
  215                 p = malloc(READSTR);
  216                 j = snprint(p, READSTR, "in: %llud\n", nif->inpackets);
  217                 j += snprint(p+j, READSTR-j, "link: %d\n", nif->link);
  218                 j += snprint(p+j, READSTR-j, "out: %llud\n", nif->outpackets);
  219                 j += snprint(p+j, READSTR-j, "crc errs: %d\n", nif->crcs);
  220                 j += snprint(p+j, READSTR-j, "overflows: %d\n", nif->overflows);
  221                 j += snprint(p+j, READSTR-j, "soft overflows: %d\n", nif->soverflows);
  222                 j += snprint(p+j, READSTR-j, "framing errs: %d\n", nif->frames);
  223                 j += snprint(p+j, READSTR-j, "buffer errs: %d\n", nif->buffs);
  224                 j += snprint(p+j, READSTR-j, "output errs: %d\n", nif->oerrs);
  225                 j += snprint(p+j, READSTR-j, "prom: %d\n", nif->prom);
  226                 j += snprint(p+j, READSTR-j, "mbps: %d\n", nif->mbps);
  227                 j += snprint(p+j, READSTR-j, "addr: ");
  228                 for(i = 0; i < nif->alen; i++)
  229                         j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);
  230                 snprint(p+j, READSTR-j, "\n");
  231                 n = readstr(offset, a, n, p);
  232                 free(p);
  233                 return n;
  234         case Naddrqid:
  235                 p = malloc(READSTR);
  236                 j = 0;
  237                 for(i = 0; i < nif->alen; i++)
  238                         j += snprint(p+j, READSTR-j, "%2.2ux", nif->addr[i]);
  239                 n = readstr(offset, a, n, p);
  240                 free(p);
  241                 return n;
  242         case Ntypeqid:
  243                 f = nif->f[NETID(c->qid.path)];
  244                 return readnum(offset, a, n, f->type, NUMSIZE);
  245         case Nifstatqid:
  246                 return 0;
  247         }
  248         error(Ebadarg);
  249         return -1;      /* not reached */
  250 }
  251 
  252 Block*
  253 netifbread(Netif *nif, Chan *c, long n, ulong offset)
  254 {
  255         if((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
  256                 return devbread(c, n, offset);
  257 
  258         return qbread(nif->f[NETID(c->qid.path)]->in, n);
  259 }
  260 
  261 /*
  262  *  make sure this type isn't already in use on this device
  263  */
  264 static int
  265 typeinuse(Netif *nif, int type)
  266 {
  267         Netfile *f, **fp, **efp;
  268 
  269         if(type <= 0)
  270                 return 0;
  271 
  272         efp = &nif->f[nif->nfile];
  273         for(fp = nif->f; fp < efp; fp++){
  274                 f = *fp;
  275                 if(f == 0)
  276                         continue;
  277                 if(f->type == type)
  278                         return 1;
  279         }
  280         return 0;
  281 }
  282 
  283 /*
  284  *  the devxxx.c that calls us handles writing data, it knows best
  285  */
  286 long
  287 netifwrite(Netif *nif, Chan *c, void *a, long n)
  288 {
  289         Netfile *f;
  290         int type;
  291         char *p, buf[64];
  292         uchar binaddr[Nmaxaddr];
  293 
  294         if(NETTYPE(c->qid.path) != Nctlqid)
  295                 error(Eperm);
  296 
  297         if(n >= sizeof(buf))
  298                 n = sizeof(buf)-1;
  299         memmove(buf, a, n);
  300         buf[n] = 0;
  301 
  302         if(waserror()){
  303                 qunlock(nif);
  304                 nexterror();
  305         }
  306 
  307         qlock(nif);
  308         f = nif->f[NETID(c->qid.path)];
  309         if((p = matchtoken(buf, "connect")) != 0){
  310                 type = atoi(p);
  311                 if(typeinuse(nif, type))
  312                         error(Einuse);
  313                 f->type = type;
  314                 if(f->type < 0)
  315                         nif->all++;
  316         } else if(matchtoken(buf, "promiscuous")){
  317                 if(f->prom == 0){
  318                         if(nif->prom == 0 && nif->promiscuous != nil)
  319                                 nif->promiscuous(nif->arg, 1);
  320                         f->prom = 1;
  321                         nif->prom++;
  322                 }
  323         } else if((p = matchtoken(buf, "scanbs")) != 0){
  324                 /* scan for base stations */
  325                 if(f->scan == 0){
  326                         type = atoi(p);
  327                         if(type < 5)
  328                                 type = 5;
  329                         if(nif->scanbs != nil)
  330                                 nif->scanbs(nif->arg, type);
  331                         f->scan = type;
  332                         nif->scan++;
  333                 }
  334         } else if(matchtoken(buf, "bridge")){
  335                 f->bridge = 1;
  336         } else if(matchtoken(buf, "headersonly")){
  337                 f->headersonly = 1;
  338         } else if((p = matchtoken(buf, "addmulti")) != 0){
  339                 if(parseaddr(binaddr, p, nif->alen) < 0)
  340                         error("bad address");
  341                 p = netmulti(nif, f, binaddr, 1);
  342                 if(p)
  343                         error(p);
  344         } else if((p = matchtoken(buf, "remmulti")) != 0){
  345                 if(parseaddr(binaddr, p, nif->alen) < 0)
  346                         error("bad address");
  347                 p = netmulti(nif, f, binaddr, 0);
  348                 if(p)
  349                         error(p);
  350         } else
  351                 n = -1;
  352         qunlock(nif);
  353         poperror();
  354         return n;
  355 }
  356 
  357 int
  358 netifwstat(Netif *nif, Chan *c, uchar *db, int n)
  359 {
  360         Dir *dir;
  361         Netfile *f;
  362         int m;
  363 
  364         f = nif->f[NETID(c->qid.path)];
  365         if(f == 0)
  366                 error(Enonexist);
  367 
  368         if(netown(f, up->user, OWRITE) < 0)
  369                 error(Eperm);
  370 
  371         dir = smalloc(sizeof(Dir)+n);
  372         m = convM2D(db, n, &dir[0], (char*)&dir[1]);
  373         if(m == 0){
  374                 free(dir);
  375                 error(Eshortstat);
  376         }
  377         if(!emptystr(dir[0].uid))
  378                 strncpy(f->owner, dir[0].uid, KNAMELEN);
  379         if(dir[0].mode != ~0UL)
  380                 f->mode = dir[0].mode;
  381         free(dir);
  382         return m;
  383 }
  384 
  385 int
  386 netifstat(Netif *nif, Chan *c, uchar *db, int n)
  387 {
  388         return devstat(c, db, n, (Dirtab *)nif, 0, netifgen);
  389 }
  390 
  391 void
  392 netifclose(Netif *nif, Chan *c)
  393 {
  394         Netfile *f;
  395         int t;
  396         Netaddr *ap;
  397 
  398         if((c->flag & COPEN) == 0)
  399                 return;
  400 
  401         t = NETTYPE(c->qid.path);
  402         if(t != Ndataqid && t != Nctlqid)
  403                 return;
  404 
  405         f = nif->f[NETID(c->qid.path)];
  406         qlock(f);
  407         if(--(f->inuse) == 0){
  408                 if(f->prom){
  409                         qlock(nif);
  410                         if(--(nif->prom) == 0 && nif->promiscuous != nil)
  411                                 nif->promiscuous(nif->arg, 0);
  412                         qunlock(nif);
  413                         f->prom = 0;
  414                 }
  415                 if(f->scan){
  416                         qlock(nif);
  417                         if(--(nif->scan) == 0 && nif->scanbs != nil)
  418                                 nif->scanbs(nif->arg, 0);
  419                         qunlock(nif);
  420                         f->prom = 0;
  421                         f->scan = 0;
  422                 }
  423                 if(f->nmaddr){
  424                         qlock(nif);
  425                         t = 0;
  426                         for(ap = nif->maddr; ap; ap = ap->next){
  427                                 if(f->maddr[t/8] & (1<<(t%8)))
  428                                         netmulti(nif, f, ap->addr, 0);
  429                         }
  430                         qunlock(nif);
  431                         f->nmaddr = 0;
  432                 }
  433                 if(f->type < 0){
  434                         qlock(nif);
  435                         --(nif->all);
  436                         qunlock(nif);
  437                 }
  438                 f->owner[0] = 0;
  439                 f->type = 0;
  440                 f->bridge = 0;
  441                 f->headersonly = 0;
  442                 qclose(f->in);
  443         }
  444         qunlock(f);
  445 }
  446 
  447 Lock netlock;
  448 
  449 static int
  450 netown(Netfile *p, char *o, int omode)
  451 {
  452         static int access[] = { 0400, 0200, 0600, 0100 };
  453         int mode;
  454         int t;
  455 
  456         lock(&netlock);
  457         if(*p->owner){
  458                 if(strncmp(o, p->owner, KNAMELEN) == 0) /* User */
  459                         mode = p->mode;
  460                 else if(strncmp(o, eve, KNAMELEN) == 0) /* Bootes is group */
  461                         mode = p->mode<<3;
  462                 else
  463                         mode = p->mode<<6;              /* Other */
  464 
  465                 t = access[omode&3];
  466                 if((t & mode) == t){
  467                         unlock(&netlock);
  468                         return 0;
  469                 } else {
  470                         unlock(&netlock);
  471                         return -1;
  472                 }
  473         }
  474         strncpy(p->owner, o, KNAMELEN);
  475         p->mode = 0660;
  476         unlock(&netlock);
  477         return 0;
  478 }
  479 
  480 /*
  481  *  Increment the reference count of a network device.
  482  *  If id < 0, return an unused ether device.
  483  */
  484 static int
  485 openfile(Netif *nif, int id)
  486 {
  487         Netfile *f, **fp, **efp;
  488 
  489         if(id >= 0){
  490                 f = nif->f[id];
  491                 if(f == 0)
  492                         error(Enodev);
  493                 qlock(f);
  494                 qreopen(f->in);
  495                 f->inuse++;
  496                 qunlock(f);
  497                 return id;
  498         }
  499 
  500         qlock(nif);
  501         if(waserror()){
  502                 qunlock(nif);
  503                 nexterror();
  504         }
  505         efp = &nif->f[nif->nfile];
  506         for(fp = nif->f; fp < efp; fp++){
  507                 f = *fp;
  508                 if(f == 0){
  509                         f = malloc(sizeof(Netfile));
  510                         if(f == 0)
  511                                 exhausted("memory");
  512                         f->in = qopen(nif->limit, Qmsg, 0, 0);
  513                         if(f->in == nil){
  514                                 free(f);
  515                                 exhausted("memory");
  516                         }
  517                         *fp = f;
  518                         qlock(f);
  519                 } else {
  520                         qlock(f);
  521                         if(f->inuse){
  522                                 qunlock(f);
  523                                 continue;
  524                         }
  525                 }
  526                 f->inuse = 1;
  527                 qreopen(f->in);
  528                 netown(f, up->user, 0);
  529                 qunlock(f);
  530                 qunlock(nif);
  531                 poperror();
  532                 return fp - nif->f;
  533         }
  534         error(Enodev);
  535         return -1;      /* not reached */
  536 }
  537 
  538 /*
  539  *  look for a token starting a string,
  540  *  return a pointer to first non-space char after it
  541  */
  542 static char*
  543 matchtoken(char *p, char *token)
  544 {
  545         int n;
  546 
  547         n = strlen(token);
  548         if(strncmp(p, token, n))
  549                 return 0;
  550         p += n;
  551         if(*p == 0)
  552                 return p;
  553         if(*p != ' ' && *p != '\t' && *p != '\n')
  554                 return 0;
  555         while(*p == ' ' || *p == '\t' || *p == '\n')
  556                 p++;
  557         return p;
  558 }
  559 
  560 void
  561 hnputv(void *p, uvlong v)
  562 {
  563         uchar *a;
  564 
  565         a = p;
  566         hnputl(a, v>>32);
  567         hnputl(a+4, v);
  568 }
  569 
  570 void
  571 hnputl(void *p, uint v)
  572 {
  573         uchar *a;
  574 
  575         a = p;
  576         a[0] = v>>24;
  577         a[1] = v>>16;
  578         a[2] = v>>8;
  579         a[3] = v;
  580 }
  581 
  582 void
  583 hnputs(void *p, ushort v)
  584 {
  585         uchar *a;
  586 
  587         a = p;
  588         a[0] = v>>8;
  589         a[1] = v;
  590 }
  591 
  592 uvlong
  593 nhgetv(void *p)
  594 {
  595         uchar *a;
  596 
  597         a = p;
  598         return ((vlong)nhgetl(a) << 32) | nhgetl(a+4);
  599 }
  600 
  601 uint
  602 nhgetl(void *p)
  603 {
  604         uchar *a;
  605 
  606         a = p;
  607         return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
  608 }
  609 
  610 ushort
  611 nhgets(void *p)
  612 {
  613         uchar *a;
  614 
  615         a = p;
  616         return (a[0]<<8)|(a[1]<<0);
  617 }
  618 
  619 static ulong
  620 hash(uchar *a, int len)
  621 {
  622         ulong sum = 0;
  623 
  624         while(len-- > 0)
  625                 sum = (sum << 1) + *a++;
  626         return sum%Nmhash;
  627 }
  628 
  629 int
  630 activemulti(Netif *nif, uchar *addr, int alen)
  631 {
  632         Netaddr *hp;
  633 
  634         for(hp = nif->mhash[hash(addr, alen)]; hp; hp = hp->hnext)
  635                 if(memcmp(addr, hp->addr, alen) == 0){
  636                         if(hp->ref)
  637                                 return 1;
  638                         else
  639                                 break;
  640                 }
  641         return 0;
  642 }
  643 
  644 static int
  645 parseaddr(uchar *to, char *from, int alen)
  646 {
  647         char nip[4];
  648         char *p;
  649         int i;
  650 
  651         p = from;
  652         for(i = 0; i < alen; i++){
  653                 if(*p == 0)
  654                         return -1;
  655                 nip[0] = *p++;
  656                 if(*p == 0)
  657                         return -1;
  658                 nip[1] = *p++;
  659                 nip[2] = 0;
  660                 to[i] = strtoul(nip, 0, 16);
  661                 if(*p == ':')
  662                         p++;
  663         }
  664         return 0;
  665 }
  666 
  667 /*
  668  *  keep track of multicast addresses
  669  */
  670 static char*
  671 netmulti(Netif *nif, Netfile *f, uchar *addr, int add)
  672 {
  673         Netaddr **l, *ap;
  674         int i;
  675         ulong h;
  676 
  677         if(nif->multicast == nil)
  678                 return "interface does not support multicast";
  679 
  680         l = &nif->maddr;
  681         i = 0;
  682         for(ap = *l; ap; ap = *l){
  683                 if(memcmp(addr, ap->addr, nif->alen) == 0)
  684                         break;
  685                 i++;
  686                 l = &ap->next;
  687         }
  688 
  689         if(add){
  690                 if(ap == 0){
  691                         *l = ap = smalloc(sizeof(*ap));
  692                         memmove(ap->addr, addr, nif->alen);
  693                         ap->next = 0;
  694                         ap->ref = 1;
  695                         h = hash(addr, nif->alen);
  696                         ap->hnext = nif->mhash[h];
  697                         nif->mhash[h] = ap;
  698                 } else {
  699                         ap->ref++;
  700                 }
  701                 if(ap->ref == 1){
  702                         nif->nmaddr++;
  703                         nif->multicast(nif->arg, addr, 1);
  704                 }
  705                 if(i < 8*sizeof(f->maddr)){
  706                         if((f->maddr[i/8] & (1<<(i%8))) == 0)
  707                                 f->nmaddr++;
  708                         f->maddr[i/8] |= 1<<(i%8);
  709                 }
  710         } else {
  711                 if(ap == 0 || ap->ref == 0)
  712                         return 0;
  713                 ap->ref--;
  714                 if(ap->ref == 0){
  715                         nif->nmaddr--;
  716                         nif->multicast(nif->arg, addr, 0);
  717                 }
  718                 if(i < 8*sizeof(f->maddr)){
  719                         if((f->maddr[i/8] & (1<<(i%8))) != 0)
  720                                 f->nmaddr--;
  721                         f->maddr[i/8] &= ~(1<<(i%8));
  722                 }
  723         }
  724         return 0;
  725 }

Cache object: f4638837519c51411255ff3e7c711206


[ 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.