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