bpf_filter.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:12k
源码类别:

VxWorks

开发平台:

C/C++

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