diff options
-rw-r--r-- | rpkid/portal-gui/scripts/rpkigui-rcynic.py | 43 | ||||
-rw-r--r-- | rpkid/rpki/gui/app/views.py | 5 | ||||
-rw-r--r-- | rpkid/rpki/gui/cacheview/admin.py | 12 | ||||
-rw-r--r-- | rpkid/rpki/gui/cacheview/models.py | 111 | ||||
-rw-r--r-- | rpkid/rpki/gui/models.py | 13 | ||||
-rw-r--r-- | rpkid/rpki/gui/routeview/models.py | 8 |
6 files changed, 86 insertions, 106 deletions
diff --git a/rpkid/portal-gui/scripts/rpkigui-rcynic.py b/rpkid/portal-gui/scripts/rpkigui-rcynic.py index abf56ca1..41557962 100644 --- a/rpkid/portal-gui/scripts/rpkigui-rcynic.py +++ b/rpkid/portal-gui/scripts/rpkigui-rcynic.py @@ -18,15 +18,16 @@ default_logfile = '/var/rcynic/data/summary.xml' default_root = '/var/rcynic/data' import time, vobject -from rpki.gui.cacheview import models + +from django.db import transaction +import django.db.models + from rpki.rcynic import rcynic_xml_iterator, label_iterator from rpki.sundial import datetime import rpki -from django.db import transaction -import django.db.models +from rpki.gui.cacheview import models debug = False -fam_map = { 'roa_prefix_set_ipv6': 6, 'roa_prefix_set_ipv4': 4 } class rcynic_object(object): @@ -99,10 +100,6 @@ class rcynic_object(object): return True -# munge IPv6 addresses -def munge(family, value): - return value if family == 4 else (value >> 65) & 0x7fffffffffffffffL - class rcynic_cert(rcynic_object): model_class = models.Cert @@ -129,18 +126,17 @@ class rcynic_cert(rcynic_object): else: obj.asns.add(q[0]) - for family, addrset in (4, cert.resources.v4), (6, cert.resources.v6): + for cls, addr_obj, addrset in (models.AddressRange, obj.addresses, cert.resources.v4), (models.AddressRangeV6, obj.addresses_v6, cert.resources.v6): for rng in addrset: if debug: sys.stderr.write('processing %s\n' % rng) - attrs = { 'family': family, 'min': munge(family, rng.min), - 'max': munge(family, rng.max) } - q = models.AddressRange.objects.filter(**attrs) + attrs = { 'prefix_min': rng.min, 'prefix_max': rng.max } + q = cls.objects.filter(**attrs) if not q: - obj.addresses.create(**attrs) + addr_obj.create(**attrs) else: - obj.addresses.add(q[0]) + addr_obj.add(q[0]) if debug: print 'finished processing rescert at %s' % cert.uri @@ -153,17 +149,22 @@ class rcynic_roa(rcynic_object): obj.save() obj.prefixes.clear() for pfxset in roa.prefix_sets: - family = fam_map[pfxset.__class__.__name__] + if pfxset.__class__.__name__ == 'roa_prefix_set_ipv6': + roa_cls = models.ROAPrefixV6 + prefix_obj = obj.prefixes_v6 + else: + roa_cls = models.ROAPrefixV4 + prefix_obj = obj.prefixes + for pfx in pfxset: - attrs = { 'family' : family, - 'prefix_min': munge(family, pfx.min()), - 'prefix_max': munge(family, pfx.max()), + attrs = { 'prefix_min': pfx.min(), + 'prefix_max': pfx.max(), 'max_length': pfx.max_prefixlen } - q = models.ROAPrefix.objects.filter(**attrs) + q = roa_cls.objects.filter(**attrs) if not q: - obj.prefixes.create(**attrs) + prefix_obj.create(**attrs) else: - obj.prefixes.add(q[0]) + prefix_obj.add(q[0]) class rcynic_gbr(rcynic_object): model_class = models.Ghostbuster diff --git a/rpkid/rpki/gui/app/views.py b/rpkid/rpki/gui/app/views.py index b96cbff2..82721266 100644 --- a/rpkid/rpki/gui/app/views.py +++ b/rpkid/rpki/gui/app/views.py @@ -927,9 +927,8 @@ def route_view(request): # see draft-sidr-roa-validation-10 # 1. fetch all covering ROAs - # FIXME: need to munge IPv6 address prior to this query! - roas = rpki.gui.cacheview.models.ROAPrefix.objects.filter(prefix_min__lte=obj.prefix_min, - prefix_max__gte=obj.prefix_max, family=obj.family) + roas = rpki.gui.cacheview.models.ROAPrefixV4.objects.filter(prefix_min__lte=obj.prefix_min, + prefix_max__gte=obj.prefix_max) # 2. if there are candidate set is empty, end with invalid if not roas.exists(): obj.status = 'unknown' diff --git a/rpkid/rpki/gui/cacheview/admin.py b/rpkid/rpki/gui/cacheview/admin.py index 05bab881..74b62961 100644 --- a/rpkid/rpki/gui/cacheview/admin.py +++ b/rpkid/rpki/gui/cacheview/admin.py @@ -25,10 +25,16 @@ class ASRangeAdmin(admin.ModelAdmin): class AddressRangeAdmin(admin.ModelAdmin): pass +class AddressRangeV6Admin(admin.ModelAdmin): + pass + class CertAdmin(admin.ModelAdmin): pass -class ROAPrefixAdmin(admin.ModelAdmin): +class ROAPrefixV4Admin(admin.ModelAdmin): + pass + +class ROAPrefixV6Admin(admin.ModelAdmin): pass class ROAAdmin(admin.ModelAdmin): @@ -46,11 +52,13 @@ class ValidationStatus_ROAAdmin(admin.ModelAdmin): pass class ValidationStatus_GhostbusterAdmin(admin.ModelAdmin): pass admin.site.register(models.AddressRange, AddressRangeAdmin) +admin.site.register(models.AddressRangeV6, AddressRangeV6Admin) admin.site.register(models.ASRange, AddressRangeAdmin) admin.site.register(models.Cert, CertAdmin) admin.site.register(models.Ghostbuster, GhostbusterAdmin) admin.site.register(models.ROA, ROAAdmin) -admin.site.register(models.ROAPrefix, ROAPrefixAdmin) +admin.site.register(models.ROAPrefixV4, ROAPrefixV4Admin) +admin.site.register(models.ROAPrefixV6, ROAPrefixV6Admin) admin.site.register(models.ValidationLabel, ValidationLabelAdmin) admin.site.register(models.ValidationStatus_Cert, ValidationStatus_CertAdmin) admin.site.register(models.ValidationStatus_ROA, ValidationStatus_ROAAdmin) diff --git a/rpkid/rpki/gui/cacheview/models.py b/rpkid/rpki/gui/cacheview/models.py index dfeb4e0b..598d7f1d 100644 --- a/rpkid/rpki/gui/cacheview/models.py +++ b/rpkid/rpki/gui/cacheview/models.py @@ -21,48 +21,24 @@ from django.db import models import rpki.ipaddrs import rpki.resource_set +import rpki.gui.models class TelephoneField(models.CharField): def __init__(self, *args, **kwargs): kwargs['max_length'] = 255 models.CharField.__init__(self, *args, **kwargs) -class AddressRange(models.Model): - """Represents an IP address range. - - The db backend doesn't support unsigned 64-bit integer, so store - the /63 in the database, and have the display function regenerate - the full value. since nothing larger than a /48 should be - announced globally, it should be ok to pad the lower 65 bits of - `max` with 1s. """ - - family = models.PositiveSmallIntegerField(null=False) - min = models.BigIntegerField(null=False) - max = models.BigIntegerField(null=False) - - def get_min_display(self): - "Return the min address value as an rpki.ipaddr object." - return rpki.ipaddrs.v4addr(self.min) if self.family == 4 else rpki.ipaddrs.v6addr(self.min << 65) - - def get_max_display(self): - "Return the max address value as an rpki.ipaddr object." - # FIXME this may fail for an IPv6 /64 single block, since we - # don't store the lower 65 bits in the database - return rpki.ipaddrs.v4addr(self.max) if self.family == 4 else rpki.ipaddrs.v6addr((self.max << 65) | 0x1ffffffffffffffffL) - - class Meta: - ordering = ('family', 'min', 'max') +class AddressRange(rpki.gui.models.PrefixV4): @models.permalink def get_absolute_url(self): return ('rpki.gui.cacheview.views.addressrange_detail', [str(self.pk)]) - def as_resource_range(self): - cls = rpki.resource_set.resource_range_ipv4 if self.family == 4 else rpki.resource_set.resource_range_ipv6 - return cls(self.get_min_display(), self.get_max_display()) +class AddressRangeV6(rpki.gui.models.PrefixV6): - def __unicode__(self): - return u'%s' % self.as_resource_range() + @models.permalink + def get_absolute_url(self): + return ('rpki.gui.cacheview.views.addressrange_detail_v6', [str(self.pk)]) class ASRange(models.Model): min = models.PositiveIntegerField(null=False) @@ -89,16 +65,13 @@ class ValidationLabel(models.Model): Represents a specific error condition defined in the rcynic XML output file. """ - label = models.CharField(max_length=79, db_index=True, unique=True) + label = models.CharField(max_length=79, db_index=True, unique=True, null=False) status = models.CharField(max_length=255, null=False) kind = models.PositiveSmallIntegerField(choices=kinds, null=False) def __unicode__(self): return self.label - class Meta: - verbose_name_plural = 'ValidationLabels' - generations = list(enumerate(('current', 'backup'))) generations_dict = dict((val, key) for (key, val) in generations) @@ -167,6 +140,7 @@ class Cert(SignedObject): Object representing a resource certificate. """ addresses = models.ManyToManyField(AddressRange, related_name='certs') + addresses_v6 = models.ManyToManyField(AddressRangeV6, related_name='certs') asns = models.ManyToManyField(ASRange, related_name='certs') issuer = models.ForeignKey('Cert', related_name='children', null=True, blank=True) sia = models.CharField(max_length=255, null=False) @@ -180,61 +154,46 @@ class ValidationStatus_Cert(ValidationStatus): null=False) class ROAPrefix(models.Model): - """One prefix in a ROA. - - See comment above in AddressRange about how IPv6 addresses are - stored. + "Abstract base class for ROA mixin." - The prefix is broken out into min and max values rather than min/bits in - order to allow for searches using sql. """ - - family = models.PositiveSmallIntegerField(null=False) - prefix_min = models.BigIntegerField(null=False, db_index=True) - prefix_max = models.BigIntegerField(null=False, db_index=True) max_length = models.PositiveSmallIntegerField(null=False) class Meta: - ordering = ('prefix_min', 'prefix_max', 'max_length') - verbose_name_plural = 'ROAPrefixes' - - def min(self): - "Return the min prefix value as an rpki.ipaddrs.v?addr object." - if self.family == 4: - return rpki.ipaddrs.v4addr(self.prefix_min) - return rpki.ipaddrs.v6addr(self.prefix_min << 65) - - def max(self): - "Return the max prefix value as an rpki.ipaddrs.v?addr object." - if self.family == 4: - return rpki.ipaddrs.v4addr(self.prefix_max) - return rpki.ipaddrs.v6addr((self.prefix_max << 65) | 0x1ffffffffffffffffL) - - def get_prefix_min_display(self): - return str(self.min()) - - def get_prefix_max_display(self): - return str(self.max()) - - def as_resource_range(self): - "Return the prefix as a rpki.resource_set.resource_range_ip object." - if self.family == 4: - return rpki.resource_set.resource_range_ipv4(self.min(), self.max()) - else: - return rpki.resource_set.resource_range_ipv6((self.min() << 65), - (self.max() << 65) | 0x1ffffffffffffffffL) + abstract = True def as_roa_prefix(self): "Return value as a rpki.resource_set.roa_prefix_ip object." rng = self.as_resource_range() - cls = rpki.resource_set.roa_prefix_ipv4 if self.family == 4 else rpki.resource_set.roa_prefix_ipv6 - return cls(rng.min, rng.prefixlen(), self.max_length) + return self.roa_cls(rng.prefix_min, rng.prefixlen(), self.max_length) def __unicode__(self): - return u'%s' % str(self.as_roa_prefix()) + p = self.as_resource_range() + if p.prefixlen() == self.max_length: + return str(p) + return '%s-%s' % (str(p), self.max_length) + +# ROAPrefix is declared first, so subclass picks up __unicode__ from it. +class ROAPrefixV4(ROAPrefix, rpki.gui.models.PrefixV4): + "One v4 prefix in a ROA." + + roa_cls = rpki.resource_set.roa_prefix_ipv4 + + class Meta: + ordering = ('prefix_min',) + +# ROAPrefix is declared first, so subclass picks up __unicode__ from it. +class ROAPrefixV6(ROAPrefix, rpki.gui.models.PrefixV6): + "One v6 prefix in a ROA." + + roa_cls = rpki.resource_set.roa_prefix_ipv6 + + class Meta: + ordering = ('prefix_min',) class ROA(SignedObject): asid = models.PositiveIntegerField(null=False) - prefixes = models.ManyToManyField(ROAPrefix, related_name='roas') + prefixes = models.ManyToManyField(ROAPrefixV4, related_name='roas') + prefixes_v6 = models.ManyToManyField(ROAPrefixV6, related_name='roas') issuer = models.ForeignKey('Cert', related_name='roas', null=False) @models.permalink diff --git a/rpkid/rpki/gui/models.py b/rpkid/rpki/gui/models.py index 323d43e6..933fe5ee 100644 --- a/rpkid/rpki/gui/models.py +++ b/rpkid/rpki/gui/models.py @@ -54,12 +54,17 @@ class Prefix(models.Model): def prefixlen(self): "Returns the prefix length for the prefix in this object." - return self.as_range().prefixlen() + return self.as_resource_range().prefixlen() def get_prefix_display(self): - "Returns a string version of the prefix in this object." + "Return a string representatation of this IP prefix." return str(self.as_resource_range()) + def __unicode__(self): + """This method may be overridden by subclasses. The default + implementation calls get_prefix_display(). """ + return self.get_prefix_display() + class Meta: abstract = True @@ -74,7 +79,7 @@ class PrefixV4(Prefix): prefix_min = IPv4AddressField(db_index=True, null=False) prefix_max = IPv4AddressField(db_index=True, null=False) - class Meta: + class Meta(Prefix.Meta): abstract = True class PrefixV6(Prefix): @@ -85,7 +90,7 @@ class PrefixV6(Prefix): prefix_min = IPv6AddressField(db_index=True, null=False) prefix_max = IPv6AddressField(db_index=True, null=False) - class Meta: + class Meta(Prefix.Meta): abstract = True # vim:sw=4 ts=8 expandtab diff --git a/rpkid/rpki/gui/routeview/models.py b/rpkid/rpki/gui/routeview/models.py index 99dd0297..912ae929 100644 --- a/rpkid/rpki/gui/routeview/models.py +++ b/rpkid/rpki/gui/routeview/models.py @@ -9,4 +9,12 @@ class RouteOrigin(rpki.gui.models.PrefixV4): def __unicode__(self): return u"AS%d's route origin for %s" % (self.asn, self.get_prefix_display()) +class RouteOriginV6(rpki.gui.models.PrefixV6): + "Represents a BGP routing table entry." + + asn = django.db.models.PositiveIntegerField(help_text='origin AS', null=False) + + def __unicode__(self): + return u"AS%d's route origin for %s" % (self.asn, self.get_prefix_display()) + # vim:sw=4 ts=8 expandtab |