1/*#define CHASE_CHAIN*/
2/*
3 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that: (1) source code distributions
8 * retain the above copyright notice and this paragraph in its entirety, (2)
9 * distributions including binary code include the above copyright notice and
10 * this paragraph in its entirety in the documentation or other materials
11 * provided with the distribution, and (3) all advertising materials mentioning
12 * features or use of this software display the following acknowledgement:
13 * ``This product includes software developed by the University of California,
14 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15 * the University nor the names of its contributors may be used to endorse
16 * or promote products derived from this software without specific prior
17 * written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 *
22 * $FreeBSD: head/contrib/libpcap/gencode.c 56891 2000-01-30 00:43:38Z fenner $
23 */
24#ifndef lint
25static const char rcsid[] =
26 "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.100 1999/12/08 19:54:03 mcr Exp $ (LBL)";
27#endif
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/time.h>
32#ifdef __NetBSD__
33#include <sys/param.h>
34#endif
35
36#if __STDC__
37struct mbuf;
38struct rtentry;
39#endif
40
41#include <net/if.h>
42#include <net/ethernet.h>
--- 12 unchanged lines hidden (view full) ---
55
56#include "pcap-int.h"
57
58#include "ethertype.h"
59#include "nlpid.h"
60#include "gencode.h"
61#include "ppp.h"
62#include <pcap-namedb.h>
63#ifdef INET6
64#include <netdb.h>
65#include <sys/socket.h>
66#endif /*INET6*/
67
68#include "gnuc.h"
69#ifdef HAVE_OS_PROTO_H
70#include "os-proto.h"
71#endif
72
73#define JMP(c) ((c)|BPF_JMP|BPF_K)
74
--- 67 unchanged lines hidden (view full) ---
142static struct block *gen_cmp(u_int, u_int, bpf_int32);
143static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
144static struct block *gen_bcmp(u_int, u_int, const u_char *);
145static struct block *gen_uncond(int);
146static inline struct block *gen_true(void);
147static inline struct block *gen_false(void);
148static struct block *gen_linktype(int);
149static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
150#ifdef INET6
151static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
152#endif
153static struct block *gen_ehostop(const u_char *, int);
154static struct block *gen_fhostop(const u_char *, int);
155static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
156static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int);
157#ifdef INET6
158static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int);
159#endif
160static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
161static struct block *gen_ipfrag(void);
162static struct block *gen_portatom(int, bpf_int32);
163#ifdef INET6
164static struct block *gen_portatom6(int, bpf_int32);
165#endif
166struct block *gen_portop(int, int, int);
167static struct block *gen_port(int, int, int);
168#ifdef INET6
169struct block *gen_portop6(int, int, int);
170static struct block *gen_port6(int, int, int);
171#endif
172static int lookup_proto(const char *, int);
173static struct block *gen_proto(int, int, int);
174static struct slist *xfer_to_x(struct arth *);
175static struct slist *xfer_to_a(struct arth *);
176static struct block *gen_len(int, int);
177
178static void *
179newchunk(n)
180 u_int n;
181{
182 struct chunk *cp;
183 int k, size;
184
185#ifndef __NetBSD__
186 /* XXX Round up to nearest long. */
187 n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
188#else
189 /* XXX Round up to structure boundary. */
190 n = ALIGN(n);
191#endif
192
193 cp = &chunks[cur_chunk];
194 if (n > cp->n_left) {
195 ++cp, k = ++cur_chunk;
196 if (k >= NCHUNKS)
197 bpf_error("out of memory");
198 size = CHUNK0SIZE << k;
199 cp->m = (void *)malloc(size);
--- 71 unchanged lines hidden (view full) ---
271static inline void
272syntax()
273{
274 bpf_error("syntax error in filter expression");
275}
276
277static bpf_u_int32 netmask;
278static int snaplen;
279int no_optimize;
280
281int
282pcap_compile(pcap_t *p, struct bpf_program *program,
283 char *buf, int optimize, bpf_u_int32 mask)
284{
285 extern int n_errors;
286 int len;
287
288 no_optimize = 0;
289 n_errors = 0;
290 root = NULL;
291 bpf_pcap = p;
292 if (setjmp(top_ctx)) {
293 freechunks();
294 return (-1);
295 }
296
--- 5 unchanged lines hidden (view full) ---
302 (void)pcap_parse();
303
304 if (n_errors)
305 syntax();
306
307 if (root == NULL)
308 root = gen_retblk(snaplen);
309
310 if (optimize && !no_optimize) {
311 bpf_optimize(&root);
312 if (root == NULL ||
313 (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
314 bpf_error("expression rejects all packets");
315 }
316 program->bf_insns = icode_to_fcode(root, &len);
317 program->bf_len = len;
318
319 freechunks();
320 return (0);
321}
322
323/*
324 * entry point for using the compiler with no pcap open
325 * pass in all the stuff that is needed explicitly instead.
326 */
327int
328pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
329 struct bpf_program *program,
330 char *buf, int optimize, bpf_u_int32 mask)
331{
332 extern int n_errors;
333 int len;
334
335 n_errors = 0;
336 root = NULL;
337 bpf_pcap = NULL;
338 if (setjmp(top_ctx)) {
339 freechunks();
340 return (-1);
341 }
342
343 netmask = mask;
344
345 /* XXX needed? I don't grok the use of globals here. */
346 snaplen = snaplen_arg;
347
348 lex_init(buf ? buf : "");
349 init_linktype(linktype_arg);
350 (void)pcap_parse();
351
352 if (n_errors)
353 syntax();
354
355 if (root == NULL)
356 root = gen_retblk(snaplen_arg);
357
358 if (optimize) {
359 bpf_optimize(&root);
360 if (root == NULL ||
361 (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
362 bpf_error("expression rejects all packets");
363 }
364 program->bf_insns = icode_to_fcode(root, &len);
365 program->bf_len = len;
--- 196 unchanged lines hidden (view full) ---
562 return;
563
564 case DLT_NULL:
565 off_linktype = 0;
566 off_nl = 4;
567 return;
568
569 case DLT_PPP:
570#ifdef DLT_CHDLC
571 case DLT_CHDLC:
572#endif
573 off_linktype = 2;
574 off_nl = 4;
575 return;
576
577 case DLT_PPP_BSDOS:
578 off_linktype = 5;
579 off_nl = 24;
580 return;
--- 77 unchanged lines hidden (view full) ---
658 switch (linktype) {
659
660 case DLT_SLIP:
661 return gen_false();
662
663 case DLT_PPP:
664 if (proto == ETHERTYPE_IP)
665 proto = PPP_IP; /* XXX was 0x21 */
666#ifdef INET6
667 else if (proto == ETHERTYPE_IPV6)
668 proto = PPP_IPV6;
669#endif
670 break;
671
672 case DLT_PPP_BSDOS:
673 switch (proto) {
674
675 case ETHERTYPE_IP:
676 b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);
677 b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);
678 gen_or(b0, b1);
679 b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);
680 gen_or(b1, b0);
681 return b0;
682
683#ifdef INET6
684 case ETHERTYPE_IPV6:
685 proto = PPP_IPV6;
686 /* more to go? */
687 break;
688#endif
689
690 case ETHERTYPE_DN:
691 proto = PPP_DECNET;
692 break;
693
694 case ETHERTYPE_ATALK:
695 proto = PPP_APPLE;
696 break;
697
698 case ETHERTYPE_NS:
699 proto = PPP_NS;
700 break;
701 }
702 break;
703
704 case DLT_NULL:
705 /* XXX */
706 if (proto == ETHERTYPE_IP)
707 return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));
708#ifdef INET6
709 else if (proto == ETHERTYPE_IPV6)
710 return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET6)));
711#endif
712 else
713 return gen_false();
714 case DLT_EN10MB:
715 /*
716 * Having to look at SAP's here is quite disgusting,
717 * but given an internal architecture that _knows_ that
718 * it's looking at IP on Ethernet...
719 */
--- 50 unchanged lines hidden (view full) ---
770 abort();
771 }
772 b0 = gen_linktype(proto);
773 b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
774 gen_and(b0, b1);
775 return b1;
776}
777
778#ifdef INET6
779static struct block *
780gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
781 struct in6_addr *addr;
782 struct in6_addr *mask;
783 int dir, proto;
784 u_int src_off, dst_off;
785{
786 struct block *b0, *b1;
787 u_int offset;
788 u_int32_t *a, *m;
789
790 switch (dir) {
791
792 case Q_SRC:
793 offset = src_off;
794 break;
795
796 case Q_DST:
797 offset = dst_off;
798 break;
799
800 case Q_AND:
801 b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
802 b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
803 gen_and(b0, b1);
804 return b1;
805
806 case Q_OR:
807 case Q_DEFAULT:
808 b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
809 b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
810 gen_or(b0, b1);
811 return b1;
812
813 default:
814 abort();
815 }
816 /* this order is important */
817 a = (u_int32_t *)addr;
818 m = (u_int32_t *)mask;
819 b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
820 b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
821 gen_and(b0, b1);
822 b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
823 gen_and(b0, b1);
824 b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
825 gen_and(b0, b1);
826 b0 = gen_linktype(proto);
827 gen_and(b0, b1);
828 return b1;
829}
830#endif /*INET6*/
831
832static struct block *
833gen_ehostop(eaddr, dir)
834 register const u_char *eaddr;
835 register int dir;
836{
837 register struct block *b0, *b1;
838
839 switch (dir) {
840 case Q_SRC:
--- 190 unchanged lines hidden (view full) ---
1031 bpf_error("'icmp' modifier applied to host");
1032
1033 case Q_IGMP:
1034 bpf_error("'igmp' modifier applied to host");
1035
1036 case Q_IGRP:
1037 bpf_error("'igrp' modifier applied to host");
1038
1039 case Q_PIM:
1040 bpf_error("'pim' modifier applied to host");
1041
1042 case Q_ATALK:
1043 bpf_error("ATALK host filtering not implemented");
1044
1045 case Q_DECNET:
1046 return gen_dnhostop(addr, dir, off_nl);
1047
1048 case Q_SCA:
1049 bpf_error("SCA host filtering not implemented");
--- 4 unchanged lines hidden (view full) ---
1054 case Q_MOPDL:
1055 bpf_error("MOPDL host filtering not implemented");
1056
1057 case Q_MOPRC:
1058 bpf_error("MOPRC host filtering not implemented");
1059
1060 case Q_ISO:
1061 bpf_error("ISO host filtering not implemented");
1062
1063#ifdef INET6
1064 case Q_IPV6:
1065 bpf_error("'ip6' modifier applied to ip host");
1066
1067 case Q_ICMPV6:
1068 bpf_error("'icmp6' modifier applied to host");
1069#endif /* INET6 */
1070
1071 case Q_AH:
1072 bpf_error("'ah' modifier applied to host");
1073
1074 case Q_ESP:
1075 bpf_error("'esp' modifier applied to host");
1076
1077 default:
1078 abort();
1079 }
1080 /* NOTREACHED */
1081}
1082
1083#ifdef INET6
1084static struct block *
1085gen_host6(addr, mask, proto, dir)
1086 struct in6_addr *addr;
1087 struct in6_addr *mask;
1088 int proto;
1089 int dir;
1090{
1091 struct block *b0, *b1;
1092
1093 switch (proto) {
1094
1095 case Q_DEFAULT:
1096 return gen_host6(addr, mask, Q_IPV6, dir);
1097
1098 case Q_IP:
1099 bpf_error("'ip' modifier applied to ip6 host");
1100
1101 case Q_RARP:
1102 bpf_error("'rarp' modifier applied to ip6 host");
1103
1104 case Q_ARP:
1105 bpf_error("'arp' modifier applied to ip6 host");
1106
1107 case Q_TCP:
1108 bpf_error("'tcp' modifier applied to host");
1109
1110 case Q_UDP:
1111 bpf_error("'udp' modifier applied to host");
1112
1113 case Q_ICMP:
1114 bpf_error("'icmp' modifier applied to host");
1115
1116 case Q_IGMP:
1117 bpf_error("'igmp' modifier applied to host");
1118
1119 case Q_IGRP:
1120 bpf_error("'igrp' modifier applied to host");
1121
1122 case Q_PIM:
1123 bpf_error("'pim' modifier applied to host");
1124
1125 case Q_ATALK:
1126 bpf_error("ATALK host filtering not implemented");
1127
1128 case Q_DECNET:
1129 bpf_error("'decnet' modifier applied to ip6 host");
1130
1131 case Q_SCA:
1132 bpf_error("SCA host filtering not implemented");
1133
1134 case Q_LAT:
1135 bpf_error("LAT host filtering not implemented");
1136
1137 case Q_MOPDL:
1138 bpf_error("MOPDL host filtering not implemented");
1139
1140 case Q_MOPRC:
1141 bpf_error("MOPRC host filtering not implemented");
1142
1143 case Q_IPV6:
1144 return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6,
1145 off_nl + 8, off_nl + 24);
1146
1147 case Q_ICMPV6:
1148 bpf_error("'icmp6' modifier applied to host");
1149
1150 case Q_AH:
1151 bpf_error("'ah' modifier applied to host");
1152
1153 case Q_ESP:
1154 bpf_error("'esp' modifier applied to host");
1155
1156 default:
1157 abort();
1158 }
1159 /* NOTREACHED */
1160}
1161#endif /*INET6*/
1162
1163static struct block *
1164gen_gateway(eaddr, alist, proto, dir)
1165 const u_char *eaddr;
1166 bpf_u_int32 **alist;
1167 int proto;
1168 int dir;
1169{
1170 struct block *b0, *b1, *tmp;
1171
--- 31 unchanged lines hidden (view full) ---
1203gen_proto_abbrev(proto)
1204 int proto;
1205{
1206 struct block *b0, *b1;
1207
1208 switch (proto) {
1209
1210 case Q_TCP:
1211 b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
1212#ifdef INET6
1213 b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
1214 gen_or(b0, b1);
1215#endif
1216 break;
1217
1218 case Q_UDP:
1219 b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
1220#ifdef INET6
1221 b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
1222 gen_or(b0, b1);
1223#endif
1224 break;
1225
1226 case Q_ICMP:
1227 b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
1228 break;
1229
1230 case Q_IGMP:
1231 b1 = gen_proto(2, Q_IP, Q_DEFAULT);
1232 break;
1233
1234#ifndef IPPROTO_IGRP
1235#define IPPROTO_IGRP 9
1236#endif
1237 case Q_IGRP:
1238 b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
1239 break;
1240
1241#ifndef IPPROTO_PIM
1242#define IPPROTO_PIM 103
1243#endif
1244
1245 case Q_PIM:
1246 b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
1247#ifdef INET6
1248 b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
1249 gen_or(b0, b1);
1250#endif
1251 break;
1252
1253 case Q_IP:
1254 b1 = gen_linktype(ETHERTYPE_IP);
1255 break;
1256
1257 case Q_ARP:
1258 b1 = gen_linktype(ETHERTYPE_ARP);
1259 break;
1260
--- 23 unchanged lines hidden (view full) ---
1284 case Q_MOPDL:
1285 b1 = gen_linktype(ETHERTYPE_MOPDL);
1286 break;
1287
1288 case Q_MOPRC:
1289 b1 = gen_linktype(ETHERTYPE_MOPRC);
1290 break;
1291
1292#ifdef INET6
1293 case Q_IPV6:
1294 b1 = gen_linktype(ETHERTYPE_IPV6);
1295 break;
1296
1297#ifndef IPPROTO_ICMPV6
1298#define IPPROTO_ICMPV6 58
1299#endif
1300 case Q_ICMPV6:
1301 b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
1302 break;
1303#endif /* INET6 */
1304
1305#ifndef IPPROTO_AH
1306#define IPPROTO_AH 51
1307#endif
1308 case Q_AH:
1309 b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
1310#ifdef INET6
1311 b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
1312 gen_or(b0, b1);
1313#endif
1314 break;
1315
1316#ifndef IPPROTO_ESP
1317#define IPPROTO_ESP 50
1318#endif
1319 case Q_ESP:
1320 b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
1321#ifdef INET6
1322 b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
1323 gen_or(b0, b1);
1324#endif
1325 break;
1326
1327 case Q_ISO:
1328 b1 = gen_linktype(LLC_ISO_LSAP);
1329 break;
1330
1331 case Q_ESIS:
1332 b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
1333 break;
1334
--- 40 unchanged lines hidden (view full) ---
1375
1376 b = new_block(JMP(BPF_JEQ));
1377 b->stmts = s;
1378 b->s.k = v;
1379
1380 return b;
1381}
1382
1383#ifdef INET6
1384static struct block *
1385gen_portatom6(off, v)
1386 int off;
1387 bpf_int32 v;
1388{
1389 return gen_cmp(off_nl + 40 + off, BPF_H, v);
1390}
1391#endif/*INET6*/
1392
1393struct block *
1394gen_portop(port, proto, dir)
1395 int port, proto, dir;
1396{
1397 struct block *b0, *b1, *tmp;
1398
1399 /* ip proto 'proto' */
1400 tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);
--- 55 unchanged lines hidden (view full) ---
1456
1457 default:
1458 abort();
1459 }
1460 gen_and(b0, b1);
1461 return b1;
1462}
1463
1464#ifdef INET6
1465struct block *
1466gen_portop6(port, proto, dir)
1467 int port, proto, dir;
1468{
1469 struct block *b0, *b1, *tmp;
1470
1471 /* ip proto 'proto' */
1472 b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto);
1473
1474 switch (dir) {
1475 case Q_SRC:
1476 b1 = gen_portatom6(0, (bpf_int32)port);
1477 break;
1478
1479 case Q_DST:
1480 b1 = gen_portatom6(2, (bpf_int32)port);
1481 break;
1482
1483 case Q_OR:
1484 case Q_DEFAULT:
1485 tmp = gen_portatom6(0, (bpf_int32)port);
1486 b1 = gen_portatom6(2, (bpf_int32)port);
1487 gen_or(tmp, b1);
1488 break;
1489
1490 case Q_AND:
1491 tmp = gen_portatom6(0, (bpf_int32)port);
1492 b1 = gen_portatom6(2, (bpf_int32)port);
1493 gen_and(tmp, b1);
1494 break;
1495
1496 default:
1497 abort();
1498 }
1499 gen_and(b0, b1);
1500
1501 return b1;
1502}
1503
1504static struct block *
1505gen_port6(port, ip_proto, dir)
1506 int port;
1507 int ip_proto;
1508 int dir;
1509{
1510 struct block *b0, *b1, *tmp;
1511
1512 /* ether proto ip */
1513 b0 = gen_linktype(ETHERTYPE_IPV6);
1514
1515 switch (ip_proto) {
1516 case IPPROTO_UDP:
1517 case IPPROTO_TCP:
1518 b1 = gen_portop6(port, ip_proto, dir);
1519 break;
1520
1521 case PROTO_UNDEF:
1522 tmp = gen_portop6(port, IPPROTO_TCP, dir);
1523 b1 = gen_portop6(port, IPPROTO_UDP, dir);
1524 gen_or(tmp, b1);
1525 break;
1526
1527 default:
1528 abort();
1529 }
1530 gen_and(b0, b1);
1531 return b1;
1532}
1533#endif /* INET6 */
1534
1535static int
1536lookup_proto(name, proto)
1537 register const char *name;
1538 register int proto;
1539{
1540 register int v;
1541
1542 switch (proto) {
--- 14 unchanged lines hidden (view full) ---
1557
1558 default:
1559 v = PROTO_UNDEF;
1560 break;
1561 }
1562 return v;
1563}
1564
1565struct stmt *
1566gen_joinsp(s, n)
1567 struct stmt **s;
1568 int n;
1569{
1570}
1571
1572struct block *
1573gen_protochain(v, proto, dir)
1574 int v;
1575 int proto;
1576 int dir;
1577{
1578#ifdef NO_PROTOCHAIN
1579 return gen_proto(v, proto, dir);
1580#else
1581 struct block *b0, *b;
1582 struct slist *s[100], *sp;
1583 int fix2, fix3, fix4, fix5;
1584 int ahcheck, again, end;
1585 int i, max;
1586 int reg1 = alloc_reg();
1587 int reg2 = alloc_reg();
1588
1589 memset(s, 0, sizeof(s));
1590 fix2 = fix3 = fix4 = fix5 = 0;
1591
1592 switch (proto) {
1593 case Q_IP:
1594 case Q_IPV6:
1595 break;
1596 case Q_DEFAULT:
1597 b0 = gen_protochain(v, Q_IP, dir);
1598 b = gen_protochain(v, Q_IPV6, dir);
1599 gen_or(b0, b);
1600 return b;
1601 default:
1602 bpf_error("bad protocol applied for 'protochain'");
1603 /*NOTREACHED*/
1604 }
1605
1606 no_optimize = 1; /*this code is not compatible with optimzer yet */
1607
1608 /*
1609 * s[0] is a dummy entry to protect other BPF insn from damaged
1610 * by s[fix] = foo with uninitialized variable "fix". It is somewhat
1611 * hard to find interdependency made by jump table fixup.
1612 */
1613 i = 0;
1614 s[i] = new_stmt(0); /*dummy*/
1615 i++;
1616
1617 switch (proto) {
1618 case Q_IP:
1619 b0 = gen_linktype(ETHERTYPE_IP);
1620
1621 /* A = ip->ip_p */
1622 s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
1623 s[i]->s.k = off_nl + 9;
1624 i++;
1625 /* X = ip->ip_hl << 2 */
1626 s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
1627 s[i]->s.k = off_nl;
1628 i++;
1629 break;
1630#ifdef INET6
1631 case Q_IPV6:
1632 b0 = gen_linktype(ETHERTYPE_IPV6);
1633
1634 /* A = ip6->ip_nxt */
1635 s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
1636 s[i]->s.k = off_nl + 6;
1637 i++;
1638 /* X = sizeof(struct ip6_hdr) */
1639 s[i] = new_stmt(BPF_LDX|BPF_IMM);
1640 s[i]->s.k = 40;
1641 i++;
1642 break;
1643#endif
1644 default:
1645 bpf_error("unsupported proto to gen_protochain");
1646 /*NOTREACHED*/
1647 }
1648
1649 /* again: if (A == v) goto end; else fall through; */
1650 again = i;
1651 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1652 s[i]->s.k = v;
1653 s[i]->s.jt = NULL; /*later*/
1654 s[i]->s.jf = NULL; /*update in next stmt*/
1655 fix5 = i;
1656 i++;
1657
1658#ifndef IPPROTO_NONE
1659#define IPPROTO_NONE 59
1660#endif
1661 /* if (A == IPPROTO_NONE) goto end */
1662 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1663 s[i]->s.jt = NULL; /*later*/
1664 s[i]->s.jf = NULL; /*update in next stmt*/
1665 s[i]->s.k = IPPROTO_NONE;
1666 s[fix5]->s.jf = s[i];
1667 fix2 = i;
1668 i++;
1669
1670#ifdef INET6
1671 if (proto == Q_IPV6) {
1672 int v6start, v6end, v6advance, j;
1673
1674 v6start = i;
1675 /* if (A == IPPROTO_HOPOPTS) goto v6advance */
1676 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1677 s[i]->s.jt = NULL; /*later*/
1678 s[i]->s.jf = NULL; /*update in next stmt*/
1679 s[i]->s.k = IPPROTO_HOPOPTS;
1680 s[fix2]->s.jf = s[i];
1681 i++;
1682 /* if (A == IPPROTO_DSTOPTS) goto v6advance */
1683 s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1684 s[i]->s.jt = NULL; /*later*/
1685 s[i]->s.jf = NULL; /*update in next stmt*/
1686 s[i]->s.k = IPPROTO_DSTOPTS;
1687 i++;
1688 /* if (A == IPPROTO_ROUTING) goto v6advance */
1689 s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1690 s[i]->s.jt = NULL; /*later*/
1691 s[i]->s.jf = NULL; /*update in next stmt*/
1692 s[i]->s.k = IPPROTO_ROUTING;
1693 i++;
1694 /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
1695 s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1696 s[i]->s.jt = NULL; /*later*/
1697 s[i]->s.jf = NULL; /*later*/
1698 s[i]->s.k = IPPROTO_FRAGMENT;
1699 fix3 = i;
1700 v6end = i;
1701 i++;
1702
1703 /* v6advance: */
1704 v6advance = i;
1705
1706 /*
1707 * in short,
1708 * A = P[X + 1];
1709 * X = X + (P[X] + 1) * 8;
1710 */
1711 /* A = X */
1712 s[i] = new_stmt(BPF_MISC|BPF_TXA);
1713 i++;
1714 /* MEM[reg1] = A */
1715 s[i] = new_stmt(BPF_ST);
1716 s[i]->s.k = reg1;
1717 i++;
1718 /* A += 1 */
1719 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1720 s[i]->s.k = 1;
1721 i++;
1722 /* X = A */
1723 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1724 i++;
1725 /* A = P[X + packet head]; */
1726 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1727 s[i]->s.k = off_nl;
1728 i++;
1729 /* MEM[reg2] = A */
1730 s[i] = new_stmt(BPF_ST);
1731 s[i]->s.k = reg2;
1732 i++;
1733 /* X = MEM[reg1] */
1734 s[i] = new_stmt(BPF_LDX|BPF_MEM);
1735 s[i]->s.k = reg1;
1736 i++;
1737 /* A = P[X + packet head] */
1738 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1739 s[i]->s.k = off_nl;
1740 i++;
1741 /* A += 1 */
1742 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1743 s[i]->s.k = 1;
1744 i++;
1745 /* A *= 8 */
1746 s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
1747 s[i]->s.k = 8;
1748 i++;
1749 /* X = A; */
1750 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1751 i++;
1752 /* A = MEM[reg2] */
1753 s[i] = new_stmt(BPF_LD|BPF_MEM);
1754 s[i]->s.k = reg2;
1755 i++;
1756
1757 /* goto again; (must use BPF_JA for backward jump) */
1758 s[i] = new_stmt(BPF_JMP|BPF_JA);
1759 s[i]->s.k = again - i - 1;
1760 s[i - 1]->s.jf = s[i];
1761 i++;
1762
1763 /* fixup */
1764 for (j = v6start; j <= v6end; j++)
1765 s[j]->s.jt = s[v6advance];
1766 } else
1767#endif
1768 {
1769 /* nop */
1770 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1771 s[i]->s.k = 0;
1772 s[fix2]->s.jf = s[i];
1773 i++;
1774 }
1775
1776 /* ahcheck: */
1777 ahcheck = i;
1778 /* if (A == IPPROTO_AH) then fall through; else goto end; */
1779 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1780 s[i]->s.jt = NULL; /*later*/
1781 s[i]->s.jf = NULL; /*later*/
1782 s[i]->s.k = IPPROTO_AH;
1783 if (fix3)
1784 s[fix3]->s.jf = s[ahcheck];
1785 fix4 = i;
1786 i++;
1787
1788 /*
1789 * in short,
1790 * A = P[X + 1];
1791 * X = X + (P[X] + 2) * 4;
1792 */
1793 /* A = X */
1794 s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
1795 i++;
1796 /* MEM[reg1] = A */
1797 s[i] = new_stmt(BPF_ST);
1798 s[i]->s.k = reg1;
1799 i++;
1800 /* A += 1 */
1801 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1802 s[i]->s.k = 1;
1803 i++;
1804 /* X = A */
1805 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1806 i++;
1807 /* A = P[X + packet head]; */
1808 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1809 s[i]->s.k = off_nl;
1810 i++;
1811 /* MEM[reg2] = A */
1812 s[i] = new_stmt(BPF_ST);
1813 s[i]->s.k = reg2;
1814 i++;
1815 /* X = MEM[reg1] */
1816 s[i] = new_stmt(BPF_LDX|BPF_MEM);
1817 s[i]->s.k = reg1;
1818 i++;
1819 /* A = P[X + packet head] */
1820 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1821 s[i]->s.k = off_nl;
1822 i++;
1823 /* A += 2 */
1824 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1825 s[i]->s.k = 2;
1826 i++;
1827 /* A *= 4 */
1828 s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
1829 s[i]->s.k = 4;
1830 i++;
1831 /* X = A; */
1832 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1833 i++;
1834 /* A = MEM[reg2] */
1835 s[i] = new_stmt(BPF_LD|BPF_MEM);
1836 s[i]->s.k = reg2;
1837 i++;
1838
1839 /* goto again; (must use BPF_JA for backward jump) */
1840 s[i] = new_stmt(BPF_JMP|BPF_JA);
1841 s[i]->s.k = again - i - 1;
1842 i++;
1843
1844 /* end: nop */
1845 end = i;
1846 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1847 s[i]->s.k = 0;
1848 s[fix2]->s.jt = s[end];
1849 s[fix4]->s.jf = s[end];
1850 s[fix5]->s.jt = s[end];
1851 i++;
1852
1853 /*
1854 * make slist chain
1855 */
1856 max = i;
1857 for (i = 0; i < max - 1; i++)
1858 s[i]->next = s[i + 1];
1859 s[max - 1]->next = NULL;
1860
1861 /*
1862 * emit final check
1863 */
1864 b = new_block(JMP(BPF_JEQ));
1865 b->stmts = s[1]; /*remember, s[0] is dummy*/
1866 b->s.k = v;
1867
1868 free_reg(reg1);
1869 free_reg(reg2);
1870
1871 gen_and(b0, b);
1872 return b;
1873#endif
1874}
1875
1876static struct block *
1877gen_proto(v, proto, dir)
1878 int v;
1879 int proto;
1880 int dir;
1881{
1882 struct block *b0, *b1;
1883
1884 if (dir != Q_DEFAULT)
1885 bpf_error("direction applied to 'proto'");
1886
1887 switch (proto) {
1888 case Q_DEFAULT:
1889#ifdef INET6
1890 b0 = gen_proto(v, Q_IP, dir);
1891 b1 = gen_proto(v, Q_IPV6, dir);
1892 gen_or(b0, b1);
1893 return b1;
1894#else
1895 /*FALLTHROUGH*/
1896#endif
1897 case Q_IP:
1898 b0 = gen_linktype(ETHERTYPE_IP);
1899#ifndef CHASE_CHAIN
1900 b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
1901#else
1902 b1 = gen_protochain(v, Q_IP);
1903#endif
1904 gen_and(b0, b1);
1905 return b1;
1906
1907 case Q_ISO:
1908 b0 = gen_linktype(LLC_ISO_LSAP);
1909 b1 = gen_cmp(off_nl + 3, BPF_B, (long)v);
1910 gen_and(b0, b1);
1911 return b1;
--- 48 unchanged lines hidden (view full) ---
1960 case Q_IGMP:
1961 bpf_error("'igmp proto' is bogus");
1962 /* NOTREACHED */
1963
1964 case Q_IGRP:
1965 bpf_error("'igrp proto' is bogus");
1966 /* NOTREACHED */
1967
1968 case Q_PIM:
1969 bpf_error("'pim proto' is bogus");
1970 /* NOTREACHED */
1971
1972#ifdef INET6
1973 case Q_IPV6:
1974 b0 = gen_linktype(ETHERTYPE_IPV6);
1975#ifndef CHASE_CHAIN
1976 b1 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)v);
1977#else
1978 b1 = gen_protochain(v, Q_IPV6);
1979#endif
1980 gen_and(b0, b1);
1981 return b1;
1982
1983 case Q_ICMPV6:
1984 bpf_error("'icmp6 proto' is bogus");
1985#endif /* INET6 */
1986
1987 case Q_AH:
1988 bpf_error("'ah proto' is bogus");
1989
1990 case Q_ESP:
1991 bpf_error("'ah proto' is bogus");
1992
1993 default:
1994 abort();
1995 /* NOTREACHED */
1996 }
1997 /* NOTREACHED */
1998}
1999
2000struct block *
2001gen_scode(name, q)
2002 register const char *name;
2003 struct qual q;
2004{
2005 int proto = q.proto;
2006 int dir = q.dir;
2007 int tproto;
2008 u_char *eaddr;
2009 bpf_u_int32 mask, addr, **alist;
2010#ifdef INET6
2011 int tproto6;
2012 struct sockaddr_in *sin;
2013 struct sockaddr_in6 *sin6;
2014 struct addrinfo *res, *res0;
2015 struct in6_addr mask128;
2016#endif /*INET6*/
2017 struct block *b, *tmp;
2018 int port, real_proto;
2019
2020 switch (q.addr) {
2021
2022 case Q_NET:
2023 addr = pcap_nametonetaddr(name);
2024 if (addr == 0)
--- 33 unchanged lines hidden (view full) ---
2058 } else if (proto == Q_DECNET) {
2059 unsigned short dn_addr = __pcap_nametodnaddr(name);
2060 /*
2061 * I don't think DECNET hosts can be multihomed, so
2062 * there is no need to build up a list of addresses
2063 */
2064 return (gen_host(dn_addr, 0, proto, dir));
2065 } else {
2066#ifndef INET6
2067 alist = pcap_nametoaddr(name);
2068 if (alist == NULL || *alist == NULL)
2069 bpf_error("unknown host '%s'", name);
2070 tproto = proto;
2071 if (off_linktype == -1 && tproto == Q_DEFAULT)
2072 tproto = Q_IP;
2073 b = gen_host(**alist++, 0xffffffff, tproto, dir);
2074 while (*alist) {
2075 tmp = gen_host(**alist++, 0xffffffff,
2076 tproto, dir);
2077 gen_or(b, tmp);
2078 b = tmp;
2079 }
2080 return b;
2081#else
2082 memset(&mask128, 0xff, sizeof(mask128));
2083 res0 = res = pcap_nametoaddr(name);
2084 if (res == NULL)
2085 bpf_error("unknown host '%s'", name);
2086 b = tmp = NULL;
2087 tproto = tproto6 = proto;
2088 if (off_linktype == -1 && tproto == Q_DEFAULT) {
2089 tproto = Q_IP;
2090 tproto6 = Q_IPV6;
2091 }
2092 while (res) {
2093 switch (res->ai_family) {
2094 case AF_INET:
2095 sin = (struct sockaddr_in *)
2096 res->ai_addr;
2097 tmp = gen_host(ntohl(sin->sin_addr.s_addr),
2098 0xffffffff, tproto, dir);
2099 break;
2100 case AF_INET6:
2101 sin6 = (struct sockaddr_in6 *)
2102 res->ai_addr;
2103 tmp = gen_host6(&sin6->sin6_addr,
2104 &mask128, tproto6, dir);
2105 break;
2106 }
2107 if (b)
2108 gen_or(b, tmp);
2109 b = tmp;
2110
2111 res = res->ai_next;
2112 }
2113 freeaddrinfo(res0);
2114 return b;
2115#endif /*INET6*/
2116 }
2117
2118 case Q_PORT:
2119 if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP)
2120 bpf_error("illegal qualifier of 'port'");
2121 if (pcap_nametoport(name, &port, &real_proto) == 0)
2122 bpf_error("unknown port '%s'", name);
2123 if (proto == Q_UDP) {
--- 5 unchanged lines hidden (view full) ---
2129 }
2130 if (proto == Q_TCP) {
2131 if (real_proto == IPPROTO_UDP)
2132 bpf_error("port '%s' is udp", name);
2133 else
2134 /* override PROTO_UNDEF */
2135 real_proto = IPPROTO_TCP;
2136 }
2137#ifndef INET6
2138 return gen_port(port, real_proto, dir);
2139#else
2140 {
2141 struct block *b;
2142 b = gen_port(port, real_proto, dir);
2143 gen_or(gen_port6(port, real_proto, dir), b);
2144 return b;
2145 }
2146#endif /* INET6 */
2147
2148 case Q_GATEWAY:
2149#ifndef INET6
2150 eaddr = pcap_ether_hostton(name);
2151 if (eaddr == NULL)
2152 bpf_error("unknown ether host: %s", name);
2153
2154 alist = pcap_nametoaddr(name);
2155 if (alist == NULL || *alist == NULL)
2156 bpf_error("unknown host '%s'", name);
2157 return gen_gateway(eaddr, alist, proto, dir);
2158#else
2159 bpf_error("'gateway' not supported in this configuration");
2160#endif /*INET6*/
2161
2162 case Q_PROTO:
2163 real_proto = lookup_proto(name, proto);
2164 if (real_proto >= 0)
2165 return gen_proto(real_proto, proto, dir);
2166 else
2167 bpf_error("unknown protocol: %s", name);
2168
2169 case Q_PROTOCHAIN:
2170 real_proto = lookup_proto(name, proto);
2171 if (real_proto >= 0)
2172 return gen_protochain(real_proto, proto, dir);
2173 else
2174 bpf_error("unknown protocol: %s", name);
2175
2176
2177 case Q_UNDEF:
2178 syntax();
2179 /* NOTREACHED */
2180 }
2181 abort();
2182 /* NOTREACHED */
2183}
2184
--- 86 unchanged lines hidden (view full) ---
2271 proto = IPPROTO_UDP;
2272 else if (proto == Q_TCP)
2273 proto = IPPROTO_TCP;
2274 else if (proto == Q_DEFAULT)
2275 proto = PROTO_UNDEF;
2276 else
2277 bpf_error("illegal qualifier of 'port'");
2278
2279#ifndef INET6
2280 return gen_port((int)v, proto, dir);
2281#else
2282 {
2283 struct block *b;
2284 b = gen_port((int)v, proto, dir);
2285 gen_or(gen_port6((int)v, proto, dir), b);
2286 return b;
2287 }
2288#endif /* INET6 */
2289
2290 case Q_GATEWAY:
2291 bpf_error("'gateway' requires a name");
2292 /* NOTREACHED */
2293
2294 case Q_PROTO:
2295 return gen_proto((int)v, proto, dir);
2296
2297 case Q_PROTOCHAIN:
2298 return gen_protochain((int)v, proto, dir);
2299
2300 case Q_UNDEF:
2301 syntax();
2302 /* NOTREACHED */
2303
2304 default:
2305 abort();
2306 /* NOTREACHED */
2307 }
2308 /* NOTREACHED */
2309}
2310
2311#ifdef INET6
2312struct block *
2313gen_mcode6(s1, s2, masklen, q)
2314 register const char *s1, *s2;
2315 register int masklen;
2316 struct qual q;
2317{
2318 struct addrinfo *res;
2319 struct in6_addr *addr;
2320 struct in6_addr mask;
2321 struct block *b;
2322 u_int32_t *a, *m;
2323
2324 if (s2)
2325 bpf_error("no mask %s supported", s2);
2326
2327 res = pcap_nametoaddr(s1);
2328 if (!res)
2329 bpf_error("invalid ip6 address %s", s1);
2330 if (res->ai_next)
2331 bpf_error("%s resolved to multiple address", s1);
2332 addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
2333
2334 if (sizeof(mask) * 8 < masklen)
2335 bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
2336 memset(&mask, 0xff, masklen / 8);
2337 if (masklen % 8) {
2338 mask.s6_addr[masklen / 8] =
2339 (0xff << (8 - masklen % 8)) & 0xff;
2340 }
2341
2342 a = (u_int32_t *)addr;
2343 m = (u_int32_t *)&mask;
2344 if ((a[0] & ~m[0]) || (a[1] & ~m[1])
2345 || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
2346 bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
2347 }
2348
2349 switch (q.addr) {
2350
2351 case Q_DEFAULT:
2352 case Q_HOST:
2353 if (masklen != 128)
2354 bpf_error("Mask syntax for networks only");
2355 /* FALLTHROUGH */
2356
2357 case Q_NET:
2358 b = gen_host6(addr, &mask, q.proto, q.dir);
2359 freeaddrinfo(res);
2360 return b;
2361
2362 default:
2363 bpf_error("invalid qualifier against IPv6 address");
2364 /* NOTREACHED */
2365 }
2366}
2367#endif /*INET6*/
2368
2369struct block *
2370gen_ecode(eaddr, q)
2371 register const u_char *eaddr;
2372 struct qual q;
2373{
2374 if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
2375 if (linktype == DLT_EN10MB)
2376 return gen_ehostop(eaddr, (int)q.dir);
2377 if (linktype == DLT_FDDI)
--- 81 unchanged lines hidden (view full) ---
2459 case Q_ARP:
2460 case Q_RARP:
2461 case Q_ATALK:
2462 case Q_DECNET:
2463 case Q_SCA:
2464 case Q_LAT:
2465 case Q_MOPRC:
2466 case Q_MOPDL:
2467#ifdef INET6
2468 case Q_IPV6:
2469#endif
2470 /* XXX Note that we assume a fixed link header here. */
2471 s = xfer_to_x(index);
2472 tmp = new_stmt(BPF_LD|BPF_IND|size);
2473 tmp->s.k = off_nl;
2474 sappend(s, tmp);
2475 sappend(index->s, s);
2476
2477 b = gen_proto_abbrev(proto);
2478 if (index->b)
2479 gen_and(index->b, b);
2480 index->b = b;
2481 break;
2482
2483 case Q_TCP:
2484 case Q_UDP:
2485 case Q_ICMP:
2486 case Q_IGMP:
2487 case Q_IGRP:
2488 case Q_PIM:
2489 s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
2490 s->s.k = off_nl;
2491 sappend(s, xfer_to_a(index));
2492 sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
2493 sappend(s, new_stmt(BPF_MISC|BPF_TAX));
2494 sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
2495 tmp->s.k = off_nl;
2496 sappend(index->s, s);
2497
2498 gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
2499 if (index->b)
2500 gen_and(index->b, b);
2501#ifdef INET6
2502 gen_and(gen_proto_abbrev(Q_IP), b);
2503#endif
2504 index->b = b;
2505 break;
2506#ifdef INET6
2507 case Q_ICMPV6:
2508 bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
2509 /*NOTREACHED*/
2510#endif
2511 }
2512 index->regno = regno;
2513 s = new_stmt(BPF_ST);
2514 s->s.k = regno;
2515 sappend(index->s, s);
2516
2517 return index;
2518}
--- 309 unchanged lines hidden (view full) ---
2828 break;
2829
2830 case Q_IP:
2831 b0 = gen_linktype(ETHERTYPE_IP);
2832 b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
2833 b1->s.code = JMP(BPF_JGE);
2834 gen_and(b0, b1);
2835 return b1;
2836
2837#ifdef INET6
2838 case Q_IPV6:
2839 b0 = gen_linktype(ETHERTYPE_IPV6);
2840 b1 = gen_cmp(off_nl + 24, BPF_B, (bpf_int32)255);
2841 gen_and(b0, b1);
2842 return b1;
2843#endif /* INET6 */
2844 }
2845 bpf_error("only IP multicast filters supported on ethernet/FDDI");
2846}
2847
2848/*
2849 * generate command for inbound/outbound. It's here so we can
2850 * make it link-type specific. 'dir' = 0 implies "inbound",
2851 * = 1 implies "outbound".
--- 13 unchanged lines hidden ---
2/*
3 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that: (1) source code distributions
8 * retain the above copyright notice and this paragraph in its entirety, (2)
9 * distributions including binary code include the above copyright notice and
10 * this paragraph in its entirety in the documentation or other materials
11 * provided with the distribution, and (3) all advertising materials mentioning
12 * features or use of this software display the following acknowledgement:
13 * ``This product includes software developed by the University of California,
14 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15 * the University nor the names of its contributors may be used to endorse
16 * or promote products derived from this software without specific prior
17 * written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 *
22 * $FreeBSD: head/contrib/libpcap/gencode.c 56891 2000-01-30 00:43:38Z fenner $
23 */
24#ifndef lint
25static const char rcsid[] =
26 "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.100 1999/12/08 19:54:03 mcr Exp $ (LBL)";
27#endif
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/time.h>
32#ifdef __NetBSD__
33#include <sys/param.h>
34#endif
35
36#if __STDC__
37struct mbuf;
38struct rtentry;
39#endif
40
41#include <net/if.h>
42#include <net/ethernet.h>
--- 12 unchanged lines hidden (view full) ---
55
56#include "pcap-int.h"
57
58#include "ethertype.h"
59#include "nlpid.h"
60#include "gencode.h"
61#include "ppp.h"
62#include <pcap-namedb.h>
63#ifdef INET6
64#include <netdb.h>
65#include <sys/socket.h>
66#endif /*INET6*/
67
68#include "gnuc.h"
69#ifdef HAVE_OS_PROTO_H
70#include "os-proto.h"
71#endif
72
73#define JMP(c) ((c)|BPF_JMP|BPF_K)
74
--- 67 unchanged lines hidden (view full) ---
142static struct block *gen_cmp(u_int, u_int, bpf_int32);
143static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32);
144static struct block *gen_bcmp(u_int, u_int, const u_char *);
145static struct block *gen_uncond(int);
146static inline struct block *gen_true(void);
147static inline struct block *gen_false(void);
148static struct block *gen_linktype(int);
149static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
150#ifdef INET6
151static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
152#endif
153static struct block *gen_ehostop(const u_char *, int);
154static struct block *gen_fhostop(const u_char *, int);
155static struct block *gen_dnhostop(bpf_u_int32, int, u_int);
156static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int);
157#ifdef INET6
158static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int);
159#endif
160static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
161static struct block *gen_ipfrag(void);
162static struct block *gen_portatom(int, bpf_int32);
163#ifdef INET6
164static struct block *gen_portatom6(int, bpf_int32);
165#endif
166struct block *gen_portop(int, int, int);
167static struct block *gen_port(int, int, int);
168#ifdef INET6
169struct block *gen_portop6(int, int, int);
170static struct block *gen_port6(int, int, int);
171#endif
172static int lookup_proto(const char *, int);
173static struct block *gen_proto(int, int, int);
174static struct slist *xfer_to_x(struct arth *);
175static struct slist *xfer_to_a(struct arth *);
176static struct block *gen_len(int, int);
177
178static void *
179newchunk(n)
180 u_int n;
181{
182 struct chunk *cp;
183 int k, size;
184
185#ifndef __NetBSD__
186 /* XXX Round up to nearest long. */
187 n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
188#else
189 /* XXX Round up to structure boundary. */
190 n = ALIGN(n);
191#endif
192
193 cp = &chunks[cur_chunk];
194 if (n > cp->n_left) {
195 ++cp, k = ++cur_chunk;
196 if (k >= NCHUNKS)
197 bpf_error("out of memory");
198 size = CHUNK0SIZE << k;
199 cp->m = (void *)malloc(size);
--- 71 unchanged lines hidden (view full) ---
271static inline void
272syntax()
273{
274 bpf_error("syntax error in filter expression");
275}
276
277static bpf_u_int32 netmask;
278static int snaplen;
279int no_optimize;
280
281int
282pcap_compile(pcap_t *p, struct bpf_program *program,
283 char *buf, int optimize, bpf_u_int32 mask)
284{
285 extern int n_errors;
286 int len;
287
288 no_optimize = 0;
289 n_errors = 0;
290 root = NULL;
291 bpf_pcap = p;
292 if (setjmp(top_ctx)) {
293 freechunks();
294 return (-1);
295 }
296
--- 5 unchanged lines hidden (view full) ---
302 (void)pcap_parse();
303
304 if (n_errors)
305 syntax();
306
307 if (root == NULL)
308 root = gen_retblk(snaplen);
309
310 if (optimize && !no_optimize) {
311 bpf_optimize(&root);
312 if (root == NULL ||
313 (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
314 bpf_error("expression rejects all packets");
315 }
316 program->bf_insns = icode_to_fcode(root, &len);
317 program->bf_len = len;
318
319 freechunks();
320 return (0);
321}
322
323/*
324 * entry point for using the compiler with no pcap open
325 * pass in all the stuff that is needed explicitly instead.
326 */
327int
328pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
329 struct bpf_program *program,
330 char *buf, int optimize, bpf_u_int32 mask)
331{
332 extern int n_errors;
333 int len;
334
335 n_errors = 0;
336 root = NULL;
337 bpf_pcap = NULL;
338 if (setjmp(top_ctx)) {
339 freechunks();
340 return (-1);
341 }
342
343 netmask = mask;
344
345 /* XXX needed? I don't grok the use of globals here. */
346 snaplen = snaplen_arg;
347
348 lex_init(buf ? buf : "");
349 init_linktype(linktype_arg);
350 (void)pcap_parse();
351
352 if (n_errors)
353 syntax();
354
355 if (root == NULL)
356 root = gen_retblk(snaplen_arg);
357
358 if (optimize) {
359 bpf_optimize(&root);
360 if (root == NULL ||
361 (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
362 bpf_error("expression rejects all packets");
363 }
364 program->bf_insns = icode_to_fcode(root, &len);
365 program->bf_len = len;
--- 196 unchanged lines hidden (view full) ---
562 return;
563
564 case DLT_NULL:
565 off_linktype = 0;
566 off_nl = 4;
567 return;
568
569 case DLT_PPP:
570#ifdef DLT_CHDLC
571 case DLT_CHDLC:
572#endif
573 off_linktype = 2;
574 off_nl = 4;
575 return;
576
577 case DLT_PPP_BSDOS:
578 off_linktype = 5;
579 off_nl = 24;
580 return;
--- 77 unchanged lines hidden (view full) ---
658 switch (linktype) {
659
660 case DLT_SLIP:
661 return gen_false();
662
663 case DLT_PPP:
664 if (proto == ETHERTYPE_IP)
665 proto = PPP_IP; /* XXX was 0x21 */
666#ifdef INET6
667 else if (proto == ETHERTYPE_IPV6)
668 proto = PPP_IPV6;
669#endif
670 break;
671
672 case DLT_PPP_BSDOS:
673 switch (proto) {
674
675 case ETHERTYPE_IP:
676 b0 = gen_cmp(off_linktype, BPF_H, PPP_IP);
677 b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC);
678 gen_or(b0, b1);
679 b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC);
680 gen_or(b1, b0);
681 return b0;
682
683#ifdef INET6
684 case ETHERTYPE_IPV6:
685 proto = PPP_IPV6;
686 /* more to go? */
687 break;
688#endif
689
690 case ETHERTYPE_DN:
691 proto = PPP_DECNET;
692 break;
693
694 case ETHERTYPE_ATALK:
695 proto = PPP_APPLE;
696 break;
697
698 case ETHERTYPE_NS:
699 proto = PPP_NS;
700 break;
701 }
702 break;
703
704 case DLT_NULL:
705 /* XXX */
706 if (proto == ETHERTYPE_IP)
707 return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));
708#ifdef INET6
709 else if (proto == ETHERTYPE_IPV6)
710 return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET6)));
711#endif
712 else
713 return gen_false();
714 case DLT_EN10MB:
715 /*
716 * Having to look at SAP's here is quite disgusting,
717 * but given an internal architecture that _knows_ that
718 * it's looking at IP on Ethernet...
719 */
--- 50 unchanged lines hidden (view full) ---
770 abort();
771 }
772 b0 = gen_linktype(proto);
773 b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask);
774 gen_and(b0, b1);
775 return b1;
776}
777
778#ifdef INET6
779static struct block *
780gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
781 struct in6_addr *addr;
782 struct in6_addr *mask;
783 int dir, proto;
784 u_int src_off, dst_off;
785{
786 struct block *b0, *b1;
787 u_int offset;
788 u_int32_t *a, *m;
789
790 switch (dir) {
791
792 case Q_SRC:
793 offset = src_off;
794 break;
795
796 case Q_DST:
797 offset = dst_off;
798 break;
799
800 case Q_AND:
801 b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
802 b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
803 gen_and(b0, b1);
804 return b1;
805
806 case Q_OR:
807 case Q_DEFAULT:
808 b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
809 b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
810 gen_or(b0, b1);
811 return b1;
812
813 default:
814 abort();
815 }
816 /* this order is important */
817 a = (u_int32_t *)addr;
818 m = (u_int32_t *)mask;
819 b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
820 b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
821 gen_and(b0, b1);
822 b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
823 gen_and(b0, b1);
824 b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
825 gen_and(b0, b1);
826 b0 = gen_linktype(proto);
827 gen_and(b0, b1);
828 return b1;
829}
830#endif /*INET6*/
831
832static struct block *
833gen_ehostop(eaddr, dir)
834 register const u_char *eaddr;
835 register int dir;
836{
837 register struct block *b0, *b1;
838
839 switch (dir) {
840 case Q_SRC:
--- 190 unchanged lines hidden (view full) ---
1031 bpf_error("'icmp' modifier applied to host");
1032
1033 case Q_IGMP:
1034 bpf_error("'igmp' modifier applied to host");
1035
1036 case Q_IGRP:
1037 bpf_error("'igrp' modifier applied to host");
1038
1039 case Q_PIM:
1040 bpf_error("'pim' modifier applied to host");
1041
1042 case Q_ATALK:
1043 bpf_error("ATALK host filtering not implemented");
1044
1045 case Q_DECNET:
1046 return gen_dnhostop(addr, dir, off_nl);
1047
1048 case Q_SCA:
1049 bpf_error("SCA host filtering not implemented");
--- 4 unchanged lines hidden (view full) ---
1054 case Q_MOPDL:
1055 bpf_error("MOPDL host filtering not implemented");
1056
1057 case Q_MOPRC:
1058 bpf_error("MOPRC host filtering not implemented");
1059
1060 case Q_ISO:
1061 bpf_error("ISO host filtering not implemented");
1062
1063#ifdef INET6
1064 case Q_IPV6:
1065 bpf_error("'ip6' modifier applied to ip host");
1066
1067 case Q_ICMPV6:
1068 bpf_error("'icmp6' modifier applied to host");
1069#endif /* INET6 */
1070
1071 case Q_AH:
1072 bpf_error("'ah' modifier applied to host");
1073
1074 case Q_ESP:
1075 bpf_error("'esp' modifier applied to host");
1076
1077 default:
1078 abort();
1079 }
1080 /* NOTREACHED */
1081}
1082
1083#ifdef INET6
1084static struct block *
1085gen_host6(addr, mask, proto, dir)
1086 struct in6_addr *addr;
1087 struct in6_addr *mask;
1088 int proto;
1089 int dir;
1090{
1091 struct block *b0, *b1;
1092
1093 switch (proto) {
1094
1095 case Q_DEFAULT:
1096 return gen_host6(addr, mask, Q_IPV6, dir);
1097
1098 case Q_IP:
1099 bpf_error("'ip' modifier applied to ip6 host");
1100
1101 case Q_RARP:
1102 bpf_error("'rarp' modifier applied to ip6 host");
1103
1104 case Q_ARP:
1105 bpf_error("'arp' modifier applied to ip6 host");
1106
1107 case Q_TCP:
1108 bpf_error("'tcp' modifier applied to host");
1109
1110 case Q_UDP:
1111 bpf_error("'udp' modifier applied to host");
1112
1113 case Q_ICMP:
1114 bpf_error("'icmp' modifier applied to host");
1115
1116 case Q_IGMP:
1117 bpf_error("'igmp' modifier applied to host");
1118
1119 case Q_IGRP:
1120 bpf_error("'igrp' modifier applied to host");
1121
1122 case Q_PIM:
1123 bpf_error("'pim' modifier applied to host");
1124
1125 case Q_ATALK:
1126 bpf_error("ATALK host filtering not implemented");
1127
1128 case Q_DECNET:
1129 bpf_error("'decnet' modifier applied to ip6 host");
1130
1131 case Q_SCA:
1132 bpf_error("SCA host filtering not implemented");
1133
1134 case Q_LAT:
1135 bpf_error("LAT host filtering not implemented");
1136
1137 case Q_MOPDL:
1138 bpf_error("MOPDL host filtering not implemented");
1139
1140 case Q_MOPRC:
1141 bpf_error("MOPRC host filtering not implemented");
1142
1143 case Q_IPV6:
1144 return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6,
1145 off_nl + 8, off_nl + 24);
1146
1147 case Q_ICMPV6:
1148 bpf_error("'icmp6' modifier applied to host");
1149
1150 case Q_AH:
1151 bpf_error("'ah' modifier applied to host");
1152
1153 case Q_ESP:
1154 bpf_error("'esp' modifier applied to host");
1155
1156 default:
1157 abort();
1158 }
1159 /* NOTREACHED */
1160}
1161#endif /*INET6*/
1162
1163static struct block *
1164gen_gateway(eaddr, alist, proto, dir)
1165 const u_char *eaddr;
1166 bpf_u_int32 **alist;
1167 int proto;
1168 int dir;
1169{
1170 struct block *b0, *b1, *tmp;
1171
--- 31 unchanged lines hidden (view full) ---
1203gen_proto_abbrev(proto)
1204 int proto;
1205{
1206 struct block *b0, *b1;
1207
1208 switch (proto) {
1209
1210 case Q_TCP:
1211 b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
1212#ifdef INET6
1213 b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
1214 gen_or(b0, b1);
1215#endif
1216 break;
1217
1218 case Q_UDP:
1219 b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
1220#ifdef INET6
1221 b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
1222 gen_or(b0, b1);
1223#endif
1224 break;
1225
1226 case Q_ICMP:
1227 b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
1228 break;
1229
1230 case Q_IGMP:
1231 b1 = gen_proto(2, Q_IP, Q_DEFAULT);
1232 break;
1233
1234#ifndef IPPROTO_IGRP
1235#define IPPROTO_IGRP 9
1236#endif
1237 case Q_IGRP:
1238 b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
1239 break;
1240
1241#ifndef IPPROTO_PIM
1242#define IPPROTO_PIM 103
1243#endif
1244
1245 case Q_PIM:
1246 b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
1247#ifdef INET6
1248 b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
1249 gen_or(b0, b1);
1250#endif
1251 break;
1252
1253 case Q_IP:
1254 b1 = gen_linktype(ETHERTYPE_IP);
1255 break;
1256
1257 case Q_ARP:
1258 b1 = gen_linktype(ETHERTYPE_ARP);
1259 break;
1260
--- 23 unchanged lines hidden (view full) ---
1284 case Q_MOPDL:
1285 b1 = gen_linktype(ETHERTYPE_MOPDL);
1286 break;
1287
1288 case Q_MOPRC:
1289 b1 = gen_linktype(ETHERTYPE_MOPRC);
1290 break;
1291
1292#ifdef INET6
1293 case Q_IPV6:
1294 b1 = gen_linktype(ETHERTYPE_IPV6);
1295 break;
1296
1297#ifndef IPPROTO_ICMPV6
1298#define IPPROTO_ICMPV6 58
1299#endif
1300 case Q_ICMPV6:
1301 b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
1302 break;
1303#endif /* INET6 */
1304
1305#ifndef IPPROTO_AH
1306#define IPPROTO_AH 51
1307#endif
1308 case Q_AH:
1309 b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
1310#ifdef INET6
1311 b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
1312 gen_or(b0, b1);
1313#endif
1314 break;
1315
1316#ifndef IPPROTO_ESP
1317#define IPPROTO_ESP 50
1318#endif
1319 case Q_ESP:
1320 b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
1321#ifdef INET6
1322 b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
1323 gen_or(b0, b1);
1324#endif
1325 break;
1326
1327 case Q_ISO:
1328 b1 = gen_linktype(LLC_ISO_LSAP);
1329 break;
1330
1331 case Q_ESIS:
1332 b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
1333 break;
1334
--- 40 unchanged lines hidden (view full) ---
1375
1376 b = new_block(JMP(BPF_JEQ));
1377 b->stmts = s;
1378 b->s.k = v;
1379
1380 return b;
1381}
1382
1383#ifdef INET6
1384static struct block *
1385gen_portatom6(off, v)
1386 int off;
1387 bpf_int32 v;
1388{
1389 return gen_cmp(off_nl + 40 + off, BPF_H, v);
1390}
1391#endif/*INET6*/
1392
1393struct block *
1394gen_portop(port, proto, dir)
1395 int port, proto, dir;
1396{
1397 struct block *b0, *b1, *tmp;
1398
1399 /* ip proto 'proto' */
1400 tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);
--- 55 unchanged lines hidden (view full) ---
1456
1457 default:
1458 abort();
1459 }
1460 gen_and(b0, b1);
1461 return b1;
1462}
1463
1464#ifdef INET6
1465struct block *
1466gen_portop6(port, proto, dir)
1467 int port, proto, dir;
1468{
1469 struct block *b0, *b1, *tmp;
1470
1471 /* ip proto 'proto' */
1472 b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto);
1473
1474 switch (dir) {
1475 case Q_SRC:
1476 b1 = gen_portatom6(0, (bpf_int32)port);
1477 break;
1478
1479 case Q_DST:
1480 b1 = gen_portatom6(2, (bpf_int32)port);
1481 break;
1482
1483 case Q_OR:
1484 case Q_DEFAULT:
1485 tmp = gen_portatom6(0, (bpf_int32)port);
1486 b1 = gen_portatom6(2, (bpf_int32)port);
1487 gen_or(tmp, b1);
1488 break;
1489
1490 case Q_AND:
1491 tmp = gen_portatom6(0, (bpf_int32)port);
1492 b1 = gen_portatom6(2, (bpf_int32)port);
1493 gen_and(tmp, b1);
1494 break;
1495
1496 default:
1497 abort();
1498 }
1499 gen_and(b0, b1);
1500
1501 return b1;
1502}
1503
1504static struct block *
1505gen_port6(port, ip_proto, dir)
1506 int port;
1507 int ip_proto;
1508 int dir;
1509{
1510 struct block *b0, *b1, *tmp;
1511
1512 /* ether proto ip */
1513 b0 = gen_linktype(ETHERTYPE_IPV6);
1514
1515 switch (ip_proto) {
1516 case IPPROTO_UDP:
1517 case IPPROTO_TCP:
1518 b1 = gen_portop6(port, ip_proto, dir);
1519 break;
1520
1521 case PROTO_UNDEF:
1522 tmp = gen_portop6(port, IPPROTO_TCP, dir);
1523 b1 = gen_portop6(port, IPPROTO_UDP, dir);
1524 gen_or(tmp, b1);
1525 break;
1526
1527 default:
1528 abort();
1529 }
1530 gen_and(b0, b1);
1531 return b1;
1532}
1533#endif /* INET6 */
1534
1535static int
1536lookup_proto(name, proto)
1537 register const char *name;
1538 register int proto;
1539{
1540 register int v;
1541
1542 switch (proto) {
--- 14 unchanged lines hidden (view full) ---
1557
1558 default:
1559 v = PROTO_UNDEF;
1560 break;
1561 }
1562 return v;
1563}
1564
1565struct stmt *
1566gen_joinsp(s, n)
1567 struct stmt **s;
1568 int n;
1569{
1570}
1571
1572struct block *
1573gen_protochain(v, proto, dir)
1574 int v;
1575 int proto;
1576 int dir;
1577{
1578#ifdef NO_PROTOCHAIN
1579 return gen_proto(v, proto, dir);
1580#else
1581 struct block *b0, *b;
1582 struct slist *s[100], *sp;
1583 int fix2, fix3, fix4, fix5;
1584 int ahcheck, again, end;
1585 int i, max;
1586 int reg1 = alloc_reg();
1587 int reg2 = alloc_reg();
1588
1589 memset(s, 0, sizeof(s));
1590 fix2 = fix3 = fix4 = fix5 = 0;
1591
1592 switch (proto) {
1593 case Q_IP:
1594 case Q_IPV6:
1595 break;
1596 case Q_DEFAULT:
1597 b0 = gen_protochain(v, Q_IP, dir);
1598 b = gen_protochain(v, Q_IPV6, dir);
1599 gen_or(b0, b);
1600 return b;
1601 default:
1602 bpf_error("bad protocol applied for 'protochain'");
1603 /*NOTREACHED*/
1604 }
1605
1606 no_optimize = 1; /*this code is not compatible with optimzer yet */
1607
1608 /*
1609 * s[0] is a dummy entry to protect other BPF insn from damaged
1610 * by s[fix] = foo with uninitialized variable "fix". It is somewhat
1611 * hard to find interdependency made by jump table fixup.
1612 */
1613 i = 0;
1614 s[i] = new_stmt(0); /*dummy*/
1615 i++;
1616
1617 switch (proto) {
1618 case Q_IP:
1619 b0 = gen_linktype(ETHERTYPE_IP);
1620
1621 /* A = ip->ip_p */
1622 s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
1623 s[i]->s.k = off_nl + 9;
1624 i++;
1625 /* X = ip->ip_hl << 2 */
1626 s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
1627 s[i]->s.k = off_nl;
1628 i++;
1629 break;
1630#ifdef INET6
1631 case Q_IPV6:
1632 b0 = gen_linktype(ETHERTYPE_IPV6);
1633
1634 /* A = ip6->ip_nxt */
1635 s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
1636 s[i]->s.k = off_nl + 6;
1637 i++;
1638 /* X = sizeof(struct ip6_hdr) */
1639 s[i] = new_stmt(BPF_LDX|BPF_IMM);
1640 s[i]->s.k = 40;
1641 i++;
1642 break;
1643#endif
1644 default:
1645 bpf_error("unsupported proto to gen_protochain");
1646 /*NOTREACHED*/
1647 }
1648
1649 /* again: if (A == v) goto end; else fall through; */
1650 again = i;
1651 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1652 s[i]->s.k = v;
1653 s[i]->s.jt = NULL; /*later*/
1654 s[i]->s.jf = NULL; /*update in next stmt*/
1655 fix5 = i;
1656 i++;
1657
1658#ifndef IPPROTO_NONE
1659#define IPPROTO_NONE 59
1660#endif
1661 /* if (A == IPPROTO_NONE) goto end */
1662 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1663 s[i]->s.jt = NULL; /*later*/
1664 s[i]->s.jf = NULL; /*update in next stmt*/
1665 s[i]->s.k = IPPROTO_NONE;
1666 s[fix5]->s.jf = s[i];
1667 fix2 = i;
1668 i++;
1669
1670#ifdef INET6
1671 if (proto == Q_IPV6) {
1672 int v6start, v6end, v6advance, j;
1673
1674 v6start = i;
1675 /* if (A == IPPROTO_HOPOPTS) goto v6advance */
1676 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1677 s[i]->s.jt = NULL; /*later*/
1678 s[i]->s.jf = NULL; /*update in next stmt*/
1679 s[i]->s.k = IPPROTO_HOPOPTS;
1680 s[fix2]->s.jf = s[i];
1681 i++;
1682 /* if (A == IPPROTO_DSTOPTS) goto v6advance */
1683 s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1684 s[i]->s.jt = NULL; /*later*/
1685 s[i]->s.jf = NULL; /*update in next stmt*/
1686 s[i]->s.k = IPPROTO_DSTOPTS;
1687 i++;
1688 /* if (A == IPPROTO_ROUTING) goto v6advance */
1689 s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1690 s[i]->s.jt = NULL; /*later*/
1691 s[i]->s.jf = NULL; /*update in next stmt*/
1692 s[i]->s.k = IPPROTO_ROUTING;
1693 i++;
1694 /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
1695 s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1696 s[i]->s.jt = NULL; /*later*/
1697 s[i]->s.jf = NULL; /*later*/
1698 s[i]->s.k = IPPROTO_FRAGMENT;
1699 fix3 = i;
1700 v6end = i;
1701 i++;
1702
1703 /* v6advance: */
1704 v6advance = i;
1705
1706 /*
1707 * in short,
1708 * A = P[X + 1];
1709 * X = X + (P[X] + 1) * 8;
1710 */
1711 /* A = X */
1712 s[i] = new_stmt(BPF_MISC|BPF_TXA);
1713 i++;
1714 /* MEM[reg1] = A */
1715 s[i] = new_stmt(BPF_ST);
1716 s[i]->s.k = reg1;
1717 i++;
1718 /* A += 1 */
1719 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1720 s[i]->s.k = 1;
1721 i++;
1722 /* X = A */
1723 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1724 i++;
1725 /* A = P[X + packet head]; */
1726 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1727 s[i]->s.k = off_nl;
1728 i++;
1729 /* MEM[reg2] = A */
1730 s[i] = new_stmt(BPF_ST);
1731 s[i]->s.k = reg2;
1732 i++;
1733 /* X = MEM[reg1] */
1734 s[i] = new_stmt(BPF_LDX|BPF_MEM);
1735 s[i]->s.k = reg1;
1736 i++;
1737 /* A = P[X + packet head] */
1738 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1739 s[i]->s.k = off_nl;
1740 i++;
1741 /* A += 1 */
1742 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1743 s[i]->s.k = 1;
1744 i++;
1745 /* A *= 8 */
1746 s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
1747 s[i]->s.k = 8;
1748 i++;
1749 /* X = A; */
1750 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1751 i++;
1752 /* A = MEM[reg2] */
1753 s[i] = new_stmt(BPF_LD|BPF_MEM);
1754 s[i]->s.k = reg2;
1755 i++;
1756
1757 /* goto again; (must use BPF_JA for backward jump) */
1758 s[i] = new_stmt(BPF_JMP|BPF_JA);
1759 s[i]->s.k = again - i - 1;
1760 s[i - 1]->s.jf = s[i];
1761 i++;
1762
1763 /* fixup */
1764 for (j = v6start; j <= v6end; j++)
1765 s[j]->s.jt = s[v6advance];
1766 } else
1767#endif
1768 {
1769 /* nop */
1770 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1771 s[i]->s.k = 0;
1772 s[fix2]->s.jf = s[i];
1773 i++;
1774 }
1775
1776 /* ahcheck: */
1777 ahcheck = i;
1778 /* if (A == IPPROTO_AH) then fall through; else goto end; */
1779 s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
1780 s[i]->s.jt = NULL; /*later*/
1781 s[i]->s.jf = NULL; /*later*/
1782 s[i]->s.k = IPPROTO_AH;
1783 if (fix3)
1784 s[fix3]->s.jf = s[ahcheck];
1785 fix4 = i;
1786 i++;
1787
1788 /*
1789 * in short,
1790 * A = P[X + 1];
1791 * X = X + (P[X] + 2) * 4;
1792 */
1793 /* A = X */
1794 s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
1795 i++;
1796 /* MEM[reg1] = A */
1797 s[i] = new_stmt(BPF_ST);
1798 s[i]->s.k = reg1;
1799 i++;
1800 /* A += 1 */
1801 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1802 s[i]->s.k = 1;
1803 i++;
1804 /* X = A */
1805 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1806 i++;
1807 /* A = P[X + packet head]; */
1808 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1809 s[i]->s.k = off_nl;
1810 i++;
1811 /* MEM[reg2] = A */
1812 s[i] = new_stmt(BPF_ST);
1813 s[i]->s.k = reg2;
1814 i++;
1815 /* X = MEM[reg1] */
1816 s[i] = new_stmt(BPF_LDX|BPF_MEM);
1817 s[i]->s.k = reg1;
1818 i++;
1819 /* A = P[X + packet head] */
1820 s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
1821 s[i]->s.k = off_nl;
1822 i++;
1823 /* A += 2 */
1824 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1825 s[i]->s.k = 2;
1826 i++;
1827 /* A *= 4 */
1828 s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
1829 s[i]->s.k = 4;
1830 i++;
1831 /* X = A; */
1832 s[i] = new_stmt(BPF_MISC|BPF_TAX);
1833 i++;
1834 /* A = MEM[reg2] */
1835 s[i] = new_stmt(BPF_LD|BPF_MEM);
1836 s[i]->s.k = reg2;
1837 i++;
1838
1839 /* goto again; (must use BPF_JA for backward jump) */
1840 s[i] = new_stmt(BPF_JMP|BPF_JA);
1841 s[i]->s.k = again - i - 1;
1842 i++;
1843
1844 /* end: nop */
1845 end = i;
1846 s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
1847 s[i]->s.k = 0;
1848 s[fix2]->s.jt = s[end];
1849 s[fix4]->s.jf = s[end];
1850 s[fix5]->s.jt = s[end];
1851 i++;
1852
1853 /*
1854 * make slist chain
1855 */
1856 max = i;
1857 for (i = 0; i < max - 1; i++)
1858 s[i]->next = s[i + 1];
1859 s[max - 1]->next = NULL;
1860
1861 /*
1862 * emit final check
1863 */
1864 b = new_block(JMP(BPF_JEQ));
1865 b->stmts = s[1]; /*remember, s[0] is dummy*/
1866 b->s.k = v;
1867
1868 free_reg(reg1);
1869 free_reg(reg2);
1870
1871 gen_and(b0, b);
1872 return b;
1873#endif
1874}
1875
1876static struct block *
1877gen_proto(v, proto, dir)
1878 int v;
1879 int proto;
1880 int dir;
1881{
1882 struct block *b0, *b1;
1883
1884 if (dir != Q_DEFAULT)
1885 bpf_error("direction applied to 'proto'");
1886
1887 switch (proto) {
1888 case Q_DEFAULT:
1889#ifdef INET6
1890 b0 = gen_proto(v, Q_IP, dir);
1891 b1 = gen_proto(v, Q_IPV6, dir);
1892 gen_or(b0, b1);
1893 return b1;
1894#else
1895 /*FALLTHROUGH*/
1896#endif
1897 case Q_IP:
1898 b0 = gen_linktype(ETHERTYPE_IP);
1899#ifndef CHASE_CHAIN
1900 b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v);
1901#else
1902 b1 = gen_protochain(v, Q_IP);
1903#endif
1904 gen_and(b0, b1);
1905 return b1;
1906
1907 case Q_ISO:
1908 b0 = gen_linktype(LLC_ISO_LSAP);
1909 b1 = gen_cmp(off_nl + 3, BPF_B, (long)v);
1910 gen_and(b0, b1);
1911 return b1;
--- 48 unchanged lines hidden (view full) ---
1960 case Q_IGMP:
1961 bpf_error("'igmp proto' is bogus");
1962 /* NOTREACHED */
1963
1964 case Q_IGRP:
1965 bpf_error("'igrp proto' is bogus");
1966 /* NOTREACHED */
1967
1968 case Q_PIM:
1969 bpf_error("'pim proto' is bogus");
1970 /* NOTREACHED */
1971
1972#ifdef INET6
1973 case Q_IPV6:
1974 b0 = gen_linktype(ETHERTYPE_IPV6);
1975#ifndef CHASE_CHAIN
1976 b1 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)v);
1977#else
1978 b1 = gen_protochain(v, Q_IPV6);
1979#endif
1980 gen_and(b0, b1);
1981 return b1;
1982
1983 case Q_ICMPV6:
1984 bpf_error("'icmp6 proto' is bogus");
1985#endif /* INET6 */
1986
1987 case Q_AH:
1988 bpf_error("'ah proto' is bogus");
1989
1990 case Q_ESP:
1991 bpf_error("'ah proto' is bogus");
1992
1993 default:
1994 abort();
1995 /* NOTREACHED */
1996 }
1997 /* NOTREACHED */
1998}
1999
2000struct block *
2001gen_scode(name, q)
2002 register const char *name;
2003 struct qual q;
2004{
2005 int proto = q.proto;
2006 int dir = q.dir;
2007 int tproto;
2008 u_char *eaddr;
2009 bpf_u_int32 mask, addr, **alist;
2010#ifdef INET6
2011 int tproto6;
2012 struct sockaddr_in *sin;
2013 struct sockaddr_in6 *sin6;
2014 struct addrinfo *res, *res0;
2015 struct in6_addr mask128;
2016#endif /*INET6*/
2017 struct block *b, *tmp;
2018 int port, real_proto;
2019
2020 switch (q.addr) {
2021
2022 case Q_NET:
2023 addr = pcap_nametonetaddr(name);
2024 if (addr == 0)
--- 33 unchanged lines hidden (view full) ---
2058 } else if (proto == Q_DECNET) {
2059 unsigned short dn_addr = __pcap_nametodnaddr(name);
2060 /*
2061 * I don't think DECNET hosts can be multihomed, so
2062 * there is no need to build up a list of addresses
2063 */
2064 return (gen_host(dn_addr, 0, proto, dir));
2065 } else {
2066#ifndef INET6
2067 alist = pcap_nametoaddr(name);
2068 if (alist == NULL || *alist == NULL)
2069 bpf_error("unknown host '%s'", name);
2070 tproto = proto;
2071 if (off_linktype == -1 && tproto == Q_DEFAULT)
2072 tproto = Q_IP;
2073 b = gen_host(**alist++, 0xffffffff, tproto, dir);
2074 while (*alist) {
2075 tmp = gen_host(**alist++, 0xffffffff,
2076 tproto, dir);
2077 gen_or(b, tmp);
2078 b = tmp;
2079 }
2080 return b;
2081#else
2082 memset(&mask128, 0xff, sizeof(mask128));
2083 res0 = res = pcap_nametoaddr(name);
2084 if (res == NULL)
2085 bpf_error("unknown host '%s'", name);
2086 b = tmp = NULL;
2087 tproto = tproto6 = proto;
2088 if (off_linktype == -1 && tproto == Q_DEFAULT) {
2089 tproto = Q_IP;
2090 tproto6 = Q_IPV6;
2091 }
2092 while (res) {
2093 switch (res->ai_family) {
2094 case AF_INET:
2095 sin = (struct sockaddr_in *)
2096 res->ai_addr;
2097 tmp = gen_host(ntohl(sin->sin_addr.s_addr),
2098 0xffffffff, tproto, dir);
2099 break;
2100 case AF_INET6:
2101 sin6 = (struct sockaddr_in6 *)
2102 res->ai_addr;
2103 tmp = gen_host6(&sin6->sin6_addr,
2104 &mask128, tproto6, dir);
2105 break;
2106 }
2107 if (b)
2108 gen_or(b, tmp);
2109 b = tmp;
2110
2111 res = res->ai_next;
2112 }
2113 freeaddrinfo(res0);
2114 return b;
2115#endif /*INET6*/
2116 }
2117
2118 case Q_PORT:
2119 if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP)
2120 bpf_error("illegal qualifier of 'port'");
2121 if (pcap_nametoport(name, &port, &real_proto) == 0)
2122 bpf_error("unknown port '%s'", name);
2123 if (proto == Q_UDP) {
--- 5 unchanged lines hidden (view full) ---
2129 }
2130 if (proto == Q_TCP) {
2131 if (real_proto == IPPROTO_UDP)
2132 bpf_error("port '%s' is udp", name);
2133 else
2134 /* override PROTO_UNDEF */
2135 real_proto = IPPROTO_TCP;
2136 }
2137#ifndef INET6
2138 return gen_port(port, real_proto, dir);
2139#else
2140 {
2141 struct block *b;
2142 b = gen_port(port, real_proto, dir);
2143 gen_or(gen_port6(port, real_proto, dir), b);
2144 return b;
2145 }
2146#endif /* INET6 */
2147
2148 case Q_GATEWAY:
2149#ifndef INET6
2150 eaddr = pcap_ether_hostton(name);
2151 if (eaddr == NULL)
2152 bpf_error("unknown ether host: %s", name);
2153
2154 alist = pcap_nametoaddr(name);
2155 if (alist == NULL || *alist == NULL)
2156 bpf_error("unknown host '%s'", name);
2157 return gen_gateway(eaddr, alist, proto, dir);
2158#else
2159 bpf_error("'gateway' not supported in this configuration");
2160#endif /*INET6*/
2161
2162 case Q_PROTO:
2163 real_proto = lookup_proto(name, proto);
2164 if (real_proto >= 0)
2165 return gen_proto(real_proto, proto, dir);
2166 else
2167 bpf_error("unknown protocol: %s", name);
2168
2169 case Q_PROTOCHAIN:
2170 real_proto = lookup_proto(name, proto);
2171 if (real_proto >= 0)
2172 return gen_protochain(real_proto, proto, dir);
2173 else
2174 bpf_error("unknown protocol: %s", name);
2175
2176
2177 case Q_UNDEF:
2178 syntax();
2179 /* NOTREACHED */
2180 }
2181 abort();
2182 /* NOTREACHED */
2183}
2184
--- 86 unchanged lines hidden (view full) ---
2271 proto = IPPROTO_UDP;
2272 else if (proto == Q_TCP)
2273 proto = IPPROTO_TCP;
2274 else if (proto == Q_DEFAULT)
2275 proto = PROTO_UNDEF;
2276 else
2277 bpf_error("illegal qualifier of 'port'");
2278
2279#ifndef INET6
2280 return gen_port((int)v, proto, dir);
2281#else
2282 {
2283 struct block *b;
2284 b = gen_port((int)v, proto, dir);
2285 gen_or(gen_port6((int)v, proto, dir), b);
2286 return b;
2287 }
2288#endif /* INET6 */
2289
2290 case Q_GATEWAY:
2291 bpf_error("'gateway' requires a name");
2292 /* NOTREACHED */
2293
2294 case Q_PROTO:
2295 return gen_proto((int)v, proto, dir);
2296
2297 case Q_PROTOCHAIN:
2298 return gen_protochain((int)v, proto, dir);
2299
2300 case Q_UNDEF:
2301 syntax();
2302 /* NOTREACHED */
2303
2304 default:
2305 abort();
2306 /* NOTREACHED */
2307 }
2308 /* NOTREACHED */
2309}
2310
2311#ifdef INET6
2312struct block *
2313gen_mcode6(s1, s2, masklen, q)
2314 register const char *s1, *s2;
2315 register int masklen;
2316 struct qual q;
2317{
2318 struct addrinfo *res;
2319 struct in6_addr *addr;
2320 struct in6_addr mask;
2321 struct block *b;
2322 u_int32_t *a, *m;
2323
2324 if (s2)
2325 bpf_error("no mask %s supported", s2);
2326
2327 res = pcap_nametoaddr(s1);
2328 if (!res)
2329 bpf_error("invalid ip6 address %s", s1);
2330 if (res->ai_next)
2331 bpf_error("%s resolved to multiple address", s1);
2332 addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
2333
2334 if (sizeof(mask) * 8 < masklen)
2335 bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
2336 memset(&mask, 0xff, masklen / 8);
2337 if (masklen % 8) {
2338 mask.s6_addr[masklen / 8] =
2339 (0xff << (8 - masklen % 8)) & 0xff;
2340 }
2341
2342 a = (u_int32_t *)addr;
2343 m = (u_int32_t *)&mask;
2344 if ((a[0] & ~m[0]) || (a[1] & ~m[1])
2345 || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
2346 bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
2347 }
2348
2349 switch (q.addr) {
2350
2351 case Q_DEFAULT:
2352 case Q_HOST:
2353 if (masklen != 128)
2354 bpf_error("Mask syntax for networks only");
2355 /* FALLTHROUGH */
2356
2357 case Q_NET:
2358 b = gen_host6(addr, &mask, q.proto, q.dir);
2359 freeaddrinfo(res);
2360 return b;
2361
2362 default:
2363 bpf_error("invalid qualifier against IPv6 address");
2364 /* NOTREACHED */
2365 }
2366}
2367#endif /*INET6*/
2368
2369struct block *
2370gen_ecode(eaddr, q)
2371 register const u_char *eaddr;
2372 struct qual q;
2373{
2374 if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
2375 if (linktype == DLT_EN10MB)
2376 return gen_ehostop(eaddr, (int)q.dir);
2377 if (linktype == DLT_FDDI)
--- 81 unchanged lines hidden (view full) ---
2459 case Q_ARP:
2460 case Q_RARP:
2461 case Q_ATALK:
2462 case Q_DECNET:
2463 case Q_SCA:
2464 case Q_LAT:
2465 case Q_MOPRC:
2466 case Q_MOPDL:
2467#ifdef INET6
2468 case Q_IPV6:
2469#endif
2470 /* XXX Note that we assume a fixed link header here. */
2471 s = xfer_to_x(index);
2472 tmp = new_stmt(BPF_LD|BPF_IND|size);
2473 tmp->s.k = off_nl;
2474 sappend(s, tmp);
2475 sappend(index->s, s);
2476
2477 b = gen_proto_abbrev(proto);
2478 if (index->b)
2479 gen_and(index->b, b);
2480 index->b = b;
2481 break;
2482
2483 case Q_TCP:
2484 case Q_UDP:
2485 case Q_ICMP:
2486 case Q_IGMP:
2487 case Q_IGRP:
2488 case Q_PIM:
2489 s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
2490 s->s.k = off_nl;
2491 sappend(s, xfer_to_a(index));
2492 sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
2493 sappend(s, new_stmt(BPF_MISC|BPF_TAX));
2494 sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
2495 tmp->s.k = off_nl;
2496 sappend(index->s, s);
2497
2498 gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
2499 if (index->b)
2500 gen_and(index->b, b);
2501#ifdef INET6
2502 gen_and(gen_proto_abbrev(Q_IP), b);
2503#endif
2504 index->b = b;
2505 break;
2506#ifdef INET6
2507 case Q_ICMPV6:
2508 bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
2509 /*NOTREACHED*/
2510#endif
2511 }
2512 index->regno = regno;
2513 s = new_stmt(BPF_ST);
2514 s->s.k = regno;
2515 sappend(index->s, s);
2516
2517 return index;
2518}
--- 309 unchanged lines hidden (view full) ---
2828 break;
2829
2830 case Q_IP:
2831 b0 = gen_linktype(ETHERTYPE_IP);
2832 b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224);
2833 b1->s.code = JMP(BPF_JGE);
2834 gen_and(b0, b1);
2835 return b1;
2836
2837#ifdef INET6
2838 case Q_IPV6:
2839 b0 = gen_linktype(ETHERTYPE_IPV6);
2840 b1 = gen_cmp(off_nl + 24, BPF_B, (bpf_int32)255);
2841 gen_and(b0, b1);
2842 return b1;
2843#endif /* INET6 */
2844 }
2845 bpf_error("only IP multicast filters supported on ethernet/FDDI");
2846}
2847
2848/*
2849 * generate command for inbound/outbound. It's here so we can
2850 * make it link-type specific. 'dir' = 0 implies "inbound",
2851 * = 1 implies "outbound".
--- 13 unchanged lines hidden ---