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 */
25
26 #include <stdio.h>
27 #include <stddef.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/time.h>
34 #include <sys/isa_defs.h>
35
36 #include <sys/socket.h>
37 #include <sys/vlan.h>
38 #include <net/if.h>
39 #include <netinet/in_systm.h>
40 #include <netinet/in.h>
41 #include <netinet/ip.h>
42 #include <netinet/if_ether.h>
43 #include <netinet/tcp.h>
44 #include <netinet/udp.h>
45 #include <inet/ip.h>
46 #include <inet/ip6.h>
47 #include <netdb.h>
48 #include <rpc/rpc.h>
49 #include <setjmp.h>
50
51 #include <sys/pfmod.h>
52 #include "snoop.h"
53 #include "snoop_vlan.h"
54
55 /*
56 * This module generates code for the kernel packet filter.
57 * The kernel packet filter is more efficient since it
58 * operates without context switching or moving data into
59 * the capture buffer. On the other hand, it is limited
60 * in its filtering ability i.e. can't cope with variable
61 * length headers, can't compare the packet size, 1 and 4 octet
62 * comparisons are awkward, code space is limited to ENMAXFILTERS
63 * halfwords, etc.
64 * The parser is the same for the user-level packet filter though
65 * more limited in the variety of expressions it can generate
66 * code for. If the pf compiler finds an expression it can't
67 * handle, it tries to set up a split filter in kernel and do the
68 * remaining filtering in userland. If that also fails, it resorts
69 * to userland filter. (See additional comment in pf_compile)
70 */
71
72 extern struct Pf_ext_packetfilt pf;
73 static ushort_t *pfp;
74 jmp_buf env;
75
76 int eaddr; /* need ethernet addr */
77
78 int opstack; /* operand stack depth */
79
80 #define EQ(val) (strcmp(token, val) == 0)
81 #define IPV4_ONLY 0
82 #define IPV6_ONLY 1
83 #define IPV4_AND_IPV6 2
84
85 typedef struct {
86 int transport_protocol;
87 int network_protocol;
88 /*
89 * offset is the offset in bytes from the beginning
90 * of the network protocol header to where the transport
91 * protocol type is.
92 */
93 int offset;
94 } transport_table_t;
95
96 typedef struct network_table {
97 char *nmt_name;
98 int nmt_val;
99 } network_table_t;
100
101 static network_table_t ether_network_mapping_table[] = {
102 { "pup", ETHERTYPE_PUP },
103 { "ip", ETHERTYPE_IP },
104 { "arp", ETHERTYPE_ARP },
105 { "revarp", ETHERTYPE_REVARP },
106 { "at", ETHERTYPE_AT },
107 { "aarp", ETHERTYPE_AARP },
108 { "vlan", ETHERTYPE_VLAN },
109 { "ip6", ETHERTYPE_IPV6 },
110 { "slow", ETHERTYPE_SLOW },
111 { "ppoed", ETHERTYPE_PPPOED },
112 { "ppoes", ETHERTYPE_PPPOES },
113 { "NULL", -1 }
114
115 };
116
117 static network_table_t ib_network_mapping_table[] = {
118 { "pup", ETHERTYPE_PUP },
119 { "ip", ETHERTYPE_IP },
120 { "arp", ETHERTYPE_ARP },
121 { "revarp", ETHERTYPE_REVARP },
122 { "at", ETHERTYPE_AT },
123 { "aarp", ETHERTYPE_AARP },
124 { "vlan", ETHERTYPE_VLAN },
125 { "ip6", ETHERTYPE_IPV6 },
126 { "slow", ETHERTYPE_SLOW },
127 { "ppoed", ETHERTYPE_PPPOED },
128 { "ppoes", ETHERTYPE_PPPOES },
129 { "NULL", -1 }
130
131 };
132
133 static network_table_t ipnet_network_mapping_table[] = {
134 { "ip", (DL_IPNETINFO_VERSION << 8 | AF_INET) },
135 { "ip6", (DL_IPNETINFO_VERSION << 8 | AF_INET6) },
136 { "NULL", -1 }
137
138 };
139
140 static transport_table_t ether_transport_mapping_table[] = {
141 {IPPROTO_TCP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
142 {IPPROTO_TCP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
143 {IPPROTO_UDP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
144 {IPPROTO_UDP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
145 {IPPROTO_OSPF, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
146 {IPPROTO_OSPF, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
147 {IPPROTO_SCTP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
148 {IPPROTO_SCTP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
149 {IPPROTO_ICMP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
150 {IPPROTO_ICMPV6, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
151 {IPPROTO_ENCAP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
152 {IPPROTO_ESP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
153 {IPPROTO_ESP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
154 {IPPROTO_AH, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
155 {IPPROTO_AH, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
156 {-1, 0, 0} /* must be the final entry */
157 };
158
159 static transport_table_t ipnet_transport_mapping_table[] = {
160 {IPPROTO_TCP, (DL_IPNETINFO_VERSION << 8 | AF_INET),
161 IPV4_TYPE_HEADER_OFFSET},
162 {IPPROTO_TCP, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
163 IPV6_TYPE_HEADER_OFFSET},
164 {IPPROTO_UDP, (DL_IPNETINFO_VERSION << 8 | AF_INET),
165 IPV4_TYPE_HEADER_OFFSET},
166 {IPPROTO_UDP, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
167 IPV6_TYPE_HEADER_OFFSET},
168 {IPPROTO_OSPF, (DL_IPNETINFO_VERSION << 8 | AF_INET),
169 IPV4_TYPE_HEADER_OFFSET},
170 {IPPROTO_OSPF, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
171 IPV6_TYPE_HEADER_OFFSET},
172 {IPPROTO_SCTP, (DL_IPNETINFO_VERSION << 8 | AF_INET),
173 IPV4_TYPE_HEADER_OFFSET},
174 {IPPROTO_SCTP, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
175 IPV6_TYPE_HEADER_OFFSET},
176 {IPPROTO_ICMP, (DL_IPNETINFO_VERSION << 8 | AF_INET),
177 IPV4_TYPE_HEADER_OFFSET},
178 {IPPROTO_ICMPV6, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
179 IPV6_TYPE_HEADER_OFFSET},
180 {IPPROTO_ENCAP, (DL_IPNETINFO_VERSION << 8 | AF_INET),
181 IPV4_TYPE_HEADER_OFFSET},
182 {IPPROTO_ESP, (DL_IPNETINFO_VERSION << 8 | AF_INET),
183 IPV4_TYPE_HEADER_OFFSET},
184 {IPPROTO_ESP, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
185 IPV6_TYPE_HEADER_OFFSET},
186 {IPPROTO_AH, (DL_IPNETINFO_VERSION << 8 | AF_INET),
187 IPV4_TYPE_HEADER_OFFSET},
188 {IPPROTO_AH, (DL_IPNETINFO_VERSION << 8 | AF_INET6),
189 IPV6_TYPE_HEADER_OFFSET},
190 {-1, 0, 0} /* must be the final entry */
191 };
192
193 static transport_table_t ib_transport_mapping_table[] = {
194 {IPPROTO_TCP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
195 {IPPROTO_TCP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
196 {IPPROTO_UDP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
197 {IPPROTO_UDP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
198 {IPPROTO_OSPF, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
199 {IPPROTO_OSPF, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
200 {IPPROTO_SCTP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
201 {IPPROTO_SCTP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
202 {IPPROTO_ICMP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
203 {IPPROTO_ICMPV6, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
204 {IPPROTO_ENCAP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
205 {IPPROTO_ESP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
206 {IPPROTO_ESP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
207 {IPPROTO_AH, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET},
208 {IPPROTO_AH, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
209 {-1, 0, 0} /* must be the final entry */
210 };
211
212 typedef struct datalink {
213 uint_t dl_type;
214 void (*dl_match_fn)(uint_t datatype);
215 transport_table_t *dl_trans_map_tbl;
216 network_table_t *dl_net_map_tbl;
217 int dl_link_header_len;
218 int dl_link_type_offset;
219 int dl_link_dest_offset;
220 int dl_link_src_offset;
221 int dl_link_addr_len;
222 } datalink_t;
223
224 datalink_t dl;
225
226 #define IPV4_SRCADDR_OFFSET (dl.dl_link_header_len + 12)
227 #define IPV4_DSTADDR_OFFSET (dl.dl_link_header_len + 16)
228 #define IPV6_SRCADDR_OFFSET (dl.dl_link_header_len + 8)
229 #define IPV6_DSTADDR_OFFSET (dl.dl_link_header_len + 24)
230
231 #define IPNET_SRCZONE_OFFSET 16
232 #define IPNET_DSTZONE_OFFSET 20
233
234 static int inBrace = 0, inBraceOR = 0;
235 static int foundOR = 0;
236 char *tkp, *sav_tkp;
237 char *token;
238 enum { EOL, ALPHA, NUMBER, FIELD, ADDR_IP, ADDR_ETHER, SPECIAL,
239 ADDR_IP6 } tokentype;
240 uint_t tokenval;
241
242 enum direction { ANY, TO, FROM };
243 enum direction dir;
244
245 extern void next();
246
247 static void pf_expression();
248 static void pf_check_vlan_tag(uint_t offset);
249 static void pf_clear_offset_register();
250 static void pf_emit_load_offset(uint_t offset);
251 static void pf_match_ethertype(uint_t ethertype);
252 static void pf_match_ipnettype(uint_t type);
253 static void pf_match_ibtype(uint_t type);
254 static void pf_check_transport_protocol(uint_t transport_protocol);
255 static void pf_compare_value_mask_generic(int offset, uint_t len,
256 uint_t val, int mask, uint_t op);
257 static void pf_matchfn(const char *name);
258
259 /*
260 * This pointer points to the function that last generated
261 * instructions to change the offset register. It's used
262 * for comparisons to see if we need to issue more instructions
263 * to change the register.
264 *
265 * It's initialized to pf_clear_offset_register because the offset
266 * register in pfmod is initialized to zero, similar to the state
267 * it would be in after executing the instructions issued by
268 * pf_clear_offset_register.
269 */
270 static void *last_offset_operation = (void*)pf_clear_offset_register;
271
272 static void
pf_emit(x)273 pf_emit(x)
274 ushort_t x;
275 {
276 if (pfp > &pf.Pf_Filter[PF_MAXFILTERS - 1])
277 longjmp(env, 1);
278 *pfp++ = x;
279 }
280
281 static void
pf_codeprint(code,len)282 pf_codeprint(code, len)
283 ushort_t *code;
284 int len;
285 {
286 ushort_t *pc;
287 ushort_t *plast = code + len;
288 int op, action;
289
290 if (len > 0) {
291 printf("Kernel Filter:\n");
292 }
293
294 for (pc = code; pc < plast; pc++) {
295 printf("\t%3d: ", pc - code);
296
297 op = *pc & 0xfc00; /* high 10 bits */
298 action = *pc & 0x3ff; /* low 6 bits */
299
300 switch (action) {
301 case ENF_PUSHLIT:
302 printf("PUSHLIT ");
303 break;
304 case ENF_PUSHZERO:
305 printf("PUSHZERO ");
306 break;
307 #ifdef ENF_PUSHONE
308 case ENF_PUSHONE:
309 printf("PUSHONE ");
310 break;
311 #endif
312 #ifdef ENF_PUSHFFFF
313 case ENF_PUSHFFFF:
314 printf("PUSHFFFF ");
315 break;
316 #endif
317 #ifdef ENF_PUSHFF00
318 case ENF_PUSHFF00:
319 printf("PUSHFF00 ");
320 break;
321 #endif
322 #ifdef ENF_PUSH00FF
323 case ENF_PUSH00FF:
324 printf("PUSH00FF ");
325 break;
326 #endif
327 case ENF_LOAD_OFFSET:
328 printf("LOAD_OFFSET ");
329 break;
330 case ENF_BRTR:
331 printf("BRTR ");
332 break;
333 case ENF_BRFL:
334 printf("BRFL ");
335 break;
336 case ENF_POP:
337 printf("POP ");
338 break;
339 }
340
341 if (action >= ENF_PUSHWORD)
342 printf("PUSHWORD %d ", action - ENF_PUSHWORD);
343
344 switch (op) {
345 case ENF_EQ:
346 printf("EQ ");
347 break;
348 case ENF_LT:
349 printf("LT ");
350 break;
351 case ENF_LE:
352 printf("LE ");
353 break;
354 case ENF_GT:
355 printf("GT ");
356 break;
357 case ENF_GE:
358 printf("GE ");
359 break;
360 case ENF_AND:
361 printf("AND ");
362 break;
363 case ENF_OR:
364 printf("OR ");
365 break;
366 case ENF_XOR:
367 printf("XOR ");
368 break;
369 case ENF_COR:
370 printf("COR ");
371 break;
372 case ENF_CAND:
373 printf("CAND ");
374 break;
375 case ENF_CNOR:
376 printf("CNOR ");
377 break;
378 case ENF_CNAND:
379 printf("CNAND ");
380 break;
381 case ENF_NEQ:
382 printf("NEQ ");
383 break;
384 }
385
386 if (action == ENF_PUSHLIT ||
387 action == ENF_LOAD_OFFSET ||
388 action == ENF_BRTR ||
389 action == ENF_BRFL) {
390 pc++;
391 printf("\n\t%3d: %d (0x%04x)", pc - code, *pc, *pc);
392 }
393
394 printf("\n");
395 }
396 }
397
398 /*
399 * Emit packet filter code to check a
400 * field in the packet for a particular value.
401 * Need different code for each field size.
402 * Since the pf can only compare 16 bit quantities
403 * we have to use masking to compare byte values.
404 * Long word (32 bit) quantities have to be done
405 * as two 16 bit comparisons.
406 */
407 static void
pf_compare_value(int offset,uint_t len,uint_t val)408 pf_compare_value(int offset, uint_t len, uint_t val)
409 {
410 /*
411 * If the property being filtered on is absent in the media
412 * packet, error out.
413 */
414 if (offset == -1)
415 pr_err("filter option unsupported on media");
416
417 switch (len) {
418 case 1:
419 pf_emit(ENF_PUSHWORD + offset / 2);
420 #if defined(_BIG_ENDIAN)
421 if (offset % 2)
422 #else
423 if (!(offset % 2))
424 #endif
425 {
426 #ifdef ENF_PUSH00FF
427 pf_emit(ENF_PUSH00FF | ENF_AND);
428 #else
429 pf_emit(ENF_PUSHLIT | ENF_AND);
430 pf_emit(0x00FF);
431 #endif
432 pf_emit(ENF_PUSHLIT | ENF_EQ);
433 pf_emit(val);
434 } else {
435 #ifdef ENF_PUSHFF00
436 pf_emit(ENF_PUSHFF00 | ENF_AND);
437 #else
438 pf_emit(ENF_PUSHLIT | ENF_AND);
439 pf_emit(0xFF00);
440 #endif
441 pf_emit(ENF_PUSHLIT | ENF_EQ);
442 pf_emit(val << 8);
443 }
444 break;
445
446 case 2:
447 pf_emit(ENF_PUSHWORD + offset / 2);
448 pf_emit(ENF_PUSHLIT | ENF_EQ);
449 pf_emit((ushort_t)val);
450 break;
451
452 case 4:
453 pf_emit(ENF_PUSHWORD + offset / 2);
454 pf_emit(ENF_PUSHLIT | ENF_EQ);
455 #if defined(_BIG_ENDIAN)
456 pf_emit(val >> 16);
457 #elif defined(_LITTLE_ENDIAN)
458 pf_emit(val & 0xffff);
459 #else
460 #error One of _BIG_ENDIAN and _LITTLE_ENDIAN must be defined
461 #endif
462 pf_emit(ENF_PUSHWORD + (offset / 2) + 1);
463 pf_emit(ENF_PUSHLIT | ENF_EQ);
464 #if defined(_BIG_ENDIAN)
465 pf_emit(val & 0xffff);
466 #else
467 pf_emit(val >> 16);
468 #endif
469 pf_emit(ENF_AND);
470 break;
471 }
472 }
473
474 /*
475 * same as pf_compare_value, but only for emiting code to
476 * compare ipv6 addresses.
477 */
478 static void
pf_compare_value_v6(int offset,uint_t len,struct in6_addr val)479 pf_compare_value_v6(int offset, uint_t len, struct in6_addr val)
480 {
481 int i;
482
483 for (i = 0; i < len; i += 2) {
484 pf_emit(ENF_PUSHWORD + offset / 2 + i / 2);
485 pf_emit(ENF_PUSHLIT | ENF_EQ);
486 pf_emit(*(uint16_t *)&val.s6_addr[i]);
487 if (i != 0)
488 pf_emit(ENF_AND);
489 }
490 }
491
492
493 /*
494 * Same as above except mask the field value
495 * before doing the comparison. The comparison checks
496 * to make sure the values are equal.
497 */
498 static void
pf_compare_value_mask(int offset,uint_t len,uint_t val,int mask)499 pf_compare_value_mask(int offset, uint_t len, uint_t val, int mask)
500 {
501 pf_compare_value_mask_generic(offset, len, val, mask, ENF_EQ);
502 }
503
504 /*
505 * Same as above except the values are compared to see if they are not
506 * equal.
507 */
508 static void
pf_compare_value_mask_neq(int offset,uint_t len,uint_t val,int mask)509 pf_compare_value_mask_neq(int offset, uint_t len, uint_t val, int mask)
510 {
511 pf_compare_value_mask_generic(offset, len, val, mask, ENF_NEQ);
512 }
513
514 /*
515 * Similar to pf_compare_value.
516 *
517 * This is the utility function that does the actual work to compare
518 * two values using a mask. The comparison operation is passed into
519 * the function.
520 */
521 static void
pf_compare_value_mask_generic(int offset,uint_t len,uint_t val,int mask,uint_t op)522 pf_compare_value_mask_generic(int offset, uint_t len, uint_t val, int mask,
523 uint_t op)
524 {
525 /*
526 * If the property being filtered on is absent in the media
527 * packet, error out.
528 */
529 if (offset == -1)
530 pr_err("filter option unsupported on media");
531
532 switch (len) {
533 case 1:
534 pf_emit(ENF_PUSHWORD + offset / 2);
535 #if defined(_BIG_ENDIAN)
536 if (offset % 2)
537 #else
538 if (!offset % 2)
539 #endif
540 {
541 pf_emit(ENF_PUSHLIT | ENF_AND);
542 pf_emit(mask & 0x00ff);
543 pf_emit(ENF_PUSHLIT | op);
544 pf_emit(val);
545 } else {
546 pf_emit(ENF_PUSHLIT | ENF_AND);
547 pf_emit((mask << 8) & 0xff00);
548 pf_emit(ENF_PUSHLIT | op);
549 pf_emit(val << 8);
550 }
551 break;
552
553 case 2:
554 pf_emit(ENF_PUSHWORD + offset / 2);
555 pf_emit(ENF_PUSHLIT | ENF_AND);
556 pf_emit(htons((ushort_t)mask));
557 pf_emit(ENF_PUSHLIT | op);
558 pf_emit(htons((ushort_t)val));
559 break;
560
561 case 4:
562 pf_emit(ENF_PUSHWORD + offset / 2);
563 pf_emit(ENF_PUSHLIT | ENF_AND);
564 pf_emit(htons((ushort_t)((mask >> 16) & 0xffff)));
565 pf_emit(ENF_PUSHLIT | op);
566 pf_emit(htons((ushort_t)((val >> 16) & 0xffff)));
567
568 pf_emit(ENF_PUSHWORD + (offset / 2) + 1);
569 pf_emit(ENF_PUSHLIT | ENF_AND);
570 pf_emit(htons((ushort_t)(mask & 0xffff)));
571 pf_emit(ENF_PUSHLIT | op);
572 pf_emit(htons((ushort_t)(val & 0xffff)));
573
574 pf_emit(ENF_AND);
575 break;
576 }
577 }
578
579 /*
580 * Like pf_compare_value() but compare on a 32-bit zoneid value.
581 * The argument val passed in is in network byte order.
582 */
583 static void
pf_compare_zoneid(int offset,uint32_t val)584 pf_compare_zoneid(int offset, uint32_t val)
585 {
586 int i;
587
588 for (i = 0; i < sizeof (uint32_t) / 2; i ++) {
589 pf_emit(ENF_PUSHWORD + offset / 2 + i);
590 pf_emit(ENF_PUSHLIT | ENF_EQ);
591 pf_emit(((uint16_t *)&val)[i]);
592 if (i != 0)
593 pf_emit(ENF_AND);
594 }
595 }
596
597 /*
598 * Generate pf code to match an IPv4 or IPv6 address.
599 */
600 static void
pf_ipaddr_match(which,hostname,inet_type)601 pf_ipaddr_match(which, hostname, inet_type)
602 enum direction which;
603 char *hostname;
604 int inet_type;
605 {
606 bool_t found_host;
607 uint_t *addr4ptr;
608 uint_t addr4;
609 struct in6_addr *addr6ptr;
610 int h_addr_index;
611 struct hostent *hp = NULL;
612 int error_num = 0;
613 boolean_t first = B_TRUE;
614 int pass = 0;
615 int i;
616
617 /*
618 * The addr4offset and addr6offset variables simplify the code which
619 * generates the address comparison filter. With these two variables,
620 * duplicate code need not exist for the TO and FROM case.
621 * A value of -1 describes the ANY case (TO and FROM).
622 */
623 int addr4offset;
624 int addr6offset;
625
626 found_host = 0;
627
628 if (tokentype == ADDR_IP) {
629 hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
630 if (hp == NULL) {
631 if (error_num == TRY_AGAIN) {
632 pr_err("could not resolve %s (try again later)",
633 hostname);
634 } else {
635 pr_err("could not resolve %s", hostname);
636 }
637 }
638 inet_type = IPV4_ONLY;
639 } else if (tokentype == ADDR_IP6) {
640 hp = getipnodebyname(hostname, AF_INET6, 0, &error_num);
641 if (hp == NULL) {
642 if (error_num == TRY_AGAIN) {
643 pr_err("could not resolve %s (try again later)",
644 hostname);
645 } else {
646 pr_err("could not resolve %s", hostname);
647 }
648 }
649 inet_type = IPV6_ONLY;
650 } else if (tokentype == ALPHA) {
651 /* Some hostname i.e. tokentype is ALPHA */
652 switch (inet_type) {
653 case IPV4_ONLY:
654 /* Only IPv4 address is needed */
655 hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
656 if (hp != NULL) {
657 found_host = 1;
658 }
659 break;
660 case IPV6_ONLY:
661 /* Only IPv6 address is needed */
662 hp = getipnodebyname(hostname, AF_INET6, 0, &error_num);
663 if (hp != NULL) {
664 found_host = 1;
665 }
666 break;
667 case IPV4_AND_IPV6:
668 /* Both IPv4 and IPv6 are needed */
669 hp = getipnodebyname(hostname, AF_INET6,
670 AI_ALL | AI_V4MAPPED, &error_num);
671 if (hp != NULL) {
672 found_host = 1;
673 }
674 break;
675 default:
676 found_host = 0;
677 }
678
679 if (!found_host) {
680 if (error_num == TRY_AGAIN) {
681 pr_err("could not resolve %s (try again later)",
682 hostname);
683 } else {
684 pr_err("could not resolve %s", hostname);
685 }
686 }
687 } else {
688 pr_err("unknown token type: %s", hostname);
689 }
690
691 switch (which) {
692 case TO:
693 addr4offset = IPV4_DSTADDR_OFFSET;
694 addr6offset = IPV6_DSTADDR_OFFSET;
695 break;
696 case FROM:
697 addr4offset = IPV4_SRCADDR_OFFSET;
698 addr6offset = IPV6_SRCADDR_OFFSET;
699 break;
700 case ANY:
701 addr4offset = -1;
702 addr6offset = -1;
703 break;
704 }
705
706 if (hp != NULL && hp->h_addrtype == AF_INET) {
707 pf_matchfn("ip");
708 if (dl.dl_type == DL_ETHER)
709 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
710 h_addr_index = 0;
711 addr4ptr = (uint_t *)hp->h_addr_list[h_addr_index];
712 while (addr4ptr != NULL) {
713 if (addr4offset == -1) {
714 pf_compare_value(IPV4_SRCADDR_OFFSET, 4,
715 *addr4ptr);
716 if (h_addr_index != 0)
717 pf_emit(ENF_OR);
718 pf_compare_value(IPV4_DSTADDR_OFFSET, 4,
719 *addr4ptr);
720 pf_emit(ENF_OR);
721 } else {
722 pf_compare_value(addr4offset, 4,
723 *addr4ptr);
724 if (h_addr_index != 0)
725 pf_emit(ENF_OR);
726 }
727 addr4ptr = (uint_t *)hp->h_addr_list[++h_addr_index];
728 }
729 pf_emit(ENF_AND);
730 } else {
731 /* first pass: IPv4 addresses */
732 h_addr_index = 0;
733 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
734 first = B_TRUE;
735 while (addr6ptr != NULL) {
736 if (IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
737 if (first) {
738 pf_matchfn("ip");
739 if (dl.dl_type == DL_ETHER) {
740 pf_check_vlan_tag(
741 ENCAP_ETHERTYPE_OFF/2);
742 }
743 pass++;
744 }
745 IN6_V4MAPPED_TO_INADDR(addr6ptr,
746 (struct in_addr *)&addr4);
747 if (addr4offset == -1) {
748 pf_compare_value(IPV4_SRCADDR_OFFSET, 4,
749 addr4);
750 if (!first)
751 pf_emit(ENF_OR);
752 pf_compare_value(IPV4_DSTADDR_OFFSET, 4,
753 addr4);
754 pf_emit(ENF_OR);
755 } else {
756 pf_compare_value(addr4offset, 4,
757 addr4);
758 if (!first)
759 pf_emit(ENF_OR);
760 }
761 if (first)
762 first = B_FALSE;
763 }
764 addr6ptr = (struct in6_addr *)
765 hp->h_addr_list[++h_addr_index];
766 }
767 if (!first) {
768 pf_emit(ENF_AND);
769 }
770 /* second pass: IPv6 addresses */
771 h_addr_index = 0;
772 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
773 first = B_TRUE;
774 while (addr6ptr != NULL) {
775 if (!IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
776 if (first) {
777 pf_matchfn("ip6");
778 if (dl.dl_type == DL_ETHER) {
779 pf_check_vlan_tag(
780 ENCAP_ETHERTYPE_OFF/2);
781 }
782 pass++;
783 }
784 if (addr6offset == -1) {
785 pf_compare_value_v6(IPV6_SRCADDR_OFFSET,
786 16, *addr6ptr);
787 if (!first)
788 pf_emit(ENF_OR);
789 pf_compare_value_v6(IPV6_DSTADDR_OFFSET,
790 16, *addr6ptr);
791 pf_emit(ENF_OR);
792 } else {
793 pf_compare_value_v6(addr6offset, 16,
794 *addr6ptr);
795 if (!first)
796 pf_emit(ENF_OR);
797 }
798 if (first)
799 first = B_FALSE;
800 }
801 addr6ptr = (struct in6_addr *)
802 hp->h_addr_list[++h_addr_index];
803 }
804 if (!first) {
805 pf_emit(ENF_AND);
806 }
807 if (pass == 2) {
808 pf_emit(ENF_OR);
809 }
810 }
811
812 if (hp != NULL) {
813 freehostent(hp);
814 }
815 }
816
817
818 static void
pf_compare_address(int offset,uint_t len,uchar_t * addr)819 pf_compare_address(int offset, uint_t len, uchar_t *addr)
820 {
821 uint32_t val;
822 uint16_t sval;
823 boolean_t didone = B_FALSE;
824
825 /*
826 * If the property being filtered on is absent in the media
827 * packet, error out.
828 */
829 if (offset == -1)
830 pr_err("filter option unsupported on media");
831
832 while (len > 0) {
833 if (len >= 4) {
834 (void) memcpy(&val, addr, 4);
835 pf_compare_value(offset, 4, val);
836 addr += 4;
837 offset += 4;
838 len -= 4;
839 } else if (len >= 2) {
840 (void) memcpy(&sval, addr, 2);
841 pf_compare_value(offset, 2, sval);
842 addr += 2;
843 offset += 2;
844 len -= 2;
845 } else {
846 pf_compare_value(offset++, 1, *addr++);
847 len--;
848 }
849 if (didone)
850 pf_emit(ENF_AND);
851 didone = B_TRUE;
852 }
853 }
854
855 /*
856 * Compare ethernet addresses.
857 */
858 static void
pf_etheraddr_match(which,hostname)859 pf_etheraddr_match(which, hostname)
860 enum direction which;
861 char *hostname;
862 {
863 struct ether_addr e, *ep = NULL;
864
865 if (isxdigit(*hostname))
866 ep = ether_aton(hostname);
867 if (ep == NULL) {
868 if (ether_hostton(hostname, &e))
869 if (!arp_for_ether(hostname, &e))
870 pr_err("cannot obtain ether addr for %s",
871 hostname);
872 ep = &e;
873 }
874
875 pf_clear_offset_register();
876
877 switch (which) {
878 case TO:
879 pf_compare_address(dl.dl_link_dest_offset, dl.dl_link_addr_len,
880 (uchar_t *)ep);
881 break;
882 case FROM:
883 pf_compare_address(dl.dl_link_src_offset, dl.dl_link_addr_len,
884 (uchar_t *)ep);
885 break;
886 case ANY:
887 pf_compare_address(dl.dl_link_dest_offset, dl.dl_link_addr_len,
888 (uchar_t *)ep);
889 pf_compare_address(dl.dl_link_src_offset, dl.dl_link_addr_len,
890 (uchar_t *)ep);
891 pf_emit(ENF_OR);
892 break;
893 }
894 }
895
896 /*
897 * Emit code to compare the network part of
898 * an IP address.
899 */
900 static void
pf_netaddr_match(which,netname)901 pf_netaddr_match(which, netname)
902 enum direction which;
903 char *netname;
904 {
905 uint_t addr;
906 uint_t mask = 0xff000000;
907 struct netent *np;
908
909 if (isdigit(*netname)) {
910 addr = inet_network(netname);
911 } else {
912 np = getnetbyname(netname);
913 if (np == NULL)
914 pr_err("net %s not known", netname);
915 addr = np->n_net;
916 }
917
918 /*
919 * Left justify the address and figure
920 * out a mask based on the supplied address.
921 * Set the mask according to the number of zero
922 * low-order bytes.
923 * Note: this works only for whole octet masks.
924 */
925 if (addr) {
926 while ((addr & ~mask) != 0) {
927 mask |= (mask >> 8);
928 }
929 }
930
931 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
932
933 switch (which) {
934 case TO:
935 pf_compare_value_mask(IPV4_DSTADDR_OFFSET, 4, addr, mask);
936 break;
937 case FROM:
938 pf_compare_value_mask(IPV4_SRCADDR_OFFSET, 4, addr, mask);
939 break;
940 case ANY:
941 pf_compare_value_mask(IPV4_SRCADDR_OFFSET, 4, addr, mask);
942 pf_compare_value_mask(IPV4_DSTADDR_OFFSET, 4, addr, mask);
943 pf_emit(ENF_OR);
944 break;
945 }
946 }
947
948 /*
949 * Emit code to match on src or destination zoneid.
950 * The zoneid passed in is in network byte order.
951 */
952 static void
pf_match_zone(enum direction which,uint32_t zoneid)953 pf_match_zone(enum direction which, uint32_t zoneid)
954 {
955 if (dl.dl_type != DL_IPNET)
956 pr_err("zone filter option unsupported on media");
957
958 switch (which) {
959 case TO:
960 pf_compare_zoneid(IPNET_DSTZONE_OFFSET, zoneid);
961 break;
962 case FROM:
963 pf_compare_zoneid(IPNET_SRCZONE_OFFSET, zoneid);
964 break;
965 case ANY:
966 pf_compare_zoneid(IPNET_SRCZONE_OFFSET, zoneid);
967 pf_compare_zoneid(IPNET_DSTZONE_OFFSET, zoneid);
968 pf_emit(ENF_OR);
969 break;
970 }
971 }
972
973 /*
974 * A helper function to keep the code to emit instructions
975 * to change the offset register in one place.
976 *
977 * INPUTS: offset - An value representing an offset in 16-bit
978 * words.
979 * OUTPUTS: If there is enough room in the storage for the
980 * packet filtering program, instructions to load
981 * a constant to the offset register. Otherwise,
982 * nothing.
983 */
984 static void
pf_emit_load_offset(uint_t offset)985 pf_emit_load_offset(uint_t offset)
986 {
987 pf_emit(ENF_LOAD_OFFSET | ENF_NOP);
988 pf_emit(offset);
989 }
990
991 /*
992 * Clear pfmod's offset register.
993 *
994 * INPUTS: none
995 * OUTPUTS: Instructions to clear the offset register if
996 * there is enough space remaining in the packet
997 * filtering program structure's storage, and
998 * the last thing done to the offset register was
999 * not clearing the offset register. Otherwise,
1000 * nothing.
1001 */
1002 static void
pf_clear_offset_register()1003 pf_clear_offset_register()
1004 {
1005 if (last_offset_operation != (void*)pf_clear_offset_register) {
1006 pf_emit_load_offset(0);
1007 last_offset_operation = (void*)pf_clear_offset_register;
1008 }
1009 }
1010
1011 /*
1012 * This function will issue opcodes to check if a packet
1013 * is VLAN tagged, and if so, update the offset register
1014 * with the appropriate offset.
1015 *
1016 * Note that if the packet is not VLAN tagged, then the offset
1017 * register will be cleared.
1018 *
1019 * If the interface type is not an ethernet type, then this
1020 * function returns without doing anything.
1021 *
1022 * If the last attempt to change the offset register occured because
1023 * of a call to this function that was called with the same offset,
1024 * then we don't issue packet filtering instructions.
1025 *
1026 * INPUTS: offset - an offset in 16 bit words. The function
1027 * will set the offset register to this
1028 * value if the packet is VLAN tagged.
1029 * OUTPUTS: If the conditions are met, packet filtering instructions.
1030 */
1031 static void
pf_check_vlan_tag(uint_t offset)1032 pf_check_vlan_tag(uint_t offset)
1033 {
1034 static uint_t last_offset = 0;
1035
1036 if ((interface->mac_type == DL_ETHER ||
1037 interface->mac_type == DL_CSMACD) &&
1038 (last_offset_operation != (void*)pf_check_vlan_tag ||
1039 last_offset != offset)) {
1040 /*
1041 * First thing is to clear the offset register.
1042 * We don't know what state it is in, and if it
1043 * is not zero, then we have no idea what we load
1044 * when we execute ENF_PUSHWORD.
1045 */
1046 pf_clear_offset_register();
1047
1048 /*
1049 * Check the ethertype.
1050 */
1051 pf_compare_value(dl.dl_link_type_offset, 2,
1052 htons(ETHERTYPE_VLAN));
1053
1054 /*
1055 * And if it's not VLAN, don't load offset to the offset
1056 * register.
1057 */
1058 pf_emit(ENF_BRFL | ENF_NOP);
1059 pf_emit(3);
1060
1061 /*
1062 * Otherwise, load offset to the offset register.
1063 */
1064 pf_emit_load_offset(offset);
1065
1066 /*
1067 * Now get rid of the results of the comparison,
1068 * we don't want the results of the comparison to affect
1069 * other logic in the packet filtering program.
1070 */
1071 pf_emit(ENF_POP | ENF_NOP);
1072
1073 /*
1074 * Set the last operation at the end, or any time
1075 * after the call to pf_clear_offset because
1076 * pf_clear_offset uses it.
1077 */
1078 last_offset_operation = (void*)pf_check_vlan_tag;
1079 last_offset = offset;
1080 }
1081 }
1082
1083 /*
1084 * Utility function used to emit packet filtering code
1085 * to match an ethertype.
1086 *
1087 * INPUTS: ethertype - The ethertype we want to check for.
1088 * Don't call htons on the ethertype before
1089 * calling this function.
1090 * OUTPUTS: If there is sufficient storage available, packet
1091 * filtering code to check an ethertype. Otherwise,
1092 * nothing.
1093 */
1094 static void
pf_match_ethertype(uint_t ethertype)1095 pf_match_ethertype(uint_t ethertype)
1096 {
1097 /*
1098 * If the user wants to filter on ethertype VLAN,
1099 * then clear the offset register so that the offset
1100 * for ENF_PUSHWORD points to the right place in the
1101 * packet.
1102 *
1103 * Otherwise, call pf_check_vlan_tag to set the offset
1104 * register such that the contents of the offset register
1105 * plus the argument for ENF_PUSHWORD point to the right
1106 * part of the packet, whether or not the packet is VLAN
1107 * tagged. We call pf_check_vlan_tag with an offset of
1108 * two words because if the packet is VLAN tagged, we have
1109 * to move past the ethertype in the ethernet header, and
1110 * past the lower two octets of the VLAN header to get to
1111 * the ethertype in the VLAN header.
1112 */
1113 if (ethertype == ETHERTYPE_VLAN)
1114 pf_clear_offset_register();
1115 else
1116 pf_check_vlan_tag(2);
1117
1118 pf_compare_value(dl.dl_link_type_offset, 2, htons(ethertype));
1119 }
1120
1121 static void
pf_match_ipnettype(uint_t type)1122 pf_match_ipnettype(uint_t type)
1123 {
1124 pf_compare_value(dl.dl_link_type_offset, 2, htons(type));
1125 }
1126
1127 static void
pf_match_ibtype(uint_t type)1128 pf_match_ibtype(uint_t type)
1129 {
1130 pf_compare_value(dl.dl_link_type_offset, 2, htons(type));
1131 }
1132
1133 /*
1134 * This function uses the table above to generate a
1135 * piece of a packet filtering program to check a transport
1136 * protocol type.
1137 *
1138 * INPUTS: tranport_protocol - the transport protocol we're
1139 * interested in.
1140 * OUTPUTS: If there is sufficient storage, then packet filtering
1141 * code to check a transport protocol type. Otherwise,
1142 * nothing.
1143 */
1144 static void
pf_check_transport_protocol(uint_t transport_protocol)1145 pf_check_transport_protocol(uint_t transport_protocol)
1146 {
1147 int i;
1148 uint_t number_of_matches = 0;
1149
1150 for (i = 0; dl.dl_trans_map_tbl[i].transport_protocol != -1; i++) {
1151 if (transport_protocol ==
1152 (uint_t)dl.dl_trans_map_tbl[i].transport_protocol) {
1153 number_of_matches++;
1154 dl.dl_match_fn(dl.dl_trans_map_tbl[i].network_protocol);
1155 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
1156 pf_compare_value(dl.dl_trans_map_tbl[i].offset +
1157 dl.dl_link_header_len, 1,
1158 transport_protocol);
1159 pf_emit(ENF_AND);
1160 if (number_of_matches > 1) {
1161 /*
1162 * Since we have two or more matches, in
1163 * order to have a correct and complete
1164 * program we need to OR the result of
1165 * each block of comparisons together.
1166 */
1167 pf_emit(ENF_OR);
1168 }
1169 }
1170 }
1171 }
1172
1173 static void
pf_matchfn(const char * proto)1174 pf_matchfn(const char *proto)
1175 {
1176 int i;
1177
1178 for (i = 0; dl.dl_net_map_tbl[i].nmt_val != -1; i++) {
1179 if (strcmp(proto, dl.dl_net_map_tbl[i].nmt_name) == 0) {
1180 dl.dl_match_fn(dl.dl_net_map_tbl[i].nmt_val);
1181 break;
1182 }
1183 }
1184 }
1185
1186 static void
pf_primary()1187 pf_primary()
1188 {
1189 for (;;) {
1190 if (tokentype == FIELD)
1191 break;
1192
1193 if (EQ("ip")) {
1194 pf_matchfn("ip");
1195 opstack++;
1196 next();
1197 break;
1198 }
1199
1200 if (EQ("ip6")) {
1201 pf_matchfn("ip6");
1202 opstack++;
1203 next();
1204 break;
1205 }
1206
1207 if (EQ("pppoe")) {
1208 pf_matchfn("pppoe");
1209 pf_match_ethertype(ETHERTYPE_PPPOES);
1210 pf_emit(ENF_OR);
1211 opstack++;
1212 next();
1213 break;
1214 }
1215
1216 if (EQ("pppoed")) {
1217 pf_matchfn("pppoed");
1218 opstack++;
1219 next();
1220 break;
1221 }
1222
1223 if (EQ("pppoes")) {
1224 pf_matchfn("pppoes");
1225 opstack++;
1226 next();
1227 break;
1228 }
1229
1230 if (EQ("arp")) {
1231 pf_matchfn("arp");
1232 opstack++;
1233 next();
1234 break;
1235 }
1236
1237 if (EQ("vlan")) {
1238 pf_matchfn("vlan");
1239 pf_compare_value_mask_neq(VLAN_ID_OFFSET, 2,
1240 0, VLAN_ID_MASK);
1241 pf_emit(ENF_AND);
1242 opstack++;
1243 next();
1244 break;
1245 }
1246
1247 if (EQ("vlan-id")) {
1248 next();
1249 if (tokentype != NUMBER)
1250 pr_err("VLAN ID expected");
1251 pf_matchfn("vlan-id");
1252 pf_compare_value_mask(VLAN_ID_OFFSET, 2, tokenval,
1253 VLAN_ID_MASK);
1254 pf_emit(ENF_AND);
1255 opstack++;
1256 next();
1257 break;
1258 }
1259
1260 if (EQ("rarp")) {
1261 pf_matchfn("rarp");
1262 opstack++;
1263 next();
1264 break;
1265 }
1266
1267 if (EQ("tcp")) {
1268 pf_check_transport_protocol(IPPROTO_TCP);
1269 opstack++;
1270 next();
1271 break;
1272 }
1273
1274 if (EQ("udp")) {
1275 pf_check_transport_protocol(IPPROTO_UDP);
1276 opstack++;
1277 next();
1278 break;
1279 }
1280
1281 if (EQ("ospf")) {
1282 pf_check_transport_protocol(IPPROTO_OSPF);
1283 opstack++;
1284 next();
1285 break;
1286 }
1287
1288
1289 if (EQ("sctp")) {
1290 pf_check_transport_protocol(IPPROTO_SCTP);
1291 opstack++;
1292 next();
1293 break;
1294 }
1295
1296 if (EQ("icmp")) {
1297 pf_check_transport_protocol(IPPROTO_ICMP);
1298 opstack++;
1299 next();
1300 break;
1301 }
1302
1303 if (EQ("icmp6")) {
1304 pf_check_transport_protocol(IPPROTO_ICMPV6);
1305 opstack++;
1306 next();
1307 break;
1308 }
1309
1310 if (EQ("ip-in-ip")) {
1311 pf_check_transport_protocol(IPPROTO_ENCAP);
1312 opstack++;
1313 next();
1314 break;
1315 }
1316
1317 if (EQ("esp")) {
1318 pf_check_transport_protocol(IPPROTO_ESP);
1319 opstack++;
1320 next();
1321 break;
1322 }
1323
1324 if (EQ("ah")) {
1325 pf_check_transport_protocol(IPPROTO_AH);
1326 opstack++;
1327 next();
1328 break;
1329 }
1330
1331 if (EQ("(")) {
1332 inBrace++;
1333 next();
1334 pf_expression();
1335 if (EQ(")")) {
1336 if (inBrace)
1337 inBraceOR--;
1338 inBrace--;
1339 next();
1340 }
1341 break;
1342 }
1343
1344 if (EQ("to") || EQ("dst")) {
1345 dir = TO;
1346 next();
1347 continue;
1348 }
1349
1350 if (EQ("from") || EQ("src")) {
1351 dir = FROM;
1352 next();
1353 continue;
1354 }
1355
1356 if (EQ("ether")) {
1357 eaddr = 1;
1358 next();
1359 continue;
1360 }
1361
1362 if (EQ("inet")) {
1363 next();
1364 if (EQ("host"))
1365 next();
1366 if (tokentype != ALPHA && tokentype != ADDR_IP)
1367 pr_err("host/IPv4 addr expected after inet");
1368 pf_ipaddr_match(dir, token, IPV4_ONLY);
1369 opstack++;
1370 next();
1371 break;
1372 }
1373
1374 if (EQ("inet6")) {
1375 next();
1376 if (EQ("host"))
1377 next();
1378 if (tokentype != ALPHA && tokentype != ADDR_IP6)
1379 pr_err("host/IPv6 addr expected after inet6");
1380 pf_ipaddr_match(dir, token, IPV6_ONLY);
1381 opstack++;
1382 next();
1383 break;
1384 }
1385
1386 if (EQ("proto")) {
1387 next();
1388 if (tokentype != NUMBER)
1389 pr_err("IP proto type expected");
1390 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
1391 pf_compare_value(
1392 IPV4_TYPE_HEADER_OFFSET + dl.dl_link_header_len, 1,
1393 tokenval);
1394 opstack++;
1395 next();
1396 break;
1397 }
1398
1399 if (EQ("broadcast")) {
1400 pf_clear_offset_register();
1401 pf_compare_value(dl.dl_link_dest_offset, 4, 0xffffffff);
1402 opstack++;
1403 next();
1404 break;
1405 }
1406
1407 if (EQ("multicast")) {
1408 pf_clear_offset_register();
1409 pf_compare_value_mask(
1410 dl.dl_link_dest_offset, 1, 0x01, 0x01);
1411 opstack++;
1412 next();
1413 break;
1414 }
1415
1416 if (EQ("ethertype")) {
1417 next();
1418 if (tokentype != NUMBER)
1419 pr_err("ether type expected");
1420 pf_match_ethertype(tokenval);
1421 opstack++;
1422 next();
1423 break;
1424 }
1425
1426 if (EQ("net") || EQ("dstnet") || EQ("srcnet")) {
1427 if (EQ("dstnet"))
1428 dir = TO;
1429 else if (EQ("srcnet"))
1430 dir = FROM;
1431 next();
1432 pf_netaddr_match(dir, token);
1433 dir = ANY;
1434 opstack++;
1435 next();
1436 break;
1437 }
1438
1439 if (EQ("zone")) {
1440 next();
1441 if (tokentype != NUMBER)
1442 pr_err("zoneid expected after inet");
1443 pf_match_zone(dir, BE_32((uint32_t)(tokenval)));
1444 opstack++;
1445 next();
1446 break;
1447 }
1448
1449 /*
1450 * Give up on anything that's obviously
1451 * not a primary.
1452 */
1453 if (EQ("and") || EQ("or") ||
1454 EQ("not") || EQ("decnet") || EQ("apple") ||
1455 EQ("length") || EQ("less") || EQ("greater") ||
1456 EQ("port") || EQ("srcport") || EQ("dstport") ||
1457 EQ("rpc") || EQ("gateway") || EQ("nofrag") ||
1458 EQ("bootp") || EQ("dhcp") || EQ("dhcp6") ||
1459 EQ("slp") || EQ("ldap")) {
1460 break;
1461 }
1462
1463 if (EQ("host") || EQ("between") ||
1464 tokentype == ALPHA || /* assume its a hostname */
1465 tokentype == ADDR_IP ||
1466 tokentype == ADDR_IP6 ||
1467 tokentype == ADDR_ETHER) {
1468 if (EQ("host") || EQ("between"))
1469 next();
1470 if (eaddr || tokentype == ADDR_ETHER) {
1471 pf_etheraddr_match(dir, token);
1472 } else if (tokentype == ALPHA) {
1473 pf_ipaddr_match(dir, token, IPV4_AND_IPV6);
1474 } else if (tokentype == ADDR_IP) {
1475 pf_ipaddr_match(dir, token, IPV4_ONLY);
1476 } else {
1477 pf_ipaddr_match(dir, token, IPV6_ONLY);
1478 }
1479 dir = ANY;
1480 eaddr = 0;
1481 opstack++;
1482 next();
1483 break;
1484 }
1485
1486 break; /* unknown token */
1487 }
1488 }
1489
1490 static void
pf_alternation()1491 pf_alternation()
1492 {
1493 int s = opstack;
1494
1495 pf_primary();
1496 for (;;) {
1497 if (EQ("and"))
1498 next();
1499 pf_primary();
1500 if (opstack != s + 2)
1501 break;
1502 pf_emit(ENF_AND);
1503 opstack--;
1504 }
1505 }
1506
1507 static void
pf_expression()1508 pf_expression()
1509 {
1510 pf_alternation();
1511 while (EQ("or") || EQ(",")) {
1512 if (inBrace)
1513 inBraceOR++;
1514 else
1515 foundOR++;
1516 next();
1517 pf_alternation();
1518 pf_emit(ENF_OR);
1519 opstack--;
1520 }
1521 }
1522
1523 /*
1524 * Attempt to compile the expression
1525 * in the string "e". If we can generate
1526 * pf code for it then return 1 - otherwise
1527 * return 0 and leave it up to the user-level
1528 * filter.
1529 */
1530 int
pf_compile(e,print)1531 pf_compile(e, print)
1532 char *e;
1533 int print;
1534 {
1535 char *argstr;
1536 char *sav_str, *ptr, *sav_ptr;
1537 int inBr = 0, aheadOR = 0;
1538
1539 argstr = strdup(e);
1540 sav_str = e;
1541 tkp = argstr;
1542 dir = ANY;
1543
1544 pfp = &pf.Pf_Filter[0];
1545 if (setjmp(env)) {
1546 return (0);
1547 }
1548
1549 /*
1550 * Set media specific packet offsets that this code uses.
1551 */
1552 if (interface->mac_type == DL_ETHER) {
1553 dl.dl_type = DL_ETHER;
1554 dl.dl_match_fn = pf_match_ethertype;
1555 dl.dl_trans_map_tbl = ether_transport_mapping_table;
1556 dl.dl_net_map_tbl = ether_network_mapping_table;
1557 dl.dl_link_header_len = 14;
1558 dl.dl_link_type_offset = 12;
1559 dl.dl_link_dest_offset = 0;
1560 dl.dl_link_src_offset = 6;
1561 dl.dl_link_addr_len = 6;
1562 }
1563
1564 if (interface->mac_type == DL_IB) {
1565 dl.dl_type = DL_IB;
1566 dl.dl_link_header_len = 4;
1567 dl.dl_link_type_offset = 0;
1568 dl.dl_link_dest_offset = dl.dl_link_src_offset = -1;
1569 dl.dl_link_addr_len = 20;
1570 dl.dl_match_fn = pf_match_ibtype;
1571 dl.dl_trans_map_tbl = ib_transport_mapping_table;
1572 dl.dl_net_map_tbl = ib_network_mapping_table;
1573 }
1574
1575 if (interface->mac_type == DL_IPNET) {
1576 dl.dl_type = DL_IPNET;
1577 dl.dl_link_header_len = 24;
1578 dl.dl_link_type_offset = 0;
1579 dl.dl_link_dest_offset = dl.dl_link_src_offset = -1;
1580 dl.dl_link_addr_len = -1;
1581 dl.dl_match_fn = pf_match_ipnettype;
1582 dl.dl_trans_map_tbl = ipnet_transport_mapping_table;
1583 dl.dl_net_map_tbl = ipnet_network_mapping_table;
1584 }
1585
1586 next();
1587 pf_expression();
1588
1589 if (tokentype != EOL) {
1590 /*
1591 * The idea here is to do as much filtering as possible in
1592 * the kernel. So even if we find a token we don't understand,
1593 * we try to see if we can still set up a portion of the filter
1594 * in the kernel and use the userland filter to filter the
1595 * remaining stuff. Obviously, if our filter expression is of
1596 * type A AND B, we can filter A in kernel and then apply B
1597 * to the packets that got through. The same is not true for
1598 * a filter of type A OR B. We can't apply A first and then B
1599 * on the packets filtered through A.
1600 *
1601 * (We need to keep track of the fact when we find an OR,
1602 * and the fact that we are inside brackets when we find OR.
1603 * The variable 'foundOR' tells us if there was an OR behind,
1604 * 'inBraceOR' tells us if we found an OR before we could find
1605 * the end brace i.e. ')', and variable 'aheadOR' checks if
1606 * there is an OR in the expression ahead. if either of these
1607 * cases become true, we can't split the filtering)
1608 */
1609
1610 if (foundOR || inBraceOR) {
1611 /* FORGET IN KERNEL FILTERING */
1612 return (0);
1613 } else {
1614
1615 /* CHECK IF NO OR AHEAD */
1616 sav_ptr = (char *)((uintptr_t)sav_str +
1617 (uintptr_t)sav_tkp -
1618 (uintptr_t)argstr);
1619 ptr = sav_ptr;
1620 while (*ptr != '\0') {
1621 switch (*ptr) {
1622 case '(':
1623 inBr++;
1624 break;
1625 case ')':
1626 inBr--;
1627 break;
1628 case 'o':
1629 case 'O':
1630 if ((*(ptr + 1) == 'R' ||
1631 *(ptr + 1) == 'r') && !inBr)
1632 aheadOR = 1;
1633 break;
1634 case ',':
1635 if (!inBr)
1636 aheadOR = 1;
1637 break;
1638 }
1639 ptr++;
1640 }
1641 if (!aheadOR) {
1642 /* NO OR AHEAD, SPLIT UP THE FILTERING */
1643 pf.Pf_FilterLen = pfp - &pf.Pf_Filter[0];
1644 pf.Pf_Priority = 5;
1645 if (print) {
1646 pf_codeprint(&pf.Pf_Filter[0],
1647 pf.Pf_FilterLen);
1648 }
1649 compile(sav_ptr, print);
1650 return (2);
1651 } else
1652 return (0);
1653 }
1654 }
1655
1656 pf.Pf_FilterLen = pfp - &pf.Pf_Filter[0];
1657 pf.Pf_Priority = 5; /* unimportant, so long as > 2 */
1658 if (print) {
1659 pf_codeprint(&pf.Pf_Filter[0], pf.Pf_FilterLen);
1660 }
1661 return (1);
1662 }
1663