Deleted Added
sdiff udiff text old ( 39294 ) new ( 56891 )
full compact
1/*
2 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21#ifndef lint
22static const char rcsid[] =
23 "@(#) $Header: gencode.c,v 1.94 98/07/12 13:06:49 leres Exp $ (LBL)";
24#endif
25
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <sys/time.h>
29
30#if __STDC__
31struct mbuf;
32struct rtentry;
33#endif
34
35#include <net/if.h>
36#include <net/ethernet.h>

--- 12 unchanged lines hidden (view full) ---

49
50#include "pcap-int.h"
51
52#include "ethertype.h"
53#include "nlpid.h"
54#include "gencode.h"
55#include "ppp.h"
56#include <pcap-namedb.h>
57
58#include "gnuc.h"
59#ifdef HAVE_OS_PROTO_H
60#include "os-proto.h"
61#endif
62
63#define JMP(c) ((c)|BPF_JMP|BPF_K)
64

--- 67 unchanged lines hidden (view full) ---

132static struct block *gen_cmp(u_int, u_int, bpf_int32);
133static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
134static struct block *gen_bcmp(u_int, u_int, const u_char *);
135static struct block *gen_uncond(int);
136static inline struct block *gen_true(void);
137static inline struct block *gen_false(void);
138static struct block *gen_linktype(int);
139static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
140static struct block *gen_ehostop(const u_char *, int);
141static struct block *gen_fhostop(const u_char *, int);
142static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
143static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int);
144static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
145static struct block *gen_ipfrag(void);
146static struct block *gen_portatom(int, bpf_int32);
147struct block *gen_portop(int, int, int);
148static struct block *gen_port(int, int, int);
149static int lookup_proto(const char *, int);
150static struct block *gen_proto(int, int, int);
151static struct slist *xfer_to_x(struct arth *);
152static struct slist *xfer_to_a(struct arth *);
153static struct block *gen_len(int, int);
154
155static void *
156newchunk(n)
157 u_int n;
158{
159 struct chunk *cp;
160 int k, size;
161
162 /* XXX Round up to nearest long. */
163 n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
164
165 cp = &chunks[cur_chunk];
166 if (n > cp->n_left) {
167 ++cp, k = ++cur_chunk;
168 if (k >= NCHUNKS)
169 bpf_error("out of memory");
170 size = CHUNK0SIZE << k;
171 cp->m = (void *)malloc(size);

--- 71 unchanged lines hidden (view full) ---

243static inline void
244syntax()
245{
246 bpf_error("syntax error in filter expression");
247}
248
249static bpf_u_int32 netmask;
250static int snaplen;
251
252int
253pcap_compile(pcap_t *p, struct bpf_program *program,
254 char *buf, int optimize, bpf_u_int32 mask)
255{
256 extern int n_errors;
257 int len;
258
259 n_errors = 0;
260 root = NULL;
261 bpf_pcap = p;
262 if (setjmp(top_ctx)) {
263 freechunks();
264 return (-1);
265 }
266

--- 5 unchanged lines hidden (view full) ---

272 (void)pcap_parse();
273
274 if (n_errors)
275 syntax();
276
277 if (root == NULL)
278 root = gen_retblk(snaplen);
279
280 if (optimize) {
281 bpf_optimize(&root);
282 if (root == NULL ||
283 (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
284 bpf_error("expression rejects all packets");
285 }
286 program->bf_insns = icode_to_fcode(root, &len);
287 program->bf_len = len;

--- 196 unchanged lines hidden (view full) ---

484 return;
485
486 case DLT_NULL:
487 off_linktype = 0;
488 off_nl = 4;
489 return;
490
491 case DLT_PPP:
492 off_linktype = 2;
493 off_nl = 4;
494 return;
495
496 case DLT_PPP_BSDOS:
497 off_linktype = 5;
498 off_nl = 24;
499 return;

--- 77 unchanged lines hidden (view full) ---

577 switch (linktype) {
578
579 case DLT_SLIP:
580 return gen_false();
581
582 case DLT_PPP:
583 if (proto == ETHERTYPE_IP)
584 proto = PPP_IP; /* XXX was 0x21 */
585 break;
586
587 case DLT_PPP_BSDOS:
588 switch (proto) {
589
590 case ETHERTYPE_IP:
591 b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);
592 b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);
593 gen_or(b0, b1);
594 b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);
595 gen_or(b1, b0);
596 return b0;
597
598 case ETHERTYPE_DN:
599 proto = PPP_DECNET;
600 break;
601
602 case ETHERTYPE_ATALK:
603 proto = PPP_APPLE;
604 break;
605
606 case ETHERTYPE_NS:
607 proto = PPP_NS;
608 break;
609 }
610 break;
611
612 case DLT_NULL:
613 /* XXX */
614 if (proto == ETHERTYPE_IP)
615 return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));
616 else
617 return gen_false();
618 case DLT_EN10MB:
619 /*
620 * Having to look at SAP's here is quite disgusting,
621 * but given an internal architecture that _knows_ that
622 * it's looking at IP on Ethernet...
623 */

