Skip to content

Commit d6b1fb4

Browse files
author
Capirca Team
committed
Merge pull request #293 from XioNoX:filter_term
PiperOrigin-RevId: 416431802
2 parents f0181c6 + 83bbb2e commit d6b1fb4

File tree

7 files changed

+62
-5
lines changed

7 files changed

+62
-5
lines changed

capirca/lib/aclgenerator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ class ACLGenerator:
219219
'restrict_address_family',
220220
'counter',
221221
'destination_tag',
222+
'filter_term',
222223
'logging',
223224
'loss_priority',
224225
'owner',

capirca/lib/juniper.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,13 @@ def __str__(self):
279279
term_prefix = ''
280280

281281
# term name
282-
config.Append('%s term %s {' %(term_prefix, self.term.name))
282+
config.Append('%s term %s {' % (term_prefix, self.term.name))
283+
284+
# The "filter" keyword is not compatible with from or then
285+
if self.term.filter_term:
286+
config.Append('filter %s;' % self.term.filter_term)
287+
config.Append('}') # end term accept-foo-to-bar { ... }
288+
return str(config)
283289

284290
# a default action term doesn't have any from { clause
285291
has_match_criteria = (self.term.address or
@@ -445,8 +451,7 @@ def __str__(self):
445451
# protocol
446452
if self.term.protocol_except:
447453
# same as above
448-
config.Append(family_keywords['protocol-except'] + ' '
449-
+ self._Group(self.term.protocol_except))
454+
config.Append(family_keywords['protocol-except'] + ' ' + self._Group(self.term.protocol_except))
450455

451456
# port
452457
if self.term.port:
@@ -880,6 +885,7 @@ def _BuildTokens(self):
880885
'dscp_set',
881886
'encapsulate',
882887
'ether_type',
888+
'filter_term',
883889
'flexible_match_range',
884890
'forwarding_class',
885891
'forwarding_class_except',
@@ -913,7 +919,7 @@ def _BuildTokens(self):
913919
'tcp-established',
914920
'tcp-initial',
915921
'inactive'}
916-
})
922+
})
917923
return supported_tokens, supported_sub_tokens
918924

919925
def _TranslatePolicy(self, pol, exp_info):

capirca/lib/policy.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ class Term:
318318
dscp-except: VarType.DSCP_EXCEPT
319319
comments: VarType.COMMENT
320320
encapsulate: VarType.ENCAPSULATE
321+
filter-term: VarType.FILTER_TERM
321322
flexible-match-range: VarType.FLEXIBLE_MATCH_RANGE
322323
forwarding-class: VarType.FORWARDING_CLASS
323324
forwarding-class-except: VarType.FORWARDING_CLASS_EXCEPT
@@ -411,6 +412,7 @@ def __init__(self, obj):
411412
self.destination_address_exclude = []
412413
self.destination_port = []
413414
self.destination_prefix = []
415+
self.filter_term = None
414416
self.forwarding_class = []
415417
self.forwarding_class_except = []
416418
self.logging = []
@@ -709,6 +711,8 @@ def __str__(self):
709711
if self.destination_prefix_except:
710712
ret_str.append(' destination_prefix_except: %s' %
711713
self.destination_prefix_except)
714+
if self.filter_term:
715+
ret_str.append(' filter_term: %s' % self.filter_term)
712716
if self.forwarding_class:
713717
ret_str.append(' forwarding_class: %s' % self.forwarding_class)
714718
if self.forwarding_class_except:
@@ -896,6 +900,10 @@ def __eq__(self, other):
896900
if self.precedence != other.precedence:
897901
return False
898902

903+
# filter
904+
if self.filter_term != other.filter_term:
905+
return False
906+
899907
# forwarding-class
900908
if sorted(self.forwarding_class) != sorted(other.forwarding_class):
901909
return False
@@ -1193,6 +1201,8 @@ def AddObject(self, obj):
11931201
self.target_resources.append(obj.value)
11941202
elif obj.var_type is VarType.TARGET_SERVICE_ACCOUNTS:
11951203
self.target_service_accounts.append(obj.value)
1204+
elif obj.var_type is VarType.FILTER_TERM:
1205+
self.filter_term = obj.value
11961206
else:
11971207
raise TermObjectTypeError(
11981208
'%s isn\'t a type I know how to deal with' % (type(obj)))
@@ -1226,8 +1236,11 @@ def SanityCheck(self):
12261236
raise ParseError(
12271237
'term "%s" has both verbatim and non-verbatim tokens.' % self.name)
12281238
else:
1229-
if not self.action and not self.routing_instance and not self.next_ip and not self.encapsulate:
1239+
if (not self.action and not self.routing_instance and not self.next_ip and
1240+
not self.encapsulate and not self.filter_term):
12301241
raise TermNoActionError('no action specified for term %s' % self.name)
1242+
if self.filter_term and self.action:
1243+
raise InvalidTermActionError('term "%s" has both filter and action tokens.' % self.name)
12311244
# have we specified a port with a protocol that doesn't support ports?
12321245
if self.source_port or self.destination_port or self.port:
12331246
if not any(proto in self.protocol for proto in ['tcp', 'udp', 'sctp']):
@@ -1497,8 +1510,10 @@ class VarType:
14971510
TARGET_RESOURCES = 59
14981511
TARGET_SERVICE_ACCOUNTS = 60
14991512
ENCAPSULATE = 61
1513+
FILTER_TERM = 62
15001514
RESTRICT_ADDRESS_FAMILY = 63
15011515

