Statistics
| Branch: | Tag: | Revision:

root / flowspec / forms.py @ 6d153302

History | View | Annotate | Download (8.4 kB)

1 9cad4715 Leonidas Poulopoulos
from django import forms
2 9cad4715 Leonidas Poulopoulos
from django.utils.safestring import mark_safe
3 9cad4715 Leonidas Poulopoulos
from django.utils.translation import ugettext as _
4 9cad4715 Leonidas Poulopoulos
from django.utils.translation import ugettext_lazy
5 9cad4715 Leonidas Poulopoulos
from django.template.defaultfilters import filesizeformat
6 6d153302 Leonidas Poulopoulos
from flowspy.flowspec.models import *
7 9cad4715 Leonidas Poulopoulos
from ipaddr import *
8 6d153302 Leonidas Poulopoulos
from django.core.urlresolvers import reverse
9 97e42c7d Leonidas Poulopoulos
from django.contrib.auth.models import User
10 6d153302 Leonidas Poulopoulos
from django.db.models import Avg, Max, Min, Count
11 6d153302 Leonidas Poulopoulos
12 9cad4715 Leonidas Poulopoulos
13 9cad4715 Leonidas Poulopoulos
class RouteForm(forms.ModelForm):
14 9cad4715 Leonidas Poulopoulos
#    name = forms.CharField(help_text=ugettext_lazy("A unique route name,"
15 9cad4715 Leonidas Poulopoulos
#                                         " e.g. uoa_block_p80"), label=ugettext_lazy("Route Name"), required=False)
16 9cad4715 Leonidas Poulopoulos
#    source = forms.CharField(help_text=ugettext_lazy("A qualified IP Network address. CIDR notation,"
17 9cad4715 Leonidas Poulopoulos
#                                         " e.g.10.10.0.1/32"), label=ugettext_lazy("Source Address"), required=False)
18 9cad4715 Leonidas Poulopoulos
#    source_ports = forms.ModelMultipleChoiceField(queryset=MatchPort.objects.all(), help_text=ugettext_lazy("A set of source ports to block"), label=ugettext_lazy("Source Ports"), required=False)
19 9cad4715 Leonidas Poulopoulos
#    destination = forms.CharField(help_text=ugettext_lazy("A qualified IP Network address. CIDR notation,"
20 9cad4715 Leonidas Poulopoulos
#                                         " e.g.10.10.0.1/32"), label=ugettext_lazy("Destination Address"), required=False)
21 9cad4715 Leonidas Poulopoulos
#    destination_ports = forms.ModelMultipleChoiceField(queryset=MatchPort.objects.all(), help_text=ugettext_lazy("A set of destination ports to block"), label=ugettext_lazy("Destination Ports"), required=False)
22 9cad4715 Leonidas Poulopoulos
#    ports = forms.ModelMultipleChoiceField(queryset=MatchPort.objects.all(), help_text=ugettext_lazy("A set of ports to block"), label=ugettext_lazy("Ports"), required=False)
23 9cad4715 Leonidas Poulopoulos
    class Meta:
24 9cad4715 Leonidas Poulopoulos
        model = Route
25 9cad4715 Leonidas Poulopoulos
    
26 9cad4715 Leonidas Poulopoulos
    def clean_source(self):
27 9cad4715 Leonidas Poulopoulos
        data = self.cleaned_data['source']
28 9cad4715 Leonidas Poulopoulos
        if data:
29 9cad4715 Leonidas Poulopoulos
            try:
30 9cad4715 Leonidas Poulopoulos
                address = IPNetwork(data)
31 9cad4715 Leonidas Poulopoulos
                return self.cleaned_data["source"]
32 9cad4715 Leonidas Poulopoulos
            except Exception:
33 9cad4715 Leonidas Poulopoulos
                raise forms.ValidationError('Invalid network address format')
34 9cad4715 Leonidas Poulopoulos
35 9cad4715 Leonidas Poulopoulos
    def clean_destination(self):
36 9cad4715 Leonidas Poulopoulos
        data = self.cleaned_data['destination']