--- 50 unchanged lines hidden (view full) ---

674 abort();
675 }
676 b0 = gen_linktype(proto);
677 b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
678 gen_and(b0, b1);
679 return b1;
680}
681
682static struct block *
683gen_ehostop(eaddr, dir)
684 register const u_char *eaddr;
685 register int dir;
686{
687 register struct block *b0, *b1;
688
689 switch (dir) {
690 case Q_SRC:

--- 190 unchanged lines hidden (view full) ---

881 bpf_error("'icmp' modifier applied to host");
882
883 case Q_IGMP:
884 bpf_error("'igmp' modifier applied to host");
885
886 case Q_IGRP:
887 bpf_error("'igrp' modifier applied to host");
888
889 case Q_ATALK:
890 bpf_error("ATALK host filtering not implemented");
891
892 case Q_DECNET:
893 return gen_dnhostop(addr, dir, off_nl);
894
895 case Q_SCA:
896 bpf_error("SCA host filtering not implemented");

--- 4 unchanged lines hidden (view full) ---

901 case Q_MOPDL:
902 bpf_error("MOPDL host filtering not implemented");
903
904 case Q_MOPRC:
905 bpf_error("MOPRC host filtering not implemented");
906
907 case Q_ISO:
908 bpf_error("ISO host filtering not implemented");
909
910 default:
911 abort();
912 }
913 /* NOTREACHED */
914}
915
916static struct block *
917gen_gateway(eaddr, alist, proto, dir)
918 const u_char *eaddr;
919 bpf_u_int32 **alist;
920 int proto;
921 int dir;
922{
923 struct block *b0, *b1, *tmp;
924

--- 31 unchanged lines hidden (view full) ---

956gen_proto_abbrev(proto)
957 int proto;
958{
959 struct block *b0, *b1;
960
961 switch (proto) {
962
963 case Q_TCP:
964 b0 = gen_linktype(ETHERTYPE_IP);
965 b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_TCP);
966 gen_and(b0, b1);
967 break;
968
969 case Q_UDP:
970 b0 = gen_linktype(ETHERTYPE_IP);
971 b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_UDP);
972 gen_and(b0, b1);
973 break;
974
975 case Q_ICMP:
976 b0 = gen_linktype(ETHERTYPE_IP);
977 b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_ICMP);
978 gen_and(b0, b1);
979 break;
980
981 case Q_IGMP:
982 b0 = gen_linktype(ETHERTYPE_IP);
983 b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)2);
984 gen_and(b0, b1);
985 break;
986
987#ifndef IPPROTO_IGRP
988#define IPPROTO_IGRP 9
989#endif
990 case Q_IGRP:
991 b0 = gen_linktype(ETHERTYPE_IP);
992 b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_IGRP);
993 gen_and(b0, b1);
994 break;
995
996 case Q_IP:
997 b1 = gen_linktype(ETHERTYPE_IP);
998 break;
999
1000 case Q_ARP:
1001 b1 = gen_linktype(ETHERTYPE_ARP);
1002 break;
1003

--- 23 unchanged lines hidden (view full) ---

1027 case Q_MOPDL:
1028 b1 = gen_linktype(ETHERTYPE_MOPDL);
1029 break;
1030
1031 case Q_MOPRC:
1032 b1 = gen_linktype(ETHERTYPE_MOPRC);
1033 break;
1034
1035 case Q_ISO:
1036 b1 = gen_linktype(LLC_ISO_LSAP);
1037 break;
1038
1039 case Q_ESIS:
1040 b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
1041 break;
1042

