diff --git a/flowspec/admin.py b/flowspec/admin.py
index 18c9a5193d5f009b288a46388832d3ac5d02a394..ddb49aadc9bed29f0a307518b193371f9519e81a 100644
--- a/flowspec/admin.py
+++ b/flowspec/admin.py
@@ -18,7 +18,7 @@
 #
 
 from django.contrib import admin
-from flowspec.models import MatchPort, MatchDscp, MatchProtocol, FragmentType, ThenAction, Route
+from flowspec.models import MatchPort, MatchDscp, MatchProtocol, FragmentType, ThenAction, Route, Rule
 from accounts.models import UserProfile
 from utils import proxy as PR
 from tasks import *
@@ -29,19 +29,25 @@ from flowspec.forms import *
 from longerusername.forms import UserCreationForm, UserChangeForm
 
 
+class RuleAdmin(admin.ModelAdmin):
+    form = RuleForm
+
 class RouteAdmin(admin.ModelAdmin):
     form = RouteForm
     actions = ['deactivate']
-    search_fields = ['destination', 'name', 'applier__username']
+    search_fields = ['destination', 'name', 'applier_username']
 
     def deactivate(self, request, queryset):
-        queryset = queryset.filter(status='ACTIVE')
+        queryset = queryset.filter(rule__status='ACTIVE')
         response = batch_delete.delay(queryset, reason="ADMININACTIVE")
         self.message_user(request, "Added request %s to job que. Check in a while for result" % response)
     deactivate.short_description = "Remove selected routes from network"
 
     def save_model(self, request, obj, form, change):
-        obj.status = "PENDING"
+        rule = Rule()
+        rule.save()
+        obj.rule = rule
+        obj.rule.status = "PENDING"
         obj.save()
         if change:
             obj.commit_edit()
@@ -51,14 +57,11 @@ class RouteAdmin(admin.ModelAdmin):
     def has_delete_permission(self, request, obj=None):
         return False
 
-    list_display = ('name', 'status', 'applier_username', 'applier_peers', 'get_match', 'get_then', 'response', "expires", "comments")
+    list_display = ('name', 'status', 'applier_username', 'applier_peers', 'get_match', 'get_then', 'response', "comments")
 
     fieldsets = [
-        (None, {'fields': ['name', 'applier']}),
         ("Match", {'fields': ['source', 'sourceport', 'destination', 'destinationport', 'port']}),
         ('Advanced Match Statements', {'fields': ['dscp', 'fragmenttype', 'icmpcode', 'icmptype', 'packetlength', 'protocol', 'tcpflag'], 'classes': ['collapse']}),
-        ("Then", {'fields': ['then']}),
-        ("Expires", {'fields': ['expires']}),
         (None, {'fields': ['comments', ]}),
 
     ]
diff --git a/flowspec/forms.py b/flowspec/forms.py
index 856ab6ce97e74ad423b5d0247a7ecefd7509c3d5..0f9872b53efe07f9aad506c477b4fc716e947a1f 100644
--- a/flowspec/forms.py
+++ b/flowspec/forms.py
@@ -86,12 +86,9 @@ class UserProfileForm(forms.ModelForm):
         model = UserProfile
 
 
-class RouteForm(forms.ModelForm):
-    sourceport = PortRangeForm()
-    destinationport = PortRangeForm()
-    port = PortRangeForm()
+class RuleForm(forms.ModelForm):
     class Meta:
-        model = Route
+        model = Rule
 
     def clean_applier(self):
         applier = self.cleaned_data['applier']
@@ -100,31 +97,11 @@ class RouteForm(forms.ModelForm):
         else:
             raise forms.ValidationError('This field is required.')
 
-    def clean_source(self):
-        # run validator which is used by rest framework too
-        source = self.cleaned_data['source']
-        res = clean_source(
-            User.objects.get(pk=self.data['applier']),
-            source
-        )
-        if res != source:
-            raise forms.ValidationError(res)
-        else:
-            return res
-
-    def clean_destination(self):
-        destination = self.cleaned_data.get('destination')
-        res = clean_destination(
-            User.objects.get(pk=self.data['applier']),
-            destination
-        )
-        if destination != res:
-            raise forms.ValidationError(res)
-        else:
-            return res
 
     def clean_expires(self):
         date = self.cleaned_data['expires']
+        if not date:
+            raise forms.ValidationError('This field is required.')
         res = clean_expires(date)
         if date != res:
             raise forms.ValidationError(res)
@@ -143,8 +120,72 @@ class RouteForm(forms.ModelForm):
             peers = Peer.objects.all()
         else:
             peers = user.userprofile.peers.all()