37 9cad4715 Leonidas Poulopoulos
        if data:
38 9cad4715 Leonidas Poulopoulos
            try:
39 9cad4715 Leonidas Poulopoulos
                address = IPNetwork(data)
40 9cad4715 Leonidas Poulopoulos
                return self.cleaned_data["destination"]
41 9cad4715 Leonidas Poulopoulos
            except Exception:
42 9cad4715 Leonidas Poulopoulos
                raise forms.ValidationError('Invalid network address format')
43 9cad4715 Leonidas Poulopoulos
44 9cad4715 Leonidas Poulopoulos
    def clean(self):
45 6d153302 Leonidas Poulopoulos
        name = self.cleaned_data.get('name', None)
46 9cad4715 Leonidas Poulopoulos
        source = self.cleaned_data.get('source', None)
47 9cad4715 Leonidas Poulopoulos
        sourceports = self.cleaned_data.get('sourceport', None)
48 9cad4715 Leonidas Poulopoulos
        ports = self.cleaned_data.get('port', None)
49 6d153302 Leonidas Poulopoulos
        then = self.cleaned_data.get('then', None)
50 9cad4715 Leonidas Poulopoulos
        destination = self.cleaned_data.get('destination', None)
51 9cad4715 Leonidas Poulopoulos
        destinationports = self.cleaned_data.get('destinationport', None)
52 97e42c7d Leonidas Poulopoulos
        user = self.cleaned_data.get('applier', None)
53 6d153302 Leonidas Poulopoulos
        peer = user.get_profile().peer
54 6d153302 Leonidas Poulopoulos
        networks = peer.networks.all()
55 97e42c7d Leonidas Poulopoulos
        mynetwork = False
56 6d153302 Leonidas Poulopoulos
        route_pk_list = []
57 6d153302 Leonidas Poulopoulos
        
58 97e42c7d Leonidas Poulopoulos
        if destination:
59 97e42c7d Leonidas Poulopoulos
            for network in networks:
60 97e42c7d Leonidas Poulopoulos
                net = IPNetwork(network.network)
61 97e42c7d Leonidas Poulopoulos
                if IPNetwork(destination) in net:
62 97e42c7d Leonidas Poulopoulos
                    mynetwork = True
63 97e42c7d Leonidas Poulopoulos
            if not mynetwork:
64 97e42c7d Leonidas Poulopoulos
                 raise forms.ValidationError('Destination address/network should belong to your administrative address space. Check My Profile to review your networks')
65 9cad4715 Leonidas Poulopoulos
        if (sourceports and ports):
66 9cad4715 Leonidas Poulopoulos
            raise forms.ValidationError('Cannot create rule for source ports and ports at the same time. Select either ports or source ports')
67 9cad4715 Leonidas Poulopoulos
        if (destinationports and ports):
68 9cad4715 Leonidas Poulopoulos
            raise forms.ValidationError('Cannot create rule for destination ports and ports at the same time. Select either ports or destination ports')
69 9cad4715 Leonidas Poulopoulos
        if sourceports and not source:
70 9cad4715 Leonidas Poulopoulos
            raise forms.ValidationError('Once source port is matched, source has to be filled as well. Either deselect source port or fill source address')
71 9cad4715 Leonidas Poulopoulos
        if destinationports and not destination:
72 9cad4715 Leonidas Poulopoulos
            raise forms.ValidationError('Once destination port is matched, destination has to be filled as well. Either deselect destination port or fill destination address')
73 9cad4715 Leonidas Poulopoulos
        if not (source or sourceports or ports or destination or destinationports):
74 9cad4715 Leonidas Poulopoulos
            raise forms.ValidationError('Fill at least a Route Match Condition')
75 6d153302 Leonidas Poulopoulos
        existing_routes = Route.objects.exclude(status='EXPIRED').exclude(status='PENDING').exclude(status='ERROR').exclude(status='ADMININACTIVE')
76 6d153302 Leonidas Poulopoulos
        existing_routes = existing_routes.filter(applier__userprofile__peer=peer)
77 6d153302 Leonidas Poulopoulos
        if source:
78 6d153302 Leonidas Poulopoulos
            source = IPNetwork(source).compressed
79 6d153302 Leonidas Poulopoulos
            existing_routes = existing_routes.filter(source=source)
80 6d153302 Leonidas Poulopoulos
        else:
81 6d153302 Leonidas Poulopoulos
            existing_routes = existing_routes.filter(source=None)
82 6d153302 Leonidas Poulopoulos
        if sourceports:
83 6d153302 Leonidas Poulopoulos
            route_pk_list=get_matchingport_route_pks(sourceports, existing_routes)
84 6d153302 Leonidas Poulopoulos
            if route_pk_list:
85 6d153302 Leonidas Poulopoulos
                existing_routes = existing_routes.filter(pk__in=route_pk_list)
86 6d153302 Leonidas Poulopoulos
        else:
87 6d153302 Leonidas Poulopoulos
            existing_routes = existing_routes.filter(sourceport=None)
88 6d153302 Leonidas Poulopoulos
        if destinationports:
89 6d153302 Leonidas Poulopoulos
            route_pk_list=get_matchingport_route_pks(destinationports, existing_routes)
90 6d153302 Leonidas Poulopoulos
            if route_pk_list:
91 6d153302 Leonidas Poulopoulos
                existing_routes = existing_routes.filter(pk__in=route_pk_list)
92 6d153302 Leonidas Poulopoulos
        else:
93 6d153302 Leonidas Poulopoulos
            existing_routes = existing_routes.filter(destinationport=None)
94 6d153302 Leonidas Poulopoulos
        if ports:
95 6d153302 Leonidas Poulopoulos
            route_pk_list=get_matchingport_route_pks(ports, existing_routes)
96 6d153302 Leonidas Poulopoulos
            if route_pk_list:
97 6d153302 Leonidas Poulopoulos
                existing_routes = existing_routes.filter(pk__in=route_pk_list)              
98 6d153302 Leonidas Poulopoulos
        else:
99 6d153302 Leonidas Poulopoulos
            existing_routes = existing_routes.filter(port=None)
100 6d153302 Leonidas Poulopoulos
        
101 6d153302 Leonidas Poulopoulos
        for route in existing_routes:
102 6d153302 Leonidas Poulopoulos
            if name != route.name:
103 6d153302 Leonidas Poulopoulos
                existing_url = reverse('edit-route', args=[route.name])
104 6d153302 Leonidas Poulopoulos
                if IPNetwork(destination) in IPNetwork(route.destination):
105 6d153302 Leonidas Poulopoulos
                    raise forms.ValidationError('There is an exact %s rule, %s whose destination (%s) is supernet of (or the same as) network (%s).<br>To avoid overlapping try editing rule <a href=\'%s\'>%s</a>' %(route.status, route.name, route.destination, destination, existing_url, route.name))
106 6d153302 Leonidas Poulopoulos
                if IPNetwork(route.destination) in IPNetwork(destination):
107 6d153302 Leonidas Poulopoulos
                    raise forms.ValidationError('There is an exact %s rule, %s whose destination network (%s) belongs to the destination network %s.<br>To avoid overlapping try editing rule <a href=\'%s\'>%s</a>' %(route.status, route.name, route.destination, destination, existing_url, route.name))
108 6d153302 Leonidas Poulopoulos
        
109 6d153302 Leonidas Poulopoulos
110 97e42c7d Leonidas Poulopoulos
        return self.cleaned_data
111 97e42c7d Leonidas Poulopoulos
112 97e42c7d Leonidas Poulopoulos
class ThenPlainForm(forms.ModelForm):
113 97e42c7d Leonidas Poulopoulos
#    action = forms.CharField(initial='rate-limit')
114 97e42c7d Leonidas Poulopoulos
    class Meta:
115 97e42c7d Leonidas Poulopoulos
        model = ThenAction
116 97e42c7d Leonidas Poulopoulos
    
117 97e42c7d Leonidas Poulopoulos
    def clean_action_value(self):
