1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <stddef.h>
36 #include <unistd.h>
37 #include <stropts.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/vlan.h>
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <netinet/ip.h>
44 #include <inet/ip6.h>
45 #include <inet/ip.h>
46 #include <netinet/if_ether.h>
47 #include <netinet/tcp.h>
48 #include <netinet/udp.h>
49 #include <netdb.h>
50 #include <arpa/inet.h>
51 #include <rpc/rpc.h>
52 #include <rpc/rpcent.h>
53 #include <sys/dlpi.h>
54
55 #include <snoop.h>
56 #include "snoop_vlan.h"
57
58 #define IPV4_ONLY 0
59 #define IPV6_ONLY 1
60 #define IPV4_AND_IPV6 2
61
62 /*
63 * The following constants represent the offsets in bytes from the beginning
64 * of the IP(v6) header of the source and destination IP(v6) addresses.
65 * These are useful when generating filter code.
66 */
67 #define IPV4_SRCADDR_OFFSET 12
68 #define IPV4_DSTADDR_OFFSET 16
69 #define IPV6_SRCADDR_OFFSET 8
70 #define IPV6_DSTADDR_OFFSET 24
71 #define IP_VERS(p) (((*(uchar_t *)p) & 0xf0) >> 4)
72 #define MASKED_IPV4_VERS 0x40
73 #define MASKED_IPV6_VERS 0x60
74 #define IP_HDR_LEN(p) (((*(uchar_t *)p) & 0xf) * 4)
75 #define TCP_HDR_LEN(p) ((((*((uchar_t *)p+12)) >> 4) & 0xf) * 4)
76
77 /*
78 * Coding the constant below is tacky, but the compiler won't let us
79 * be more clever. E.g., &((struct ip *)0)->ip_xxx
80 */
81 #define IP_PROTO_OF(p) (((uchar_t *)p)[9])
82
83 /*
84 * AppleTalk uses 802.2 Ethernet encapsulation with LLC/SNAP headers,
85 * for 8 octets of overhead, and the common AppleTalk DDP Ethernet
86 * header is another 4 octets.
87 *
88 * The following constants represents the offsets in bytes from the beginning
89 * of the Ethernet payload to various parts of the DDP header.
90 */
91
92 #define AT_DST_NET_OFFSET 12
93 #define AT_SRC_NET_OFFSET 14
94 #define AT_DST_NODE_OFFSET 16
95 #define AT_SRC_NODE_OFFSET 17
96
97 /*
98 * Offset for the source and destination zoneid in the ipnet header.
99 */
100 #define IPNET_SRCZONE_OFFSET 16
101 #define IPNET_DSTZONE_OFFSET 20
102
103 int eaddr; /* need ethernet addr */
104
105 int opstack; /* operand stack depth */
106
107 /*
108 * These are the operators of the user-level filter.
109 * STOP ends execution of the filter expression and
110 * returns the truth value at the top of the stack.
111 * OP_LOAD_OCTET, OP_LOAD_SHORT and OP_LOAD_LONG pop
112 * an offset value from the stack and load a value of
113 * an appropriate size from the packet (octet, short or
114 * long). The offset is computed from a base value that
115 * may be set via the OP_OFFSET operators.
116 * OP_EQ, OP_NE, OP_GT, OP_GE, OP_LT, OP_LE pop two values
117 * from the stack and return the result of their comparison.
118 * OP_AND, OP_OR, OP_XOR pop two values from the stack and
119 * do perform a bitwise operation on them - returning a result
120 * to the stack. OP_NOT inverts the bits of the value on the
121 * stack.
122 * OP_BRFL and OP_BRTR branch to an offset in the code array
123 * depending on the value at the top of the stack: true (not 0)
124 * or false (0).
125 * OP_ADD, OP_SUB, OP_MUL, OP_DIV and OP_REM pop two values
126 * from the stack and perform arithmetic.
127 * The OP_OFFSET operators change the base from which the
128 * OP_LOAD operators compute their offsets.
129 * OP_OFFSET_ZERO sets the offset to zero - beginning of packet.
130 * OP_OFFSET_LINK sets the base to the first octet after
131 * the link (DLC) header. OP_OFFSET_IP, OP_OFFSET_TCP,
132 * and OP_OFFSET_UDP do the same for those headers - they
133 * set the offset base to the *end* of the header - not the
134 * beginning. The OP_OFFSET_RPC operator is a bit unusual.
135 * It points the base at the cached RPC header. For the
136 * purposes of selection, RPC reply headers look like call
137 * headers except for the direction value.
138 * OP_OFFSET_ETHERTYPE sets base according to the following
139 * algorithm:
140 * if the packet is not VLAN tagged, then set base to
141 * the ethertype field in the ethernet header
142 * else set base to the ethertype field of the VLAN header
143 * OP_OFFSET_POP restores the offset base to the value prior
144 * to the most recent OP_OFFSET call.
145 */
146 enum optype {
147 OP_STOP = 0,
148 OP_LOAD_OCTET,
149 OP_LOAD_SHORT,
150 OP_LOAD_LONG,
151 OP_LOAD_CONST,
152 OP_LOAD_LENGTH,
153 OP_EQ,
154 OP_NE,
155 OP_GT,
156 OP_GE,
157 OP_LT,
158 OP_LE,
159 OP_AND,
160 OP_OR,
161 OP_XOR,
162 OP_NOT,
163 OP_BRFL,
164 OP_BRTR,
165 OP_ADD,
166 OP_SUB,
167 OP_MUL,
168 OP_DIV,
169 OP_REM,
170 OP_OFFSET_POP,
171 OP_OFFSET_ZERO,
172 OP_OFFSET_LINK,
173 OP_OFFSET_IP,
174 OP_OFFSET_TCP,
175 OP_OFFSET_UDP,
176 OP_OFFSET_RPC,
177 OP_OFFSET_SLP,
178 OP_OFFSET_ETHERTYPE,
179 OP_LAST
180 };
181
182 static char *opnames[] = {
183 "STOP",
184 "LOAD_OCTET",
185 "LOAD_SHORT",
186 "LOAD_LONG",
187 "LOAD_CONST",
188 "LOAD_LENGTH",
189 "EQ",
190 "NE",
191 "GT",
192 "GE",
193 "LT",
194 "LE",
195 "AND",
196 "OR",
197 "XOR",
198 "NOT",
199 "BRFL",
200 "BRTR",
201 "ADD",
202 "SUB",
203 "MUL",
204 "DIV",
205 "REM",
206 "OFFSET_POP",
207 "OFFSET_ZERO",
208 "OFFSET_ETHER",
209 "OFFSET_IP",
210 "OFFSET_TCP",
211 "OFFSET_UDP",
212 "OFFSET_RPC",
213 "OP_OFFSET_SLP",
214 "OFFSET_ETHERTYPE",
215 ""
216 };
217
218 #define MAXOPS 1024
219 #define MAXSS 64
220 static uint_t oplist[MAXOPS]; /* array of operators */
221 static uint_t *curr_op; /* last op generated */
222
223 extern int valid_slp(uchar_t *, int); /* decides if a SLP msg is valid */
224 extern struct hostent *lgetipnodebyname(const char *, int, int, int *);
225
226 static void alternation();
227 static uint_t chain();
228 static void codeprint();
229 static void emitop();
230 static void emitval();
231 static void expression();
232 static struct xid_entry *find_rpc();
233 static void optimize();
234 static void ethertype_match();
235
236 /*
237 * Get a ushort from a possibly unaligned character buffer.
238 *
239 * INPUTS: buffer - where the data is. Must be at least
240 * sizeof(uint16_t) bytes long.
241 * OUPUTS: An unsigned short that contains the data at buffer.
242 * No calls to ntohs or htons are done on the data.
243 */
244 static uint16_t
get_u16(uchar_t * buffer)245 get_u16(uchar_t *buffer)
246 {
247 uint8_t *bufraw = buffer;
248
249 /*
250 * ntohs is used only as a cheap way to flip the bits
251 * around on a little endian platform. The value will
252 * still be in host order or network order, depending on
253 * the order it was in when it was passed in.
254 */
255 return (ntohs(bufraw[0] << 8 | bufraw[1]));
256 }
257
258 /*
259 * Returns the ULP for an IPv4 or IPv6 packet
260 * Assumes that the packet has already been checked to verify
261 * that it's either IPv4 or IPv6
262 *
263 * XXX Will need to be updated for AH and ESP
264 * XXX when IPsec is supported for v6.
265 */
266 static uchar_t
ip_proto_of(uchar_t * ip)267 ip_proto_of(uchar_t *ip)
268 {
269 uchar_t nxt;
270 boolean_t not_done = B_TRUE;
271 uchar_t *ptr = ip;
272
273 switch (IP_VERS(ip)) {
274 case IPV4_VERSION:
275 return (IP_PROTO_OF(ip));
276 case IPV6_VERSION:
277
278 nxt = ip[6];
279 ptr += 40; /* size of ip6 header */
280 do {
281 switch (nxt) {
282 /*
283 * XXX Add IPsec headers here when supported for v6
284 * XXX (the AH will have a different size...)
285 */
286 case IPPROTO_HOPOPTS:
287 case IPPROTO_ROUTING:
288 case IPPROTO_FRAGMENT:
289 case IPPROTO_DSTOPTS:
290 ptr += (8 * (ptr[1] + 1));
291 nxt = *ptr;
292 break;
293
294 default:
295 not_done = B_FALSE;
296 break;
297 }
298 } while (not_done);
299 return (nxt);
300 default:
301 break; /* shouldn't get here... */
302 }
303 return (0);
304 }
305
306 /*
307 * Returns the total IP header length.
308 * For v4, this includes any options present.
309 * For v6, this is the length of the IPv6 header plus
310 * any extension headers present.
311 *
312 * XXX Will need to be updated for AH and ESP
313 * XXX when IPsec is supported for v6.
314 */
315 static int
ip_hdr_len(uchar_t * ip)316 ip_hdr_len(uchar_t *ip)
317 {
318 uchar_t nxt;
319 int hdr_len;
320 boolean_t not_done = B_TRUE;
321 int len = 40; /* IPv6 header size */
322 uchar_t *ptr = ip;
323
324 switch (IP_VERS(ip)) {
325 case IPV4_VERSION:
326 return (IP_HDR_LEN(ip));
327 case IPV6_VERSION:
328 nxt = ip[6];
329 ptr += len;
330 do {
331 switch (nxt) {
332 /*
333 * XXX Add IPsec headers here when supported for v6
334 * XXX (the AH will have a different size...)
335 */
336 case IPPROTO_HOPOPTS:
337 case IPPROTO_ROUTING:
338 case IPPROTO_FRAGMENT:
339 case IPPROTO_DSTOPTS:
340 hdr_len = (8 * (ptr[1] + 1));
341 len += hdr_len;
342 ptr += hdr_len;
343 nxt = *ptr;
344 break;
345
346 default:
347 not_done = B_FALSE;
348 break;
349 }
350 } while (not_done);
351 return (len);
352 default:
353 break;
354 }
355 return (0); /* not IP */
356 }
357
358 static void
codeprint()359 codeprint()
360 {
361 uint_t *op;
362
363 printf("User filter:\n");
364
365 for (op = oplist; *op; op++) {
366 if (*op <= OP_LAST)
367 printf("\t%2d: %s\n", op - oplist, opnames[*op]);
368 else
369 printf("\t%2d: (%d)\n", op - oplist, *op);
370
371 switch (*op) {
372 case OP_LOAD_CONST:
373 case OP_BRTR:
374 case OP_BRFL:
375 op++;
376 if ((int)*op < 0)
377 printf("\t%2d: 0x%08x (%d)\n",
378 op - oplist, *op, *op);
379 else
380 printf("\t%2d: %d (0x%08x)\n",
381 op - oplist, *op, *op);
382 }
383 }
384 printf("\t%2d: STOP\n", op - oplist);
385 printf("\n");
386 }
387
388
389 /*
390 * Take a pass through the generated code and optimize
391 * branches. A branch true (BRTR) that has another BRTR
392 * at its destination can use the address of the destination
393 * BRTR. A BRTR that points to a BRFL (branch false) should
394 * point to the address following the BRFL.
395 * A similar optimization applies to BRFL operators.
396 */
397 static void
optimize(uint_t * oplistp)398 optimize(uint_t *oplistp)
399 {
400 uint_t *op;
401
402 for (op = oplistp; *op; op++) {
403 switch (*op) {
404 case OP_LOAD_CONST:
405 op++;
406 break;
407 case OP_BRTR:
408 op++;
409 optimize(&oplist[*op]);
410 if (oplist[*op] == OP_BRFL)
411 *op += 2;
412 else if (oplist[*op] == OP_BRTR)
413 *op = oplist[*op + 1];
414 break;
415 case OP_BRFL:
416 op++;
417 optimize(&oplist[*op]);
418 if (oplist[*op] == OP_BRTR)
419 *op += 2;
420 else if (oplist[*op] == OP_BRFL)
421 *op = oplist[*op + 1];
422 break;
423 }
424 }
425 }
426
427 /*
428 * RPC packets are tough to filter.
429 * While the call packet has all the interesting
430 * info: program number, version, procedure etc,
431 * the reply packet has none of this information.
432 * If we want to do useful filtering based on this
433 * information then we have to stash the information
434 * from the call packet, and use the XID in the reply
435 * to find the stashed info. The stashed info is
436 * kept in a circular lifo, assuming that a call packet
437 * will be followed quickly by its reply.
438 */
439
440 struct xid_entry {
441 unsigned x_xid; /* The XID (32 bits) */
442 unsigned x_dir; /* CALL or REPLY */
443 unsigned x_rpcvers; /* Protocol version (2) */
444 unsigned x_prog; /* RPC program number */
445 unsigned x_vers; /* RPC version number */
446 unsigned x_proc; /* RPC procedure number */
447 };
448 static struct xid_entry xe_table[XID_CACHE_SIZE];
449 static struct xid_entry *xe_first = &xe_table[0];
450 static struct xid_entry *xe = &xe_table[0];
451 static struct xid_entry *xe_last = &xe_table[XID_CACHE_SIZE - 1];
452
453 static struct xid_entry *
find_rpc(struct rpc_msg * rpc)454 find_rpc(struct rpc_msg *rpc)
455 {
456 struct xid_entry *x;
457
458 for (x = xe; x >= xe_first; x--)
459 if (x->x_xid == rpc->rm_xid)
460 return (x);
461 for (x = xe_last; x > xe; x--)
462 if (x->x_xid == rpc->rm_xid)
463 return (x);
464 return (NULL);
465 }
466
467 static void
stash_rpc(struct rpc_msg * rpc)468 stash_rpc(struct rpc_msg *rpc)
469 {
470 struct xid_entry *x;
471
472 if (find_rpc(rpc))
473 return;
474
475 x = xe++;
476 if (xe > xe_last)
477 xe = xe_first;
478 x->x_xid = rpc->rm_xid;
479 x->x_dir = htonl(REPLY);
480 x->x_prog = rpc->rm_call.cb_prog;
481 x->x_vers = rpc->rm_call.cb_vers;
482 x->x_proc = rpc->rm_call.cb_proc;
483 }
484
485 /*
486 * SLP can multicast requests, and recieve unicast replies in which
487 * neither the source nor destination port is identifiable as a SLP
488 * port. Hence, we need to do as RPC does, and keep track of packets we
489 * are interested in. For SLP, however, we use ports, not XIDs, and
490 * a smaller cache size is more efficient since every incoming packet
491 * needs to be checked.
492 */
493
494 #define SLP_CACHE_SIZE 64
495 static uint_t slp_table[SLP_CACHE_SIZE];
496 static int slp_index = 0;
497
498 /*
499 * Returns the index of dport in the table if found, otherwise -1.
500 */
501 static int
find_slp(uint_t dport)502 find_slp(uint_t dport) {
503 int i;
504
505 if (!dport)
506 return (0);
507
508 for (i = slp_index; i >= 0; i--)
509 if (slp_table[i] == dport) {
510 return (i);
511 }
512 for (i = SLP_CACHE_SIZE - 1; i > slp_index; i--)
513 if (slp_table[i] == dport) {
514 return (i);
515 }
516 return (-1);
517 }
518
stash_slp(uint_t sport)519 static void stash_slp(uint_t sport) {
520 if (slp_table[slp_index - 1] == sport)
521 /* avoid redundancy due to multicast retransmissions */
522 return;
523
524 slp_table[slp_index++] = sport;
525 if (slp_index == SLP_CACHE_SIZE)
526 slp_index = 0;
527 }
528
529 /*
530 * This routine takes a packet and returns true or false
531 * according to whether the filter expression selects it
532 * or not.
533 * We assume here that offsets for short and long values
534 * are even - we may die with an alignment error if the
535 * CPU doesn't support odd addresses. Note that long
536 * values are loaded as two shorts so that 32 bit word
537 * alignment isn't important.
538 *
539 * IPv6 is a bit stickier to handle than IPv4...
540 */
541
542 int
want_packet(uchar_t * pkt,int len,int origlen)543 want_packet(uchar_t *pkt, int len, int origlen)
544 {
545 uint_t stack[MAXSS]; /* operand stack */
546 uint_t *op; /* current operator */
547 uint_t *sp; /* top of operand stack */
548 uchar_t *base; /* base for offsets into packet */
549 uchar_t *ip; /* addr of IP header, unaligned */
550 uchar_t *tcp; /* addr of TCP header, unaligned */
551 uchar_t *udp; /* addr of UDP header, unaligned */
552 struct rpc_msg rpcmsg; /* addr of RPC header */
553 struct rpc_msg *rpc;
554 int newrpc = 0;
555 uchar_t *slphdr; /* beginning of SLP header */
556 uint_t slp_sport, slp_dport;
557 int off, header_size;
558 uchar_t *offstack[MAXSS]; /* offset stack */
559 uchar_t **offp; /* current offset */
560 uchar_t *opkt = NULL;
561 uint_t olen;
562
563 sp = stack;
564 *sp = 1;
565 base = pkt;
566 offp = offstack;
567
568 header_size = (*interface->header_len)((char *)pkt, len);
569
570 for (op = oplist; *op; op++) {
571 switch ((enum optype) *op) {
572 case OP_LOAD_OCTET:
573 if ((base + *sp) > (pkt + len))
574 return (0); /* packet too short */
575
576 *sp = *((uchar_t *)(base + *sp));
577 break;
578 case OP_LOAD_SHORT:
579 off = *sp;
580
581 if ((base + off + sizeof (uint16_t) - 1) > (pkt + len))
582 return (0); /* packet too short */
583
584 *sp = ntohs(get_u16((uchar_t *)(base + off)));
585 break;
586 case OP_LOAD_LONG:
587 off = *sp;
588
589 if ((base + off + sizeof (uint32_t) - 1) > (pkt + len))
590 return (0); /* packet too short */
591
592 /*
593 * Handle 3 possible alignments
594 */
595 switch ((((unsigned)base) + off) % sizeof (uint_t)) {
596 case 0:
597 *sp = *(uint_t *)(base + off);
598 break;
599
600 case 2:
601 *((ushort_t *)(sp)) =
602 *((ushort_t *)(base + off));
603 *(((ushort_t *)sp) + 1) =
604 *((ushort_t *)(base + off) + 1);
605 break;
606
607 case 1:
608 case 3:
609 *((uchar_t *)(sp)) =
610 *((uchar_t *)(base + off));
611 *(((uchar_t *)sp) + 1) =
612 *((uchar_t *)(base + off) + 1);
613 *(((uchar_t *)sp) + 2) =
614 *((uchar_t *)(base + off) + 2);
615 *(((uchar_t *)sp) + 3) =
616 *((uchar_t *)(base + off) + 3);
617 break;
618 }
619 *sp = ntohl(*sp);
620 break;
621 case OP_LOAD_CONST:
622 if (sp >= &stack[MAXSS])
623 return (0);
624 *(++sp) = *(++op);
625 break;
626 case OP_LOAD_LENGTH:
627 if (sp >= &stack[MAXSS])
628 return (0);
629 *(++sp) = origlen;
630 break;
631 case OP_EQ:
632 if (sp < &stack[1])
633 return (0);
634 sp--;
635 *sp = *sp == *(sp + 1);
636 break;
637 case OP_NE:
638 if (sp < &stack[1])
639 return (0);
640 sp--;
641 *sp = *sp != *(sp + 1);
642 break;
643 case OP_GT:
644 if (sp < &stack[1])
645 return (0);
646 sp--;
647 *sp = *sp > *(sp + 1);
648 break;
649 case OP_GE:
650 if (sp < &stack[1])
651 return (0);
652 sp--;
653 *sp = *sp >= *(sp + 1);
654 break;
655 case OP_LT:
656 if (sp < &stack[1])
657 return (0);
658 sp--;
659 *sp = *sp < *(sp + 1);
660 break;
661 case OP_LE:
662 if (sp < &stack[1])
663 return (0);
664 sp--;
665 *sp = *sp <= *(sp + 1);
666 break;
667 case OP_AND:
668 if (sp < &stack[1])
669 return (0);
670 sp--;
671 *sp &= *(sp + 1);
672 break;
673 case OP_OR:
674 if (sp < &stack[1])
675 return (0);
676 sp--;
677 *sp |= *(sp + 1);
678 break;
679 case OP_XOR:
680 if (sp < &stack[1])
681 return (0);
682 sp--;
683 *sp ^= *(sp + 1);
684 break;
685 case OP_NOT:
686 *sp = !*sp;
687 break;
688 case OP_BRFL:
689 op++;
690 if (!*sp)
691 op = &oplist[*op] - 1;
692 break;
693 case OP_BRTR:
694 op++;
695 if (*sp)
696 op = &oplist[*op] - 1;
697 break;
698 case OP_ADD:
699 if (sp < &stack[1])
700 return (0);
701 sp--;
702 *sp += *(sp + 1);
703 break;
704 case OP_SUB:
705 if (sp < &stack[1])
706 return (0);
707 sp--;
708 *sp -= *(sp + 1);
709 break;
710 case OP_MUL:
711 if (sp < &stack[1])
712 return (0);
713 sp--;
714 *sp *= *(sp + 1);
715 break;
716 case OP_DIV:
717 if (sp < &stack[1])
718 return (0);
719 sp--;
720 *sp /= *(sp + 1);
721 break;
722 case OP_REM:
723 if (sp < &stack[1])
724 return (0);
725 sp--;
726 *sp %= *(sp + 1);
727 break;
728 case OP_OFFSET_POP:
729 if (offp < &offstack[0])
730 return (0);
731 base = *offp--;
732 if (opkt != NULL) {
733 pkt = opkt;
734 len = olen;
735 opkt = NULL;
736 }
737 break;
738 case OP_OFFSET_ZERO:
739 if (offp >= &offstack[MAXSS])
740 return (0);
741 *++offp = base;
742 base = pkt;
743 break;
744 case OP_OFFSET_LINK:
745 if (offp >= &offstack[MAXSS])
746 return (0);
747 *++offp = base;
748 base = pkt + header_size;
749 /*
750 * If the offset exceeds the packet length,
751 * we should not be interested in this packet...
752 * Just return 0.
753 */
754 if (base > pkt + len) {
755 return (0);
756 }
757 break;
758 case OP_OFFSET_IP:
759 if (offp >= &offstack[MAXSS])
760 return (0);
761 *++offp = base;
762 ip = pkt + header_size;
763 base = ip + ip_hdr_len(ip);
764 if (base == ip) {
765 return (0); /* not IP */
766 }
767 if (base > pkt + len) {
768 return (0); /* bad pkt */
769 }
770 break;
771 case OP_OFFSET_TCP:
772 if (offp >= &offstack[MAXSS])
773 return (0);
774 *++offp = base;
775 ip = pkt + header_size;
776 tcp = ip + ip_hdr_len(ip);
777 if (tcp == ip) {
778 return (0); /* not IP */
779 }
780 base = tcp + TCP_HDR_LEN(tcp);
781 if (base > pkt + len) {
782 return (0);
783 }
784 break;
785 case OP_OFFSET_UDP:
786 if (offp >= &offstack[MAXSS])
787 return (0);
788 *++offp = base;
789 ip = pkt + header_size;
790 udp = ip + ip_hdr_len(ip);
791 if (udp == ip) {
792 return (0); /* not IP */
793 }
794 base = udp + sizeof (struct udphdr);
795 if (base > pkt + len) {
796 return (0);
797 }
798 break;
799 case OP_OFFSET_RPC:
800 if (offp >= &offstack[MAXSS])
801 return (0);
802 *++offp = base;
803 ip = pkt + header_size;
804 rpc = NULL;
805
806 if (IP_VERS(ip) != IPV4_VERSION &&
807 IP_VERS(ip) != IPV6_VERSION) {
808 if (sp >= &stack[MAXSS])
809 return (0);
810 *(++sp) = 0;
811 break;
812 }
813
814 switch (ip_proto_of(ip)) {
815 case IPPROTO_UDP:
816 udp = ip + ip_hdr_len(ip);
817 rpc = (struct rpc_msg *)(udp +
818 sizeof (struct udphdr));
819 break;
820 case IPPROTO_TCP:
821 tcp = ip + ip_hdr_len(ip);
822 /*
823 * Need to skip an extra 4 for the xdr_rec
824 * field.
825 */
826 rpc = (struct rpc_msg *)(tcp +
827 TCP_HDR_LEN(tcp) + 4);
828 break;
829 }
830 /*
831 * We need to have at least 24 bytes of a RPC
832 * packet to look at to determine the validity
833 * of it.
834 */
835 if (rpc == NULL || (uchar_t *)rpc + 24 > pkt + len) {
836 if (sp >= &stack[MAXSS])
837 return (0);
838 *(++sp) = 0;
839 break;
840 }
841 /* align */
842 (void) memcpy(&rpcmsg, rpc, 24);
843 if (!valid_rpc((char *)&rpcmsg, 24)) {
844 if (sp >= &stack[MAXSS])
845 return (0);
846 *(++sp) = 0;
847 break;
848 }
849 if (ntohl(rpcmsg.rm_direction) == CALL) {
850 base = (uchar_t *)rpc;
851 newrpc = 1;
852 if (sp >= &stack[MAXSS])
853 return (0);
854 *(++sp) = 1;
855 } else {
856 opkt = pkt;
857 olen = len;
858
859 pkt = base = (uchar_t *)find_rpc(&rpcmsg);
860 len = sizeof (struct xid_entry);
861 if (sp >= &stack[MAXSS])
862 return (0);
863 *(++sp) = base != NULL;
864 }
865 break;
866 case OP_OFFSET_SLP:
867 slphdr = NULL;
868 ip = pkt + header_size;
869
870 if (IP_VERS(ip) != IPV4_VERSION &&
871 IP_VERS(ip) != IPV6_VERSION) {
872 if (sp >= &stack[MAXSS])
873 return (0);
874 *(++sp) = 0;
875 break;
876 }
877
878 switch (ip_proto_of(ip)) {
879 struct udphdr udp_h;
880 struct tcphdr tcp_h;
881 case IPPROTO_UDP:
882 udp = ip + ip_hdr_len(ip);
883 /* align */
884 memcpy(&udp_h, udp, sizeof (udp_h));
885 slp_sport = ntohs(udp_h.uh_sport);
886 slp_dport = ntohs(udp_h.uh_dport);
887 slphdr = udp + sizeof (struct udphdr);
888 break;
889 case IPPROTO_TCP:
890 tcp = ip + ip_hdr_len(ip);
891 /* align */
892 memcpy(&tcp_h, tcp, sizeof (tcp_h));
893 slp_sport = ntohs(tcp_h.th_sport);
894 slp_dport = ntohs(tcp_h.th_dport);
895 slphdr = tcp + TCP_HDR_LEN(tcp);
896 break;
897 }
898 if (slphdr == NULL || slphdr > pkt + len) {
899 if (sp >= &stack[MAXSS])
900 return (0);
901 *(++sp) = 0;
902 break;
903 }
904 if (slp_sport == 427 || slp_dport == 427) {
905 if (sp >= &stack[MAXSS])
906 return (0);
907 *(++sp) = 1;
908 if (slp_sport != 427 && slp_dport == 427)
909 stash_slp(slp_sport);
910 break;
911 } else if (find_slp(slp_dport) != -1) {
912 if (valid_slp(slphdr, len)) {
913 if (sp >= &stack[MAXSS])
914 return (0);
915 *(++sp) = 1;
916 break;
917 }
918 /* else fallthrough to reject */
919 }
920 if (sp >= &stack[MAXSS])
921 return (0);
922 *(++sp) = 0;
923 break;
924 case OP_OFFSET_ETHERTYPE:
925 /*
926 * Set base to the location of the ethertype as
927 * appropriate for this link type. Note that it's
928 * not called "ethertype" for every link type, but
929 * we need to call it something.
930 */
931 if (offp >= &offstack[MAXSS])
932 return (0);
933 *++offp = base;
934 base = pkt + interface->network_type_offset;
935
936 /*
937 * Below, we adjust the offset for unusual
938 * link-layer headers that may have the protocol
939 * type in a variable location beyond what was set
940 * above.
941 */
942 switch (interface->mac_type) {
943 case DL_ETHER:
944 case DL_CSMACD:
945 /*
946 * If this is a VLAN-tagged packet, we need
947 * to point to the ethertype field in the
948 * VLAN header. Move past the ethertype
949 * field in the ethernet header.
950 */
951 if (ntohs(get_u16(base)) == ETHERTYPE_VLAN)
952 base += (ENCAP_ETHERTYPE_OFF);
953 break;
954 }
955 if (base > pkt + len) {
956 /* Went too far, drop the packet */
957 return (0);
958 }
959 break;
960 }
961 }
962
963 if (*sp && newrpc)
964 stash_rpc(&rpcmsg);
965
966 return (*sp);
967 }
968
969 static void
load_const(uint_t constval)970 load_const(uint_t constval)
971 {
972 emitop(OP_LOAD_CONST);
973 emitval(constval);
974 }
975
976 static void
load_value(int offset,int len)977 load_value(int offset, int len)
978 {
979 if (offset >= 0)
980 load_const(offset);
981
982 switch (len) {
983 case 1:
984 emitop(OP_LOAD_OCTET);
985 break;
986 case 2:
987 emitop(OP_LOAD_SHORT);
988 break;
989 case 4:
990 emitop(OP_LOAD_LONG);
991 break;
992 }
993 }
994
995 /*
996 * Emit code to compare a field in
997 * the packet against a constant value.
998 */
999 static void
compare_value(uint_t offset,uint_t len,uint_t val)1000 compare_value(uint_t offset, uint_t len, uint_t val)
1001 {
1002 load_const(val);
1003 load_value(offset, len);
1004 emitop(OP_EQ);
1005 }
1006
1007 static void
compare_addr_v4(uint_t offset,uint_t len,uint_t val)1008 compare_addr_v4(uint_t offset, uint_t len, uint_t val)
1009 {
1010 load_const(ntohl(val));
1011 load_value(offset, len);
1012 emitop(OP_EQ);
1013 }
1014
1015 static void
compare_addr_v6(uint_t offset,uint_t len,struct in6_addr val)1016 compare_addr_v6(uint_t offset, uint_t len, struct in6_addr val)
1017 {
1018 int i;
1019 uint32_t value;
1020
1021 for (i = 0; i < len; i += 4) {
1022 value = ntohl(*(uint32_t *)&val.s6_addr[i]);
1023 load_const(value);
1024 load_value(offset + i, 4);
1025 emitop(OP_EQ);
1026 if (i != 0)
1027 emitop(OP_AND);
1028 }
1029 }
1030
1031 /*
1032 * Same as above except do the comparison
1033 * after and'ing a mask value. Useful
1034 * for comparing IP network numbers
1035 */
1036 static void
compare_value_mask(uint_t offset,uint_t len,uint_t val,int mask)1037 compare_value_mask(uint_t offset, uint_t len, uint_t val, int mask)
1038 {
1039 load_value(offset, len);
1040 load_const(mask);
1041 emitop(OP_AND);
1042 load_const(val);
1043 emitop(OP_EQ);
1044 }
1045
1046 /*
1047 * Compare two zoneid's. The arg val passed in is stored in network
1048 * byte order.
1049 */
1050 static void
compare_value_zone(uint_t offset,uint32_t val)1051 compare_value_zone(uint_t offset, uint32_t val)
1052 {
1053 load_const(ntohl(val));
1054 load_value(offset, 4);
1055 emitop(OP_EQ);
1056 }
1057
1058 /* Emit an operator into the code array */
1059 static void
emitop(enum optype opcode)1060 emitop(enum optype opcode)
1061 {
1062 if (curr_op >= &oplist[MAXOPS])
1063 pr_err("expression too long");
1064 *curr_op++ = opcode;
1065 }
1066
1067 /*
1068 * Remove n operators recently emitted into
1069 * the code array. Used by alternation().
1070 */
1071 static void
unemit(int numops)1072 unemit(int numops)
1073 {
1074 curr_op -= numops;
1075 }
1076
1077
1078 /*
1079 * Same as emitop except that we're emitting
1080 * a value that's not an operator.
1081 */
1082 static void
emitval(uint_t val)1083 emitval(uint_t val)
1084 {
1085 if (curr_op >= &oplist[MAXOPS])
1086 pr_err("expression too long");
1087 *curr_op++ = val;
1088 }
1089
1090 /*
1091 * Used to chain forward branches together
1092 * for later resolution by resolve_chain().
1093 */
1094 static uint_t
chain(int p)1095 chain(int p)
1096 {
1097 uint_t pos = curr_op - oplist;
1098
1099 emitval(p);
1100 return (pos);
1101 }
1102
1103 /*
1104 * Proceed backward through the code array
1105 * following a chain of forward references.
1106 * At each reference install the destination
1107 * branch offset.
1108 */
1109 static void
resolve_chain(uint_t p)1110 resolve_chain(uint_t p)
1111 {
1112 uint_t n;
1113 uint_t pos = curr_op - oplist;
1114
1115 while (p) {
1116 n = oplist[p];
1117 oplist[p] = pos;
1118 p = n;
1119 }
1120 }
1121
1122 #define EQ(val) (strcmp(token, val) == 0)
1123
1124 char *tkp, *sav_tkp;
1125 char *token;
1126 enum { EOL, ALPHA, NUMBER, FIELD, ADDR_IP, ADDR_ETHER, SPECIAL,
1127 ADDR_IP6, ADDR_AT } tokentype;
1128 uint_t tokenval;
1129
1130 /*
1131 * This is the scanner. Each call returns the next
1132 * token in the filter expression. A token is either:
1133 * EOL: The end of the line - no more tokens.
1134 * ALPHA: A name that begins with a letter and contains
1135 * letters or digits, hyphens or underscores.
1136 * NUMBER: A number. The value can be represented as
1137 * a decimal value (1234) or an octal value
1138 * that begins with zero (066) or a hex value
1139 * that begins with 0x or 0X (0xff).
1140 * FIELD: A name followed by a left square bracket.
1141 * ADDR_IP: An IP address. Any sequence of digits
1142 * separated by dots e.g. 109.104.40.13
1143 * ADDR_ETHER: An ethernet address. Any sequence of hex
1144 * digits separated by colons e.g. 8:0:20:0:76:39
1145 * SPECIAL: A special character e.g. ">" or "(". The scanner
1146 * correctly handles digraphs - two special characters
1147 * that constitute a single token e.g. "==" or ">=".
1148 * ADDR_IP6: An IPv6 address.
1149 *
1150 * ADDR_AT: An AppleTalk Phase II address. A sequence of two numbers
1151 * separated by a dot.
1152 *
1153 * The current token is maintained in "token" and and its
1154 * type in "tokentype". If tokentype is NUMBER then the
1155 * value is held in "tokenval".
1156 */
1157
1158 static const char *namechars =
1159 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
1160 static const char *numchars = "0123456789abcdefABCDEFXx:.";
1161
1162 void
next()1163 next()
1164 {
1165 static int savechar;
1166 char *p;
1167 int size, size1;
1168 int base, colons, dots, alphas, double_colon;
1169
1170 colons = 0;
1171 double_colon = 0;
1172
1173 if (*tkp == '\0') {
1174 token = tkp;
1175 *tkp = savechar;
1176 }
1177
1178 sav_tkp = tkp;
1179
1180 while (isspace(*tkp)) tkp++;
1181 token = tkp;
1182 if (*token == '\0') {
1183 tokentype = EOL;
1184 return;
1185 }
1186
1187 /* A token containing ':' cannot be ALPHA type */
1188 tkp = token + strspn(token, numchars);
1189 for (p = token; p < tkp; p++) {
1190 if (*p == ':') {
1191 colons++;
1192 if (*(p+1) == ':')
1193 double_colon++;
1194 }
1195 }
1196
1197 tkp = token;
1198 if (isalpha(*tkp) && !colons) {
1199 tokentype = ALPHA;
1200 tkp += strspn(tkp, namechars);
1201 if (*tkp == '[') {
1202 tokentype = FIELD;
1203 *tkp++ = '\0';
1204 }
1205 } else
1206
1207 /*
1208 * RFC1123 states that host names may now start with digits. Need
1209 * to change parser to account for this. Also, need to distinguish
1210 * between 1.2.3.4 and 1.2.3.a where the first case is an IP address
1211 * and the second is a domain name. 333aaa needs to be distinguished
1212 * from 0x333aaa. The first is a host name and the second is a number.
1213 *
1214 * The (colons > 1) conditional differentiates between ethernet
1215 * and IPv6 addresses, and an expression of the form base[expr:size],
1216 * which can only contain one ':' character.
1217 */
1218 if (isdigit(*tkp) || colons > 1) {
1219 tkp = token + strspn(token, numchars);
1220 dots = alphas = 0;
1221 for (p = token; p < tkp; p++) {
1222 if (*p == '.')
1223 dots++;
1224 else if (isalpha(*p))
1225 alphas = 1;
1226 }
1227 if (colons > 1) {
1228 if (colons == 5 && double_colon == 0) {
1229 tokentype = ADDR_ETHER;
1230 } else {
1231 tokentype = ADDR_IP6;
1232 }
1233 } else if (dots) {
1234 size = tkp - token;
1235 size1 = strspn(token, "0123456789.");
1236 if (dots == 1 && size == size1) {
1237 tokentype = ADDR_AT;
1238 } else
1239 if (dots != 3 || size != size1) {
1240 tokentype = ALPHA;
1241 if (*tkp != '\0' && !isspace(*tkp)) {
1242 tkp += strspn(tkp, namechars);
1243 if (*tkp == '[') {
1244 tokentype = FIELD;
1245 *tkp++ = '\0';
1246 }
1247 }
1248 } else
1249 tokentype = ADDR_IP;
1250 } else if (token + strspn(token, namechars) <= tkp) {
1251 /*
1252 * With the above check, if there are more
1253 * characters after the last digit, assume
1254 * that it is not a number.
1255 */
1256 tokentype = NUMBER;
1257 p = tkp;
1258 tkp = token;
1259 base = 10;
1260 if (*tkp == '0') {
1261 base = 8;
1262 tkp++;
1263 if (*tkp == 'x' || *tkp == 'X')
1264 base = 16;
1265 }
1266 if ((base == 10 || base == 8) && alphas) {
1267 tokentype = ALPHA;
1268 tkp = p;
1269 } else if (base == 16) {
1270 size = 2 + strspn(token+2,
1271 "0123456789abcdefABCDEF");
1272 size1 = p - token;
1273 if (size != size1) {
1274 tokentype = ALPHA;
1275 tkp = p;
1276 } else
1277 /*
1278 * handles the case of 0x so an error message
1279 * is not printed. Treats 0x as 0.
1280 */
1281 if (size == 2) {
1282 tokenval = 0;
1283 tkp = token +2;
1284 } else {
1285 tokenval = strtoul(token, &tkp, base);
1286 }
1287 } else {
1288 tokenval = strtoul(token, &tkp, base);
1289 }
1290 } else {
1291 tokentype = ALPHA;
1292 tkp += strspn(tkp, namechars);
1293 if (*tkp == '[') {
1294 tokentype = FIELD;
1295 *tkp++ = '\0';
1296 }
1297 }
1298 } else {
1299 tokentype = SPECIAL;
1300 tkp++;
1301 if ((*token == '=' && *tkp == '=') ||
1302 (*token == '>' && *tkp == '=') ||
1303 (*token == '<' && *tkp == '=') ||
1304 (*token == '!' && *tkp == '='))
1305 tkp++;
1306 }
1307
1308 savechar = *tkp;
1309 *tkp = '\0';
1310 }
1311
1312 typedef struct match_type {
1313 char *m_name;
1314 int m_offset;
1315 int m_size;
1316 int m_value;
1317 int m_depend;
1318 enum optype m_optype;
1319 } match_type_t;
1320
1321 static match_type_t ether_match_types[] = {
1322 /*
1323 * Table initialized assuming Ethernet data link headers.
1324 * m_offset is an offset beyond the offset op, which is why
1325 * the offset is zero for when snoop needs to check an ethertype.
1326 */
1327 "ip", 0, 2, ETHERTYPE_IP, -1, OP_OFFSET_ETHERTYPE,
1328 "ip6", 0, 2, ETHERTYPE_IPV6, -1, OP_OFFSET_ETHERTYPE,
1329 "arp", 0, 2, ETHERTYPE_ARP, -1, OP_OFFSET_ETHERTYPE,
1330 "rarp", 0, 2, ETHERTYPE_REVARP, -1, OP_OFFSET_ETHERTYPE,
1331 "pppoed", 0, 2, ETHERTYPE_PPPOED, -1, OP_OFFSET_ETHERTYPE,
1332 "pppoes", 0, 2, ETHERTYPE_PPPOES, -1, OP_OFFSET_ETHERTYPE,
1333 "tcp", 9, 1, IPPROTO_TCP, 0, OP_OFFSET_LINK,
1334 "tcp", 6, 1, IPPROTO_TCP, 1, OP_OFFSET_LINK,
1335 "udp", 9, 1, IPPROTO_UDP, 0, OP_OFFSET_LINK,
1336 "udp", 6, 1, IPPROTO_UDP, 1, OP_OFFSET_LINK,
1337 "icmp", 9, 1, IPPROTO_ICMP, 0, OP_OFFSET_LINK,
1338 "icmp6", 6, 1, IPPROTO_ICMPV6, 1, OP_OFFSET_LINK,
1339 "ospf", 9, 1, IPPROTO_OSPF, 0, OP_OFFSET_LINK,
1340 "ospf", 6, 1, IPPROTO_OSPF, 1, OP_OFFSET_LINK,
1341 "ip-in-ip", 9, 1, IPPROTO_ENCAP, 0, OP_OFFSET_LINK,
1342 "esp", 9, 1, IPPROTO_ESP, 0, OP_OFFSET_LINK,
1343 "esp", 6, 1, IPPROTO_ESP, 1, OP_OFFSET_LINK,
1344 "ah", 9, 1, IPPROTO_AH, 0, OP_OFFSET_LINK,
1345 "ah", 6, 1, IPPROTO_AH, 1, OP_OFFSET_LINK,
1346 "sctp", 9, 1, IPPROTO_SCTP, 0, OP_OFFSET_LINK,
1347 "sctp", 6, 1, IPPROTO_SCTP, 1, OP_OFFSET_LINK,
1348 0, 0, 0, 0, 0, 0
1349 };
1350
1351 static match_type_t ipnet_match_types[] = {
1352 /*
1353 * Table initialized assuming Ethernet data link headers.
1354 * m_offset is an offset beyond the offset op, which is why
1355 * the offset is zero for when snoop needs to check an ethertype.
1356 */
1357 "ip", 0, 1, IPV4_VERSION, -1, OP_OFFSET_ETHERTYPE,
1358 "ip6", 0, 1, IPV6_VERSION, -1, OP_OFFSET_ETHERTYPE,
1359 "tcp", 9, 1, IPPROTO_TCP, 0, OP_OFFSET_LINK,
1360 "tcp", 6, 1, IPPROTO_TCP, 1, OP_OFFSET_LINK,
1361 "udp", 9, 1, IPPROTO_UDP, 0, OP_OFFSET_LINK,
1362 "udp", 6, 1, IPPROTO_UDP, 1, OP_OFFSET_LINK,
1363 "icmp", 9, 1, IPPROTO_ICMP, 0, OP_OFFSET_LINK,
1364 "icmp6", 6, 1, IPPROTO_ICMPV6, 1, OP_OFFSET_LINK,
1365 "ospf", 9, 1, IPPROTO_OSPF, 0, OP_OFFSET_LINK,
1366 "ospf", 6, 1, IPPROTO_OSPF, 1, OP_OFFSET_LINK,
1367 "ip-in-ip", 9, 1, IPPROTO_ENCAP, 0, OP_OFFSET_LINK,
1368 "esp", 9, 1, IPPROTO_ESP, 0, OP_OFFSET_LINK,
1369 "esp", 6, 1, IPPROTO_ESP, 1, OP_OFFSET_LINK,
1370 "ah", 9, 1, IPPROTO_AH, 0, OP_OFFSET_LINK,
1371 "ah", 6, 1, IPPROTO_AH, 1, OP_OFFSET_LINK,
1372 "sctp", 9, 1, IPPROTO_SCTP, 0, OP_OFFSET_LINK,
1373 "sctp", 6, 1, IPPROTO_SCTP, 1, OP_OFFSET_LINK,
1374 0, 0, 0, 0, 0, 0
1375 };
1376
1377 static match_type_t iptun_match_types[] = {
1378 "ip", 0, 1, IPPROTO_ENCAP, -1, OP_OFFSET_ETHERTYPE,
1379 "ip6", 0, 1, IPPROTO_IPV6, -1, OP_OFFSET_ETHERTYPE,
1380 "tcp", 9, 1, IPPROTO_TCP, 0, OP_OFFSET_LINK,
1381 "tcp", 6, 1, IPPROTO_TCP, 1, OP_OFFSET_LINK,
1382 "udp", 9, 1, IPPROTO_UDP, 0, OP_OFFSET_LINK,
1383 "udp", 6, 1, IPPROTO_UDP, 1, OP_OFFSET_LINK,
1384 "icmp", 9, 1, IPPROTO_ICMP, 0, OP_OFFSET_LINK,
1385 "icmp6", 6, 1, IPPROTO_ICMPV6, 1, OP_OFFSET_LINK,
1386 "ospf", 9, 1, IPPROTO_OSPF, 0, OP_OFFSET_LINK,
1387 "ospf", 6, 1, IPPROTO_OSPF, 1, OP_OFFSET_LINK,
1388 "ip-in-ip", 9, 1, IPPROTO_ENCAP, 0, OP_OFFSET_LINK,
1389 "esp", 9, 1, IPPROTO_ESP, 0, OP_OFFSET_LINK,
1390 "esp", 6, 1, IPPROTO_ESP, 1, OP_OFFSET_LINK,
1391 "ah", 9, 1, IPPROTO_AH, 0, OP_OFFSET_LINK,
1392 "ah", 6, 1, IPPROTO_AH, 1, OP_OFFSET_LINK,
1393 "sctp", 9, 1, IPPROTO_SCTP, 0, OP_OFFSET_LINK,
1394 "sctp", 6, 1, IPPROTO_SCTP, 1, OP_OFFSET_LINK,
1395 0, 0, 0, 0, 0, 0
1396 };
1397
1398 static void
generate_check(match_type_t match_types[],int index,int type)1399 generate_check(match_type_t match_types[], int index, int type)
1400 {
1401 match_type_t *mtp = &match_types[index];
1402 /*
1403 * Note: this code assumes the above dependencies are
1404 * not cyclic. This *should* always be true.
1405 */
1406 if (mtp->m_depend != -1)
1407 generate_check(match_types, mtp->m_depend, type);
1408
1409 emitop(mtp->m_optype);
1410 load_value(mtp->m_offset, mtp->m_size);
1411 load_const(mtp->m_value);
1412 emitop(OP_OFFSET_POP);
1413
1414 emitop(OP_EQ);
1415
1416 if (mtp->m_depend != -1)
1417 emitop(OP_AND);
1418 }
1419
1420 /*
1421 * Generate code based on the keyword argument.
1422 * This word is looked up in the match_types table
1423 * and checks a field within the packet for a given
1424 * value e.g. ether or ip type field. The match
1425 * can also have a dependency on another entry e.g.
1426 * "tcp" requires that the packet also be "ip".
1427 */
1428 static int
comparison(char * s)1429 comparison(char *s)
1430 {
1431 unsigned int i, n_checks = 0;
1432 match_type_t *match_types;
1433
1434 switch (interface->mac_type) {
1435 case DL_ETHER:
1436 match_types = ether_match_types;
1437 break;
1438 case DL_IPNET:
1439 match_types = ipnet_match_types;
1440 break;
1441 case DL_IPV4:
1442 case DL_IPV6:
1443 case DL_6TO4:
1444 match_types = iptun_match_types;
1445 break;
1446 default:
1447 return (0);
1448 }
1449
1450 for (i = 0; match_types[i].m_name != NULL; i++) {
1451 if (strcmp(s, match_types[i].m_name) != 0)
1452 continue;
1453
1454 n_checks++;
1455 generate_check(match_types, i, interface->mac_type);
1456 if (n_checks > 1)
1457 emitop(OP_OR);
1458 }
1459
1460 return (n_checks > 0);
1461 }
1462
1463 enum direction { ANY, TO, FROM };
1464 enum direction dir;
1465
1466 /*
1467 * Generate code to match an IP address. The address
1468 * may be supplied either as a hostname or in dotted format.
1469 * For source packets both the IP source address and ARP
1470 * src are checked.
1471 * Note: we don't check packet type here - whether IP or ARP.
1472 * It's possible that we'll do an improper match.
1473 */
1474 static void
ipaddr_match(enum direction which,char * hostname,int inet_type)1475 ipaddr_match(enum direction which, char *hostname, int inet_type)
1476 {
1477 bool_t found_host;
1478 int m = 0, n = 0;
1479 uint_t *addr4ptr;
1480 uint_t addr4;
1481 struct in6_addr *addr6ptr;
1482 int h_addr_index;
1483 struct hostent *hp = NULL;
1484 int error_num = 0;
1485 boolean_t freehp = B_FALSE;
1486 boolean_t first = B_TRUE;
1487
1488 /*
1489 * The addr4offset and addr6offset variables simplify the code which
1490 * generates the address comparison filter. With these two variables,
1491 * duplicate code need not exist for the TO and FROM case.
1492 * A value of -1 describes the ANY case (TO and FROM).
1493 */
1494 int addr4offset;
1495 int addr6offset;
1496
1497 found_host = 0;
1498
1499 if (tokentype == ADDR_IP) {
1500 hp = lgetipnodebyname(hostname, AF_INET, 0, &error_num);
1501 if (hp == NULL) {
1502 hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
1503 freehp = 1;
1504 }
1505 if (hp == NULL) {
1506 if (error_num == TRY_AGAIN) {
1507 pr_err("couldn't resolve %s (try again later)",
1508 hostname);
1509 } else {
1510 pr_err("couldn't resolve %s", hostname);
1511 }
1512 }
1513 inet_type = IPV4_ONLY;
1514 } else if (tokentype == ADDR_IP6) {
1515 hp = lgetipnodebyname(hostname, AF_INET6, 0, &error_num);
1516 if (hp == NULL) {
1517 hp = getipnodebyname(hostname, AF_INET6, 0, &error_num);
1518 freehp = 1;
1519 }
1520 if (hp == NULL) {
1521 if (error_num == TRY_AGAIN) {
1522 pr_err("couldn't resolve %s (try again later)",
1523 hostname);
1524 } else {
1525 pr_err("couldn't resolve %s", hostname);
1526 }
1527 }
1528 inet_type = IPV6_ONLY;
1529 } else {
1530 /* Some hostname i.e. tokentype is ALPHA */
1531 switch (inet_type) {
1532 case IPV4_ONLY:
1533 /* Only IPv4 address is needed */
1534 hp = lgetipnodebyname(hostname, AF_INET, 0, &error_num);
1535 if (hp == NULL) {
1536 hp = getipnodebyname(hostname, AF_INET, 0,
1537 &error_num);
1538 freehp = 1;
1539 }
1540 if (hp != NULL) {
1541 found_host = 1;
1542 }
1543 break;
1544 case IPV6_ONLY:
1545 /* Only IPv6 address is needed */
1546 hp = lgetipnodebyname(hostname, AF_INET6, 0,
1547 &error_num);
1548 if (hp == NULL) {
1549 hp = getipnodebyname(hostname, AF_INET6, 0,
1550 &error_num);
1551 freehp = 1;
1552 }
1553 if (hp != NULL) {
1554 found_host = 1;
1555 }
1556 break;
1557 case IPV4_AND_IPV6:
1558 /* Both IPv4 and IPv6 are needed */
1559 hp = lgetipnodebyname(hostname, AF_INET6,
1560 AI_ALL | AI_V4MAPPED, &error_num);
1561 if (hp == NULL) {
1562 hp = getipnodebyname(hostname, AF_INET6,
1563 AI_ALL | AI_V4MAPPED, &error_num);
1564 freehp = 1;
1565 }
1566 if (hp != NULL) {
1567 found_host = 1;
1568 }
1569 break;
1570 default:
1571 found_host = 0;
1572 }
1573
1574 if (!found_host) {
1575 if (error_num == TRY_AGAIN) {
1576 pr_err("could not resolve %s (try again later)",
1577 hostname);
1578 } else {
1579 pr_err("could not resolve %s", hostname);
1580 }
1581 }
1582 }
1583
1584 if (hp == NULL)
1585 return;
1586
1587 switch (which) {
1588 case TO:
1589 addr4offset = IPV4_DSTADDR_OFFSET;
1590 addr6offset = IPV6_DSTADDR_OFFSET;
1591 break;
1592 case FROM:
1593 addr4offset = IPV4_SRCADDR_OFFSET;
1594 addr6offset = IPV6_SRCADDR_OFFSET;
1595 break;
1596 case ANY:
1597 addr4offset = -1;
1598 addr6offset = -1;
1599 break;
1600 }
1601
1602 /*
1603 * The code below generates the filter.
1604 */
1605 if (hp->h_addrtype == AF_INET) {
1606 ethertype_match(interface->network_type_ip);
1607 emitop(OP_BRFL);
1608 n = chain(n);
1609 emitop(OP_OFFSET_LINK);
1610 h_addr_index = 0;
1611 addr4ptr = (uint_t *)hp->h_addr_list[h_addr_index];
1612 while (addr4ptr != NULL) {
1613 if (addr4offset == -1) {
1614 compare_addr_v4(IPV4_SRCADDR_OFFSET, 4,
1615 *addr4ptr);
1616 emitop(OP_BRTR);
1617 m = chain(m);
1618 compare_addr_v4(IPV4_DSTADDR_OFFSET, 4,
1619 *addr4ptr);
1620 } else {
1621 compare_addr_v4(addr4offset, 4, *addr4ptr);
1622 }
1623 addr4ptr = (uint_t *)hp->h_addr_list[++h_addr_index];
1624 if (addr4ptr != NULL) {
1625 emitop(OP_BRTR);
1626 m = chain(m);
1627 }
1628 }
1629 if (m != 0) {
1630 resolve_chain(m);
1631 }
1632 emitop(OP_OFFSET_POP);
1633 resolve_chain(n);
1634 } else {
1635 /* first pass: IPv4 addresses */
1636 h_addr_index = 0;
1637 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
1638 first = B_TRUE;
1639 while (addr6ptr != NULL) {
1640 if (IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
1641 if (first) {
1642 ethertype_match(
1643 interface->network_type_ip);
1644 emitop(OP_BRFL);
1645 n = chain(n);
1646 emitop(OP_OFFSET_LINK);
1647 first = B_FALSE;
1648 } else {
1649 emitop(OP_BRTR);
1650 m = chain(m);
1651 }
1652 IN6_V4MAPPED_TO_INADDR(addr6ptr,
1653 (struct in_addr *)&addr4);
1654 if (addr4offset == -1) {
1655 compare_addr_v4(IPV4_SRCADDR_OFFSET, 4,
1656 addr4);
1657 emitop(OP_BRTR);
1658 m = chain(m);
1659 compare_addr_v4(IPV4_DSTADDR_OFFSET, 4,
1660 addr4);
1661 } else {
1662 compare_addr_v4(addr4offset, 4, addr4);
1663 }
1664 }
1665 addr6ptr = (struct in6_addr *)
1666 hp->h_addr_list[++h_addr_index];
1667 }
1668 /* second pass: IPv6 addresses */
1669 h_addr_index = 0;
1670 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
1671 first = B_TRUE;
1672 while (addr6ptr != NULL) {
1673 if (!IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
1674 if (first) {
1675 /*
1676 * bypass check for IPv6 addresses
1677 * when we have an IPv4 packet
1678 */
1679 if (n != 0) {
1680 emitop(OP_BRTR);
1681 m = chain(m);
1682 emitop(OP_BRFL);
1683 m = chain(m);
1684 resolve_chain(n);
1685 n = 0;
1686 }
1687 ethertype_match(
1688 interface->network_type_ipv6);
1689 emitop(OP_BRFL);
1690 n = chain(n);
1691 emitop(OP_OFFSET_LINK);
1692 first = B_FALSE;
1693 } else {
1694 emitop(OP_BRTR);
1695 m = chain(m);
1696 }
1697 if (addr6offset == -1) {
1698 compare_addr_v6(IPV6_SRCADDR_OFFSET,
1699 16, *addr6ptr);
1700 emitop(OP_BRTR);
1701 m = chain(m);
1702 compare_addr_v6(IPV6_DSTADDR_OFFSET,
1703 16, *addr6ptr);
1704 } else {
1705 compare_addr_v6(addr6offset, 16,
1706 *addr6ptr);
1707 }
1708 }
1709 addr6ptr = (struct in6_addr *)
1710 hp->h_addr_list[++h_addr_index];
1711 }
1712 if (m != 0) {
1713 resolve_chain(m);
1714 }
1715 emitop(OP_OFFSET_POP);
1716 resolve_chain(n);
1717 }
1718
1719 /* only free struct hostent returned by getipnodebyname() */
1720 if (freehp) {
1721 freehostent(hp);
1722 }
1723 }
1724
1725 /*
1726 * Match on zoneid. The arg zone passed in is in network byte order.
1727 */
1728 static void
zone_match(enum direction which,uint32_t zone)1729 zone_match(enum direction which, uint32_t zone)
1730 {
1731
1732 switch (which) {
1733 case TO:
1734 compare_value_zone(IPNET_DSTZONE_OFFSET, zone);
1735 break;
1736 case FROM:
1737 compare_value_zone(IPNET_SRCZONE_OFFSET, zone);
1738 break;
1739 case ANY:
1740 compare_value_zone(IPNET_SRCZONE_OFFSET, zone);
1741 compare_value_zone(IPNET_DSTZONE_OFFSET, zone);
1742 emitop(OP_OR);
1743 }
1744 }
1745
1746 /*
1747 * Generate code to match an AppleTalk address. The address
1748 * must be given as two numbers with a dot between
1749 *
1750 */
1751 static void
ataddr_match(enum direction which,char * hostname)1752 ataddr_match(enum direction which, char *hostname)
1753 {
1754 uint_t net;
1755 uint_t node;
1756 uint_t m, n;
1757
1758 sscanf(hostname, "%u.%u", &net, &node);
1759
1760 emitop(OP_OFFSET_LINK);
1761 switch (which) {
1762 case TO:
1763 compare_value(AT_DST_NET_OFFSET, 2, net);
1764 emitop(OP_BRFL);
1765 m = chain(0);
1766 compare_value(AT_DST_NODE_OFFSET, 1, node);
1767 resolve_chain(m);
1768 break;
1769 case FROM:
1770 compare_value(AT_SRC_NET_OFFSET, 2, net);
1771 emitop(OP_BRFL);
1772 m = chain(0);
1773 compare_value(AT_SRC_NODE_OFFSET, 1, node);
1774 resolve_chain(m);
1775 break;
1776 case ANY:
1777 compare_value(AT_DST_NET_OFFSET, 2, net);
1778 emitop(OP_BRFL);
1779 m = chain(0);
1780 compare_value(AT_DST_NODE_OFFSET, 1, node);
1781 resolve_chain(m);
1782 emitop(OP_BRTR);
1783 n = chain(0);
1784 compare_value(AT_SRC_NET_OFFSET, 2, net);
1785 emitop(OP_BRFL);
1786 m = chain(0);
1787 compare_value(AT_SRC_NODE_OFFSET, 1, node);
1788 resolve_chain(m);
1789 resolve_chain(n);
1790 break;
1791 }
1792 emitop(OP_OFFSET_POP);
1793 }
1794
1795 /*
1796 * Compare ethernet addresses. The address may
1797 * be provided either as a hostname or as a
1798 * 6 octet colon-separated address.
1799 */
1800 static void
etheraddr_match(enum direction which,char * hostname)1801 etheraddr_match(enum direction which, char *hostname)
1802 {
1803 uint_t addr;
1804 ushort_t *addrp;
1805 int to_offset, from_offset;
1806 struct ether_addr e, *ep = NULL;
1807 int m;
1808
1809 /*
1810 * First, check the interface type for whether src/dest address
1811 * is determinable; if not, retreat early.
1812 */
1813 switch (interface->mac_type) {
1814 case DL_ETHER:
1815 from_offset = ETHERADDRL;
1816 to_offset = 0;
1817 break;
1818
1819 case DL_IB:
1820 /*
1821 * If an ethernet address is attempted to be used
1822 * on an IPoIB interface, flag error. Link address
1823 * based filtering is unsupported on IPoIB, so there
1824 * is no ipibaddr_match() or parsing support for IPoIB
1825 * 20 byte link addresses.
1826 */
1827 pr_err("filter option unsupported on media");
1828 break;
1829
1830 case DL_FDDI:
1831 from_offset = 7;
1832 to_offset = 1;
1833 break;
1834
1835 default:
1836 /*
1837 * Where do we find "ether" address for FDDI & TR?
1838 * XXX can improve? ~sparker
1839 */
1840 load_const(1);
1841 return;
1842 }
1843
1844 if (isxdigit(*hostname))
1845 ep = ether_aton(hostname);
1846 if (ep == NULL) {
1847 if (ether_hostton(hostname, &e))
1848 if (!arp_for_ether(hostname, &e))
1849 pr_err("cannot obtain ether addr for %s",
1850 hostname);
1851 ep = &e;
1852 }
1853 memcpy(&addr, (ushort_t *)ep, 4);
1854 addrp = (ushort_t *)ep + 2;
1855
1856 emitop(OP_OFFSET_ZERO);
1857 switch (which) {
1858 case TO:
1859 compare_value(to_offset, 4, ntohl(addr));
1860 emitop(OP_BRFL);
1861 m = chain(0);
1862 compare_value(to_offset + 4, 2, ntohs(*addrp));
1863 resolve_chain(m);
1864 break;
1865 case FROM:
1866 compare_value(from_offset, 4, ntohl(addr));
1867 emitop(OP_BRFL);
1868 m = chain(0);
1869 compare_value(from_offset + 4, 2, ntohs(*addrp));
1870 resolve_chain(m);
1871 break;
1872 case ANY:
1873 compare_value(to_offset, 4, ntohl(addr));
1874 compare_value(to_offset + 4, 2, ntohs(*addrp));
1875 emitop(OP_AND);
1876 emitop(OP_BRTR);
1877 m = chain(0);
1878
1879 compare_value(from_offset, 4, ntohl(addr));
1880 compare_value(from_offset + 4, 2, ntohs(*addrp));
1881 emitop(OP_AND);
1882 resolve_chain(m);
1883 break;
1884 }
1885 emitop(OP_OFFSET_POP);
1886 }
1887
1888 static void
ethertype_match(int val)1889 ethertype_match(int val)
1890 {
1891 int ether_offset = interface->network_type_offset;
1892
1893 /*
1894 * If the user is interested in ethertype VLAN,
1895 * then we need to set the offset to the beginning of the packet.
1896 * But if the user is interested in another ethertype,
1897 * such as IPv4, then we need to take into consideration
1898 * the fact that the packet might be VLAN tagged.
1899 */
1900 if (interface->mac_type == DL_ETHER ||
1901 interface->mac_type == DL_CSMACD) {
1902 if (val != ETHERTYPE_VLAN) {
1903 /*
1904 * OP_OFFSET_ETHERTYPE puts us at the ethertype
1905 * field whether or not there is a VLAN tag,
1906 * so ether_offset goes to zero if we get here.
1907 */
1908 emitop(OP_OFFSET_ETHERTYPE);
1909 ether_offset = 0;
1910 } else {
1911 emitop(OP_OFFSET_ZERO);
1912 }
1913 }
1914 compare_value(ether_offset, interface->network_type_len, val);
1915 if (interface->mac_type == DL_ETHER ||
1916 interface->mac_type == DL_CSMACD) {
1917 emitop(OP_OFFSET_POP);
1918 }
1919 }
1920
1921 /*
1922 * Match a network address. The host part
1923 * is masked out. The network address may
1924 * be supplied either as a netname or in
1925 * IP dotted format. The mask to be used
1926 * for the comparison is assumed from the
1927 * address format (see comment below).
1928 */
1929 static void
netaddr_match(enum direction which,char * netname)1930 netaddr_match(enum direction which, char *netname)
1931 {
1932 uint_t addr;
1933 uint_t mask = 0xff000000;
1934 uint_t m;
1935 struct netent *np;
1936
1937 if (isdigit(*netname)) {
1938 addr = inet_network(netname);
1939 } else {
1940 np = getnetbyname(netname);
1941 if (np == NULL)
1942 pr_err("net %s not known", netname);
1943 addr = np->n_net;
1944 }
1945
1946 /*
1947 * Left justify the address and figure
1948 * out a mask based on the supplied address.
1949 * Set the mask according to the number of zero
1950 * low-order bytes.
1951 * Note: this works only for whole octet masks.
1952 */
1953 if (addr) {
1954 while ((addr & ~mask) != 0) {
1955 mask |= (mask >> 8);
1956 }
1957 }
1958
1959 emitop(OP_OFFSET_LINK);
1960 switch (which) {
1961 case TO:
1962 compare_value_mask(16, 4, addr, mask);
1963 break;
1964 case FROM:
1965 compare_value_mask(12, 4, addr, mask);
1966 break;
1967 case ANY:
1968 compare_value_mask(12, 4, addr, mask);
1969 emitop(OP_BRTR);
1970 m = chain(0);
1971 compare_value_mask(16, 4, addr, mask);
1972 resolve_chain(m);
1973 break;
1974 }
1975 emitop(OP_OFFSET_POP);
1976 }
1977
1978 /*
1979 * Match either a UDP or TCP port number.
1980 * The port number may be provided either as
1981 * port name as listed in /etc/services ("nntp") or as
1982 * the port number itself (2049).
1983 */
1984 static void
port_match(enum direction which,char * portname)1985 port_match(enum direction which, char *portname)
1986 {
1987 struct servent *sp;
1988 uint_t m, port;
1989
1990 if (isdigit(*portname)) {
1991 port = atoi(portname);
1992 } else {
1993 sp = getservbyname(portname, NULL);
1994 if (sp == NULL)
1995 pr_err("invalid port number or name: %s", portname);
1996 port = ntohs(sp->s_port);
1997 }
1998
1999 emitop(OP_OFFSET_IP);
2000
2001 switch (which) {
2002 case TO:
2003 compare_value(2, 2, port);
2004 break;
2005 case FROM:
2006 compare_value(0, 2, port);
2007 break;
2008 case ANY:
2009 compare_value(2, 2, port);
2010 emitop(OP_BRTR);
2011 m = chain(0);
2012 compare_value(0, 2, port);
2013 resolve_chain(m);
2014 break;
2015 }
2016 emitop(OP_OFFSET_POP);
2017 }
2018
2019 /*
2020 * Generate code to match packets with a specific
2021 * RPC program number. If the progname is a name
2022 * it is converted to a number via /etc/rpc.
2023 * The program version and/or procedure may be provided
2024 * as extra qualifiers.
2025 */
2026 static void
rpc_match_prog(enum direction which,char * progname,int vers,int proc)2027 rpc_match_prog(enum direction which, char *progname, int vers, int proc)
2028 {
2029 struct rpcent *rpc;
2030 uint_t prog;
2031 uint_t m, n;
2032
2033 if (isdigit(*progname)) {
2034 prog = atoi(progname);
2035 } else {
2036 rpc = (struct rpcent *)getrpcbyname(progname);
2037 if (rpc == NULL)
2038 pr_err("invalid program name: %s", progname);
2039 prog = rpc->r_number;
2040 }
2041
2042 emitop(OP_OFFSET_RPC);
2043 emitop(OP_BRFL);
2044 n = chain(0);
2045
2046 compare_value(12, 4, prog);
2047 emitop(OP_BRFL);
2048 m = chain(0);
2049 if (vers >= 0) {
2050 compare_value(16, 4, vers);
2051 emitop(OP_BRFL);
2052 m = chain(m);
2053 }
2054 if (proc >= 0) {
2055 compare_value(20, 4, proc);
2056 emitop(OP_BRFL);
2057 m = chain(m);
2058 }
2059
2060 switch (which) {
2061 case TO:
2062 compare_value(4, 4, CALL);
2063 emitop(OP_BRFL);
2064 m = chain(m);
2065 break;
2066 case FROM:
2067 compare_value(4, 4, REPLY);
2068 emitop(OP_BRFL);
2069 m = chain(m);
2070 break;
2071 }
2072 resolve_chain(m);
2073 resolve_chain(n);
2074 emitop(OP_OFFSET_POP);
2075 }
2076
2077 /*
2078 * Generate code to parse a field specification
2079 * and load the value of the field from the packet
2080 * onto the operand stack.
2081 * The field offset may be specified relative to the
2082 * beginning of the ether header, IP header, UDP header,
2083 * or TCP header. An optional size specification may
2084 * be provided following a colon. If no size is given
2085 * one byte is assumed e.g.
2086 *
2087 * ether[0] The first byte of the ether header
2088 * ip[2:2] The second 16 bit field of the IP header
2089 */
2090 static void
load_field()2091 load_field()
2092 {
2093 int size = 1;
2094 int s;
2095
2096
2097 if (EQ("ether"))
2098 emitop(OP_OFFSET_ZERO);
2099 else if (EQ("ip") || EQ("ip6") || EQ("pppoed") || EQ("pppoes"))
2100 emitop(OP_OFFSET_LINK);
2101 else if (EQ("udp") || EQ("tcp") || EQ("icmp") || EQ("ip-in-ip") ||
2102 EQ("ah") || EQ("esp"))
2103 emitop(OP_OFFSET_IP);
2104 else
2105 pr_err("invalid field type");
2106 next();
2107 s = opstack;
2108 expression();
2109 if (opstack != s + 1)
2110 pr_err("invalid field offset");
2111 opstack--;
2112 if (*token == ':') {
2113 next();
2114 if (tokentype != NUMBER)
2115 pr_err("field size expected");
2116 size = tokenval;
2117 if (size != 1 && size != 2 && size != 4)
2118 pr_err("field size invalid");
2119 next();
2120 }
2121 if (*token != ']')
2122 pr_err("right bracket expected");
2123
2124 load_value(-1, size);
2125 emitop(OP_OFFSET_POP);
2126 }
2127
2128 /*
2129 * Check that the operand stack
2130 * contains n arguments
2131 */
2132 static void
checkstack(int numargs)2133 checkstack(int numargs)
2134 {
2135 if (opstack != numargs)
2136 pr_err("invalid expression at \"%s\".", token);
2137 }
2138
2139 static void
primary()2140 primary()
2141 {
2142 int m, m2, s;
2143
2144 for (;;) {
2145 if (tokentype == FIELD) {
2146 load_field();
2147 opstack++;
2148 next();
2149 break;
2150 }
2151
2152 if (comparison(token)) {
2153 opstack++;
2154 next();
2155 break;
2156 }
2157
2158 if (EQ("not") || EQ("!")) {
2159 next();
2160 s = opstack;
2161 primary();
2162 checkstack(s + 1);
2163 emitop(OP_NOT);
2164 break;
2165 }
2166
2167 if (EQ("(")) {
2168 next();
2169 s = opstack;
2170 expression();
2171 checkstack(s + 1);
2172 if (!EQ(")"))
2173 pr_err("right paren expected");
2174 next();
2175 }
2176
2177 if (EQ("to") || EQ("dst")) {
2178 dir = TO;
2179 next();
2180 continue;
2181 }
2182
2183 if (EQ("from") || EQ("src")) {
2184 dir = FROM;
2185 next();
2186 continue;
2187 }
2188
2189 if (EQ("ether")) {
2190 eaddr = 1;
2191 next();
2192 continue;
2193 }
2194
2195 if (EQ("proto")) {
2196 next();
2197 if (tokentype != NUMBER)
2198 pr_err("IP proto type expected");
2199 emitop(OP_OFFSET_LINK);
2200 compare_value(IPV4_TYPE_HEADER_OFFSET, 1, tokenval);
2201 emitop(OP_OFFSET_POP);
2202 opstack++;
2203 next();
2204 continue;
2205 }
2206
2207 if (EQ("broadcast")) {
2208 /*
2209 * Be tricky: FDDI ether dst address begins at
2210 * byte one. Since the address is really six
2211 * bytes long, this works for FDDI & ethernet.
2212 * XXX - Token ring?
2213 */
2214 emitop(OP_OFFSET_ZERO);
2215 if (interface->mac_type == DL_IB)
2216 pr_err("filter option unsupported on media");
2217 compare_value(1, 4, 0xffffffff);
2218 emitop(OP_OFFSET_POP);
2219 opstack++;
2220 next();
2221 break;
2222 }
2223
2224 if (EQ("multicast")) {
2225 /* XXX Token ring? */
2226 emitop(OP_OFFSET_ZERO);
2227 if (interface->mac_type == DL_FDDI) {
2228 compare_value_mask(1, 1, 0x01, 0x01);
2229 } else if (interface->mac_type == DL_IB) {
2230 pr_err("filter option unsupported on media");
2231 } else {
2232 compare_value_mask(0, 1, 0x01, 0x01);
2233 }
2234 emitop(OP_OFFSET_POP);
2235 opstack++;
2236 next();
2237 break;
2238 }
2239
2240 if (EQ("decnet")) {
2241 /* XXX Token ring? */
2242 if (interface->mac_type == DL_FDDI) {
2243 load_value(19, 2); /* ether type */
2244 load_const(0x6000);
2245 emitop(OP_GE);
2246 emitop(OP_BRFL);
2247 m = chain(0);
2248 load_value(19, 2); /* ether type */
2249 load_const(0x6009);
2250 emitop(OP_LE);
2251 resolve_chain(m);
2252 } else {
2253 emitop(OP_OFFSET_ETHERTYPE);
2254 load_value(0, 2); /* ether type */
2255 load_const(0x6000);
2256 emitop(OP_GE);
2257 emitop(OP_BRFL);
2258 m = chain(0);
2259 load_value(0, 2); /* ether type */
2260 load_const(0x6009);
2261 emitop(OP_LE);
2262 resolve_chain(m);
2263 emitop(OP_OFFSET_POP);
2264 }
2265 opstack++;
2266 next();
2267 break;
2268 }
2269
2270 if (EQ("vlan-id")) {
2271 next();
2272 if (tokentype != NUMBER)
2273 pr_err("vlan id expected");
2274 emitop(OP_OFFSET_ZERO);
2275 ethertype_match(ETHERTYPE_VLAN);
2276 emitop(OP_BRFL);
2277 m = chain(0);
2278 compare_value_mask(VLAN_ID_OFFSET, 2, tokenval,
2279 VLAN_ID_MASK);
2280 resolve_chain(m);
2281 emitop(OP_OFFSET_POP);
2282 opstack++;
2283 next();
2284 break;
2285 }
2286
2287 if (EQ("apple")) {
2288 /*
2289 * Appletalk also appears in 802.2
2290 * packets, so check for the ethertypes
2291 * at offset 12 and 20 in the MAC header.
2292 */
2293 ethertype_match(ETHERTYPE_AT);
2294 emitop(OP_BRTR);
2295 m = chain(0);
2296 ethertype_match(ETHERTYPE_AARP);
2297 emitop(OP_BRTR);
2298 m = chain(m);
2299 compare_value(20, 2, ETHERTYPE_AT); /* 802.2 */
2300 emitop(OP_BRTR);
2301 m = chain(m);
2302 compare_value(20, 2, ETHERTYPE_AARP); /* 802.2 */
2303 resolve_chain(m);
2304 opstack++;
2305 next();
2306 break;
2307 }
2308
2309 if (EQ("vlan")) {
2310 ethertype_match(ETHERTYPE_VLAN);
2311 compare_value_mask(VLAN_ID_OFFSET, 2, 0, VLAN_ID_MASK);
2312 emitop(OP_NOT);
2313 emitop(OP_AND);
2314 opstack++;
2315 next();
2316 break;
2317 }
2318
2319 if (EQ("bootp") || EQ("dhcp")) {
2320 ethertype_match(interface->network_type_ip);
2321 emitop(OP_BRFL);
2322 m = chain(0);
2323 emitop(OP_OFFSET_LINK);
2324 compare_value(9, 1, IPPROTO_UDP);
2325 emitop(OP_OFFSET_POP);
2326 emitop(OP_BRFL);
2327 m = chain(m);
2328 emitop(OP_OFFSET_IP);
2329 compare_value(0, 4,
2330 (IPPORT_BOOTPS << 16) | IPPORT_BOOTPC);
2331 emitop(OP_BRTR);
2332 m2 = chain(0);
2333 compare_value(0, 4,
2334 (IPPORT_BOOTPC << 16) | IPPORT_BOOTPS);
2335 resolve_chain(m2);
2336 emitop(OP_OFFSET_POP);
2337 resolve_chain(m);
2338 opstack++;
2339 dir = ANY;
2340 next();
2341 break;
2342 }
2343
2344 if (EQ("dhcp6")) {
2345 ethertype_match(interface->network_type_ipv6);
2346 emitop(OP_BRFL);
2347 m = chain(0);
2348 emitop(OP_OFFSET_LINK);
2349 compare_value(6, 1, IPPROTO_UDP);
2350 emitop(OP_OFFSET_POP);
2351 emitop(OP_BRFL);
2352 m = chain(m);
2353 emitop(OP_OFFSET_IP);
2354 compare_value(2, 2, IPPORT_DHCPV6S);
2355 emitop(OP_BRTR);
2356 m2 = chain(0);
2357 compare_value(2, 2, IPPORT_DHCPV6C);
2358 resolve_chain(m2);
2359 emitop(OP_OFFSET_POP);
2360 resolve_chain(m);
2361 opstack++;
2362 dir = ANY;
2363 next();
2364 break;
2365 }
2366
2367 if (EQ("ethertype")) {
2368 next();
2369 if (tokentype != NUMBER)
2370 pr_err("ether type expected");
2371 ethertype_match(tokenval);
2372 opstack++;
2373 next();
2374 break;
2375 }
2376
2377 if (EQ("pppoe")) {
2378 ethertype_match(ETHERTYPE_PPPOED);
2379 ethertype_match(ETHERTYPE_PPPOES);
2380 emitop(OP_OR);
2381 opstack++;
2382 next();
2383 break;
2384 }
2385
2386 if (EQ("inet")) {
2387 next();
2388 if (EQ("host"))
2389 next();
2390 if (tokentype != ALPHA && tokentype != ADDR_IP)
2391 pr_err("host/IPv4 addr expected after inet");
2392 ipaddr_match(dir, token, IPV4_ONLY);
2393 opstack++;
2394 next();
2395 break;
2396 }
2397
2398 if (EQ("inet6")) {
2399 next();
2400 if (EQ("host"))
2401 next();
2402 if (tokentype != ALPHA && tokentype != ADDR_IP6)
2403 pr_err("host/IPv6 addr expected after inet6");
2404 ipaddr_match(dir, token, IPV6_ONLY);
2405 opstack++;
2406 next();
2407 break;
2408 }
2409
2410 if (EQ("length")) {
2411 emitop(OP_LOAD_LENGTH);
2412 opstack++;
2413 next();
2414 break;
2415 }
2416
2417 if (EQ("less")) {
2418 next();
2419 if (tokentype != NUMBER)
2420 pr_err("packet length expected");
2421 emitop(OP_LOAD_LENGTH);
2422 load_const(tokenval);
2423 emitop(OP_LT);
2424 opstack++;
2425 next();
2426 break;
2427 }
2428
2429 if (EQ("greater")) {
2430 next();
2431 if (tokentype != NUMBER)
2432 pr_err("packet length expected");
2433 emitop(OP_LOAD_LENGTH);
2434 load_const(tokenval);
2435 emitop(OP_GT);
2436 opstack++;
2437 next();
2438 break;
2439 }
2440
2441 if (EQ("nofrag")) {
2442 emitop(OP_OFFSET_LINK);
2443 compare_value_mask(6, 2, 0, 0x1fff);
2444 emitop(OP_OFFSET_POP);
2445 emitop(OP_BRFL);
2446 m = chain(0);
2447 ethertype_match(interface->network_type_ip);
2448 resolve_chain(m);
2449 opstack++;
2450 next();
2451 break;
2452 }
2453
2454 if (EQ("net") || EQ("dstnet") || EQ("srcnet")) {
2455 if (EQ("dstnet"))
2456 dir = TO;
2457 else if (EQ("srcnet"))
2458 dir = FROM;
2459 next();
2460 netaddr_match(dir, token);
2461 dir = ANY;
2462 opstack++;
2463 next();
2464 break;
2465 }
2466
2467 if (EQ("port") || EQ("srcport") || EQ("dstport")) {
2468 if (EQ("dstport"))
2469 dir = TO;
2470 else if (EQ("srcport"))
2471 dir = FROM;
2472 next();
2473 port_match(dir, token);
2474 dir = ANY;
2475 opstack++;
2476 next();
2477 break;
2478 }
2479
2480 if (EQ("rpc")) {
2481 uint_t vers, proc;
2482 char savetoken[32];
2483
2484 vers = proc = -1;
2485 next();
2486 (void) strlcpy(savetoken, token, sizeof (savetoken));
2487 next();
2488 if (*token == ',') {
2489 next();
2490 if (tokentype != NUMBER)
2491 pr_err("version number expected");
2492 vers = tokenval;
2493 next();
2494 }
2495 if (*token == ',') {
2496 next();
2497 if (tokentype != NUMBER)
2498 pr_err("proc number expected");
2499 proc = tokenval;
2500 next();
2501 }
2502 rpc_match_prog(dir, savetoken, vers, proc);
2503 dir = ANY;
2504 opstack++;
2505 break;
2506 }
2507
2508 if (EQ("slp")) {
2509 /* filter out TCP handshakes */
2510 emitop(OP_OFFSET_LINK);
2511 compare_value(9, 1, IPPROTO_TCP);
2512 emitop(OP_LOAD_CONST);
2513 emitval(52);
2514 emitop(OP_LOAD_CONST);
2515 emitval(2);
2516 emitop(OP_LOAD_SHORT);
2517 emitop(OP_GE);
2518 emitop(OP_AND); /* proto == TCP && len < 52 */
2519 emitop(OP_NOT);
2520 emitop(OP_BRFL); /* pkt too short to be a SLP call */
2521 m = chain(0);
2522
2523 emitop(OP_OFFSET_POP);
2524 emitop(OP_OFFSET_SLP);
2525 resolve_chain(m);
2526 opstack++;
2527 next();
2528 break;
2529 }
2530
2531 if (EQ("ldap")) {
2532 dir = ANY;
2533 port_match(dir, "ldap");
2534 opstack++;
2535 next();
2536 break;
2537 }
2538
2539 if (EQ("and") || EQ("or")) {
2540 break;
2541 }
2542
2543 if (EQ("zone")) {
2544 next();
2545 if (tokentype != NUMBER)
2546 pr_err("zoneid expected");
2547 zone_match(dir, BE_32((uint32_t)(tokenval)));
2548 opstack++;
2549 next();
2550 break;
2551 }
2552
2553 if (EQ("gateway")) {
2554 next();
2555 if (eaddr || tokentype != ALPHA)
2556 pr_err("hostname required: %s", token);
2557 etheraddr_match(dir, token);
2558 dir = ANY;
2559 emitop(OP_BRFL);
2560 m = chain(0);
2561 ipaddr_match(dir, token, IPV4_AND_IPV6);
2562 emitop(OP_NOT);
2563 resolve_chain(m);
2564 opstack++;
2565 next();
2566 }
2567
2568 if (EQ("host") || EQ("between") ||
2569 tokentype == ALPHA || /* assume its a hostname */
2570 tokentype == ADDR_IP ||
2571 tokentype == ADDR_IP6 ||
2572 tokentype == ADDR_AT ||
2573 tokentype == ADDR_ETHER) {
2574 if (EQ("host") || EQ("between"))
2575 next();
2576 if (eaddr || tokentype == ADDR_ETHER) {
2577 etheraddr_match(dir, token);
2578 } else if (tokentype == ALPHA) {
2579 ipaddr_match(dir, token, IPV4_AND_IPV6);
2580 } else if (tokentype == ADDR_AT) {
2581 ataddr_match(dir, token);
2582 } else if (tokentype == ADDR_IP) {
2583 ipaddr_match(dir, token, IPV4_ONLY);
2584 } else {
2585 ipaddr_match(dir, token, IPV6_ONLY);
2586 }
2587 dir = ANY;
2588 eaddr = 0;
2589 opstack++;
2590 next();
2591 break;
2592 }
2593
2594 if (tokentype == NUMBER) {
2595 load_const(tokenval);
2596 opstack++;
2597 next();
2598 break;
2599 }
2600
2601 break; /* unknown token */
2602 }
2603 }
2604
2605 struct optable {
2606 char *op_tok;
2607 enum optype op_type;
2608 };
2609
2610 static struct optable
2611 mulops[] = {
2612 "*", OP_MUL,
2613 "/", OP_DIV,
2614 "%", OP_REM,
2615 "&", OP_AND,
2616 "", OP_STOP,
2617 };
2618
2619 static struct optable
2620 addops[] = {
2621 "+", OP_ADD,
2622 "-", OP_SUB,
2623 "|", OP_OR,
2624 "^", OP_XOR,
2625 "", OP_STOP,
2626 };
2627
2628 static struct optable
2629 compareops[] = {
2630 "==", OP_EQ,
2631 "=", OP_EQ,
2632 "!=", OP_NE,
2633 ">", OP_GT,
2634 ">=", OP_GE,
2635 "<", OP_LT,
2636 "<=", OP_LE,
2637 "", OP_STOP,
2638 };
2639
2640 /*
2641 * Using the table, find the operator
2642 * that corresponds to the token.
2643 * Return 0 if not found.
2644 */
2645 static int
find_op(char * tok,struct optable * table)2646 find_op(char *tok, struct optable *table)
2647 {
2648 struct optable *op;
2649
2650 for (op = table; *op->op_tok; op++) {
2651 if (strcmp(tok, op->op_tok) == 0)
2652 return (op->op_type);
2653 }
2654
2655 return (0);
2656 }
2657
2658 static void
expr_mul()2659 expr_mul()
2660 {
2661 int op;
2662 int s = opstack;
2663
2664 primary();
2665 while (op = find_op(token, mulops)) {
2666 next();
2667 primary();
2668 checkstack(s + 2);
2669 emitop(op);
2670 opstack--;
2671 }
2672 }
2673
2674 static void
expr_add()2675 expr_add()
2676 {
2677 int op, s = opstack;
2678
2679 expr_mul();
2680 while (op = find_op(token, addops)) {
2681 next();
2682 expr_mul();
2683 checkstack(s + 2);
2684 emitop(op);
2685 opstack--;
2686 }
2687 }
2688
2689 static void
expr_compare()2690 expr_compare()
2691 {
2692 int op, s = opstack;
2693
2694 expr_add();
2695 while (op = find_op(token, compareops)) {
2696 next();
2697 expr_add();
2698 checkstack(s + 2);
2699 emitop(op);
2700 opstack--;
2701 }
2702 }
2703
2704 /*
2705 * Alternation ("and") is difficult because
2706 * an implied "and" is acknowledge between
2707 * two adjacent primaries. Just keep calling
2708 * the lower-level expression routine until
2709 * no value is added to the opstack.
2710 */
2711 static void
alternation()2712 alternation()
2713 {
2714 int m = 0;
2715 int s = opstack;
2716
2717 expr_compare();
2718 checkstack(s + 1);
2719 for (;;) {
2720 if (EQ("and"))
2721 next();
2722 emitop(OP_BRFL);
2723 m = chain(m);
2724 expr_compare();
2725 if (opstack != s + 2)
2726 break;
2727 opstack--;
2728 }
2729 unemit(2);
2730 resolve_chain(m);
2731 }
2732
2733 static void
expression()2734 expression()
2735 {
2736 int m = 0;
2737 int s = opstack;
2738
2739 alternation();
2740 while (EQ("or") || EQ(",")) {
2741 emitop(OP_BRTR);
2742 m = chain(m);
2743 next();
2744 alternation();
2745 checkstack(s + 2);
2746 opstack--;
2747 }
2748 resolve_chain(m);
2749 }
2750
2751 /*
2752 * Take n args from the argv list
2753 * and concatenate them into a single string.
2754 */
2755 char *
concat_args(char ** argv,int argc)2756 concat_args(char **argv, int argc)
2757 {
2758 int i, len;
2759 char *str, *p;
2760
2761 /* First add the lengths of all the strings */
2762 len = 0;
2763 for (i = 0; i < argc; i++)
2764 len += strlen(argv[i]) + 1;
2765
2766 /* allocate the big string */
2767 str = (char *)malloc(len);
2768 if (str == NULL)
2769 pr_err("no mem");
2770
2771 p = str;
2772
2773 /*
2774 * Concat the strings into the big
2775 * string using a space as separator
2776 */
2777 for (i = 0; i < argc; i++) {
2778 strcpy(p, argv[i]);
2779 p += strlen(p);
2780 *p++ = ' ';
2781 }
2782 *--p = '\0';
2783
2784 return (str);
2785 }
2786
2787 /*
2788 * Take the expression in the string "expr"
2789 * and compile it into the code array.
2790 * Print the generated code if the print
2791 * arg is set.
2792 */
2793 void
compile(char * expr,int print)2794 compile(char *expr, int print)
2795 {
2796 expr = strdup(expr);
2797 if (expr == NULL)
2798 pr_err("no mem");
2799 curr_op = oplist;
2800 tkp = expr;
2801 dir = ANY;
2802
2803 next();
2804 if (tokentype != EOL)
2805 expression();
2806 emitop(OP_STOP);
2807 if (tokentype != EOL)
2808 pr_err("invalid expression");
2809 optimize(oplist);
2810 if (print)
2811 codeprint();
2812 }
2813
2814 /*
2815 * Lookup hostname in the arp cache.
2816 */
2817 boolean_t
arp_for_ether(char * hostname,struct ether_addr * ep)2818 arp_for_ether(char *hostname, struct ether_addr *ep)
2819 {
2820 struct arpreq ar;
2821 struct hostent *hp;
2822 struct sockaddr_in *sin;
2823 int error_num;
2824 int s;
2825
2826 memset(&ar, 0, sizeof (ar));
2827 sin = (struct sockaddr_in *)&ar.arp_pa;
2828 sin->sin_family = AF_INET;
2829 hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
2830 if (hp == NULL) {
2831 return (B_FALSE);
2832 }
2833 memcpy(&sin->sin_addr, hp->h_addr, sizeof (sin->sin_addr));
2834 s = socket(AF_INET, SOCK_DGRAM, 0);
2835 if (s < 0) {
2836 return (B_FALSE);
2837 }
2838 if (ioctl(s, SIOCGARP, &ar) < 0) {
2839 close(s);
2840 return (B_FALSE);
2841 }
2842 close(s);
2843 memcpy(ep->ether_addr_octet, ar.arp_ha.sa_data, sizeof (*ep));
2844 return (B_TRUE);
2845 }
2846