Skip to content
Snippets Groups Projects
Commit 95d16cfb authored by Ryan Izard's avatar Ryan Izard
Browse files

Fixed some issues with the Firewall and string compares. There are probably...

Fixed some issues with the Firewall and string compares. There are probably some more things that need to be fixed there.
parent 21f6a55b
No related branches found
No related tags found
No related merge requests found
...@@ -40,275 +40,289 @@ import org.restlet.resource.ServerResource; ...@@ -40,275 +40,289 @@ import org.restlet.resource.ServerResource;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import net.floodlightcontroller.packet.IPv4;
public class FirewallRulesResource extends ServerResource { public class FirewallRulesResource extends ServerResource {
protected static Logger log = LoggerFactory.getLogger(FirewallRulesResource.class); protected static Logger log = LoggerFactory.getLogger(FirewallRulesResource.class);
@Get("json") @Get("json")
public List<FirewallRule> retrieve() { public List<FirewallRule> retrieve() {
IFirewallService firewall = IFirewallService firewall =
(IFirewallService)getContext().getAttributes(). (IFirewallService)getContext().getAttributes().
get(IFirewallService.class.getCanonicalName()); get(IFirewallService.class.getCanonicalName());
return firewall.getRules(); return firewall.getRules();
} }
/** /**
* Takes a Firewall Rule string in JSON format and parses it into * Takes a Firewall Rule string in JSON format and parses it into
* our firewall rule data structure, then adds it to the firewall. * our firewall rule data structure, then adds it to the firewall.
* @param fmJson The Firewall rule entry in JSON format. * @param fmJson The Firewall rule entry in JSON format.
* @return A string status message * @return A string status message
*/ */
@Post @Post
public String store(String fmJson) { public String store(String fmJson) {
IFirewallService firewall = IFirewallService firewall =
(IFirewallService)getContext().getAttributes(). (IFirewallService)getContext().getAttributes().
get(IFirewallService.class.getCanonicalName()); get(IFirewallService.class.getCanonicalName());
FirewallRule rule; FirewallRule rule = jsonToFirewallRule(fmJson);
try { if (rule == null) {
rule = jsonToFirewallRule(fmJson); return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}";
} catch (IOException e) { }
log.error("Error parsing firewall rule: " + fmJson, e); String status = null;
return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}"; if (checkRuleExists(rule, firewall.getRules())) {
} status = "Error! A similar firewall rule already exists.";
String status = null; log.error(status);
if (checkRuleExists(rule, firewall.getRules())) { return ("{\"status\" : \"" + status + "\"}");
status = "Error! A similar firewall rule already exists."; } else {
log.error(status); // add rule to firewall
return ("{\"status\" : \"" + status + "\"}"); firewall.addRule(rule);
} else { status = "Rule added";
// add rule to firewall return ("{\"status\" : \"" + status + "\", \"rule-id\" : \""+ Integer.toString(rule.ruleid) + "\"}");
firewall.addRule(rule); }
status = "Rule added"; }
return ("{\"status\" : \"" + status + "\", \"rule-id\" : \""+ Integer.toString(rule.ruleid) + "\"}");
} /**
} * Takes a Firewall Rule string in JSON format and parses it into
* our firewall rule data structure, then deletes it from the firewall.
/** * @param fmJson The Firewall rule entry in JSON format.
* Takes a Firewall Rule string in JSON format and parses it into * @return A string status message
* our firewall rule data structure, then deletes it from the firewall. */
* @param fmJson The Firewall rule entry in JSON format.
* @return A string status message @Delete
*/ public String remove(String fmJson) {
IFirewallService firewall =
@Delete (IFirewallService)getContext().getAttributes().
public String remove(String fmJson) { get(IFirewallService.class.getCanonicalName());
IFirewallService firewall =
(IFirewallService)getContext().getAttributes(). FirewallRule rule = jsonToFirewallRule(fmJson);
get(IFirewallService.class.getCanonicalName()); if (rule == null) {
//TODO compose the error with a json formatter
FirewallRule rule; return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}";
try { }
rule = jsonToFirewallRule(fmJson);
} catch (IOException e) { String status = null;
log.error("Error parsing firewall rule: " + fmJson, e); boolean exists = false;
return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}"; Iterator<FirewallRule> iter = firewall.getRules().iterator();
} while (iter.hasNext()) {
String status = null; FirewallRule r = iter.next();
boolean exists = false; if (r.ruleid == rule.ruleid) {
Iterator<FirewallRule> iter = firewall.getRules().iterator(); exists = true;
while (iter.hasNext()) { break;
FirewallRule r = iter.next(); }
if (r.ruleid == rule.ruleid) { }
exists = true; if (!exists) {
break; status = "Error! Can't delete, a rule with this ID doesn't exist.";
} log.error(status);
} } else {
if (!exists) { // delete rule from firewall
status = "Error! Can't delete, a rule with this ID doesn't exist."; firewall.deleteRule(rule.ruleid);
log.error(status); status = "Rule deleted";
} else { }
// delete rule from firewall return ("{\"status\" : \"" + status + "\"}");
firewall.deleteRule(rule.ruleid); }
status = "Rule deleted";
} /**
return ("{\"status\" : \"" + status + "\"}"); * Turns a JSON formatted Firewall Rule string into a FirewallRule instance
} * @param fmJson The JSON formatted static firewall rule
* @return The FirewallRule instance
/** * @throws IOException If there was an error parsing the JSON
* Turns a JSON formatted Firewall Rule string into a FirewallRule instance */
* @param fmJson The JSON formatted static firewall rule
* @return The FirewallRule instance public static FirewallRule jsonToFirewallRule(String fmJson) {
* @throws IOException If there was an error parsing the JSON FirewallRule rule = new FirewallRule();
*/ MappingJsonFactory f = new MappingJsonFactory();
JsonParser jp;
public static FirewallRule jsonToFirewallRule(String fmJson) throws IOException { try {
FirewallRule rule = new FirewallRule(); try {
MappingJsonFactory f = new MappingJsonFactory(); jp = f.createJsonParser(fmJson);
JsonParser jp; } catch (JsonParseException e) {
throw new IOException(e);
try { }
jp = f.createJsonParser(fmJson);
} catch (JsonParseException e) { jp.nextToken();
throw new IOException(e); if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
} throw new IOException("Expected START_OBJECT");
}
jp.nextToken();
if (jp.getCurrentToken() != JsonToken.START_OBJECT) { while (jp.nextToken() != JsonToken.END_OBJECT) {
throw new IOException("Expected START_OBJECT"); if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
} throw new IOException("Expected FIELD_NAME");
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
if (jp.getCurrentToken() != JsonToken.FIELD_NAME) { String n = jp.getCurrentName();
throw new IOException("Expected FIELD_NAME"); jp.nextToken();
} if (jp.getText().equals("")) {
continue;
String n = jp.getCurrentName(); }
jp.nextToken();
if (jp.getText().equals("")) // This is currently only applicable for remove(). In store(), ruleid takes a random number
continue; if (n.equalsIgnoreCase("ruleid")) {
try {
String tmp; rule.ruleid = Integer.parseInt(jp.getText());
} catch (IllegalArgumentException e) {
// This is currently only applicable for remove(). In store(), ruleid takes a random number log.error("Unable to parse rule ID: {}", jp.getText());
if (n == "ruleid") { }
rule.ruleid = Integer.parseInt(jp.getText()); }
}
// This assumes user having dpid info for involved switches
// This assumes user having dpid info for involved switches else if (n.equalsIgnoreCase("switchid")) {
else if (n == "switchid") { rule.any_dpid = false;
tmp = jp.getText(); try {
if (tmp.equalsIgnoreCase("-1") == false) { rule.dpid = DatapathId.of(jp.getText());
// user inputs hex format dpid } catch (NumberFormatException e) {
rule.dpid = DatapathId.of(tmp); log.error("Unable to parse switch DPID: {}", jp.getText());
rule.any_dpid = false; //TODO should return some error message via HTTP message
} }
} }
else if (n == "src-inport") { else if (n.equalsIgnoreCase("src-inport")) {
rule.in_port = OFPort.of(Integer.parseInt(jp.getText())); rule.any_in_port = false;
rule.any_in_port = false; try {
} rule.in_port = OFPort.of(Integer.parseInt(jp.getText()));
} catch (NumberFormatException e) {
else if (n == "src-mac") { log.error("Unable to parse ingress port: {}", jp.getText());
tmp = jp.getText(); //TODO should return some error message via HTTP message
if (tmp.equalsIgnoreCase("ANY") == false) { }
rule.any_dl_src = false; }
rule.dl_src = MacAddress.of(tmp);
} else if (n.equalsIgnoreCase("src-mac")) {
} if (!jp.getText().equalsIgnoreCase("ANY")) {
rule.any_dl_src = false;
else if (n == "dst-mac") { try {
tmp = jp.getText(); rule.dl_src = MacAddress.of(jp.getText());
if (tmp.equalsIgnoreCase("ANY") == false) { } catch (IllegalArgumentException e) {
rule.any_dl_dst = false; log.error("Unable to parse source MAC: {}", jp.getText());
rule.dl_dst = MacAddress.of(tmp); //TODO should return some error message via HTTP message
} }
} }
}
else if (n == "dl-type") {
tmp = jp.getText(); else if (n.equalsIgnoreCase("dst-mac")) {
if (tmp.equalsIgnoreCase("ARP")) { if (!jp.getText().equalsIgnoreCase("ANY")) {
rule.any_dl_type = false; rule.any_dl_dst = false;
rule.dl_type = EthType.ARP; try {
} rule.dl_dst = MacAddress.of(jp.getText());
if (tmp.equalsIgnoreCase("IPv4")) { } catch (IllegalArgumentException e) {
rule.any_dl_type = false; log.error("Unable to parse destination MAC: {}", jp.getText());
rule.dl_type = EthType.IPv4; //TODO should return some error message via HTTP message
} }
} }
}
else if (n == "src-ip") {
tmp = jp.getText(); else if (n.equalsIgnoreCase("dl-type")) {
if (tmp.equalsIgnoreCase("ANY") == false) { if (jp.getText().equalsIgnoreCase("ARP")) {
rule.any_nw_src = false; rule.any_dl_type = false;
rule.any_dl_type = false; rule.dl_type = EthType.ARP;
rule.dl_type = EthType.IPv4; } else if (jp.getText().equalsIgnoreCase("IPv4")) {
rule.nw_src_prefix_and_mask = IPv4AddressWithMask.of(tmp); rule.any_dl_type = false;
} rule.dl_type = EthType.IPv4;
} }
}
else if (n == "dst-ip") {
tmp = jp.getText(); else if (n.equalsIgnoreCase("src-ip")) {
if (tmp.equalsIgnoreCase("ANY") == false) { if (!jp.getText().equalsIgnoreCase("ANY")) {
rule.any_nw_dst = false; rule.any_nw_src = false;
rule.any_dl_type = false; rule.any_dl_type = false;
rule.dl_type = EthType.IPv4; rule.dl_type = EthType.IPv4;
rule.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(tmp); try {
} rule.nw_src_prefix_and_mask = IPv4AddressWithMask.of(jp.getText());
} } catch (IllegalArgumentException e) {
log.error("Unable to parse source IP: {}", jp.getText());
else if (n == "nw-proto") { //TODO should return some error message via HTTP message
tmp = jp.getText(); }
if (tmp.equalsIgnoreCase("TCP")) { }
rule.any_nw_proto = false; }
rule.nw_proto = IpProtocol.TCP;
rule.any_dl_type = false; else if (n.equalsIgnoreCase("dst-ip")) {
rule.dl_type = EthType.IPv4; if (!jp.getText().equalsIgnoreCase("ANY")) {
} else if (tmp.equalsIgnoreCase("UDP")) { rule.any_nw_dst = false;
rule.any_nw_proto = false; rule.any_dl_type = false;
rule.nw_proto = IpProtocol.UDP; rule.dl_type = EthType.IPv4;
rule.any_dl_type = false; try {
rule.dl_type = EthType.IPv4; rule.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(jp.getText());
} else if (tmp.equalsIgnoreCase("ICMP")) { } catch (IllegalArgumentException e) {
rule.any_nw_proto = false; log.error("Unable to parse destination IP: {}", jp.getText());
rule.nw_proto = IpProtocol.ICMP; //TODO should return some error message via HTTP message
rule.any_dl_type = false; }
rule.dl_type = EthType.IPv4; }
} }
}
else if (n.equalsIgnoreCase("nw-proto")) {
else if (n == "tp-src") { if (jp.getText().equalsIgnoreCase("TCP")) {
rule.any_tp_src = false; rule.any_nw_proto = false;
rule.tp_src = TransportPort.of(Integer.parseInt(jp.getText())); rule.nw_proto = IpProtocol.TCP;
} rule.any_dl_type = false;
rule.dl_type = EthType.IPv4;
else if (n == "tp-dst") { } else if (jp.getText().equalsIgnoreCase("UDP")) {
rule.any_tp_dst = false; rule.any_nw_proto = false;
rule.tp_dst = TransportPort.of(Integer.parseInt(jp.getText())); rule.nw_proto = IpProtocol.UDP;
} rule.any_dl_type = false;
rule.dl_type = EthType.IPv4;
else if (n == "priority") { } else if (jp.getText().equalsIgnoreCase("ICMP")) {
rule.priority = Integer.parseInt(jp.getText()); rule.any_nw_proto = false;
} rule.nw_proto = IpProtocol.ICMP;
rule.any_dl_type = false;
else if (n == "action") { rule.dl_type = EthType.IPv4;
if (jp.getText().equalsIgnoreCase("allow") == true) { }
rule.action = FirewallRule.FirewallAction.ALLOW; }
} else if (jp.getText().equalsIgnoreCase("deny") == true) {
rule.action = FirewallRule.FirewallAction.DROP; else if (n.equalsIgnoreCase("tp-src")) {
} rule.any_tp_src = false;
} try {
} rule.tp_src = TransportPort.of(Integer.parseInt(jp.getText()));
} catch (IllegalArgumentException e) {
return rule; log.error("Unable to parse source transport port: {}", jp.getText());
} //TODO should return some error message via HTTP message
}
public static int[] IPCIDRToPrefixBits(String cidr) { }
int ret[] = new int[2];
else if (n.equalsIgnoreCase("tp-dst")) {
// as IP can also be a prefix rather than an absolute address rule.any_tp_dst = false;
// split it over "/" to get the bit range try {
String[] parts = cidr.split("/"); rule.tp_dst = TransportPort.of(Integer.parseInt(jp.getText()));
String cidr_prefix = parts[0].trim(); } catch (IllegalArgumentException e) {
int cidr_bits = 0; log.error("Unable to parse destination transport port: {}", jp.getText());
if (parts.length == 2) { //TODO should return some error message via HTTP message
try { }
cidr_bits = Integer.parseInt(parts[1].trim()); }
} catch (Exception exp) {
cidr_bits = 32; else if (n.equalsIgnoreCase("priority")) {
} try {
} rule.priority = Integer.parseInt(jp.getText());
ret[0] = IPv4.toIPv4Address(cidr_prefix); } catch (IllegalArgumentException e) {
ret[1] = cidr_bits; log.error("Unable to parse priority: {}", jp.getText());
//TODO should return some error message via HTTP message
return ret; }
} }
public static boolean checkRuleExists(FirewallRule rule, List<FirewallRule> rules) { else if (n.equalsIgnoreCase("action")) {
Iterator<FirewallRule> iter = rules.iterator(); if (jp.getText().equalsIgnoreCase("allow") || jp.getText().equalsIgnoreCase("accept")) {
while (iter.hasNext()) { rule.action = FirewallRule.FirewallAction.ALLOW;
FirewallRule r = iter.next(); } else if (jp.getText().equalsIgnoreCase("deny") || jp.getText().equalsIgnoreCase("drop")) {
rule.action = FirewallRule.FirewallAction.DROP;
// check if we find a similar rule }
if (rule.isSameAs(r)) { }
return true; }
} } catch (IOException e) {
} log.error("Unable to parse JSON string: {}", e);
}
// no rule matched, so it doesn't exist in the rules
return false; return rule;
} }
public static boolean checkRuleExists(FirewallRule rule, List<FirewallRule> rules) {
Iterator<FirewallRule> iter = rules.iterator();
while (iter.hasNext()) {
FirewallRule r = iter.next();
// check if we find a similar rule
if (rule.isSameAs(r)) {
return true;
}
}
// no rule matched, so it doesn't exist in the rules
return false;
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment