Statistics
| Branch: | Tag: | Revision:

root / flowspec / forms.py @ 7a0ac0d1

History | View | Annotate | Download (8.3 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
import datetime
11

    
12

    
13

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

    
36
    def clean_destination(self):
37
        data = self.cleaned_data['destination']
38
        if data:
39
            try:
40
                address = IPNetwork(data)
41
                return self.cleaned_data["destination"]
42
            except Exception:
43
                raise forms.ValidationError('Invalid network address format')
44
    
45
    def clean_expires(self):
46
        date = self.cleaned_data['expires']
47
        if date:
48
            range_days = (date - datetime.date.today()).days
49
            if range_days > 0 and range_days < 11:
50
                return self.cleaned_data["expires"]
51
            else:
52
                raise forms.ValidationError('Invalid date range')
53

    
54
    def clean(self):
55
        name = self.cleaned_data.get('name', None)
56
        source = self.cleaned_data.get('source', None)
57
        sourceports = self.cleaned_data.get('sourceport', None)
58
        ports = self.cleaned_data.get('port', None)
59
        then = self.cleaned_data.get('then', None)
60
        destination = self.cleaned_data.get('destination', None)
61
        destinationports = self.cleaned_data.get('destinationport', None)
62
        user = self.cleaned_data.get('applier', None)
63
        peer = user.get_profile().peer
64
        networks = peer.networks.all()
65
        mynetwork = False
66
        route_pk_list = []
67
        
68
        if destination:
69
            for network in networks:
70
                net = IPNetwork(network.network)
71
                if IPNetwork(destination) in net:
72
                    mynetwork = True
73
            if not mynetwork:
74
                 raise forms.ValidationError('Destination address/network should belong to your administrative address space. Check My Profile to review your networks')
75
        if (sourceports and ports):
76
            raise forms.ValidationError('Cannot create rule for source ports and ports at the same time. Select either ports or source ports')
77
        if (destinationports and ports):
78
            raise forms.ValidationError('Cannot create rule for destination ports and ports at the same time. Select either ports or destination ports')
79
        if sourceports and not source:
80
            raise forms.ValidationError('Once source port is matched, source has to be filled as well. Either deselect source port or fill source address')
81
        if destinationports and not destination:
82
            raise forms.ValidationError('Once destination port is matched, destination has to be filled as well. Either deselect destination port or fill destination address')
83
        if not (source or sourceports or ports or destination or destinationports):
84
            raise forms.ValidationError('Fill at least a Route Match Condition')
85
        existing_routes = Route.objects.exclude(status='EXPIRED').exclude(status='PENDING').exclude(status='ERROR').exclude(status='ADMININACTIVE')
86
        existing_routes = existing_routes.filter(applier__userprofile__peer=peer)
87
        if source:
88
            source = IPNetwork(source).compressed
89
            existing_routes = existing_routes.filter(source=source)
90
        else:
91
            existing_routes = existing_routes.filter(source=None)
92
        if sourceports:
93
            route_pk_list=get_matchingport_route_pks(sourceports, existing_routes)
94
            if route_pk_list:
95
                existing_routes = existing_routes.filter(pk__in=route_pk_list)
96
        else:
97
            existing_routes = existing_routes.filter(sourceport=None)
98
        if destinationports:
99
            route_pk_list=get_matchingport_route_pks(destinationports, existing_routes)
100
            if route_pk_list:
101
                existing_routes = existing_routes.filter(pk__in=route_pk_list)
102
        else:
103
            existing_routes = existing_routes.filter(destinationport=None)
104
        if ports:
105
            route_pk_list=get_matchingport_route_pks(ports, existing_routes)
106
            if route_pk_list:
107
                existing_routes = existing_routes.filter(pk__in=route_pk_list)              
108
        else:
109
            existing_routes = existing_routes.filter(port=None)
110
        
111
        for route in existing_routes:
112
            if name != route.name:
113
                existing_url = reverse('edit-route', args=[route.name])
114
                if IPNetwork(destination) in IPNetwork(route.destination) or IPNetwork(route.destination) in IPNetwork(destination):
115
                    raise forms.ValidationError('Found an exact %s rule, %s with destination prefix %s<br>To avoid overlapping try editing rule <a href=\'%s\'>%s</a>' %(route.status, route.name, route.destination, existing_url, route.name))
116
        return self.cleaned_data
117

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

    
136
    def clean_action(self):
137
        action = self.cleaned_data['action']
138
        if action != 'rate-limit':
139
            raise forms.ValidationError('Cannot select something other than rate-limit')
140
        else:
141
            return self.cleaned_data["action"]
142

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

    
159
def value_list_to_list(valuelist):
160
    vl = []
161
    for val in valuelist:
162
        vl.append(val[0])
163
    return vl
164

    
165
def get_matchingport_route_pks(portlist, routes):
166
    route_pk_list = []
167
    ports_value_list = value_list_to_list(portlist.values_list('port').order_by('port'))
168
    for route in routes:
169
        rsp = value_list_to_list(route.destinationport.all().values_list('port').order_by('port'))
170
        if rsp and rsp == ports_value_list:
171
            route_pk_list.append(route.pk)
172
    return route_pk_list