118 97e42c7d Leonidas Poulopoulos
        action_value = self.cleaned_data['action_value']
119 97e42c7d Leonidas Poulopoulos
        if action_value:
120 97e42c7d Leonidas Poulopoulos
            try:
121 97e42c7d Leonidas Poulopoulos
                assert(int(action_value))
122 97e42c7d Leonidas Poulopoulos
                return "%s" %self.cleaned_data["action_value"]
123 97e42c7d Leonidas Poulopoulos
            except:
124 97e42c7d Leonidas Poulopoulos
                raise forms.ValidationError('Rate-limiting should be an integer')
125 97e42c7d Leonidas Poulopoulos
            if int(action_value) < 50:
126 97e42c7d Leonidas Poulopoulos
                raise forms.ValidationError('Rate-limiting cannot be < 50kbps')
127 97e42c7d Leonidas Poulopoulos
        else:
128 97e42c7d Leonidas Poulopoulos
            raise forms.ValidationError('Cannot be empty')
129 97e42c7d Leonidas Poulopoulos
130 97e42c7d Leonidas Poulopoulos
    def clean_action(self):
131 97e42c7d Leonidas Poulopoulos
        action = self.cleaned_data['action']
132 97e42c7d Leonidas Poulopoulos
        if action != 'rate-limit':
133 97e42c7d Leonidas Poulopoulos
            raise forms.ValidationError('Cannot select something other than rate-limit')
134 97e42c7d Leonidas Poulopoulos
        else:
135 97e42c7d Leonidas Poulopoulos
            return self.cleaned_data["action"]
136 97e42c7d Leonidas Poulopoulos
137 97e42c7d Leonidas Poulopoulos
class PortPlainForm(forms.ModelForm):
138 97e42c7d Leonidas Poulopoulos
#    action = forms.CharField(initial='rate-limit')
139 97e42c7d Leonidas Poulopoulos
    class Meta:
140 97e42c7d Leonidas Poulopoulos
        model = MatchPort
141 97e42c7d Leonidas Poulopoulos
    
142 97e42c7d Leonidas Poulopoulos
    def clean_port(self):
143 97e42c7d Leonidas Poulopoulos
        port = self.cleaned_data['port']
144 97e42c7d Leonidas Poulopoulos
        if port:
145 97e42c7d Leonidas Poulopoulos
            try:
146 97e42c7d Leonidas Poulopoulos
                assert(int(port))
147 97e42c7d Leonidas Poulopoulos
                return "%s" %self.cleaned_data["port"]
148 97e42c7d Leonidas Poulopoulos
            except:
149 97e42c7d Leonidas Poulopoulos
                raise forms.ValidationError('Port should be an integer')
150 97e42c7d Leonidas Poulopoulos
        else:
151 97e42c7d Leonidas Poulopoulos
            raise forms.ValidationError('Cannot be empty')
152 6d153302 Leonidas Poulopoulos
153 6d153302 Leonidas Poulopoulos
def value_list_to_list(valuelist):
154 6d153302 Leonidas Poulopoulos
    vl = []
155 6d153302 Leonidas Poulopoulos
    for val in valuelist:
156 6d153302 Leonidas Poulopoulos
        vl.append(val[0])
157 6d153302 Leonidas Poulopoulos
    return vl
158 6d153302 Leonidas Poulopoulos
159 6d153302 Leonidas Poulopoulos
def get_matchingport_route_pks(portlist, routes):
160 6d153302 Leonidas Poulopoulos
    route_pk_list = []
161 6d153302 Leonidas Poulopoulos
    ports_value_list = value_list_to_list(portlist.values_list('port').order_by('port'))
162 6d153302 Leonidas Poulopoulos
    for route in routes:
163 6d153302 Leonidas Poulopoulos
        rsp = value_list_to_list(route.destinationport.all().values_list('port').order_by('port'))
164 6d153302 Leonidas Poulopoulos
        if rsp and rsp == ports_value_list:
165 6d153302 Leonidas Poulopoulos
            route_pk_list.append(route.pk)
166 6d153302 Leonidas Poulopoulos
    return route_pk_list