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/net/bpf_filter.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 /*
    2  * Copyright (c) 1990, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from the Stanford/CMU enet packet filter,
    6  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
    7  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
    8  * Berkeley Laboratory.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)bpf_filter.c        8.1 (Berkeley) 6/10/93
   39  *
   40  * $FreeBSD: src/sys/net/bpf_filter.c,v 1.6.4.1 1999/09/05 08:17:28 peter Exp $
   41  */
   42 
   43 #include <sys/param.h>
   44 #include <sys/types.h>
   45 #include <sys/time.h>
   46 
   47 #ifdef sun
   48 #include <netinet/in.h>
   49 #endif
   50 
   51 #if defined(sparc) || defined(mips) || defined(ibm032)
   52 #define BPF_ALIGN
   53 #endif
   54 
   55 #ifndef BPF_ALIGN
   56 #define EXTRACT_SHORT(p)        ((u_short)ntohs(*(u_short *)p))
   57 #define EXTRACT_LONG(p)         (ntohl(*(u_long *)p))
   58 #else
   59 #define EXTRACT_SHORT(p)\
   60         ((u_short)\
   61                 ((u_short)*((u_char *)p+0)<<8|\
   62                  (u_short)*((u_char *)p+1)<<0))
   63 #define EXTRACT_LONG(p)\
   64                 ((u_long)*((u_char *)p+0)<<24|\
   65                  (u_long)*((u_char *)p+1)<<16|\
   66                  (u_long)*((u_char *)p+2)<<8|\
   67                  (u_long)*((u_char *)p+3)<<0)
   68 #endif
   69 
   70 #ifdef KERNEL
   71 #include <sys/mbuf.h>
   72 #define MINDEX(m, k) \
   73 { \
   74         register int len = m->m_len; \
   75  \
   76         while (k >= len) { \
   77                 k -= len; \
   78                 m = m->m_next; \
   79                 if (m == 0) \
   80                         return 0; \
   81                 len = m->m_len; \
   82         } \
   83 }
   84 
   85 static int      m_xhalf __P((struct mbuf *m, int k, int *err));
   86 static int      m_xword __P((struct mbuf *m, int k, int *err));
   87 
   88 static int
   89 m_xword(m, k, err)
   90         register struct mbuf *m;
   91         register int k, *err;
   92 {
   93         register int len;
   94         register u_char *cp, *np;
   95         register struct mbuf *m0;
   96 
   97         len = m->m_len;
   98         while (k >= len) {
   99                 k -= len;
  100                 m = m->m_next;
  101                 if (m == 0)
  102                         goto bad;
  103                 len = m->m_len;
  104         }
  105         cp = mtod(m, u_char *) + k;
  106         if (len - k >= 4) {
  107                 *err = 0;
  108                 return EXTRACT_LONG(cp);
  109         }
  110         m0 = m->m_next;
  111         if (m0 == 0 || m0->m_len + len - k < 4)
  112                 goto bad;
  113         *err = 0;
  114         np = mtod(m0, u_char *);
  115         switch (len - k) {
  116 
  117         case 1:
  118                 return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
  119 
  120         case 2:
  121                 return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) |
  122                         np[1];
  123 
  124         default:
  125                 return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) |
  126                         np[0];
  127         }
  128     bad:
  129         *err = 1;
  130         return 0;
  131 }
  132 
  133 static int
  134 m_xhalf(m, k, err)
  135         register struct mbuf *m;
  136         register int k, *err;
  137 {
  138         register int len;
  139         register u_char *cp;
  140         register struct mbuf *m0;
  141 
  142         len = m->m_len;
  143         while (k >= len) {
  144                 k -= len;
  145                 m = m->m_next;
  146                 if (m == 0)
  147                         goto bad;
  148                 len = m->m_len;
  149         }
  150         cp = mtod(m, u_char *) + k;
  151         if (len - k >= 2) {
  152                 *err = 0;
  153                 return EXTRACT_SHORT(cp);
  154         }
  155         m0 = m->m_next;
  156         if (m0 == 0)
  157                 goto bad;
  158         *err = 0;
  159         return (cp[0] << 8) | mtod(m0, u_char *)[0];
  160  bad:
  161         *err = 1;
  162         return 0;
  163 }
  164 #endif
  165 
  166 #include <net/bpf.h>
  167 /*
  168  * Execute the filter program starting at pc on the packet p
  169  * wirelen is the length of the original packet
  170  * buflen is the amount of data present
  171  */
  172 u_int
  173 bpf_filter(pc, p, wirelen, buflen)
  174         register struct bpf_insn *pc;
  175         register u_char *p;
  176         u_int wirelen;
  177         register u_int buflen;
  178 {
  179         register u_long A = 0, X = 0;
  180         register int k;
  181         long mem[BPF_MEMWORDS];
  182 
  183         if (pc == 0)
  184                 /*
  185                  * No filter means accept all.
  186                  */
  187                 return (u_int)-1;
  188 
  189         --pc;
  190         while (1) {
  191                 ++pc;
  192                 switch (pc->code) {
  193 
  194                 default:
  195 #ifdef KERNEL
  196                         return 0;
  197 #else
  198                         abort();
  199 #endif
  200                 case BPF_RET|BPF_K:
  201                         return (u_int)pc->k;
  202 
  203                 case BPF_RET|BPF_A:
  204                         return (u_int)A;
  205 
  206                 case BPF_LD|BPF_W|BPF_ABS:
  207                         k = pc->k;
  208                         if (k + sizeof(long) > buflen) {
  209 #ifdef KERNEL
  210                                 int merr;
  211 
  212                                 if (buflen != 0)
  213                                         return 0;
  214                                 A = m_xword((struct mbuf *)p, k, &merr);
  215                                 if (merr != 0)
  216                                         return 0;
  217                                 continue;
  218 #else
  219                                 return 0;
  220 #endif
  221                         }
  222 #ifdef BPF_ALIGN
  223                         if (((int)(p + k) & 3) != 0)
  224                                 A = EXTRACT_LONG(&p[k]);
  225                         else
  226 #endif
  227                                 A = ntohl(*(long *)(p + k));
  228                         continue;
  229 
  230                 case BPF_LD|BPF_H|BPF_ABS:
  231                         k = pc->k;
  232                         if (k + sizeof(short) > buflen) {
  233 #ifdef KERNEL
  234                                 int merr;
  235 
  236                                 if (buflen != 0)
  237                                         return 0;
  238                                 A = m_xhalf((struct mbuf *)p, k, &merr);
  239                                 continue;
  240 #else
  241                                 return 0;
  242 #endif
  243                         }
  244                         A = EXTRACT_SHORT(&p[k]);
  245                         continue;
  246 
  247                 case BPF_LD|BPF_B|BPF_ABS:
  248                         k = pc->k;
  249                         if (k >= buflen) {
  250 #ifdef KERNEL
  251                                 register struct mbuf *m;
  252 
  253                                 if (buflen != 0)
  254                                         return 0;
  255                                 m = (struct mbuf *)p;
  256                                 MINDEX(m, k);
  257                                 A = mtod(m, u_char *)[k];
  258                                 continue;
  259 #else
  260                                 return 0;
  261 #endif
  262                         }
  263                         A = p[k];
  264                         continue;
  265 
  266                 case BPF_LD|BPF_W|BPF_LEN:
  267                         A = wirelen;
  268                         continue;
  269 
  270                 case BPF_LDX|BPF_W|BPF_LEN:
  271                         X = wirelen;
  272                         continue;
  273 
  274                 case BPF_LD|BPF_W|BPF_IND:
  275                         k = X + pc->k;
  276                         if (k + sizeof(long) > buflen) {
  277 #ifdef KERNEL
  278                                 int merr;
  279 
  280                                 if (buflen != 0)
  281                                         return 0;
  282                                 A = m_xword((struct mbuf *)p, k, &merr);
  283                                 if (merr != 0)
  284                                         return 0;
  285                                 continue;
  286 #else
  287                                 return 0;
  288 #endif
  289                         }
  290 #ifdef BPF_ALIGN
  291                         if (((int)(p + k) & 3) != 0)
  292                                 A = EXTRACT_LONG(&p[k]);
  293                         else
  294 #endif
  295                                 A = ntohl(*(long *)(p + k));
  296                         continue;
  297 
  298                 case BPF_LD|BPF_H|BPF_IND:
  299                         k = X + pc->k;
  300                         if (k + sizeof(short) > buflen) {
  301 #ifdef KERNEL
  302                                 int merr;
  303 
  304                                 if (buflen != 0)
  305                                         return 0;
  306                                 A = m_xhalf((struct mbuf *)p, k, &merr);
  307                                 if (merr != 0)
  308                                         return 0;
  309                                 continue;
  310 #else
  311                                 return 0;
  312 #endif
  313                         }
  314                         A = EXTRACT_SHORT(&p[k]);
  315                         continue;
  316 
  317                 case BPF_LD|BPF_B|BPF_IND:
  318                         k = X + pc->k;
  319                         if (k >= buflen) {
  320 #ifdef KERNEL
  321                                 register struct mbuf *m;
  322 
  323                                 if (buflen != 0)
  324                                         return 0;
  325                                 m = (struct mbuf *)p;
  326                                 MINDEX(m, k);
  327                                 A = mtod(m, char *)[k];
  328                                 continue;
  329 #else
  330                                 return 0;
  331 #endif
  332                         }
  333                         A = p[k];
  334                         continue;
  335 
  336                 case BPF_LDX|BPF_MSH|BPF_B:
  337                         k = pc->k;
  338                         if (k >= buflen) {
  339 #ifdef KERNEL
  340                                 register struct mbuf *m;
  341 
  342                                 if (buflen != 0)
  343                                         return 0;
  344                                 m = (struct mbuf *)p;
  345                                 MINDEX(m, k);
  346                                 X = (mtod(m, char *)[k] & 0xf) << 2;
  347                                 continue;
  348 #else
  349                                 return 0;
  350 #endif
  351                         }
  352                         X = (p[pc->k] & 0xf) << 2;
  353                         continue;
  354 
  355                 case BPF_LD|BPF_IMM:
  356                         A = pc->k;
  357                         continue;
  358 
  359                 case BPF_LDX|BPF_IMM:
  360                         X = pc->k;
  361                         continue;
  362 
  363                 case BPF_LD|BPF_MEM:
  364                         A = mem[pc->k];
  365                         continue;
  366 
  367                 case BPF_LDX|BPF_MEM:
  368                         X = mem[pc->k];
  369                         continue;
  370 
  371                 case BPF_ST:
  372                         mem[pc->k] = A;
  373                         continue;
  374 
  375                 case BPF_STX:
  376                         mem[pc->k] = X;
  377                         continue;
  378 
  379                 case BPF_JMP|BPF_JA:
  380                         pc += pc->k;
  381                         continue;
  382 
  383                 case BPF_JMP|BPF_JGT|BPF_K:
  384                         pc += (A > pc->k) ? pc->jt : pc->jf;
  385                         continue;
  386 
  387                 case BPF_JMP|BPF_JGE|BPF_K:
  388                         pc += (A >= pc->k) ? pc->jt : pc->jf;
  389                         continue;
  390 
  391                 case BPF_JMP|BPF_JEQ|BPF_K:
  392                         pc += (A == pc->k) ? pc->jt : pc->jf;
  393                         continue;
  394 
  395                 case BPF_JMP|BPF_JSET|BPF_K:
  396                         pc += (A & pc->k) ? pc->jt : pc->jf;
  397                         continue;
  398 
  399                 case BPF_JMP|BPF_JGT|BPF_X:
  400                         pc += (A > X) ? pc->jt : pc->jf;
  401                         continue;
  402 
  403                 case BPF_JMP|BPF_JGE|BPF_X:
  404                         pc += (A >= X) ? pc->jt : pc->jf;
  405                         continue;
  406 
  407                 case BPF_JMP|BPF_JEQ|BPF_X:
  408                         pc += (A == X) ? pc->jt : pc->jf;
  409                         continue;
  410 
  411                 case BPF_JMP|BPF_JSET|BPF_X:
  412                         pc += (A & X) ? pc->jt : pc->jf;
  413                         continue;
  414 
  415                 case BPF_ALU|BPF_ADD|BPF_X:
  416                         A += X;
  417                         continue;
  418 
  419                 case BPF_ALU|BPF_SUB|BPF_X:
  420                         A -= X;
  421                         continue;
  422 
  423                 case BPF_ALU|BPF_MUL|BPF_X:
  424                         A *= X;
  425                         continue;
  426 
  427                 case BPF_ALU|BPF_DIV|BPF_X:
  428                         if (X == 0)
  429                                 return 0;
  430                         A /= X;
  431                         continue;
  432 
  433                 case BPF_ALU|BPF_AND|BPF_X:
  434                         A &= X;
  435                         continue;
  436 
  437                 case BPF_ALU|BPF_OR|BPF_X:
  438                         A |= X;
  439                         continue;
  440 
  441                 case BPF_ALU|BPF_LSH|BPF_X:
  442                         A <<= X;
  443                         continue;
  444 
  445                 case BPF_ALU|BPF_RSH|BPF_X:
  446                         A >>= X;
  447                         continue;
  448 
  449                 case BPF_ALU|BPF_ADD|BPF_K:
  450                         A += pc->k;
  451                         continue;
  452 
  453                 case BPF_ALU|BPF_SUB|BPF_K:
  454                         A -= pc->k;
  455                         continue;
  456 
  457                 case BPF_ALU|BPF_MUL|BPF_K:
  458                         A *= pc->k;
  459                         continue;
  460 
  461                 case BPF_ALU|BPF_DIV|BPF_K:
  462                         A /= pc->k;
  463                         continue;
  464 
  465                 case BPF_ALU|BPF_AND|BPF_K:
  466                         A &= pc->k;
  467                         continue;
  468 
  469                 case BPF_ALU|BPF_OR|BPF_K:
  470                         A |= pc->k;
  471                         continue;
  472 
  473                 case BPF_ALU|BPF_LSH|BPF_K:
  474                         A <<= pc->k;
  475                         continue;
  476 
  477                 case BPF_ALU|BPF_RSH|BPF_K:
  478                         A >>= pc->k;
  479                         continue;
  480 
  481                 case BPF_ALU|BPF_NEG:
  482                         A = -A;
  483                         continue;
  484 
  485                 case BPF_MISC|BPF_TAX:
  486                         X = A;
  487                         continue;
  488 
  489                 case BPF_MISC|BPF_TXA:
  490                         A = X;
  491                         continue;
  492                 }
  493         }
  494 }
  495 
  496 #ifdef KERNEL
  497 /*
  498  * Return true if the 'fcode' is a valid filter program.
  499  * The constraints are that each jump be forward and to a valid
  500  * code.  The code must terminate with either an accept or reject.
  501  * 'valid' is an array for use by the routine (it must be at least
  502  * 'len' bytes long).
  503  *
  504  * The kernel needs to be able to verify an application's filter code.
  505  * Otherwise, a bogus program could easily crash the system.
  506  */
  507 int
  508 bpf_validate(f, len)
  509         struct bpf_insn *f;
  510         int len;
  511 {
  512         register int i;
  513         register struct bpf_insn *p;
  514 
  515         for (i = 0; i < len; ++i) {
  516                 /*
  517                  * Check that that jumps are forward, and within
  518                  * the code block.
  519                  */
  520                 p = &f[i];
  521                 if (BPF_CLASS(p->code) == BPF_JMP) {
  522                         register int from = i + 1;
  523 
  524                         if (BPF_OP(p->code) == BPF_JA) {
  525                                 if (from + p->k >= len)
  526                                         return 0;
  527                         }
  528                         else if (from + p->jt >= len || from + p->jf >= len)
  529                                 return 0;
  530                 }
  531                 /*
  532                  * Check that memory operations use valid addresses.
  533                  */
  534                 if ((BPF_CLASS(p->code) == BPF_ST ||
  535                      (BPF_CLASS(p->code) == BPF_LD &&
  536                       (p->code & 0xe0) == BPF_MEM)) &&
  537                     (p->k >= BPF_MEMWORDS || p->k < 0))
  538                         return 0;
  539                 /*
  540                  * Check for constant division by 0.
  541                  */
  542                 if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
  543                         return 0;
  544         }
  545         return BPF_CLASS(f[len - 1].code) == BPF_RET;
  546 }
  547 #endif

Cache object: 904209a9f94e8a8985a50eae523f434a


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