Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

bpf_filter.c

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
00003  *      The Regents of the University of California.  All rights reserved.
00004  *
00005  * This code is derived from the Stanford/CMU enet packet filter,
00006  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
00007  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
00008  * Berkeley Laboratory.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. All advertising materials mentioning features or use of this software
00019  *    must display the following acknowledgement:
00020  *      This product includes software developed by the University of
00021  *      California, Berkeley and its contributors.
00022  * 4. Neither the name of the University nor the names of its contributors
00023  *    may be used to endorse or promote products derived from this software
00024  *    without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00027  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00030  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00031  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00032  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00033  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00034  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00035  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00036  * SUCH DAMAGE.
00037  *
00038  *      @(#)bpf.c       7.5 (Berkeley) 7/15/91
00039  */
00040 
00041 #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
00042 static const char rcsid[] =
00043     "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.35 2000/10/23 19:32:21 fenner Exp $ (LBL)";
00044 #endif
00045 
00046 #include <sys/param.h>
00047 #include <sys/types.h>
00048 #include <sys/time.h>
00049 
00050 #define SOLARIS (defined(sun) && (defined(__SVR4) || defined(__svr4__)))
00051 #if defined(__hpux) || SOLARIS
00052 # include <sys/sysmacros.h>
00053 # include <sys/stream.h>
00054 # define        mbuf    msgb
00055 # define        m_next  b_cont
00056 # define        MLEN(m) ((m)->b_wptr - (m)->b_rptr)
00057 # define        mtod(m,t)       ((t)(m)->b_rptr)
00058 #else
00059 # define        MLEN(m) ((m)->m_len)
00060 #endif
00061 
00062 #include <net/bpf.h>
00063 
00064 #if !defined(KERNEL) && !defined(_KERNEL)
00065 #include <stdlib.h>
00066 #endif
00067 
00068 #define int32 bpf_int32
00069 #define u_int32 bpf_u_int32
00070 
00071 #ifndef LBL_ALIGN
00072 #if defined(sparc) || defined(mips) || defined(ibm032) || \
00073     defined(__alpha) || defined(__hpux)
00074 #define LBL_ALIGN
00075 #endif
00076 #endif
00077 
00078 #ifndef LBL_ALIGN
00079 #include <netinet/in.h>
00080 
00081 #define EXTRACT_SHORT(p)        ((u_short)ntohs(*(u_short *)p))
00082 #define EXTRACT_LONG(p)         (ntohl(*(u_int32 *)p))
00083 #else
00084 #define EXTRACT_SHORT(p)\
00085         ((u_short)\
00086                 ((u_short)*((u_char *)p+0)<<8|\
00087                  (u_short)*((u_char *)p+1)<<0))
00088 #define EXTRACT_LONG(p)\
00089                 ((u_int32)*((u_char *)p+0)<<24|\
00090                  (u_int32)*((u_char *)p+1)<<16|\
00091                  (u_int32)*((u_char *)p+2)<<8|\
00092                  (u_int32)*((u_char *)p+3)<<0)
00093 #endif
00094 
00095 #if defined(KERNEL) || defined(_KERNEL)
00096 # if !defined(__hpux) && !SOLARIS
00097 #include <sys/mbuf.h>
00098 # endif
00099 #define MINDEX(len, _m, _k) \
00100 { \
00101         len = MLEN(m); \
00102         while ((_k) >= len) { \
00103                 (_k) -= len; \
00104                 (_m) = (_m)->m_next; \
00105                 if ((_m) == 0) \
00106                         return 0; \
00107                 len = MLEN(m); \
00108         } \
00109 }
00110 
00111 static int
00112 m_xword(m, k, err)
00113         register struct mbuf *m;
00114         register int k, *err;
00115 {
00116         register int len;
00117         register u_char *cp, *np;
00118         register struct mbuf *m0;
00119 
00120         MINDEX(len, m, k);
00121         cp = mtod(m, u_char *) + k;
00122         if (len - k >= 4) {
00123                 *err = 0;
00124                 return EXTRACT_LONG(cp);
00125         }
00126         m0 = m->m_next;
00127         if (m0 == 0 || MLEN(m0) + len - k < 4)
00128                 goto bad;
00129         *err = 0;
00130         np = mtod(m0, u_char *);
00131         switch (len - k) {
00132 
00133         case 1:
00134                 return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
00135 
00136         case 2:
00137                 return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
00138 
00139         default:
00140                 return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
00141         }
00142     bad:
00143         *err = 1;
00144         return 0;
00145 }
00146 
00147 static int
00148 m_xhalf(m, k, err)
00149         register struct mbuf *m;
00150         register int k, *err;
00151 {
00152         register int len;
00153         register u_char *cp;
00154         register struct mbuf *m0;
00155 
00156         MINDEX(len, m, k);
00157         cp = mtod(m, u_char *) + k;
00158         if (len - k >= 2) {
00159                 *err = 0;
00160                 return EXTRACT_SHORT(cp);
00161         }
00162         m0 = m->m_next;
00163         if (m0 == 0)
00164                 goto bad;
00165         *err = 0;
00166         return (cp[0] << 8) | mtod(m0, u_char *)[0];
00167  bad:
00168         *err = 1;
00169         return 0;
00170 }
00171 #endif
00172 
00173 /*
00174  * Execute the filter program starting at pc on the packet p
00175  * wirelen is the length of the original packet
00176  * buflen is the amount of data present
00177  * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
00178  * in all other cases, p is a pointer to a buffer and buflen is its size.
00179  */
00180 u_int
00181 bpf_filter(pc, p, wirelen, buflen)
00182         register struct bpf_insn *pc;
00183         register u_char *p;
00184         u_int wirelen;
00185         register u_int buflen;
00186 {
00187         register u_int32 A, X;
00188         register int k;
00189         int32 mem[BPF_MEMWORDS];
00190 #if defined(KERNEL) || defined(_KERNEL)
00191         struct mbuf *m, *n;
00192         int merr, len;
00193 
00194         if (buflen == 0) {
00195                 m = (struct mbuf *)p;
00196                 p = mtod(m, u_char *);
00197                 buflen = MLEN(m);
00198         } else
00199                 m = NULL;
00200 #endif
00201 
00202         if (pc == 0)
00203                 /*
00204                  * No filter means accept all.
00205                  */
00206                 return (u_int)-1;
00207         A = 0;
00208         X = 0;
00209         --pc;
00210         while (1) {
00211                 ++pc;
00212                 switch (pc->code) {
00213 
00214                 default:
00215 #if defined(KERNEL) || defined(_KERNEL)
00216                         return 0;
00217 #else
00218                         abort();
00219 #endif                  
00220                 case BPF_RET|BPF_K:
00221                         return (u_int)pc->k;
00222 
00223                 case BPF_RET|BPF_A:
00224                         return (u_int)A;
00225 
00226                 case BPF_LD|BPF_W|BPF_ABS:
00227                         k = pc->k;
00228                         if (k + sizeof(int32) > buflen) {
00229 #if defined(KERNEL) || defined(_KERNEL)
00230                                 if (m == NULL)
00231                                         return 0;
00232                                 A = m_xword(m, k, &merr);
00233                                 if (merr != 0)
00234                                         return 0;
00235                                 continue;
00236 #else
00237                                 return 0;
00238 #endif
00239                         }
00240                         A = EXTRACT_LONG(&p[k]);
00241                         continue;
00242 
00243                 case BPF_LD|BPF_H|BPF_ABS:
00244                         k = pc->k;
00245                         if (k + sizeof(short) > buflen) {
00246 #if defined(KERNEL) || defined(_KERNEL)
00247                                 if (m == NULL)
00248                                         return 0;
00249                                 A = m_xhalf(m, k, &merr);
00250                                 if (merr != 0)
00251                                         return 0;
00252                                 continue;
00253 #else
00254                                 return 0;
00255 #endif
00256                         }
00257                         A = EXTRACT_SHORT(&p[k]);
00258                         continue;
00259 
00260                 case BPF_LD|BPF_B|BPF_ABS:
00261                         k = pc->k;
00262                         if (k >= buflen) {
00263 #if defined(KERNEL) || defined(_KERNEL)
00264                                 if (m == NULL)
00265                                         return 0;
00266                                 n = m;
00267                                 MINDEX(len, n, k);
00268                                 A = mtod(n, u_char *)[k];
00269                                 continue;
00270 #else
00271                                 return 0;
00272 #endif
00273                         }
00274                         A = p[k];
00275                         continue;
00276 
00277                 case BPF_LD|BPF_W|BPF_LEN:
00278                         A = wirelen;
00279                         continue;
00280 
00281                 case BPF_LDX|BPF_W|BPF_LEN:
00282                         X = wirelen;
00283                         continue;
00284 
00285                 case BPF_LD|BPF_W|BPF_IND:
00286                         k = X + pc->k;
00287                         if (k + sizeof(int32) > buflen) {
00288 #if defined(KERNEL) || defined(_KERNEL)
00289                                 if (m == NULL)
00290                                         return 0;
00291                                 A = m_xword(m, k, &merr);
00292                                 if (merr != 0)
00293                                         return 0;
00294                                 continue;
00295 #else
00296                                 return 0;
00297 #endif
00298                         }
00299                         A = EXTRACT_LONG(&p[k]);
00300                         continue;
00301 
00302                 case BPF_LD|BPF_H|BPF_IND:
00303                         k = X + pc->k;
00304                         if (k + sizeof(short) > buflen) {
00305 #if defined(KERNEL) || defined(_KERNEL)
00306                                 if (m == NULL)
00307                                         return 0;
00308                                 A = m_xhalf(m, k, &merr);
00309                                 if (merr != 0)
00310                                         return 0;
00311                                 continue;
00312 #else
00313                                 return 0;
00314 #endif
00315                         }
00316                         A = EXTRACT_SHORT(&p[k]);
00317                         continue;
00318 
00319                 case BPF_LD|BPF_B|BPF_IND:
00320                         k = X + pc->k;
00321                         if (k >= buflen) {
00322 #if defined(KERNEL) || defined(_KERNEL)
00323                                 if (m == NULL)
00324                                         return 0;
00325                                 n = m;
00326                                 MINDEX(len, n, k);
00327                                 A = mtod(n, u_char *)[k];
00328                                 continue;
00329 #else
00330                                 return 0;
00331 #endif
00332                         }
00333                         A = p[k];
00334                         continue;
00335 
00336                 case BPF_LDX|BPF_MSH|BPF_B:
00337                         k = pc->k;
00338                         if (k >= buflen) {
00339 #if defined(KERNEL) || defined(_KERNEL)
00340                                 if (m == NULL)
00341                                         return 0;
00342                                 n = m;
00343                                 MINDEX(len, n, k);
00344                                 X = (mtod(n, char *)[k] & 0xf) << 2;
00345                                 continue;
00346 #else
00347                                 return 0;
00348 #endif
00349                         }
00350                         X = (p[pc->k] & 0xf) << 2;
00351                         continue;
00352 
00353                 case BPF_LD|BPF_IMM:
00354                         A = pc->k;
00355                         continue;
00356 
00357                 case BPF_LDX|BPF_IMM:
00358                         X = pc->k;
00359                         continue;
00360 
00361                 case BPF_LD|BPF_MEM:
00362                         A = mem[pc->k];
00363                         continue;
00364                         
00365                 case BPF_LDX|BPF_MEM:
00366                         X = mem[pc->k];
00367                         continue;
00368 
00369                 case BPF_ST:
00370                         mem[pc->k] = A;
00371                         continue;
00372 
00373                 case BPF_STX:
00374                         mem[pc->k] = X;
00375                         continue;
00376 
00377                 case BPF_JMP|BPF_JA:
00378                         pc += pc->k;
00379                         continue;
00380 
00381                 case BPF_JMP|BPF_JGT|BPF_K:
00382                         pc += (A > pc->k) ? pc->jt : pc->jf;
00383                         continue;
00384 
00385                 case BPF_JMP|BPF_JGE|BPF_K:
00386                         pc += (A >= pc->k) ? pc->jt : pc->jf;
00387                         continue;
00388 
00389                 case BPF_JMP|BPF_JEQ|BPF_K:
00390                         pc += (A == pc->k) ? pc->jt : pc->jf;
00391                         continue;
00392 
00393                 case BPF_JMP|BPF_JSET|BPF_K:
00394                         pc += (A & pc->k) ? pc->jt : pc->jf;
00395                         continue;
00396 
00397                 case BPF_JMP|BPF_JGT|BPF_X:
00398                         pc += (A > X) ? pc->jt : pc->jf;
00399                         continue;
00400 
00401                 case BPF_JMP|BPF_JGE|BPF_X:
00402                         pc += (A >= X) ? pc->jt : pc->jf;
00403                         continue;
00404 
00405                 case BPF_JMP|BPF_JEQ|BPF_X:
00406                         pc += (A == X) ? pc->jt : pc->jf;
00407                         continue;
00408 
00409                 case BPF_JMP|BPF_JSET|BPF_X:
00410                         pc += (A & X) ? pc->jt : pc->jf;
00411                         continue;
00412 
00413                 case BPF_ALU|BPF_ADD|BPF_X:
00414                         A += X;
00415                         continue;
00416                         
00417                 case BPF_ALU|BPF_SUB|BPF_X:
00418                         A -= X;
00419                         continue;
00420                         
00421                 case BPF_ALU|BPF_MUL|BPF_X:
00422                         A *= X;
00423                         continue;
00424                         
00425                 case BPF_ALU|BPF_DIV|BPF_X:
00426                         if (X == 0)
00427                                 return 0;
00428                         A /= X;
00429                         continue;
00430                         
00431                 case BPF_ALU|BPF_AND|BPF_X:
00432                         A &= X;
00433                         continue;
00434                         
00435                 case BPF_ALU|BPF_OR|BPF_X:
00436                         A |= X;
00437                         continue;
00438 
00439                 case BPF_ALU|BPF_LSH|BPF_X:
00440                         A <<= X;
00441                         continue;
00442 
00443                 case BPF_ALU|BPF_RSH|BPF_X:
00444                         A >>= X;
00445                         continue;
00446 
00447                 case BPF_ALU|BPF_ADD|BPF_K:
00448                         A += pc->k;
00449                         continue;
00450                         
00451                 case BPF_ALU|BPF_SUB|BPF_K:
00452                         A -= pc->k;
00453                         continue;
00454                         
00455                 case BPF_ALU|BPF_MUL|BPF_K:
00456                         A *= pc->k;
00457                         continue;
00458                         
00459                 case BPF_ALU|BPF_DIV|BPF_K:
00460                         A /= pc->k;
00461                         continue;
00462                         
00463                 case BPF_ALU|BPF_AND|BPF_K:
00464                         A &= pc->k;
00465                         continue;
00466                         
00467                 case BPF_ALU|BPF_OR|BPF_K:
00468                         A |= pc->k;
00469                         continue;
00470 
00471                 case BPF_ALU|BPF_LSH|BPF_K:
00472                         A <<= pc->k;
00473                         continue;
00474 
00475                 case BPF_ALU|BPF_RSH|BPF_K:
00476                         A >>= pc->k;
00477                         continue;
00478 
00479                 case BPF_ALU|BPF_NEG:
00480                         A = -A;
00481                         continue;
00482 
00483                 case BPF_MISC|BPF_TAX:
00484                         X = A;
00485                         continue;
00486 
00487                 case BPF_MISC|BPF_TXA:
00488                         A = X;
00489                         continue;
00490                 }
00491         }
00492 }
00493 
00494 
00495 /*
00496  * Return true if the 'fcode' is a valid filter program.
00497  * The constraints are that each jump be forward and to a valid
00498  * code.  The code must terminate with either an accept or reject. 
00499  * 'valid' is an array for use by the routine (it must be at least
00500  * 'len' bytes long).  
00501  *
00502  * The kernel needs to be able to verify an application's filter code.
00503  * Otherwise, a bogus program could easily crash the system.
00504  */
00505 int
00506 bpf_validate(f, len)
00507         struct bpf_insn *f;
00508         int len;
00509 {
00510         register int i;
00511         register struct bpf_insn *p;
00512 
00513         for (i = 0; i < len; ++i) {
00514                 /*
00515                  * Check that that jumps are forward, and within 
00516                  * the code block.
00517                  */
00518                 p = &f[i];
00519                 if (BPF_CLASS(p->code) == BPF_JMP) {
00520                         register int from = i + 1;
00521 
00522                         if (BPF_OP(p->code) == BPF_JA) {
00523                                 if (from + p->k >= (unsigned)len)
00524                                         return 0;
00525                         }
00526                         else if (from + p->jt >= len || from + p->jf >= len)
00527                                 return 0;
00528                 }
00529                 /*
00530                  * Check that memory operations use valid addresses.
00531                  */
00532                 if ((BPF_CLASS(p->code) == BPF_ST ||
00533                      (BPF_CLASS(p->code) == BPF_LD && 
00534                       (p->code & 0xe0) == BPF_MEM)) &&
00535                     (p->k >= BPF_MEMWORDS || p->k < 0))
00536                         return 0;
00537                 /*
00538                  * Check for constant division by 0.
00539                  */
00540                 if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
00541                         return 0;
00542         }
00543         return BPF_CLASS(f[len - 1].code) == BPF_RET;
00544 }

Generated on Wed Sep 14 02:55:58 2005 for bro_docs by doxygen 1.3.5