+
+        existing_routes = self.routes.all()
+        #existing_routes = existing_routes.filter(rule__applier__userprofile__peers__in=peers)
+        name = self.cleaned_data.get('name', None)
+        protocols = self.cleaned_data.get('protocol', None)
+        source = self.cleaned_data.get('source', None)
+        sourceports = self.cleaned_data.get('sourceport', None)
+        port = self.cleaned_data.get('port', None)
+        destination = self.cleaned_data.get('destination', None)
+        destinationports = self.cleaned_data.get('destinationport', None)
+        #user = self.cleaned_data.get('applier', None)
+
+        for route in existing_routes:
+            if name != route.name:
+                existing_url = reverse('edit-route', args=[route.name])
+                if IPNetwork(destination) in IPNetwork(route.destination) or IPNetwork(route.destination) in IPNetwork(destination):
+                    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))
+        return self.cleaned_data
+
+class RouteForm(forms.ModelForm):
+    sourceport = PortRangeForm()
+    destinationport = PortRangeForm()
+    port = PortRangeForm()
+    class Meta:
+        model = Route
+
+    def clean_source(self):
+        # run validator which is used by rest framework too
+        source = self.cleaned_data['source']
+        #res = clean_source(
+        #    User.objects.get(pk=self.data['applier']),
+        #    source
+        #)
+        #if res != source:
+        #    raise forms.ValidationError(res)
+        #else:
+        #    return res
+        return source
+
+    def clean_destination(self):
+        destination = self.cleaned_data.get('destination')
+        #res = clean_destination(
+        #    User.objects.get(pk=self.data['applier']),
+        #    destination
+        #)
+        #if destination != res:
+        #    raise forms.ValidationError(res)
+        #else:
+        #    return res
+        return destination
+
+    def clean(self):
+        if self.errors:
+            raise forms.ValidationError(_('Errors in form. Please review and fix them: %s' % ", ".join(self.errors)))
+        error = clean_route_form(self.cleaned_data)
+        if error:
+            raise forms.ValidationError(error)
+
+        ## check if same rule exists with other name
+        #user = self.cleaned_data['applier']
+        #if user.is_superuser:
+        #    peers = Peer.objects.all()
+        #else:
+        #    peers = user.userprofile.peers.all()
         existing_routes = Route.objects.all()
-        existing_routes = existing_routes.filter(applier__userprofile__peers__in=peers)
+        #existing_routes = existing_routes.filter(rule__applier__userprofile__peers__in=peers)
         name = self.cleaned_data.get('name', None)
         protocols = self.cleaned_data.get('protocol', None)
         source = self.cleaned_data.get('source', None)
@@ -152,7 +193,7 @@ class RouteForm(forms.ModelForm):
         port = self.cleaned_data.get('port', None)
         destination = self.cleaned_data.get('destination', None)
         destinationports = self.cleaned_data.get('destinationport', None)
-        user = self.cleaned_data.get('applier', None)
+        #user = self.cleaned_data.get('applier', None)
 
         if source:
             source = IPNetwork(source).compressed
