示例#1
0
    def _buildAcls(self):
        for aclname, aclrules in self.config.match.iteritems():
            key = eossdk.AclKey(aclname, eossdk.ACL_TYPE_IPV4)

            # todo support ipv6 also
            for i, rule in enumerate(aclrules):
                aclRule = eossdk.AclRuleIp()

                if rule.proto:
                    pr = PROTOCOLS.get(rule.proto.lower())
                    if pr:
                        aclRule.ip_protocol_is(pr)
                    else:
                        sys.stderr.write('Invalid protocol name "%s"',
                                         rule.proto)

                if rule.src_ip:
                    try:
                        srcPfx = eossdk.IpPrefix(rule.src_ip)
                        addr = eossdk.IpAddrMask(srcPfx.network(),
                                                 srcPfx.prefix_length())
                        aclRule.source_addr_is(addr)
                    except eossdk.Error:
                        sys.stderr.write('bad IP address: %s\n', rule.src_ip)
                        continue

                if rule.dst_ip:
                    try:
                        dstPfx = eossdk.IpPrefix(rule.dst_ip)
                        addr = eossdk.IpAddrMask(dstPfx.network(),
                                                 dstPfx.prefix_length())
                        aclRule.destination_addr_is(addr)
                    except eossdk.Error:
                        sys.stderr.write('bad IP address: %s\n', rule.dst_ip)
                        continue

                if rule.sport:
                    try:
                        spec = self._buildPortSpec(rule.sport)
                    except ConfigError as e:
                        sys.stderr.write('Invalid port spec %r: %s\n', spec, e)
                    else:
                        aclRule.source_port_is(spec)

                if rule.dport:
                    try:
                        spec = self._buildPortSpec(rule.dport)
                    except ConfigError as e:
                        sys.stderr.write('Invalid port spec %r: %s\n', spec, e)
                    else:
                        aclRule.destination_port_is(spec)

                self.acl_mgr.acl_rule_set(key, i, aclRule)
        self.acl_mgr.acl_commit()
示例#2
0
    def insert_routes(self, start, end, newApi):
        self.tracer.trace1("Starting to insert {} routes, \
                          starting at route# {}".format(end, start))
        for i in range(start, end):
            first = 200 + (i / 65536)
            second = (i / 256) % 256
            third = i % 256
            addrStr = "%d.%d.%d.0" % (first, second, third)
            prefix = eossdk.IpPrefix(eossdk.IpAddr(addrStr), 24)
            if i % 2550 == 0:
                self.tracer.trace3("Adding prefix " + prefix.to_string())
            rkey = eossdk.IpRouteKey(prefix)
            route = eossdk.IpRoute(rkey)
            route.tag_is(self.tag)
            via = eossdk.IpRouteVia(rkey)
            via.nexthop_group_is("mpls_nhg")
            if not newApi:
                self.ipMgr.ip_route_set(route)
            else:
                self.ipMgr.ip_route_set(route,
                                        eossdk.IP_ROUTE_ACTION_NEXTHOP_GROUP)

            self.ipMgr.ip_route_via_set(via)

        self.tracer.trace1("Finished inserting {} routes, \
                          starting at route# {}".format(end, start))
示例#3
0
 def create_ip_v6_route_key(self, i):
     first = (i / 65536) % 65536
     second = i % 65536
     addrStr = "%04x:%04x::" % (first, second)
     ip = eossdk.IpAddr(addrStr)
     prefix6 = eossdk.IpPrefix(ip, 64)
     rkey6 = eossdk.IpRouteKey(prefix6)
     return rkey6
示例#4
0
 def create_ip_route_key(self, i):
     first = 200 + (i / 65536)
     second = (i / 256) % 256
     third = i % 256
     addrStr = "%d.%d.%d.0" % (first, second, third)
     prefix = eossdk.IpPrefix(eossdk.IpAddr(addrStr), 24)
     if i % 2550 == 0:
         self.tracer.trace3("Adding prefix %s" % prefix.to_string())
     rkey = eossdk.IpRouteKey(prefix)
     return rkey
    def update_acl(self, prefix):
        global ACLENTRY
        # Configure V4 ACL
        syslog.syslog("inside Update ACL, ACLENTRY No: %s" % ACLENTRY)
        aclRule = eossdk.AclRuleIp()
        aclRule.ip_protocol_is(4)
        aclRule.action_is(eossdk.ACL_PERMIT)
        syslog.syslog("ACL Rule Created")
        srcPfx = eossdk.IpPrefix(prefix)
        addr = eossdk.IpAddrMask(srcPfx.network(), srcPfx.prefix_length())
        aclRule.source_addr_is(addr)

        dstPfx = eossdk.IpPrefix("0.0.0.0/0")
        addr = eossdk.IpAddrMask(dstPfx.network(), dstPfx.prefix_length())
        aclRule.destination_addr_is(addr)

        self.aclMgr_.acl_rule_set(self.aclKey, ACLENTRY, aclRule)
        ACLENTRY += 10
        syslog.syslog("ACL Updated: %s prefix added" % prefix)