--- 40 unchanged lines hidden (view full) ---

1083
1084 b = new_block(JMP(BPF_JEQ));
1085 b->stmts = s;
1086 b->s.k = v;
1087
1088 return b;
1089}
1090
1091struct block *
1092gen_portop(port, proto, dir)
1093 int port, proto, dir;
1094{
1095 struct block *b0, *b1, *tmp;
1096
1097 /* ip proto 'proto' */
1098 tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);

--- 55 unchanged lines hidden (view full) ---

1154
1155 default:
1156 abort();
1157 }
1158 gen_and(b0, b1);
1159 return b1;
1160}
1161
1162static int
1163lookup_proto(name, proto)
1164 register const char *name;
1165 register int proto;
1166{
1167 register int v;
1168
1169 switch (proto) {

--- 14 unchanged lines hidden (view full) ---

1184
1185 default:
1186 v = PROTO_UNDEF;
1187 break;
1188 }
1189 return v;
1190}
1191
1192static struct block *
1193gen_proto(v, proto, dir)
1194 int v;
1195 int proto;
1196 int dir;
1197{
1198 struct block *b0, *b1;
1199
1200 if (dir != Q_DEFAULT)
1201 bpf_error("direction applied to 'proto'");
1202
1203 switch (proto) {
1204 case Q_DEFAULT:
1205 case Q_IP:
1206 b0 = gen_linktype(ETHERTYPE_IP);
1207 b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
1208 gen_and(b0, b1);
1209 return b1;
1210
1211 case Q_ISO:
1212 b0 = gen_linktype(LLC_ISO_LSAP);
1213 b1 = gen_cmp(off_nl + 3, BPF_B, (long)v);
1214 gen_and(b0, b1);
1215 return b1;

--- 48 unchanged lines hidden (view full) ---

1264 case Q_IGMP:
1265 bpf_error("'igmp proto' is bogus");
1266 /* NOTREACHED */
1267
1268 case Q_IGRP:
1269 bpf_error("'igrp proto' is bogus");
1270 /* NOTREACHED */
1271
1272 default:
1273 abort();
1274 /* NOTREACHED */
1275 }
1276 /* NOTREACHED */
1277}
1278
1279struct block *
1280gen_scode(name, q)
1281 register const char *name;
1282 struct qual q;
1283{
1284 int proto = q.proto;
1285 int dir = q.dir;
1286 int tproto;
1287 u_char *eaddr;
1288 bpf_u_int32 mask, addr, **alist;
1289 struct block *b, *tmp;
1290 int port, real_proto;
1291
1292 switch (q.addr) {
1293
1294 case Q_NET:
1295 addr = pcap_nametonetaddr(name);
1296 if (addr == 0)

--- 33 unchanged lines hidden (view full) ---

1330 } else if (proto == Q_DECNET) {
1331 unsigned short dn_addr = __pcap_nametodnaddr(name);
1332 /*
1333 * I don't think DECNET hosts can be multihomed, so
1334 * there is no need to build up a list of addresses
1335 */
1336 return (gen_host(dn_addr, 0, proto, dir));
1337 } else {
1338 alist = pcap_nametoaddr(name);
1339 if (alist == NULL || *alist == NULL)
1340 bpf_error("unknown host '%s'", name);
1341 tproto = proto;
1342 if (off_linktype == -1 && tproto == Q_DEFAULT)
1343 tproto = Q_IP;
1344 b = gen_host(**alist++, 0xffffffff, tproto, dir);
1345 while (*alist) {
1346 tmp = gen_host(**alist++, 0xffffffff,
1347 tproto, dir);
1348 gen_or(b, tmp);
1349 b = tmp;
1350 }
1351 return b;
1352 }
1353
1354 case Q_PORT:
1355 if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP)
1356 bpf_error("illegal qualifier of 'port'");
1357 if (pcap_nametoport(name, &port, &real_proto) == 0)
1358 bpf_error("unknown port '%s'", name);
1359 if (proto == Q_UDP) {

--- 5 unchanged lines hidden (view full) ---

1365 }
1366 if (proto == Q_TCP) {
1367 if (real_proto == IPPROTO_UDP)
1368 bpf_error("port '%s' is udp", name);
1369 else
1370 /* override PROTO_UNDEF */
1371 real_proto = IPPROTO_TCP;
1372 }
1373 return gen_port(port, real_proto, dir);
1374
1375 case Q_GATEWAY:
1376 eaddr = pcap_ether_hostton(name);
1377 if (eaddr == NULL)
1378 bpf_error("unknown ether host: %s", name);
1379
1380 alist = pcap_nametoaddr(name);
1381 if (alist == NULL || *alist == NULL)
1382 bpf_error("unknown host '%s'", name);
1383 return gen_gateway(eaddr, alist, proto, dir);
1384
1385 case Q_PROTO:
1386 real_proto = lookup_proto(name, proto);
1387 if (real_proto >= 0)
1388 return gen_proto(real_proto, proto, dir);
1389 else
1390 bpf_error("unknown protocol: %s", name);
1391
1392 case Q_UNDEF:
1393 syntax();
1394 /* NOTREACHED */
1395 }
1396 abort();
1397 /* NOTREACHED */
1398}
1399

