Statistics
| Branch: | Tag: | Revision:

root / flowspec / forms.py @ 6d153302

History | View | Annotate | Download (8.4 kB)

1
from django import forms
2
from django.utils.safestring import mark_safe
3
from django.utils.translation import ugettext as _
4
from django.utils.translation import ugettext_lazy
5
from django.template.defaultfilters import filesizeformat
6
from flowspy.flowspec.models import *
7
from ipaddr import *
8
from django.core.urlresolvers import reverse
9
from django.contrib.auth.models import User
10
from django.db.models import Avg, Max, Min, Count
11

    
12

    
13
class RouteForm(forms.ModelForm):
14
#    name = forms.CharField(help_text=ugettext_lazy("A unique route name,"
15
#                                         " e.g. uoa_block_p80"), label=ugettext_lazy("Route Name"), required=False)
16
#    source = forms.CharField(help_text=ugettext_lazy("A qualified IP Network address. CIDR notation,"
17
#                                         " e.g.10.10.0.1/32"), label=ugettext_lazy("Source Address"), required=False)
18
#    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
#    destination = forms.CharField(help_text=ugettext_lazy("A qualified IP Network address. CIDR notation,"
20
#                                         " e.g.10.10.0.1/32"), label=ugettext_lazy("Destination Address"), required=False)
21
#    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
#    ports = forms.ModelMultipleChoiceField(queryset=MatchPort.objects.all(), help_text=ugettext_lazy("A set of ports to block"), label=ugettext_lazy("Ports"), required=False)
23
    class Meta:
24
        model = Route
25
    
26
    def clean_source(self):
27
        data = self.cleaned_data['source']
28
        if data:
29
            try:
30
                address = IPNetwork(data)
31
                return self.cleaned_data["source"]
32
            except Exception:
33
                raise forms.ValidationError('Invalid network address format')
34

    
35
    def clean_destination(self):
36
        data = self.cleaned_data['destination']
37
        if data:
38
            try:
39
                address = IPNetwork(data)
40
                return self.cleaned_data["destination"]
41
            except Exception:
42
                raise forms.ValidationError('Invalid network address format')
43

    
44
    def clean(self):
45
        name = self.cleaned_data.get('name', None)
46
        source = self.cleaned_data.get('source', None)
47
        sourceports = self.cleaned_data.get('sourceport', None)
48
        ports = self.cleaned_data.get('port', None)
49
        then = self.cleaned_data.get('then', None)
50
        destination = self.cleaned_data.get('destination', None)
51
        destinationports = self.cleaned_data.get('destinationport', None)
52
        user = self.cleaned_data.get('applier', None)
53
        peer = user.get_profile().peer
54
        networks = peer.networks.all()
55
        mynetwork = False
56
        route_pk_list = []
57
        
58
        if destination:
59
            for network in networks:
60
                net = IPNetwork(network.network)
61
                if IPNetwork(destination) in net:
62
                    mynetwork = True
63
            if not mynetwork:
64
                 raise forms.ValidationError('Destination address/network should belong to your administrative address space. Check My Profile to review your networks')
65
        if (sourceports and ports):
66
            raise forms.ValidationError('Cannot create rule for source ports and ports at the same time. Select either ports or source ports')
67
        if (destinationports and ports):
68
            raise forms.ValidationError('Cannot create rule for destination ports and ports at the same time. Select either ports or destination ports')
69
        if sourceports and not source:
70
            raise forms.ValidationError('Once source port is matched, source has to be filled as well. Either deselect source port or fill source address')
71
        if destinationports and not destination:
72
            raise forms.ValidationError('Once destination port is matched, destination has to be filled as well. Either deselect destination port or fill destination address')
73
        if not (source or sourceports or ports or destination or destinationports):
74
            raise forms.ValidationError('Fill at least a Route Match Condition')
75
        existing_routes = Route.objects.exclude(status='EXPIRED').exclude(status='PENDING').exclude(status='ERROR').exclude(status='ADMININACTIVE')
76
        existing_routes = existing_routes.filter(applier__userprofile__peer=peer)
77
        if source:
78
            source = IPNetwork(source).compressed
79
            existing_routes = existing_routes.filter(source=source)
80
        else:
81
            existing_routes = existing_routes.filter(source=None)
82
        if sourceports:
83
            route_pk_list=get_matchingport_route_pks(sourceports, existing_routes)
84
            if route_pk_list:
85
                existing_routes = existing_routes.filter(pk__in=route_pk_list)
86
        else:
87
            existing_routes = existing_routes.filter(sourceport=None)
88
        if destinationports:
89
            route_pk_list=get_matchingport_route_pks(destinationports, existing_routes)
90
            if route_pk_list:
91
                existing_routes = existing_routes.filter(pk__in=route_pk_list)
92
        else:
93
            existing_routes = existing_routes.filter(destinationport=None)
94
        if ports:
95
            route_pk_list=get_matchingport_route_pks(ports, existing_routes)
96
            if route_pk_list:
97
                existing_routes = existing_routes.filter(pk__in=route_pk_list)              
98
        else:
99
            existing_routes = existing_routes.filter(port=None)
100
        
101
        for route in existing_routes:
102
            if name != route.name:
103
                existing_url = reverse('edit-route', args=[route.name])
104
                if IPNetwork(destination) in IPNetwork(route.destination):
105
                    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
                if IPNetwork(route.destination) in IPNetwork(destination):
107
                    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
        
109

    
110
        return self.cleaned_data
111

    
112
class ThenPlainForm(forms.ModelForm):
113
#    action = forms.CharField(initial='rate-limit')
114
    class Meta:
115
        model = ThenAction
116
    
117
    def clean_action_value(self):
118
        action_value = self.cleaned_data['action_value']
119
        if action_value:
120
            try:
121
                assert(int(action_value))
122
                return "%s" %self.cleaned_data["action_value"]
123
            except:
124
                raise forms.ValidationError('Rate-limiting should be an integer')
125
            if int(action_value) < 50:
126
                raise forms.ValidationError('Rate-limiting cannot be < 50kbps')
127
        else:
128
            raise forms.ValidationError('Cannot be empty')
129

    
130
    def clean_action(self):
131
        action = self.cleaned_data['action']
132
        if action != 'rate-limit':
133
            raise forms.ValidationError('Cannot select something other than rate-limit')
134
        else:
135
            return self.cleaned_data["action"]
136

    
137
class PortPlainForm(forms.ModelForm):
138
#    action = forms.CharField(initial='rate-limit')
139
    class Meta:
140
        model = MatchPort
141
    
142
    def clean_port(self):
143
        port = self.cleaned_data['port']
144
        if port:
145
            try:
146
                assert(int(port))
147
                return "%s" %self.cleaned_data["port"]
148
            except:
149
                raise forms.ValidationError('Port should be an integer')
150
        else:
151
            raise forms.ValidationError('Cannot be empty')
152

    
153
def value_list_to_list(valuelist):
154
    vl = []
155
    for val in valuelist:
156
        vl.append(val[0])
157
    return vl
158

    
159
def get_matchingport_route_pks(portlist, routes):
160
    route_pk_list = []
161
    ports_value_list = value_list_to_list(portlist.values_list('port').order_by('port'))
162
    for route in routes:
163
        rsp = value_list_to_list(route.destinationport.all().values_list('port').order_by('port'))
164
        if rsp and rsp == ports_value_list:
165
            route_pk_list.append(route.pk)
166
    return route_pk_list