示例#6
0
    def _set_route(self, prefix, nexthop_group):
        """
        {
            "command": "set",
            "type": "route",
            "prefix": "5.3.0.0/24",
            "nexthop_group": "CYGNUS_NHG_1"
        }
        """
        prefix = eossdk.IpPrefix(str(prefix))
        route_key = eossdk.IpRouteKey(prefix)
        route = eossdk.IpRoute(route_key)
        via = eossdk.IpRouteVia(route_key)
        via.nexthop_group_is(str(nexthop_group))

        self.ip_route_mgr.ip_route_set(route)
        self.ip_route_mgr.ip_route_via_set(via)
示例#7
0
    def _del_route(self, prefix, nexthop_group=None):
        """
        {
            "command": "del",
            "type": "route",
            "prefix": "5.3.0.0/24",
            "nexthop_group": "CYGNUS_NHG_1" // optional
        }
        """
        prefix = eossdk.IpPrefix(str(prefix))
        route_key = eossdk.IpRouteKey(prefix)
        route = eossdk.IpRoute(route_key)

        if nexthop_group:
            via = eossdk.IpRouteVia(route_key)
            via.nexthop_group_is(str(nexthop_group))
            self.ip_route_mgr.ip_route_via_del(via)
        else:
            self.ip_route_mgr.ip_route_del(route_key)
示例#8
0
    def insert_v6_routes(self, start, end, newApi):
        self.tracer.trace1("Starting to insert {} v6_routes, \
                          starting at route# {}".format(end, start))
        for i in range(start, end):
            first = (i / 65536) % 65536
            second = i % 65536
            addrStr = "%04x:%04x::" % (first, second)
            ip = eossdk.IpAddr(addrStr)
            prefix6 = eossdk.IpPrefix(ip, 64)
            rkey6 = eossdk.IpRouteKey(prefix6)
            route6 = eossdk.IpRoute(rkey6)
            route6.tag_is(self.tag)
            via6 = eossdk.IpRouteVia(rkey6)
            via6.nexthop_group_is("mpls_nhg")
            if not newApi:
                self.ipMgr.ip_route_set(route6)
            else:
                self.ipMgr.ip_route_set(route6,
                                        eossdk.IP_ROUTE_ACTION_NEXTHOP_GROUP)

            self.ipMgr.ip_route_via_set(via6)

        self.tracer.trace1("Finished inserting {} routes, \
                          starting at route# {}".format(end, start))
