func CreateACLTargetsForMitigation(m *MitigationScope) []ACLTarget {
	destAddressesIPv4 := make([]string, 0)
	destAddressesIPv6 := make([]string, 0)
	srcAddressesIPv4  := make([]string, 0)
	srcAddressesIPv6  := make([]string, 0)
	destPorts         := make([]string, 0)
	sourcePorts       := make([]string, 0)
	icmpTypes         := make([]string, 0)
	aclTargets        := make([]ACLTarget, 0)
	protocols := m.TargetProtocol.List()
	for _, target := range m.TargetList {
		ip, _, _ := net.ParseCIDR(target.TargetPrefix.String())
		if ip.To4() != nil {
			destAddressesIPv4 = append(destAddressesIPv4, target.TargetPrefix.String())
		} else {
			destAddressesIPv6 = append(destAddressesIPv6, target.TargetPrefix.String())
		}
	}
	for _, srcPrefix := range m.SourcePrefix {
		ip, _, _ := net.ParseCIDR(srcPrefix.String())
		if  ip.To4() != nil {
			srcAddressesIPv4 = append(srcAddressesIPv4, srcPrefix.String())
		} else {
			srcAddressesIPv6 = append(srcAddressesIPv6, srcPrefix.String())
		}
	}
	for _, port := range m.TargetPortRange {
		if port.LowerPort == port.UpperPort {
			destPorts = append(destPorts, "eq "+strconv.Itoa(port.LowerPort))
		} else {
			destPorts = append(destPorts, "range "+strconv.Itoa(port.LowerPort)+" "+strconv.Itoa(port.UpperPort))
		}
	}
	for _, port := range m.SourcePortRange {
		if port.LowerPort == port.UpperPort {
			sourcePorts = append(sourcePorts, "eq "+strconv.Itoa(port.LowerPort))
		} else {
			sourcePorts = append(sourcePorts, "range "+strconv.Itoa(port.LowerPort)+" "+strconv.Itoa(port.UpperPort))
		}
	}
	for _, icmpType := range m.SourceICMPTypeRange {
		icmpTypes = append(icmpTypes, strconv.Itoa(icmpType.LowerType))
	}
	if len(protocols) > 0 {
		for _, protocol := range protocols {
			if protocol == 6 || protocol == 17 {
				if len(destPorts) > 0 && len(sourcePorts) > 0 {
					icmpType := EMPTY_VALUE
					for _, destPort := range destPorts {
						for _, srcPort := range sourcePorts {
							targets := createACLTargetsForMitigation(strconv.Itoa(protocol), destAddressesIPv4, destAddressesIPv6, srcAddressesIPv4, srcAddressesIPv6,
																	destPort, srcPort, icmpType)
							aclTargets = append(aclTargets, targets...)
						}
					}
				} else if len(destPorts) > 0 && len(sourcePorts) == 0 {
					srcPort := EMPTY_VALUE
					icmpType := EMPTY_VALUE
					for _, destPort := range destPorts {
						targets := createACLTargetsForMitigation(strconv.Itoa(protocol), destAddressesIPv4, destAddressesIPv6, srcAddressesIPv4, srcAddressesIPv6,
																destPort, srcPort, icmpType)
						aclTargets = append(aclTargets, targets...)
					}
				} else if len(destPorts) == 0 && len(sourcePorts) > 0 {
					destPort := EMPTY_VALUE
					icmpType := EMPTY_VALUE
					for _, srcPort := range sourcePorts {
						targets := createACLTargetsForMitigation(strconv.Itoa(protocol), destAddressesIPv4, destAddressesIPv6, srcAddressesIPv4, srcAddressesIPv6,
																destPort, srcPort, icmpType)
						aclTargets = append(aclTargets, targets...)
					}
				} else if len(destPorts) == 0 && len(sourcePorts) == 0 {
					destPort := EMPTY_VALUE
					srcPort  := EMPTY_VALUE
					icmpType := EMPTY_VALUE
					targets := createACLTargetsForMitigation(strconv.Itoa(protocol), destAddressesIPv4, destAddressesIPv6, srcAddressesIPv4, srcAddressesIPv6,
															destPort, srcPort, icmpType)
					aclTargets = append(aclTargets, targets...)
				}
			} else if len(icmpTypes) > 0 && protocol == 1 {
				destPort := EMPTY_VALUE
				srcPort  := EMPTY_VALUE
				for _, icmpType := range icmpTypes {
					targets := createACLTargetsForMitigation(strconv.Itoa(protocol), destAddressesIPv4, destAddressesIPv6, srcAddressesIPv4, srcAddressesIPv6,
															destPort, srcPort, icmpType)
					aclTargets = append(aclTargets, targets...)
				}
			} else {
				destPort := EMPTY_VALUE
				srcPort  := EMPTY_VALUE
				icmpType := EMPTY_VALUE
				targets := createACLTargetsForMitigation(strconv.Itoa(protocol), destAddressesIPv4, destAddressesIPv6, srcAddressesIPv4, srcAddressesIPv6,
														destPort, srcPort, icmpType)
				aclTargets = append(aclTargets, targets...)
			}
		}
	} else {
		protocol := EMPTY_VALUE
		destPort := EMPTY_VALUE
		srcPort  := EMPTY_VALUE
		icmpType := EMPTY_VALUE
		targets := createACLTargetsForMitigation(protocol, destAddressesIPv4, destAddressesIPv6, srcAddressesIPv4, srcAddressesIPv6,
												destPort, srcPort, icmpType)
		aclTargets = append(aclTargets, targets...)
	}
	return aclTargets
}
/*
Create ACL target for mitigation request
package models
import (
	"bytes"
	"errors"
	"net"
	"strconv"
	"strings"
	"time"
	"github.com/aristanetworks/goeapi"
	"github.com/nttdots/go-dots/dots_server/db_models"
	module "github.com/aristanetworks/goeapi/module"
	types "github.com/nttdots/go-dots/dots_common/types/data"
	log "github.com/sirupsen/logrus"
)
const (
	ARISTA_BLOCKER_CONNECTION = "aristaConnection"
	ARISTA_BLOCKER_INTERFACE  = "aristaInterface"
)
const (
	BLOCKER_TYPE_GO_ARISTA = "Arista-ACL"
	PROTECTION_TYPE_ARISTA = "AristaACL"
	ARISTA_NAME        = "name"
	ANY_VALUE          = "any"
	IPV4_VALUE         = "ip"
	IPV6_VALUE         = "ipv6"
	ACTION_TYPE_DENY   = "deny"
	ACTION_TYPE_PERMIT = "permit"
	FRAGMENTS_VALUE    = "fragments"
	EMPTY_VALUE        = ""
	TTL_KEY            = "ttl"
	HOPLIMIT_KEY       = "hop-limit"
	PORT_RANGE         = "range"
	DSCP_KEY           = "dscp"
	ECN_KEY            = "ecn"
	ECN_VALUE_CE       = "ce"
	ECN_VALUE_ECT      = "ect"
	ECN_VALUE_ECT_CE   = "ect-ce"
	ECN_VALUE_NON_ECT  = "non-ect"
	INTERFACE_VALUE    = "interface"
	ACCESS_LIST_VALUE  = "access-list"
	ACCESS_GROUP_VALUE = "access-group"
	CONFIGURE_SESSION  = "configure session"
	COMMIT_VALUE       = "commit"
	EXIT_VALUE         = "exit"
	NO_VALUE           = "no"
	INBOUND_PACKET     = "in"
	IPV4_PERMIT_RULE   = "permit ip any any"
	IPV6_PERMIT_RULE   = "permit ipv6 any any"
	LEN_CMDS_ACL_WITHOUT_RULE  = 3
)
type MitigationOrDataChannelACL struct {
	MitigationRequest *MitigationScope
	DataChannelACL    *types.ACL
}
type AristaACL struct {
	ProtectionBase
	aclTargets      []ACLTarget
}
type ACLTarget struct {
	aclType string
	aclRule string
}
type GoAristaReceiver struct {
	BlockerBase
	aristaConection string
	aristaInterface string
}
type ACLMapping struct {
	aclType            string
	protocol           string
	actionType         string
	destinationAddress string
	sourceAddress      string
	sourcePort         string
	destinationPort    string
	ttl                string
	fragment           string
	flagBits           string
	messageType        string
	dcsp               string
	ecn                string
}
func (g *GoAristaReceiver) AristaConection() string {
	return g.aristaConection
}
func (g *GoAristaReceiver) AristaInterface() string {
	return g.aristaInterface
}
func (a *AristaACL) AclTargets() []ACLTarget {
	return a.aclTargets
}
func (acl *ACLTarget) ACLType() string {
	return acl.aclType
}
func (acl *ACLTarget) ACLRule() string {
	return acl.aclRule
}
func (g *GoAristaReceiver) Connect() (err error) {
	return
}
func (g *GoAristaReceiver) GenerateProtectionCommand(m *MitigationScope) (c string, err error) {
	c = EMPTY_VALUE
	return
}
func NewGoAristaReceiver(base BlockerBase, configParams map[string][]string) *GoAristaReceiver {
	var aristaConection string
	var aristaInterface string
	a, ok := configParams[ARISTA_BLOCKER_CONNECTION]
	if ok {
		aristaConection = a[0]
	} else {
		aristaConection = ""
	}
	a, ok = configParams[ARISTA_BLOCKER_INTERFACE]
	if ok {
		aristaInterface = a[0]
	} else {
		aristaInterface = ""
	}
	return &GoAristaReceiver{
		base,
		aristaConection,
		aristaInterface,
	}
}
func (g *GoAristaReceiver) Type() BlockerType {
	return BLOCKER_TYPE_GO_ARISTA
}
func (p AristaACL) Type() ProtectionType {
	return PROTECTION_TYPE_ARISTA
}
func (g *GoAristaReceiver) ExecuteProtection(p Protection) (err error) {
	t, ok := p.(*AristaACL)
	if !ok {
		log.Warnf("GoAristaReceiver::ExecuteProtection protection type error. %T", p)
		err = errors.New("Protection type error")
		return
	}
	log.Info("GoAristaReceiver.ExecuteProtection")
	node, err := g.connectArista()
	if err != nil {
		return err
	}
	log.Infof("arista connect[%p]", node)
	acl := module.Acl(node)
	configSession := CreateConfigureSession(p.SessionName())
	cmds := []string {configSession}
	ipv4AccessList := CreateAccessList(IPV4_VALUE, p.AclName())
	ipv6AccessList := CreateAccessList(IPV6_VALUE, p.AclName())
	ipv4Cmds := []string{ipv4AccessList}
	ipv6Cmds := []string{ipv6AccessList}
	for _,target := range t.aclTargets {
		if target.ACLType() == IPV4_VALUE {
			ipv4Cmds = append(ipv4Cmds, target.ACLRule())
		} else {
			ipv6Cmds = append(ipv6Cmds, target.ACLRule())
		}
	}
	ipv4Cmds = append(ipv4Cmds, IPV4_PERMIT_RULE)
	ipv4Cmds = append(ipv4Cmds, EXIT_VALUE)
	ipv6Cmds = append(ipv6Cmds, IPV6_PERMIT_RULE)
	ipv6Cmds = append(ipv6Cmds, EXIT_VALUE)
	interfaceCmds := []string{INTERFACE_VALUE+" "+g.AristaInterface()}
	if len(ipv4Cmds) > LEN_CMDS_ACL_WITHOUT_RULE {
		cmds = append(cmds, ipv4Cmds ...)
		ipv4AccessGroup := CreateAccessGroup(IPV4_VALUE, p.AclName())
		interfaceCmds = append(interfaceCmds, ipv4AccessGroup)
	}
	if len(ipv6Cmds) > LEN_CMDS_ACL_WITHOUT_RULE {
		cmds = append(cmds, ipv6Cmds ...)
		ipv6AccessGroup := CreateAccessGroup(IPV6_VALUE, p.AclName())
		interfaceCmds = append(interfaceCmds, ipv6AccessGroup)
	}
	interfaceCmds = append(interfaceCmds, EXIT_VALUE)
	cmds = append(cmds, interfaceCmds ...)
	cmds = append(cmds, p.Action())
	if ok := acl.Configure(cmds ...); !ok {
		log.Warnf("Failed to apply configure session. cmds=%+v", cmds)
		configSession = RemoveConfigureSession(p.SessionName())
		if ok := acl.Configure([]string{configSession} ...); !ok {
			log.Warnf("Failed to remove configure session. cmds = %+v", cmds)
		}
		err = errors.New("Failed to apply configure session")
		return
	}
	if p.Action() == COMMIT_VALUE {
		configSession = RemoveConfigureSession(p.SessionName())
		if ok := acl.Configure([]string{configSession} ...); !ok {
			log.Warnf("Failed to remove configure session. cmds = %+v", cmds)
		}
	}
	err = StartProtection(p, g)
	if err != nil {
		return
	}
	return
}
func (g *GoAristaReceiver) StopProtection(p Protection) (err error) {
	t, ok := p.(*AristaACL)
	if !ok {
		log.Warnf("GoAristaReceiver::StopProtection protection type error. %T", p)
		err = errors.New("Protection type error")
		return
	}
	if !t.isEnabled {
		log.Warnf("GoAristaReceiver::StopProtection protection not started. %+v", p)
		err = errors.New("Protection not started")
		return
	}
	log.WithFields(log.Fields{
		"target_id":   t.TargetId(),
		"target_type": t.TargetType(),
		"load":        g.Load(),
	}).Infof("GoAristaReceiver.StopProtection")
	node, err := g.connectArista()
	if err != nil {
		return err
	}
	log.Infof("arista connect[%p]", node)
	acl := module.Acl(node)
	countIPv4 := 0
	countIPv6 := 0
	configSession := CreateConfigureSession(p.SessionName())
	cmds := []string {configSession}
	for _,target := range t.aclTargets {
		if countIPv4 > 0 && countIPv6 > 0 {
			break
		}
		if target.ACLType() == IPV4_VALUE {
			countIPv4 ++
		}
		if target.ACLType() == IPV6_VALUE {
			countIPv6 ++
		}
	}
	cmds = append(cmds, INTERFACE_VALUE+" "+g.AristaInterface())
	if countIPv4 > 0 {
		ipv4AccessGroup := RemoveAccessGroup(IPV4_VALUE, p.AclName())
		ipv4AccessList  := RemoveAccessList(IPV4_VALUE, p.AclName())
		cmds = append(cmds, ipv4AccessGroup)
		cmds = append(cmds, ipv4AccessList)
	}
	if countIPv6 > 0 {
		ipv6AccessGroup := RemoveAccessGroup(IPV6_VALUE, p.AclName())
		ipv6AccessList  := RemoveAccessList(IPV6_VALUE, p.AclName())
		cmds = append(cmds, ipv6AccessGroup)
		cmds = append(cmds, ipv6AccessList)
	}
	cmds = append(cmds, COMMIT_VALUE)
	if ok := acl.Configure(cmds ...); !ok {
		log.Warnf("Failed to apply configure session. cmds = %+v", cmds)
		configSession = RemoveConfigureSession(p.SessionName())
		if ok := acl.Configure([]string{configSession} ...); !ok {
			log.Warnf("Failed to remove configure session. cmds = %+v", cmds)
		}
		err = errors.New("Failed to apply configure session")
		return
	}
	configSession = RemoveConfigureSession(p.SessionName())
	if ok := acl.Configure([]string{configSession} ...); !ok {
		log.Warnf("Failed to remove configure session. cmds = %+v", cmds)
	}
	err = StopProtection(p, g)
	if err != nil {
		return
	}
	return
}
func (g *GoAristaReceiver) connectArista() (node *goeapi.Node, err error) {
    tmp, err := goeapi.ConnectTo(g.AristaConection())
	if err != nil {
	 return nil, err
	}
	log.WithFields(log.Fields{
		ARISTA_NAME: g.AristaConection(),
	}).Debug("connect to Arista")
	node = tmp
	return node, nil
}
func (g *GoAristaReceiver) RegisterProtection(r *MitigationOrDataChannelACL, targetID int64, customerID int, targetType string) (p Protection, err error) {
	droppedStatus := NewProtectionStatus(
		0, 0, 0, 0, 0,
	)
	var aclName string
	if r.DataChannelACL != nil {
		aclName = r.DataChannelACL.Name
	} else {
		aclName = r.MitigationRequest.AclName
	}
	base := ProtectionBase{
		0,
		customerID,
		targetID,
		targetType,
		aclName,
		"",
		"",
		g,
		false,
		time.Unix(0, 0),
		time.Unix(0, 0),
		time.Unix(0, 0),
		droppedStatus,
	}
	log.Debugf("stored external storage.  %+v", base)
	var aclTargets []ACLTarget
	if r.DataChannelACL != nil {
		aclTargets = CreateACLTargetsForDataChannel(r.DataChannelACL)
	} else {
		aclTargets = CreateACLTargetsForMitigation(r.MitigationRequest)
	}
	p = &AristaACL{base, aclTargets}
	dbP, err := CreateProtection2(p)
	if err != nil {
		return
	}
	return GetProtectionById(dbP.Id)
}
func (g *GoAristaReceiver) UnregisterProtection(p Protection) (err error) {
	t, ok := p.(*AristaACL)
	if !ok {
		log.Warnf("GoAristaReceiver::UnregisterProtection protection type error. %T", p)
		err = errors.New("Protection type error")
		return
	}
	log.Info("GoAristaReceiver.UnregisterProtection")
	err = DeleteProtectionById(p.Id())
	if err != nil {
		return
	}
	log.Debugf("remove from external storage, id: %d", t.Id)
	return
}
func NewAristaProtection(base ProtectionBase, params []db_models.AristaParameter) *AristaACL {
	var aclTargets []ACLTarget
	for _,param := range params {
		aclTargets = append(aclTargets, ACLTarget{param.AclType, param.AclFilteringRule})
	}
	return &AristaACL {
		base,
		aclTargets,
	}
}
func CreateACLTargetsForDataChannel(d *types.ACL) []ACLTarget {
	aclTargets := make([]ACLTarget, 0)
	aces := d.ACEs.ACE
	for _,ace := range aces {
		aclMapping := ACLMapping{}
		if *ace.Actions.Forwarding == types.ForwardingAction_Accept {
			aclMapping.actionType = ACTION_TYPE_PERMIT
		} else {
			aclMapping.actionType = ACTION_TYPE_DENY
		}
		aclMapping.aclType = IPV4_VALUE
		if matches := ace.Matches.IPv4; matches != nil {
			if matches.Flags != nil {
				flags := matches.Flags.String()
				for _, v := range strings.Split(flags, " ") {
					if v == types.IPv4Flag_Fragment.String() || v == types.IPv4Flag_More.String() {
						aclMapping.fragment = FRAGMENTS_VALUE
						break
					}
				}
			}
			if matches.Fragment != nil {
				if (matches.Fragment.Operator == nil || *matches.Fragment.Operator == types.Operator_MATCH) && 
					(*matches.Fragment.Type == types.FragmentType_ISF || *matches.Fragment.Type == types.FragmentType_LF) {
						aclMapping.fragment = FRAGMENTS_VALUE
				}
			}
			aclMapping.MapDataChannelACLRule(matches.Protocol, (*types.IPPrefix)(matches.SourceIPv4Network),
				(*types.IPPrefix)(matches.DestinationIPv4Network), matches.TTL, matches.DSCP, matches.ECN)
		} else if matches := ace.Matches.IPv6; matches != nil {
			aclMapping.aclType = IPV6_VALUE
			aclMapping.MapDataChannelACLRule(matches.Protocol, (*types.IPPrefix)(matches.SourceIPv6Network),
			    (*types.IPPrefix)(matches.DestinationIPv6Network), matches.TTL, matches.DSCP, matches.ECN)
		}
		if ace.Matches.TCP != nil {
			matches := ace.Matches.TCP
			if matches.Flags != nil {
				aclMapping.flagBits = matches.Flags.String()
			} else if matches.FlagsBitmask != nil && *matches.FlagsBitmask.Operator == types.Operator_MATCH {
				aclMapping.MapACLTcpFlagsFlowWithFlagsBitmask(matches.FlagsBitmask)
			}
			aclMapping.MapACLPort(matches.SourcePort, matches.DestinationPort)
		} else if ace.Matches.UDP != nil {
			matches := ace.Matches.UDP
			aclMapping.MapACLPort(matches.SourcePort, matches.DestinationPort)
		} else if ace.Matches.ICMP != nil {
			matches := ace.Matches.ICMP
			if matches.Type != nil {
				aclMapping.messageType = strconv.Itoa(int(*matches.Type))
			}
		}
		aclTargets = append(aclTargets, ACLTarget{aclMapping.aclType, aclMapping.CreateACLRule()})
	}
	return aclTargets
}
func (mapping *ACLMapping) MapACLTcpFlagsFlowWithFlagsBitmask(flag *types.FlagsBitmask) {
	bitMask := ""
	switch flag.Bitmask {
	case 1:   bitMask = types.TCPFlag_FIN.String()
	case 2:   bitMask = types.TCPFlag_SYN.String()
	case 4:   bitMask = types.TCPFlag_RST.String()
	case 8:   bitMask = types.TCPFlag_PSH.String()
	case 16:  bitMask = types.TCPFlag_ACK.String()
	case 32:  bitMask = types.TCPFlag_URG.String()
	}
	mapping.flagBits = bitMask
}