diff --git a/flowspec/migrations/0008_auto__add_rule__del_field_route_status__del_field_route_last_updated__.py b/flowspec/migrations/0008_auto__add_rule__del_field_route_status__del_field_route_last_updated__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a88475317597b5641a1e8bfd8d2f64fe2de4b09
--- /dev/null
+++ b/flowspec/migrations/0008_auto__add_rule__del_field_route_status__del_field_route_last_updated__.py
@@ -0,0 +1,221 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Rule'
+        db.create_table(u'flowspec_rule', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.SlugField')(max_length=128)),
+            ('applier', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
+            ('filed', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now, auto_now_add=True, blank=True)),
+            ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now, auto_now=True, blank=True)),
+            ('comments', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
+            ('requesters_address', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
+            ('expires', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2018, 7, 10, 0, 0))),
+            ('status', self.gf('django.db.models.fields.CharField')(default='INACTIVE', max_length=20, null=True, blank=True)),
+        ))
+        db.send_create_signal('flowspec', ['Rule'])
+
+        # Adding M2M table for field then on 'Rule'
+        db.create_table(u'flowspec_rule_then', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('rule', models.ForeignKey(orm['flowspec.rule'], null=False)),
+            ('thenaction', models.ForeignKey(orm['flowspec.thenaction'], null=False))
+        ))
+        db.create_unique(u'flowspec_rule_then', ['rule_id', 'thenaction_id'])
+
+        # Deleting field 'Route.status'
+        db.delete_column(u'route', 'status')
+
+        # Deleting field 'Route.last_updated'
+        db.delete_column(u'route', 'last_updated')
+
+        # Deleting field 'Route.requesters_address'
+        db.delete_column(u'route', 'requesters_address')
+
+        # Deleting field 'Route.expires'
+        db.delete_column(u'route', 'expires')
+
+        # Deleting field 'Route.filed'
+        db.delete_column(u'route', 'filed')
+
+        # Deleting field 'Route.applier'
+        db.delete_column(u'route', 'applier_id')
+
+        # Adding field 'Route.rule'
+        db.add_column(u'route', 'rule',
+                      self.gf('django.db.models.fields.related.ForeignKey')(related_name='routes', null=True, to=orm['flowspec.Rule']),
+                      keep_default=False)
+
+        # Removing M2M table for field then on 'Route'
+        db.delete_table('route_then')
+
+
+        # Changing field 'Route.destinationport'
+        db.alter_column(u'route', 'destinationport', self.gf('django.db.models.fields.CharField')(max_length=65535, null=True))
+
+        # Changing field 'Route.sourceport'
+        db.alter_column(u'route', 'sourceport', self.gf('django.db.models.fields.CharField')(max_length=65535, null=True))
+
+        # Changing field 'Route.port'
+        db.alter_column(u'route', 'port', self.gf('django.db.models.fields.CharField')(max_length=65535, null=True))
+
+    def backwards(self, orm):
+        # Deleting model 'Rule'
+        db.delete_table(u'flowspec_rule')
+
+        # Removing M2M table for field then on 'Rule'
+        db.delete_table('flowspec_rule_then')
+
+        # Adding field 'Route.status'
+        db.add_column(u'route', 'status',
+                      self.gf('django.db.models.fields.CharField')(default='PENDING', max_length=20, null=True, blank=True),
+                      keep_default=False)
+
+
+        # User chose to not deal with backwards NULL issues for 'Route.last_updated'
+        raise RuntimeError("Cannot reverse this migration. 'Route.last_updated' and its values cannot be restored.")
+        # Adding field 'Route.requesters_address'
+        db.add_column(u'route', 'requesters_address',
+                      self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'Route.expires'
+        db.add_column(u'route', 'expires',
+                      self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2017, 2, 8, 0, 0)),
+                      keep_default=False)
+
+
+        # User chose to not deal with backwards NULL issues for 'Route.filed'
+        raise RuntimeError("Cannot reverse this migration. 'Route.filed' and its values cannot be restored.")
+        # Adding field 'Route.applier'
+        db.add_column(u'route', 'applier',
+                      self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True),
+                      keep_default=False)
+
+        # Deleting field 'Route.rule'
+        db.delete_column(u'route', 'rule_id')
+
+        # Adding M2M table for field then on 'Route'
+        db.create_table(u'route_then', (
+            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+            ('route', models.ForeignKey(orm['flowspec.route'], null=False)),
+            ('thenaction', models.ForeignKey(orm['flowspec.thenaction'], null=False))
+        ))
+        db.create_unique(u'route_then', ['route_id', 'thenaction_id'])
+
+
+        # Changing field 'Route.destinationport'
+        db.alter_column(u'route', 'destinationport', self.gf('django.db.models.fields.CharField')(max_length=50, null=True))
+
+        # Changing field 'Route.sourceport'
+        db.alter_column(u'route', 'sourceport', self.gf('django.db.models.fields.CharField')(max_length=50, null=True))
+
+        # Changing field 'Route.port'
+        db.alter_column(u'route', 'port', self.gf('django.db.models.fields.CharField')(max_length=50, null=True))
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'flowspec.fragmenttype': {
+            'Meta': {'object_name': 'FragmentType'},
+            'fragmenttype': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'flowspec.matchdscp': {
+            'Meta': {'object_name': 'MatchDscp', 'db_table': "u'match_dscp'"},
+            'dscp': ('django.db.models.fields.CharField', [], {'max_length': '24'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'flowspec.matchport': {
+            'Meta': {'object_name': 'MatchPort', 'db_table': "u'match_port'"},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'port': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '24'})
+        },
+        'flowspec.matchprotocol': {
+            'Meta': {'object_name': 'MatchProtocol', 'db_table': "u'match_protocol'"},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '24'})
+        },
+        'flowspec.route': {
+            'Meta': {'object_name': 'Route', 'db_table': "u'route'"},
+            'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'destination': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'destinationport': ('django.db.models.fields.CharField', [], {'max_length': '65535', 'null': 'True', 'blank': 'True'}),
+            'dscp': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.MatchDscp']", 'null': 'True', 'blank': 'True'}),
+            'fragmenttype': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.FragmentType']", 'null': 'True', 'blank': 'True'}),
+            'icmpcode': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+            'icmptype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.SlugField', [], {'max_length': '128'}),
+            'packetlength': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'port': ('django.db.models.fields.CharField', [], {'max_length': '65535', 'null': 'True', 'blank': 'True'}),
+            'protocol': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.MatchProtocol']", 'null': 'True', 'blank': 'True'}),
+            'response': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}),
+            'rule': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'routes'", 'null': 'True', 'to': "orm['flowspec.Rule']"}),
+            'source': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'sourceport': ('django.db.models.fields.CharField', [], {'max_length': '65535', 'null': 'True', 'blank': 'True'}),
+            'tcpflag': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'})
+        },
+        'flowspec.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'applier': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'expires': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2018, 7, 10, 0, 0)'}),
+            'filed': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now_add': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.SlugField', [], {'max_length': '128'}),
+            'requesters_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'status': ('django.db.models.fields.CharField', [], {'default': "'INACTIVE'", 'max_length': '20', 'null': 'True', 'blank': 'True'}),
+            'then': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['flowspec.ThenAction']", 'symmetrical': 'False'})
+        },
+        'flowspec.thenaction': {
+            'Meta': {'ordering': "['action', 'action_value']", 'unique_together': "(('action', 'action_value'),)", 'object_name': 'ThenAction', 'db_table': "u'then_action'"},
+            'action': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
+            'action_value': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        }
+    }
+
+    complete_apps = ['flowspec']
\ No newline at end of file
diff --git a/flowspec/models.py b/flowspec/models.py
index 64319df607266e890d56b6347dbc5d27e05d216f..4f0677037e72dbc44b2f95ca79584086b3f352b3 100644
--- a/flowspec/models.py
+++ b/flowspec/models.py
@@ -22,7 +22,7 @@ from django.conf import settings
 from django.contrib.auth.models import User
 from django.contrib.sites.models import Site
 from django.utils.translation import ugettext_lazy as _
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse, NoReverseMatch
 
 from flowspec.helpers import send_new_mail, get_peer_techc_mails
 from utils import proxy as PR