示例#9
0
   def process_config(self):
      """Critical function; processes configuration and rules description files.
      Called upon initialization and then subsequently whenever inotify indicates
      the configuration file has changed on disk."""

      self.tracer.trace0("Processing config")
      syslog.syslog("Attempting to process configuration file(s)")

      # Time stamp for performance evaluation
      start_time = time.time()
      self.start_time = start_time
      
      # Attempt to parse ACLerate_config_file
      # Initially, attempt to acquire the lock to ensure file not modified
      # by another entity while it is being processed here.
      syslog.syslog("Attempting to open, lock and parse %s" % self.config_file)
      try:
          with open(self.config_file) as acl_config_file:
              for i in xrange(file_lock_attempt):
                  try:
                      fcntl.flock(acl_config_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
                      break
                  except IOError:
                      sys.stderr.write("Attempt %s to lock %s "
                                       "failed\n" % (str(i+1), self.config_file))
                  time.sleep(file_lock_interval)
              else:
                  syslog.syslog("All %s attempts to lock %s "
                                "failed" % (str(file_lock_attempt), self.config_file))
                  sys.stderr.write("All %s attempts to lock %s "
                                   "failed\n" % (str(file_lock_attempt), self.config_file))
                  return
              syslog.syslog("%s opened & locked successfully. Now parse" % self.config_file)
              acl_config_list = json.load(acl_config_file)
      except IOError:
          syslog.syslog("Cannot open %s" % self.config_file)
          sys.stderr.write("Cannot open %s\n" % self.config_file)
          return

      for acl_config in acl_config_list:

          command = acl_config.get("command")
          name = acl_config.get("name")
          acl_type = acl_config.get("type")
          interface = acl_config.get("interface")
          operation = acl_config.get("operation")
          direction = acl_config.get("direction")
          rules_file = acl_config.get("rules")
          counting = acl_config.get("counting")

          # Sanity check ACL parameters (before potentially
          # iterating over thousands of rules!).  If invalid, skip
          # processing rest of this ACL and continue to next ACL
          if not acl_validate(command, name, acl_type, direction, counting):
              syslog.syslog("Invalid ACL input data")
              sys.stderr.write("Invalid ACL input data\n")
              continue

          syslog.syslog("Processing %s command for %s ACL %s" % (command, acl_type, name))

          # Convert external ACL type to SDK's type
          sdk_type = acl_type_convert(acl_type)
          if sdk_type is None:
              syslog.syslog("Invalid ACL type")
              sys.stderr.write("Invalid ACL type specified\n")
              continue

          # Get handle to ACL.
          acl_key = eossdk.AclKey(str(name), sdk_type)

          # If input command is to delete the ACL, simply call the appropriate
          # SDK API and continue onto next ACL in the list.  i.e. no need to be
          # concerned with interfaces, rules etc.
          if command.lower() == "delete-acl":
              syslog.syslog("About to delete %s ACL %s" % (acl_type, name))
              self.acl_mgr.acl_del(acl_key)
              # Now call commit to actually push changes to HW.
              self.acl_mgr.acl_commit()
              continue

          intf_id = None
          # Next, if an interface is specified, verify it actually exists
          # and correct parameters have been specified
          if interface:
              intf_id = self.interface_validate(interface, operation, direction)
              if intf_id:
                  # Convert external direction to SDK's type
                  sdk_direction = direction_convert(direction)
                  if sdk_direction is None:
                      syslog.syslog("Invalid direction %s specified" % direction)
                      sys.stderr.write("Invalid direction %s specified\n" % direction)
                      continue
              else:
                  syslog.syslog("Invalid interface %s specified" % interface)
                  sys.stderr.write("Invalid interface %s specified\n" % interface)
                  continue

          # Set ACL counting behaviour if specified.  If not, will
          # simply fallback to default ACL behaviour.
          if counting:
              if counting.lower() == "true":
                  self.acl_mgr.acl_counters_enabled_set(acl_key, True)
              if counting.lower() == "false":
                  self.acl_mgr.acl_counters_enabled_set(acl_key, False)

          # Rules files is needed.  Does it actually exist?
          # Is a comprehensive unwind needed in the error case?
          if rules_file is None:
              syslog.syslog("Need to add/remove rules but no rule info file specified")
              sys.stderr.write("Need to add/remove rules but no rule info file specified\n")
              continue
          
          # Attempt to parse rules_file
          # Initially, attempt to acquire the lock to ensure file not modified
          # by another entity while it is being processed here.
          syslog.syslog("Attempting to open, lock and parse %s" % rules_file)
          try:
              with open(rules_file) as rule_listing_file:
                  for i in xrange(file_lock_attempt):
                      try:
                          fcntl.flock(rule_listing_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
                          break
                      except IOError:
                          sys.stderr.write("Attempt %s to lock %s "
                                           "failed\n" % (str(i+1), rule_file))
                      time.sleep(file_lock_interval)
                  else:
                      syslog.syslog("All %s attempts to lock %s "
                                    "failed" % (str(file_lock_attempt), rules_file))
                      sys.stderr.write("All %s attempts to lock %s "
                                       "failed\n" % (str(file_lock_attempt), rules_file))
                      return
                  syslog.syslog("%s opened & locked successfully. Now parse" % rules_file)
                  rule_list = json.load(rule_listing_file)
          except IOError:
              syslog.syslog("Cannot open %s" % rules_file)
              sys.stderr.write("Cannot open %s\n" % rules_file)
              continue

          # Now iterate over all rules
          for index, rule in enumerate(rule_list):
              number = rule.get("number")
              source = rule.get("source")
              destination = rule.get("destination")
              protocol = rule.get("protocol")
              action = rule.get("action")
              log = rule.get("log")

              # Rule must have a sequence number.
              if number is None:
                  syslog.syslog("Rule must have a number")
                  sys.stderr.write("Rule must have a number\n")
                  continue
    
              # If input command is to delete the rule, simply call the SDK API
              # and continue to next rule in the list.
              # i.e. no need to be concerned with addresses, protocols etc.
              if command.lower() == "delete-rule":
                  self.acl_mgr.acl_rule_del(acl_key, int(number))
                  continue

              # If here, then the command must be to add rule.
              # So verify if rule data supplied is valid.
              if rule_validate(number, source, destination, action) == False:
                  syslog.syslog("Invalid rule input data")
                  sys.stderr.write("Invalid rule input data\n")
                  continue

              # Create IP ACL rule object.  Used for IPv4 and IPv6 ACLs but
              # different object needed for Ethernet ACLs.
              # (Perhaps create object with all rule info and invoke
              # functions to process for ACL, IPv4, IPv6 etc?
              # Needs more thought on optimal way to handle different ACL type)
              acl_rule = eossdk.AclRuleIp()

              # Now parse the rule data and invoke appropriate SDK
              # APIs to create requisite data structures.
              if source:
                  try:
                      # How is "any" handled? 0.0.0.0/0?
                      if source == "any":
                          source = "0.0.0.0/0"

                      # String to IP address conversion of source?
                      sdk_prefix = eossdk.IpPrefix(str(source))
                      sdk_addr = eossdk.IpAddrMask(sdk_prefix.network(),
                                                       sdk_prefix.prefix_length())
                      acl_rule.source_addr_is(sdk_addr)
                  except eossdk.Error:
                      syslog.syslog("Error processing source address %s" % source)
                      sys.stderr.write("Error processing source address %s\n" % source)
                      continue

              if destination:
                  try:
                      # How is "any" handled? 0.0.0.0/0?
                      if destination == "any":
                          destination = "0.0.0.0/0"

                      # String to IP address conversion of destination?
                      sdk_prefix = eossdk.IpPrefix(str(destination))
                      sdk_addr = eossdk.IpAddrMask(sdk_prefix.network(),
                                                       sdk_prefix.prefix_length())
                      acl_rule.destination_addr_is(sdk_addr)
                  except eossdk.Error:
                      syslog.syslog("Error processing destination address %s" % destination)
                      sys.stderr.write("Error processing destination address %s\n" % destination)
                      continue

              if protocol:
                  protocol_number = protocol_validate(protocol, sdk_type)
                  if protocol_number:
                      acl_rule.ip_protocol_is(protocol_number)
                  else:
                      syslog.syslog("Error processing protocol %s" % protocol)
                      sys.stderr.write("Error processing protocol %s\n" % protocol)
                      continue

              # Previously verified that action is 'permit' or 'deny'
              if action:
                  try:
                      if action.lower() == "permit":
                          acl_rule.action_is(eossdk.ACL_PERMIT)
                      else:
                          acl_rule.action_is(eossdk.ACL_DENY)
                  except:
                      syslog.syslog("Error processing action %s" % action)
                      sys.stderr.write("Error processing action %s\n" % action)
                      continue

              if log:
                  try:
                      if log.lower() == "true":
                          acl_rule.log_is(True)
                      else:
                          acl_rule.log_is(False)
                  except:
                      syslog.syslog("Error processing log %s" % log)
                      sys.stderr.write("Error processing log %s\n" % log)
                      continue
 
              # Now add this rule to ACL, with appropriate sequence number
              # Should only ever be here when adding rules.... paranoid check.
              if command.lower() == "add-rule":
                  self.acl_mgr.acl_rule_set(acl_key, int(number), acl_rule)

          parsing_time = time.time()
          self.parsing_time = parsing_time

          self.parsing_duration = parsing_time - start_time

          syslog.syslog("Time to parse config files for ACL %s "
                           "is %ss" % (name, self.parsing_duration))

          self.rule_count = index+1
          syslog.syslog("Processing %s rules complete.  "
                        "Now commit ACL %s to HW" % (index+1, name))
          # Now call commit to actually push changes to HW.
          self.acl_mgr.acl_commit()

          # Should ACL be attached or detached from interface?
          if intf_id:
              if operation.lower() == "attach":
                  syslog.syslog("Attaching ACL %s to interface %s "
                                "%sbound" % (name, interface, direction.lower()))
                  self.acl_mgr.acl_apply(acl_key, intf_id, sdk_direction, True)
              if operation.lower() == "detach":
                  syslog.syslog("Detaching ACL %s from interface %s "
                                "%sbound" % (name, interface, direction.lower()))
                  self.acl_mgr.acl_apply(acl_key, intf_id, sdk_direction, False)