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