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