@@ -135,31 +135,22 @@ class ThenAction(models.Model):
         unique_together = ("action", "action_value")
 
 
-class Route(models.Model):
+class Rule(models.Model):
     name = models.SlugField(max_length=128, verbose_name=_("Name"))
     applier = models.ForeignKey(User, blank=True, null=True)
-    source = models.CharField(max_length=32, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Source Address"))
-    sourceport = models.CharField(max_length=65535, blank=True, null=True, verbose_name=_("Source Port"))
-    destination = models.CharField(max_length=32, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Destination Address"))
-    destinationport = models.CharField(max_length=65535, blank=True, null=True, verbose_name=_("Destination Port"))
-    port = models.CharField(max_length=65535, blank=True, null=True, verbose_name=_("Port"))
-    dscp = models.ManyToManyField(MatchDscp, blank=True, null=True, verbose_name="DSCP")
-    fragmenttype = models.ManyToManyField(FragmentType, blank=True, null=True, verbose_name="Fragment Type")
-    icmpcode = models.CharField(max_length=32, blank=True, null=True, verbose_name="ICMP Code")
-    icmptype = models.CharField(max_length=32, blank=True, null=True, verbose_name="ICMP Type")
-    packetlength = models.IntegerField(blank=True, null=True, verbose_name="Packet Length")
-    protocol = models.ManyToManyField(MatchProtocol, blank=True, null=True, verbose_name=_("Protocol"))
-    tcpflag = models.CharField(max_length=128, blank=True, null=True, verbose_name="TCP flag")
     then = models.ManyToManyField(ThenAction, verbose_name=_("Then"))
-    filed = models.DateTimeField(auto_now_add=True)
-    last_updated = models.DateTimeField(auto_now=True)
-    status = models.CharField(max_length=20, choices=ROUTE_STATES, blank=True, null=True, verbose_name=_("Status"), default="PENDING")
-#    is_online = models.BooleanField(default=False)
-#    is_active = models.BooleanField(default=False)
-    expires = models.DateField(default=days_offset, verbose_name=_("Expires"))
-    response = models.CharField(max_length=512, blank=True, null=True, verbose_name=_("Response"))
+    filed = models.DateTimeField(auto_now_add=True, default=datetime.datetime.now, null=False)
+    last_updated = models.DateTimeField(auto_now=True, default=datetime.datetime.now, null=False)
     comments = models.TextField(null=True, blank=True, verbose_name=_("Comments"))
     requesters_address = models.CharField(max_length=255, blank=True, null=True)
+    expires = models.DateField(default=days_offset, verbose_name=_("Expires"))
+    status = models.CharField(max_length=20, choices=ROUTE_STATES, blank=True, null=True, verbose_name=_("Status"), default="INACTIVE")
+
+
+    class Meta:
+        db_table = u'flowspec_rule'
+        verbose_name = "Rule"
+        verbose_name_plural = "Rules"
 
     @property
     def applier_username(self):
@@ -168,35 +159,32 @@ class Route(models.Model):
         else:
             return None
 
-    def __unicode__(self):
-        return self.name
-
-    class Meta:
-        db_table = u'route'
-        verbose_name = "Rule"
-        verbose_name_plural = "Rules"
-
     def save(self, *args, **kwargs):
         if not self.pk:
             hash = id_gen()
             self.name = "%s_%s" % (self.name, hash)
-        super(Route, self).save(*args, **kwargs) # Call the "real" save() method.
+        super(Rule, self).save(*args, **kwargs) # Call the "real" save() method.
 
-    def clean(self, *args, **kwargs):
-        from django.core.exceptions import ValidationError
-        if self.destination:
-            try:
-                address = IPNetwork(self.destination)
-                self.destination = address.exploded
-            except Exception:
-                raise ValidationError(_('Invalid network address format at Destination Field'))
-        if self.source:
-            try:
-                address = IPNetwork(self.source)
-                self.source = address.exploded
-            except Exception:
-                raise ValidationError(_('Invalid network address format at Source Field'))
+    def _send_mail(self, *args, **kwargs):
+        args = kwargs.get("args")
 
+        fqdn = Site.objects.get_current().domain
+        try:
+            admin_url = 'https://%s%s' % (fqdn, reverse(args.get("url_path"), kwargs={args.get("url_id"): self.name}))
+        except NoReverseMatch:
+            admin_url = "Unknown"
+        args["url"] = admin_url
+        mail_body = render_to_string('rule_action.txt', args)
+        user_mail = '%s' % self.applier.email
+        user_mail = user_mail.split(';')
+        send_new_mail(
+            args.get("subject"),
+            mail_body,
+            settings.SERVER_EMAIL, user_mail,
+            get_peer_techc_mails(self.applier, args.get("peer"))
+        )
+        return mail_body
+      
     def commit_add(self, *args, **kwargs):
         peers = self.applier.get_profile().peers.all()
         username = None
@@ -205,9 +193,10 @@ class Route(models.Model):
                 break
             for network in peer.networks.all():
                 net = IPNetwork(network)
-                if IPNetwork(self.destination) in net:
-                    username = peer
-                    break
+                for route in self.routes.all():
+                    if IPNetwork(route.destination) in net:
+                        username = peer
+                        break
         if username:
             peer = username.peer_tag
         else:
@@ -215,29 +204,17 @@ class Route(models.Model):
         send_message("[%s] Adding rule %s. Please wait..." % (self.applier.username, self.name), peer)
         response = add.delay(self)
         logger.info('Got add job id: %s' % response)
-        fqdn = Site.objects.get_current().domain
-        admin_url = 'https://%s%s' % (
-            fqdn,
-            reverse('edit-route', kwargs={'route_slug': self.name})
-        )
-        mail_body = render_to_string(
-            'rule_action.txt',
-            {
-                'route': self,
+        mail_body = self._send_mail(args={
+                'url_path': 'edit-route',
+                'url_id': 'route_slug',
+                'rule': self,
+                'routes': self.routes.all(),
                 'address': self.requesters_address,
                 'action': 'creation',
-                'url': admin_url,
-                'peer': username
-            }
-        )
-        user_mail = '%s' % self.applier.email
-        user_mail = user_mail.split(';')
-        send_new_mail(
-            settings.EMAIL_SUBJECT_PREFIX + 'Rule %s creation request submitted by %s' % (self.name, self.applier.username),
-            mail_body,
-            settings.SERVER_EMAIL, user_mail,
-            get_peer_techc_mails(self.applier, username)
-        )
+                'peer': username,
+                'subject': settings.EMAIL_SUBJECT_PREFIX + 'Rule %s creation request submitted by %s' % (self.name, self.applier.username),
+        })
+
         d = {
             'clientip': '%s' % self.requesters_address,
             'user': self.applier.username
@@ -252,9 +229,10 @@ class Route(models.Model):
                 break
             for network in peer.networks.all():
                 net = IPNetwork(network)
-                if IPNetwork(self.destination) in net:
-                    username = peer
-                    break
+                for route in self.routes.all():
+                    if IPNetwork(route.destination) in net:
+                        username = peer
+                        break
         if username:
             peer = username.peer_tag
         else:
@@ -268,31 +246,17 @@ class Route(models.Model):
         )
         response = edit.delay(self)
         logger.info('Got edit job id: %s' % response)
-        fqdn = Site.objects.get_current().domain
-        admin_url = 'https://%s%s' % (
-            fqdn,
-            reverse(
-                'edit-route',
-                kwargs={'route_slug': self.name}
-            )
-        )
-        mail_body = render_to_string(
-            'rule_action.txt',
-            {
-                'route': self,
+        mail_body = self._send_mail(args={
+                'url_path': 'edit-route',
+                'url_id': 'route_slug',
+                'rule': self,
+                'routes': self.routes.all(),
                 'address': self.requesters_address,
                 'action': 'edit',
-                'url': admin_url,
-                'peer': username
-            }
-        )
-        user_mail = '%s' % self.applier.email
-        user_mail = user_mail.split(';')
-        send_new_mail(
-            settings.EMAIL_SUBJECT_PREFIX + 'Rule %s edit request submitted by %s' % (self.name, self.applier.username),
-            mail_body, settings.SERVER_EMAIL, user_mail,
-            get_peer_techc_mails(self.applier, username)
-        )
+                'peer': username,
+                'subject': settings.EMAIL_SUBJECT_PREFIX + 'Rule %s edit request submitted by %s' % (self.name, self.applier.username),
+        })
+
         d = {
             'clientip': self.requesters_address,
             'user': self.applier.username
@@ -312,9 +276,10 @@ class Route(models.Model):
                 break
             for network in peer.networks.all():
                 net = IPNetwork(network)
-                if IPNetwork(self.destination) in net:
-                    username = peer
-                    break
+                for route in self.routes.all():
+                    if IPNetwork(route.destination) in net:
+                        username = peer
+                        break
         if username:
             peer = username.peer_tag
         else:
@@ -328,45 +293,92 @@ class Route(models.Model):
         )
         response = delete.delay(self, reason=reason)
         logger.info('Got delete job id: %s' % response)
-        fqdn = Site.objects.get_current().domain
-        admin_url = 'https://%s%s' % (
-            fqdn,
-            reverse(
-                'edit-route',
-                kwargs={'route_slug': self.name}
-            )
-        )
-        mail_body = render_to_string(
-            'rule_action.txt',
-            {
-                'route': self,
+
+        mail_body = self._send_mail(args={
+                'url_path': 'edit-route',
+                'url_id': 'route_slug',
+                'rule': self,
+                'routes': self.routes.all(),
                 'address': self.requesters_address,
                 'action': 'removal',
-                'url': admin_url,
-                'peer': username
-            }
-        )
-        user_mail = '%s' % self.applier.email
-        user_mail = user_mail.split(';')
-        send_new_mail(
-            settings.EMAIL_SUBJECT_PREFIX + 'Rule %s removal request submitted by %s' % (self.name, self.applier.username),
-            mail_body,
-            settings.SERVER_EMAIL,
-            user_mail,
-            get_peer_techc_mails(self.applier, username)
-        )
+                'peer': username,
+                'subject': settings.EMAIL_SUBJECT_PREFIX + 'Rule %s removal request submitted by %s' % (self.name, self.applier.username),
+        })
         d = {
             'clientip': self.requesters_address,
             'user': self.applier.username
         }
         logger.info(mail_body, extra=d)
 
+
+class Route(models.Model):
+    name = models.SlugField(max_length=128, verbose_name=_("Name"))
+    rule = models.ForeignKey(Rule, related_name='routes', null=True)
+    source = models.CharField(max_length=32, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Source Address"))
+    sourceport = models.CharField(max_length=65535, blank=True, null=True, verbose_name=_("Source Port"))
+    destination = models.CharField(max_length=32, help_text=_("Network address. Use address/CIDR notation"), verbose_name=_("Destination Address"))
+    destinationport = models.CharField(max_length=65535, blank=True, null=True, verbose_name=_("Destination Port"))
+    port = models.CharField(max_length=65535, blank=True, null=True, verbose_name=_("Port"))
+    dscp = models.ManyToManyField(MatchDscp, blank=True, null=True, verbose_name="DSCP")
+    fragmenttype = models.ManyToManyField(FragmentType, blank=True, null=True, verbose_name="Fragment Type")
+    icmpcode = models.CharField(max_length=32, blank=True, null=True, verbose_name="ICMP Code")
+    icmptype = models.CharField(max_length=32, blank=True, null=True, verbose_name="ICMP Type")
+    packetlength = models.IntegerField(blank=True, null=True, verbose_name="Packet Length")
+    protocol = models.ManyToManyField(MatchProtocol, blank=True, null=True, verbose_name=_("Protocol"))
+    tcpflag = models.CharField(max_length=128, blank=True, null=True, verbose_name="TCP flag")
+#    is_online = models.BooleanField(default=False)
+#    is_active = models.BooleanField(default=False)
+    response = models.CharField(max_length=512, blank=True, null=True, verbose_name=_("Response"))
+    comments = models.TextField(null=True, blank=True, verbose_name=_("Comments"))
+
+    @property
+    def applier_username(self):
+        if self.rule and self.rule.applier:
+            return self.rule.applier.username
+        else:
+            return None
+
+    def __unicode__(self):
+        return self.name
+
+    class Meta:
+        db_table = u'route'
+        verbose_name = "Route"
+        verbose_name_plural = "Routes"
+
+    def save(self, *args, **kwargs):
+        if not self.pk:
+            hash = id_gen()
+            self.name = "%s_%s" % (self.name, hash)
+        super(Route, self).save(*args, **kwargs) # Call the "real" save() method.
+
+    def clean(self, *args, **kwargs):
+        from django.core.exceptions import ValidationError
+        if self.destination:
+            try:
+                address = IPNetwork(self.destination)
+                self.destination = address.exploded
+            except Exception:
+                raise ValidationError(_('Invalid network address format at Destination Field'))
+        if self.source:
+            try:
+                address = IPNetwork(self.source)
+                self.source = address.exploded
+            except Exception:
+                raise ValidationError(_('Invalid network address format at Source Field'))
+
     def has_expired(self):
         today = datetime.date.today()
         if today > self.expires:
             return True
         return False
 
+    def status(self):
+        if self.rule:
+            return self.rule.status
+        else:
+            return ROUTE_STATES["INACTIVE"]
+
     def check_sync(self):
         if not self.is_synced():
             self.status = "OUTOFSYNC"
diff --git a/flowspec/serializers.py b/flowspec/serializers.py
index 287b53355dd47b8edfa158520b80e122d986a545..28bb9a5c3d4f6d0d0b2137077606ac7cab65a23f 100644
--- a/flowspec/serializers.py
+++ b/flowspec/serializers.py
@@ -1,6 +1,10 @@
+# -*- coding: utf-8 -*- vim:fileencoding=utf-8:
+# vim: tabstop=4:shiftwidth=4:softtabstop=4:expandtab
+
 from rest_framework import serializers
 from flowspec.models import (
     Route,
+    Rule,
     MatchPort,
     ThenAction,
     FragmentType,
@@ -14,9 +18,52 @@ from flowspec.validators import (
 )
 
 
-class RouteSerializer(serializers.HyperlinkedModelSerializer):
+class PeerSerializer(serializers.HyperlinkedModelSerializer):
+   pass
+
+class RuleSerializer(serializers.HyperlinkedModelSerializer):
     applier = serializers.CharField(source='applier_username', read_only=True)
 
+    def validate_expires(self, attrs, source):
+        print("validate expires ")
+        value = attrs[source]
+        if not value:
+            raise serializers.ValidationError('This field is required')
+        res = clean_expires(value)
+        if res != value:
+            raise serializers.ValidationError(res)
+        return attrs
+
+    def validate_then(self, attrs, source):
+        if not source:
+            raise serializers.ValidationError('This field is required')
+        return attrs
+
+    def validate(self, data):
+        user = self.context.get('request').user
+        return data
+
+
+    class Meta:
+        model = Rule
+        fields = (
+            'name',
+            'id',
+            'comments',
+            'applier',
+            'then',
+            'routes',
+            'filed',
+            'last_updated',
+            'expires',
+            'status',
+            'requesters_address',
+            'url'
+        )
+        read_only_fields = ('requesters_address', )
+
+class RouteSerializer(serializers.HyperlinkedModelSerializer):
+
     def validate(self, data):
         user = self.context.get('request').user
         # validate source
@@ -37,14 +84,6 @@ class RouteSerializer(serializers.HyperlinkedModelSerializer):
         if res != destination:
             raise serializers.ValidationError(res)
 
-        # validate expires
-        expires = data.get('expires')
-        res = clean_expires(
-            expires
-        )
-        if res != expires:
-            raise serializers.ValidationError(res)
-
         # check if rule already exists with different name
         fields = {
             'source': data.get('source'),
@@ -60,8 +99,7 @@ class RouteSerializer(serializers.HyperlinkedModelSerializer):
         fields = (
             'name',
             'id',
-            'comments',
-            'applier',
+            'rule',
             'source',
             'sourceport',
             'destination',
@@ -73,16 +111,10 @@ class RouteSerializer(serializers.HyperlinkedModelSerializer):
             'packetlength',
             'protocol',
             'tcpflag',
-            'then',
-            'filed',
-            'last_updated',
-            'status',
-            'expires',
             'response',
-            'comments',
-            'requesters_address',
+            'url',
         )
-        read_only_fields = ('status', 'expires', 'requesters_address', 'response')
+        read_only_fields = ('response', 'id')
 
 
 class PortSerializer(serializers.HyperlinkedModelSerializer):
diff --git a/flowspec/validators.py b/flowspec/validators.py
index 96bd4e7dcb47922707ddb1735d5646f66194bbf7..dcd0c9975d81c0ef974332a2a91193c28678ddd9 100644
--- a/flowspec/validators.py
+++ b/flowspec/validators.py
@@ -4,7 +4,7 @@ from django.conf import settings
 from django.core.mail import send_mail
 from django.utils.translation import ugettext as _
 from peers.models import PeerRange, Peer
-from flowspec.models import Route
+from flowspec.models import Route, Rule
 from django.core.urlresolvers import reverse
 
 
@@ -149,5 +149,5 @@ def check_if_rule_exists(fields):
         destination=IPNetwork(fields.get('destination')).compressed,
     )
     for route in routes:
-        return _('Rule exists with id %s and status %s. Please edit it.' % (route.id, route.status))
+        return _('Rule exists with id {id} and status {status}. Please edit it.'.format(id=route.id, status=route.status))
     return False
diff --git a/flowspec/viewsets.py b/flowspec/viewsets.py
index ee6f9ea17eaaae7e6fd23d2b9cf22145e8d0eeda..4b16a915b0841fe1e5e5855d22f570d92569ee7d 100644
--- a/flowspec/viewsets.py
+++ b/flowspec/viewsets.py
@@ -1,19 +1,26 @@
 from django.shortcuts import get_object_or_404
 from django.conf import settings
+from django.http import HttpResponse
 from rest_framework.exceptions import PermissionDenied
+import json
 
 from rest_framework import viewsets
 from flowspec.models import (
     Route,
+    Rule,
+    User,
     MatchPort,
     ThenAction,
     FragmentType,
     MatchProtocol
 )
+from peers.models import PeerRange
 
 from flowspec.serializers import (
+    RuleSerializer,
     RouteSerializer,
     PortSerializer,
+    PeerSerializer,
     ThenActionSerializer,
     FragmentTypeSerializer,
     MatchProtocolSerializer,
@@ -21,6 +28,71 @@ from flowspec.serializers import (
 
 from rest_framework.response import Response
 
+class PeerViewSet(viewsets.ViewSet):
+    queryset = User.objects.all()
+    def get_queryset(self):
+        if self.request.user.is_authenticated: # and not self.request.user.is_anonymous:
+	    pr = PeerRange.objects.filter(peer__user_profile__peers=self.request.user)
+            return [str(net) for net in pr]
+	else:
+	    raise PermissionDenied('User is not Authenticated')
+
+    def list(self, request):
+        return HttpResponse(json.dumps({"networks": self.get_queryset()}), content_type="application/json")
+
+class RuleViewSet(viewsets.ModelViewSet):
+    queryset = Rule.objects.all()
+    serializer_class = RuleSerializer
+
+    def get_queryset(self):
+        if settings.DEBUG:
+            if self.request.user.is_anonymous():
+                return Rule.objects.all()
+            elif self.request.user.is_authenticated():
+                return Rule.objects.filter(applier=self.request.user)
+            else:
+                raise PermissionDenied('User is not Authenticated')
+
+        if self.request.user.is_superuser:
+            return Rule.objects.all()
+        elif self.request.user.is_authenticated and not self.request.user.is_anonymous:
+            return Rule.objects.filter(applier=self.request.user)
+
+    def list(self, request):
+        serializer = RuleSerializer(self.get_queryset(), many=True, context={'request': request})
+        return Response(serializer.data)
+
+    def create(self, request):
+        serializer = RuleSerializer(context={'request': request})
+        return super(RuleViewSet, self).create(request)
+
+    def retrieve(self, request, pk=None):
+        rule = get_object_or_404(self.get_queryset(), pk=pk)
+        serializer = RuleSerializer(rule)
+        return Response(serializer.data)
+
+    def pre_save(self, obj):
+        # DEBUG
+        if settings.DEBUG:
+            if self.request.user.is_anonymous():
+                from django.contrib.auth.models import User
+                obj.applier = User.objects.all()[0]
+            elif self.request.user.is_authenticated():
+                obj.applier = self.request.user
+            else:
+                raise PermissionDenied('User is not Authenticated')
+        else:
+            obj.applier = self.request.user
+
+    def post_save(self, obj, created):
+        if created:
+            obj.commit_add()
+        else:
+            if obj.status not in ['EXPIRED', 'INACTIVE', 'ADMININACTIVE']:
+                obj.commit_edit()
+
+    def pre_delete(self, obj):
+        obj.commit_delete()
 
 class RouteViewSet(viewsets.ModelViewSet):
     queryset = Route.objects.all()
@@ -31,7 +103,7 @@ class RouteViewSet(viewsets.ModelViewSet):
             if self.request.user.is_anonymous():
                 return Route.objects.all()
             elif self.request.user.is_authenticated():
-                return Route.objects.filter(applier=self.request.user)
+                return Route.objects.filter(rule__applier=self.request.user)
             else:
                 raise PermissionDenied('User is not Authenticated')
 
@@ -66,15 +138,15 @@ class RouteViewSet(viewsets.ModelViewSet):
         else:
             obj.applier = self.request.user
 
-    def post_save(self, obj, created):
-        if created:
-            obj.commit_add()
-        else:
-            if obj.status not in ['EXPIRED', 'INACTIVE', 'ADMININACTIVE']:
-                obj.commit_edit()
+    #def post_save(self, obj, created):
+    #    if created:
+    #        obj.commit_add()
+    #    else:
+    #        if obj.status not in ['EXPIRED', 'INACTIVE', 'ADMININACTIVE']:
+    #            obj.commit_edit()
 
-    def pre_delete(self, obj):
-        obj.commit_delete()
+    #def pre_delete(self, obj):
+    #    obj.commit_delete()
 
 
 class PortViewSet(viewsets.ModelViewSet):
diff --git a/flowspy/urls.py.dist b/flowspy/urls.py.dist
index 5e69d9e514baccfe2e46375a974f8ef92259ded3..adfa4820731608eabada615214996a96477ec405 100644
--- a/flowspy/urls.py.dist
+++ b/flowspy/urls.py.dist
@@ -4,8 +4,10 @@ from django.contrib import admin
 from rest_framework import routers
 from graphs import urls as graphs_urls
 from flowspec.viewsets import (
+    RuleViewSet,
     RouteViewSet,
     PortViewSet,
+    PeerViewSet,
     ThenActionViewSet,
     FragmentTypeViewSet,
     MatchProtocolViewSet,
@@ -15,8 +17,10 @@ admin.autodiscover()
 
 # Routers provide an easy way of automatically determining the URL conf.
 router = routers.DefaultRouter()
+router.register(r'rules', RuleViewSet, base_name='rule')
 router.register(r'routes', RouteViewSet, base_name='route')
 router.register(r'ports', PortViewSet)
+router.register(r'peers', PeerViewSet)
 router.register(r'thenactions', ThenActionViewSet)
 router.register(r'fragmentypes', FragmentTypeViewSet)
 router.register(r'matchprotocol', MatchProtocolViewSet)
diff --git a/templates/rule_action.txt b/templates/rule_action.txt
index e88b2d5dece2e4a3857678e16249e4b24487ca76..56b4508f1d8e411ea07b7cc863004d8bf626af5b 100644
--- a/templates/rule_action.txt
+++ b/templates/rule_action.txt
@@ -1,10 +1,11 @@
-{% load tofqdn %}{% ifequal action 'expires' %}Rule {{route.name}} expires {% ifequal expiration_days 0 %}today{% else%}in {{expiration_days}} day{{ expiration_days|pluralize }}{% endifequal %}{% else %}A new rule {{action}} job has spawned
+{% load tofqdn %}{% ifequal action 'expires' %}Rule {{rule.name}} expires {% ifequal expiration_days 0 %}today{% else%}in {{expiration_days}} day{{ expiration_days|pluralize }}{% endifequal %}{% else %}A new rule {{action}} job has spawned
 
 Peer: {{peer.peer_name}}
 User {{route.applier.username}} requested the {{action}} of the following rule from address {{address}} {% if address|tofqdn %}({{address|tofqdn}}){% endif %}:
 
-Rule name: {{route.name}}{% endifequal %}
+Rule name: {{rule.name}}{% endifequal %}
 
+{% for route in routes %}
 Match Statements:
 * Source Address: {{route.source}}
 * Destination Address: {{route.destination}}
@@ -14,13 +15,15 @@ Match Statements:
 * Destination Ports: {% if route.port %}same as ports{% else %}{% if route.destinationport %}{{ route.destinationport }}{% else %}any{% endif %}{% endif %}
 * Fragment Types: {% if route.fragmenttype.all %}{% for fragment in route.fragmenttype.all %}{{ fragment }}{% if not forloop.last %}, {% endif %}{% endfor %}{% else %}-{% endif %}
 
+{% endfor %}
+
 
 Then Actions:
-* Action:{% for then in route.then.all %}{{ then }}{% if not forloop.last %}, {% endif %}{% endfor %}
+* Action:{% for then in rule.then.all %}{{ then }}{% if not forloop.last %}, {% endif %}{% endfor %}
 
-Comments: {% if route.comments %}{{route.comments}}{% else %}-{% endif %}
+Comments: {% if rule.comments %}{{rule.comments}}{% else %}-{% endif %}
 
-Expires: {% ifequal action 'removal' %}Now, removal requested{%else%}{{route.expires}}{% endifequal %}
+Expires: {% ifequal action 'removal' %}Now, removal requested{%else%}{{rule.expires}}{% endifequal %}
 
 Rule url: {{url}}