| /* |
| * Copyright 2015-present Open Networking Laboratory |
| * Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China |
| * Advisers: Keqiu Li, Heng Qi and Haisheng Yu |
| * This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002) |
| * and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.acl; |
| |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| import com.fasterxml.jackson.databind.node.ArrayNode; |
| import com.fasterxml.jackson.databind.node.ObjectNode; |
| import org.onlab.packet.IPv4; |
| import org.onlab.packet.Ip4Prefix; |
| import org.onosproject.rest.AbstractWebResource; |
| |
| import javax.ws.rs.Consumes; |
| import javax.ws.rs.DELETE; |
| import javax.ws.rs.GET; |
| import javax.ws.rs.POST; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.PathParam; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.List; |
| |
| /** |
| * Manage ACL rules. |
| */ |
| @Path("rules") |
| public class AclWebResource extends AbstractWebResource { |
| |
| /** |
| * Get all ACL rules. |
| * Returns array of all ACL rules. |
| * |
| * @return 200 OK |
| */ |
| @GET |
| public Response queryAclRule() { |
| List<AclRule> rules = get(AclService.class).getAclRules(); |
| ObjectMapper mapper = new ObjectMapper(); |
| ObjectNode root = mapper.createObjectNode(); |
| ArrayNode arrayNode = mapper.createArrayNode(); |
| for (AclRule rule : rules) { |
| ObjectNode node = mapper.createObjectNode(); |
| node.put("id", rule.id().toString()); |
| if (rule.srcIp() != null) { |
| node.put("srcIp", rule.srcIp().toString()); |
| } |
| if (rule.dstIp() != null) { |
| node.put("dstIp", rule.dstIp().toString()); |
| } |
| if (rule.ipProto() != 0) { |
| switch (rule.ipProto()) { |
| case IPv4.PROTOCOL_ICMP: |
| node.put("ipProto", "ICMP"); |
| break; |
| case IPv4.PROTOCOL_TCP: |
| node.put("ipProto", "TCP"); |
| break; |
| case IPv4.PROTOCOL_UDP: |
| node.put("ipProto", "UDP"); |
| break; |
| default: |
| break; |
| } |
| } |
| if (rule.dstTpPort() != 0) { |
| node.put("dstTpPort", rule.dstTpPort()); |
| } |
| node.put("action", rule.action().toString()); |
| arrayNode.add(node); |
| } |
| root.set("aclRules", arrayNode); |
| return Response.ok(root.toString(), MediaType.APPLICATION_JSON_TYPE).build(); |
| } |
| |
| /** |
| * Add a new ACL rule. |
| * |
| * @param stream JSON data describing the rule |
| * @return 200 OK |
| * @throws URISyntaxException uri syntax exception |
| */ |
| @POST |
| @Consumes(MediaType.APPLICATION_JSON) |
| public Response addAclRule(InputStream stream) throws URISyntaxException { |
| AclRule newRule = jsonToRule(stream); |
| return get(AclService.class).addAclRule(newRule) ? |
| Response.created(new URI(newRule.id().toString())).build() : |
| Response.serverError().build(); |
| } |
| |
| /** |
| * Remove ACL rule. |
| * |
| * @param id ACL rule id (in hex string format) |
| * @return 200 OK |
| */ |
| @DELETE |
| @Path("{id}") |
| public Response removeAclRule(@PathParam("id") String id) { |
| RuleId ruleId = new RuleId(Long.parseLong(id.substring(2), 16)); |
| get(AclService.class).removeAclRule(ruleId); |
| return Response.ok().build(); |
| } |
| |
| /** |
| * Remove all ACL rules. |
| * |
| * @return 200 OK |
| */ |
| @DELETE |
| public Response clearAcl() { |
| get(AclService.class).clearAcl(); |
| return Response.ok().build(); |
| } |
| |
| /** |
| * Turns a JSON string into an ACL rule instance. |
| */ |
| private AclRule jsonToRule(InputStream stream) { |
| JsonNode node; |
| try { |
| node = mapper().readTree(stream); |
| } catch (IOException e) { |
| throw new IllegalArgumentException("Unable to parse ACL request", e); |
| } |
| |
| AclRule.Builder rule = AclRule.builder(); |
| |
| String s = node.path("srcIp").asText(null); |
| if (s != null) { |
| rule.srcIp(Ip4Prefix.valueOf(s)); |
| } |
| |
| s = node.path("dstIp").asText(null); |
| if (s != null) { |
| rule.dstIp(Ip4Prefix.valueOf(s)); |
| } |
| |
| s = node.path("ipProto").asText(null); |
| if (s != null) { |
| if ("TCP".equalsIgnoreCase(s)) { |
| rule.ipProto(IPv4.PROTOCOL_TCP); |
| } else if ("UDP".equalsIgnoreCase(s)) { |
| rule.ipProto(IPv4.PROTOCOL_UDP); |
| } else if ("ICMP".equalsIgnoreCase(s)) { |
| rule.ipProto(IPv4.PROTOCOL_ICMP); |
| } else { |
| throw new IllegalArgumentException("ipProto must be assigned to TCP, UDP, or ICMP"); |
| } |
| } |
| |
| int port = node.path("dstTpPort").asInt(0); |
| if (port > 0) { |
| rule.dstTpPort((short) port); |
| } |
| |
| s = node.path("action").asText(null); |
| if (s != null) { |
| if ("allow".equalsIgnoreCase(s)) { |
| rule.action(AclRule.Action.ALLOW); |
| } else if ("deny".equalsIgnoreCase(s)) { |
| rule.action(AclRule.Action.DENY); |
| } else { |
| throw new IllegalArgumentException("action must be ALLOW or DENY"); |
| } |
| } |
| |
| return rule.build(); |
| } |
| |
| } |