blob: b52faaf11b6c746b8546eb0a57ed5aa4843ce272 [file] [log] [blame]
Pengfei Lue0c02e22015-07-07 15:41:31 +08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Pengfei Lue0c02e22015-07-07 15:41:31 +08003 * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
Pengfei Lue53419b2015-08-29 10:11:02 +08004 * Advisers: Keqiu Li, Heng Qi and Haisheng Yu
Pengfei Lue0c02e22015-07-07 15:41:31 +08005 * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
6 * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
Thomas Vachuska9bb32352015-09-25 11:31:22 -070020package org.onosproject.acl;
Pengfei Lue0c02e22015-07-07 15:41:31 +080021
22import com.google.common.base.MoreObjects;
23import org.onlab.packet.IPv4;
24import org.onlab.packet.Ip4Prefix;
25import org.onosproject.core.IdGenerator;
26
27import java.util.Objects;
28
29import static com.google.common.base.Preconditions.checkNotNull;
30import static com.google.common.base.Preconditions.checkState;
31
32/**
33 * ACL rule class.
34 */
35public final class AclRule {
36
37 private final RuleId id;
38
39 private final Ip4Prefix srcIp;
40 private final Ip4Prefix dstIp;
41 private final byte ipProto;
42 private final short dstTpPort;
43 private final Action action;
44
45 private static IdGenerator idGenerator;
46
47 /**
48 * Enum type for ACL rule's action.
49 */
50 public enum Action {
51 DENY, ALLOW
52 }
53
54 /**
55 * Constructor for serializer.
56 */
57 private AclRule() {
58 this.id = null;
59 this.srcIp = null;
60 this.dstIp = null;
61 this.ipProto = 0;
62 this.dstTpPort = 0;
63 this.action = null;
64 }
65
66 /**
67 * Create a new ACL rule.
68 *
Thomas Vachuska9bb32352015-09-25 11:31:22 -070069 * @param srcIp source IP address
70 * @param dstIp destination IP address
71 * @param ipProto IP protocol
Pengfei Lue0c02e22015-07-07 15:41:31 +080072 * @param dstTpPort destination transport layer port
Thomas Vachuska9bb32352015-09-25 11:31:22 -070073 * @param action ACL rule's action
Pengfei Lue0c02e22015-07-07 15:41:31 +080074 */
Thomas Vachuska9bb32352015-09-25 11:31:22 -070075 private AclRule(Ip4Prefix srcIp, Ip4Prefix dstIp, byte ipProto,
76 short dstTpPort, Action action) {
Pengfei Lue0c02e22015-07-07 15:41:31 +080077 checkState(idGenerator != null, "Id generator is not bound.");
78 this.id = RuleId.valueOf(idGenerator.getNewId());
79 this.srcIp = srcIp;
80 this.dstIp = dstIp;
81 this.ipProto = ipProto;
82 this.dstTpPort = dstTpPort;
83 this.action = action;
84 }
85
86 /**
87 * Check if the first CIDR address is in (or the same as) the second CIDR address.
88 */
Jonathan Hartd9df7bd2015-11-10 17:10:25 -080089 private boolean checkCidrInCidr(Ip4Prefix cidrAddr1, Ip4Prefix cidrAddr2) {
Pengfei Lue0c02e22015-07-07 15:41:31 +080090 if (cidrAddr2 == null) {
91 return true;
92 } else if (cidrAddr1 == null) {
93 return false;
94 }
95 if (cidrAddr1.prefixLength() < cidrAddr2.prefixLength()) {
96 return false;
97 }
98 int offset = 32 - cidrAddr2.prefixLength();
99
100 int cidr1Prefix = cidrAddr1.address().toInt();
101 int cidr2Prefix = cidrAddr2.address().toInt();
102 cidr1Prefix = cidr1Prefix >> offset;
103 cidr2Prefix = cidr2Prefix >> offset;
104 cidr1Prefix = cidr1Prefix << offset;
105 cidr2Prefix = cidr2Prefix << offset;
106
107 return (cidr1Prefix == cidr2Prefix);
108 }
109
110 /**
111 * Check if this ACL rule match the given ACL rule.
Thomas Vachuska9bb32352015-09-25 11:31:22 -0700112 *
Pengfei Lue0c02e22015-07-07 15:41:31 +0800113 * @param r ACL rule to check against
114 * @return true if this ACL rule matches the given ACL ruleule.
115 */
116 public boolean checkMatch(AclRule r) {
117 return (this.dstTpPort == r.dstTpPort || r.dstTpPort == 0)
118 && (this.ipProto == r.ipProto || r.ipProto == 0)
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800119 && (checkCidrInCidr(this.srcIp(), r.srcIp()))
120 && (checkCidrInCidr(this.dstIp(), r.dstIp()));
Pengfei Lue0c02e22015-07-07 15:41:31 +0800121 }
122
123 /**
124 * Returns a new ACL rule builder.
125 *
126 * @return ACL rule builder
127 */
128 public static Builder builder() {
129 return new Builder();
130 }
131
132 /**
133 * Builder of an ACL rule.
134 */
135 public static final class Builder {
136
137 private Ip4Prefix srcIp = null;
138 private Ip4Prefix dstIp = null;
139 private byte ipProto = 0;
140 private short dstTpPort = 0;
141 private Action action = Action.DENY;
142
143 private Builder() {
144 // Hide constructor
145 }
146
147 /**
148 * Sets the source IP address for the ACL rule that will be built.
149 *
150 * @param srcIp source IP address to use for built ACL rule
151 * @return this builder
152 */
Thomas Vachuska9bb32352015-09-25 11:31:22 -0700153 public Builder srcIp(Ip4Prefix srcIp) {
154 this.srcIp = srcIp;
Pengfei Lue0c02e22015-07-07 15:41:31 +0800155 return this;
156 }
157
158 /**
159 * Sets the destination IP address for the ACL rule that will be built.
160 *
161 * @param dstIp destination IP address to use for built ACL rule
162 * @return this builder
163 */
Thomas Vachuska9bb32352015-09-25 11:31:22 -0700164 public Builder dstIp(Ip4Prefix dstIp) {
165 this.dstIp = dstIp;
Pengfei Lue0c02e22015-07-07 15:41:31 +0800166 return this;
167 }
168
169 /**
170 * Sets the IP protocol for the ACL rule that will be built.
171 *
172 * @param ipProto IP protocol to use for built ACL rule
173 * @return this builder
174 */
175 public Builder ipProto(byte ipProto) {
176 this.ipProto = ipProto;
177 return this;
178 }
179
180 /**
181 * Sets the destination transport layer port for the ACL rule that will be built.
182 *
183 * @param dstTpPort destination transport layer port to use for built ACL rule
184 * @return this builder
185 */
186 public Builder dstTpPort(short dstTpPort) {
187 if ((ipProto == IPv4.PROTOCOL_TCP || ipProto == IPv4.PROTOCOL_UDP)) {
188 this.dstTpPort = dstTpPort;
189 }
190 return this;
191 }
192
193 /**
194 * Sets the action for the ACL rule that will be built.
195 *
196 * @param action action to use for built ACL rule
197 * @return this builder
198 */
199 public Builder action(Action action) {
200 this.action = action;
201 return this;
202 }
203
204 /**
205 * Builds an ACL rule from the accumulated parameters.
Thomas Vachuska9bb32352015-09-25 11:31:22 -0700206 *
Pengfei Lue0c02e22015-07-07 15:41:31 +0800207 * @return ACL rule instance
208 */
209 public AclRule build() {
210 checkState(srcIp != null && dstIp != null, "Either srcIp or dstIp must be assigned.");
211 checkState(ipProto == 0 || ipProto == IPv4.PROTOCOL_ICMP
212 || ipProto == IPv4.PROTOCOL_TCP || ipProto == IPv4.PROTOCOL_UDP,
213 "ipProto must be assigned to TCP, UDP, or ICMP.");
Thomas Vachuska9bb32352015-09-25 11:31:22 -0700214 return new AclRule(srcIp, dstIp, ipProto, dstTpPort, action);
Pengfei Lue0c02e22015-07-07 15:41:31 +0800215 }
216
217 }
218
219 /**
220 * Binds an id generator for unique ACL rule id generation.
Thomas Vachuska9bb32352015-09-25 11:31:22 -0700221 * <p>
Pengfei Lue0c02e22015-07-07 15:41:31 +0800222 * Note: A generator cannot be bound if there is already a generator bound.
223 *
224 * @param newIdGenerator id generator
225 */
226 public static void bindIdGenerator(IdGenerator newIdGenerator) {
227 checkState(idGenerator == null, "Id generator is already bound.");
228 idGenerator = checkNotNull(newIdGenerator);
229 }
230
231 public RuleId id() {
232 return id;
233 }
234
235 public Ip4Prefix srcIp() {
236 return srcIp;
237 }
238
239 public Ip4Prefix dstIp() {
240 return this.dstIp;
241 }
242
243 public byte ipProto() {
244 return ipProto;
245 }
246
247 public short dstTpPort() {
248 return dstTpPort;
249 }
250
251 public Action action() {
252 return action;
253 }
254
255 @Override
256 public int hashCode() {
Thomas Vachuska9bb32352015-09-25 11:31:22 -0700257 return Objects.hash(action, id.fingerprint(), ipProto, srcIp, dstIp, dstTpPort);
Pengfei Lue0c02e22015-07-07 15:41:31 +0800258 }
259
260 @Override
261 public boolean equals(Object obj) {
262 if (this == obj) {
263 return true;
264 }
265 if (obj instanceof AclRule) {
266 AclRule that = (AclRule) obj;
267 return Objects.equals(id, that.id) &&
268 Objects.equals(srcIp, that.srcIp) &&
269 Objects.equals(dstIp, that.dstIp) &&
270 Objects.equals(ipProto, that.ipProto) &&
271 Objects.equals(dstTpPort, that.dstTpPort) &&
272 Objects.equals(action, that.action);
273 }
274 return false;
275 }
276
277 @Override
278 public String toString() {
279 return MoreObjects.toStringHelper(this)
280 .omitNullValues()
281 .add("id", id)
282 .add("srcIp", srcIp)
283 .add("dstIp", dstIp)
284 .add("ipProto", ipProto)
285 .add("dstTpPort", dstTpPort)
286 .add("action", action)
287 .toString();
288 }
289
290}