--- 86 unchanged lines hidden (view full) ---

1486 proto = IPPROTO_UDP;
1487 else if (proto == Q_TCP)
1488 proto = IPPROTO_TCP;
1489 else if (proto == Q_DEFAULT)
1490 proto = PROTO_UNDEF;
1491 else
1492 bpf_error("illegal qualifier of 'port'");
1493
1494 return gen_port((int)v, proto, dir);
1495
1496 case Q_GATEWAY:
1497 bpf_error("'gateway' requires a name");
1498 /* NOTREACHED */
1499
1500 case Q_PROTO:
1501 return gen_proto((int)v, proto, dir);
1502
1503 case Q_UNDEF:
1504 syntax();
1505 /* NOTREACHED */
1506
1507 default:
1508 abort();
1509 /* NOTREACHED */
1510 }
1511 /* NOTREACHED */
1512}
1513
1514struct block *
1515gen_ecode(eaddr, q)
1516 register const u_char *eaddr;
1517 struct qual q;
1518{
1519 if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
1520 if (linktype == DLT_EN10MB)
1521 return gen_ehostop(eaddr, (int)q.dir);
1522 if (linktype == DLT_FDDI)

--- 81 unchanged lines hidden (view full) ---

1604 case Q_ARP:
1605 case Q_RARP:
1606 case Q_ATALK:
1607 case Q_DECNET:
1608 case Q_SCA:
1609 case Q_LAT:
1610 case Q_MOPRC:
1611 case Q_MOPDL:
1612 /* XXX Note that we assume a fixed link header here. */
1613 s = xfer_to_x(index);
1614 tmp = new_stmt(BPF_LD|BPF_IND|size);
1615 tmp->s.k = off_nl;
1616 sappend(s, tmp);
1617 sappend(index->s, s);
1618
1619 b = gen_proto_abbrev(proto);
1620 if (index->b)
1621 gen_and(index->b, b);
1622 index->b = b;
1623 break;
1624
1625 case Q_TCP:
1626 case Q_UDP:
1627 case Q_ICMP:
1628 case Q_IGMP:
1629 case Q_IGRP:
1630 s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
1631 s->s.k = off_nl;
1632 sappend(s, xfer_to_a(index));
1633 sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
1634 sappend(s, new_stmt(BPF_MISC|BPF_TAX));
1635 sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
1636 tmp->s.k = off_nl;
1637 sappend(index->s, s);
1638
1639 gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
1640 if (index->b)
1641 gen_and(index->b, b);
1642 index->b = b;
1643 break;
1644 }
1645 index->regno = regno;
1646 s = new_stmt(BPF_ST);
1647 s->s.k = regno;
1648 sappend(index->s, s);
1649
1650 return index;
1651}

--- 309 unchanged lines hidden (view full) ---

1961 break;
1962
1963 case Q_IP:
1964 b0 = gen_linktype(ETHERTYPE_IP);
1965 b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
1966 b1->s.code = JMP(BPF_JGE);
1967 gen_and(b0, b1);
1968 return b1;
1969 }
1970 bpf_error("only IP multicast filters supported on ethernet/FDDI");
1971}
1972
1973/*
1974 * generate command for inbound/outbound. It's here so we can
1975 * make it link-type specific. 'dir' = 0 implies "inbound",
1976 * = 1 implies "outbound".

--- 13 unchanged lines hidden ---