1516+
15021517
def __init__(self, var_type, value):
15031518
self.var_type = var_type
15041519
if self.var_type == self.COMMENT or self.var_type == self.LOG_NAME:
@@ -1675,6 +1690,7 @@ def __ne__(self, other):
16751690
'ESCAPEDSTRING',
16761691
'ETHER_TYPE',
16771692
'EXPIRATION',
1693+
'FILTER_TERM',
16781694
'FLEXIBLE_MATCH_RANGE',
16791695
'FORWARDING_CLASS',
16801696
'FORWARDING_CLASS_EXCEPT',
@@ -1757,6 +1773,7 @@ def __ne__(self, other):
17571773
'encapsulate': 'ENCAPSULATE',
17581774
'ether-type': 'ETHER_TYPE',
17591775
'expiration': 'EXPIRATION',
1776+
'filter-term': 'FILTER_TERM',
17601777
'flexible-match-range': 'FLEXIBLE_MATCH_RANGE',
17611778
'forwarding-class': 'FORWARDING_CLASS',
17621779
'forwarding-class-except': 'FORWARDING_CLASS_EXCEPT',
@@ -1939,6 +1956,7 @@ def p_term_spec(p):
19391956
| term_spec ether_type_spec
19401957
| term_spec exclude_spec
19411958
| term_spec expiration_spec
1959+
| term_spec filter_term_spec
19421960
| term_spec flexible_match_range_spec
19431961
| term_spec forwarding_class_spec
19441962
| term_spec forwarding_class_except_spec
@@ -2380,6 +2398,9 @@ def p_ttl_spec(p):
23802398
""" ttl_spec : TTL ':' ':' INTEGER """
23812399
p[0] = VarType(VarType.TTL, p[4])
23822400

2401+
def p_filter_term_spec(p):
2402+
""" filter_term_spec : FILTER_TERM ':' ':' STRING """
2403+
p[0] = VarType(VarType.FILTER_TERM, p[4])
23832404

23842405
def p_one_or_more_strings(p):
23852406
""" one_or_more_strings : one_or_more_strings STRING

doc/generators/juniper.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ The default format is _inet4_, and is implied if not other argument is given.
4646
* _dscp_set::_ Match a DSCP set.
4747
* _ether_type::_ Match EtherType field.
4848
* _expiration::_ stop rendering this term after specified date. [YYYY](YYYY.md)-[MM](MM.md)-[DD](DD.md)
49+
* _filter-term::_ Include another filter
4950
* _flexible-match-range Filter based on flexible match options.
5051
* _forwarding-class::_ Specify the forwarding class to match.
5152
* _forwarding-class_except::_ Do not match the specified forwarding classes.

policies/pol/sample_juniper_loopback.pol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ term reject-imap-requests {
196196
action:: reject-with-tcp-rst
197197
}
198198

199+
term next-filter {
200+
filter-term:: my-next-filter
201+
}
202+
199203
term af-mismatch {
200204
comment:: "Will not be generated as target is inet"
201205
comment:: "but address_family is inet6"

tests/lib/juniper_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,12 @@
393393
action:: accept
394394
}
395395
"""
396+
GOOD_TERM_FILTER = """
397+
term good-term-filter {
398+
comment:: "This is a COMMENT"
399+
filter-term:: my-filter
400+
}
401+
"""
396402
BAD_TERM_1 = """
397403
term bad-term-1 {
398404
protocol:: tcp udp
@@ -545,6 +551,12 @@
545551
action:: deny
546552
}
547553
"""
554+
BAD_TERM_FILTER = """
555+
term bad_term_filter {
556+
filter-term:: my-filter
557+
action:: deny
558+
}
559+
"""
548560

549561
MIXED_TESTING_TERM = """
550562
term good-term {
@@ -572,6 +584,7 @@
572584
'encapsulate',
573585
'ether_type',
574586
'expiration',
587+
'filter_term',
575588
'flexible_match_range',
576589
'forwarding_class',
577590
'forwarding_class_except',
@@ -1194,6 +1207,16 @@ def testMultiplePrecedence(self):
11941207

11951208
self.naming.GetServiceByProto.assert_called_once_with('SSH', 'tcp')
11961209

1210+
def testFilterTerm(self):
1211+
jcl = juniper.Juniper(policy.ParsePolicy(GOOD_HEADER + GOOD_TERM_FILTER,
1212+
self.naming), EXP_INFO)
1213+
output = str(jcl)
1214+
self.assertIn('filter my-filter;', output, output)
1215+
1216+
def testFilterActionTerm(self):
1217+
with self.assertRaises(policy.InvalidTermActionError):
1218+
policy.ParsePolicy(GOOD_HEADER + BAD_TERM_FILTER, self.naming)
1219+
11971220
def testArbitraryOptions(self):
11981221
self.naming.GetServiceByProto.return_value = ['22']
11991222

tests/lib/srxlo_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
'dscp_set',
7777
'ether_type',
7878
'expiration',
79+
'filter_term',
7980
'forwarding_class',
8081
'forwarding_class_except',
8182
'fragment_offset',

0 commit comments

Comments
 (0)