aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki/gui/routeview
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2014-04-05 22:42:12 +0000
committerRob Austein <sra@hactrn.net>2014-04-05 22:42:12 +0000
commitfe0bf509f528dbdc50c7182f81057c6a4e15e4bd (patch)
tree07c9a923d4a0ccdfea11c49cd284f6d5757c5eda /rpkid/rpki/gui/routeview
parentaa28ef54c271fbe4d52860ff8cf13cab19e2207c (diff)
Source tree reorg, phase 1. Almost everything moved, no file contents changed.
svn path=/branches/tk685/; revision=5757
Diffstat (limited to 'rpkid/rpki/gui/routeview')
-rw-r--r--rpkid/rpki/gui/routeview/__init__.py0
-rw-r--r--rpkid/rpki/gui/routeview/api.py69
-rw-r--r--rpkid/rpki/gui/routeview/models.py81
-rw-r--r--rpkid/rpki/gui/routeview/util.py236
4 files changed, 0 insertions, 386 deletions
diff --git a/rpkid/rpki/gui/routeview/__init__.py b/rpkid/rpki/gui/routeview/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/rpkid/rpki/gui/routeview/__init__.py
+++ /dev/null
diff --git a/rpkid/rpki/gui/routeview/api.py b/rpkid/rpki/gui/routeview/api.py
deleted file mode 100644
index cf699c9a..00000000
--- a/rpkid/rpki/gui/routeview/api.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (C) 2012 SPARTA, Inc. a Parsons Company
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-# PERFORMANCE OF THIS SOFTWARE.
-
-__version__ = '$Id$'
-
-import json
-from django import http
-from rpki.gui.routeview.models import RouteOrigin, RouteOriginV6
-from rpki import resource_set
-import rpki.exceptions
-
-def route_list(request):
- """Implements the REST query against the route models to allow the client
- to search for routes.
-
- The only search currently supported is returning all the routes covered by
- the prefix given in the 'prefix__in=' query string parameter.
-
- By default, only returns up to 10 matching routes, but the client may
- request a different limit with the 'count=' query string parameter.
-
- """
- hard_limit = 100
-
- if request.method == 'GET' and 'prefix__in' in request.GET:
- # find all routers covered by this prefix
- match_prefix = request.GET.get('prefix__in')
- # max number of items to return
- limit = request.GET.get('count', 10)
- if limit < 1 or limit > hard_limit:
- return http.HttpResponseBadRequest('invalid value for count parameter')
-
- try:
- if ':' in match_prefix:
- # v6
- pfx = resource_set.resource_range_ipv6.parse_str(match_prefix)
- manager = RouteOriginV6
- else:
- # v4
- pfx = resource_set.resource_range_ipv4.parse_str(match_prefix)
- manager = RouteOrigin
- except (AssertionError, rpki.exceptions.BadIPResource), e:
- return http.HttpResponseBadRequest(e)
-
- try:
- qs = manager.objects.filter(prefix_min__gte=pfx.min,
- prefix_max__lte=pfx.max)[:limit]
- # FIXME - a REST API should really return the url of the resource,
- # but since we are combining two separate tables, the .pk is not a
- # unique identifier.
- matches = [{'prefix': str(x.as_resource_range()), 'asn': x.asn} for x in qs]
- except IndexError:
- # no matches
- matches = []
-
- return http.HttpResponse(json.dumps(matches), content_type='text/javascript')
-
- return http.HttpResponseBadRequest()
diff --git a/rpkid/rpki/gui/routeview/models.py b/rpkid/rpki/gui/routeview/models.py
deleted file mode 100644
index 052860c4..00000000
--- a/rpkid/rpki/gui/routeview/models.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (C) 2010, 2011 SPARTA, Inc. dba Cobham Analytic Solutions
-# Copyright (C) 2012 SPARTA, Inc. a Parsons Company
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-# PERFORMANCE OF THIS SOFTWARE.
-
-__version__ = '$Id$'
-
-from django.db.models import PositiveIntegerField, permalink
-import rpki.gui.models
-
-
-class RouteOrigin(rpki.gui.models.PrefixV4):
- "Represents an IPv4 BGP routing table entry."
-
- asn = 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())
-
- @property
- def roas(self):
- "Return a queryset of ROAs which cover this route."
- return rpki.gui.cacheview.models.ROA.objects.filter(
- prefixes__prefix_min__lte=self.prefix_min,
- prefixes__prefix_max__gte=self.prefix_max
- )
-
- @property
- def roa_prefixes(self):
- "Return a queryset of ROA prefixes which cover this route."
- return rpki.gui.cacheview.models.ROAPrefixV4.objects.filter(
- prefix_min__lte=self.prefix_min,
- prefix_max__gte=self.prefix_max
- )
-
- @property
- def status(self):
- "Returns the validation status of this route origin object."
- roas = self.roas
- # subselect exact match
- if self.asn != 0 and roas.filter(asid=self.asn, prefixes__max_length__gte=self.prefixlen).exists():
- return 'valid'
- elif roas.exists():
- return 'invalid'
- return 'unknown'
-
- @permalink
- def get_absolute_url(self):
- return ('rpki.gui.app.views.route_detail', [str(self.pk)])
-
- class Meta:
- # sort by increasing mask length (/16 before /24)
- ordering = ('prefix_min', '-prefix_max')
-
-
-class RouteOriginV6(rpki.gui.models.PrefixV6):
- "Represents an IPv6 BGP routing table entry."
-
- asn = 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())
-
- class Meta:
- ordering = ('prefix_min', '-prefix_max')
-
-
-# this goes at the end of the file to avoid problems with circular imports
-import rpki.gui.cacheview.models
diff --git a/rpkid/rpki/gui/routeview/util.py b/rpkid/rpki/gui/routeview/util.py
deleted file mode 100644
index 7884224c..00000000
--- a/rpkid/rpki/gui/routeview/util.py
+++ /dev/null
@@ -1,236 +0,0 @@
-# Copyright (C) 2012, 2013 SPARTA, Inc. a Parsons Company
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH
-# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-# AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT,
-# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-# PERFORMANCE OF THIS SOFTWARE.
-
-__version__ = '$Id$'
-__all__ = ('import_routeviews_dump')
-
-import itertools
-import _mysql_exceptions
-import os.path
-import subprocess
-import time
-import logging
-import urlparse
-from urllib import urlretrieve, unquote
-
-from django.db import transaction, connection
-
-from rpki.resource_set import resource_range_ipv4, resource_range_ipv6
-from rpki.exceptions import BadIPResource
-import rpki.gui.app.timestamp
-
-# globals
-logger = logging.getLogger(__name__)
-
-# Eventually this can be retrived from rpki.conf
-DEFAULT_URL = 'http://archive.routeviews.org/oix-route-views/oix-full-snapshot-latest.dat.bz2'
-
-def parse_text(f):
- last_prefix = None
- cursor = connection.cursor()
- range_class = resource_range_ipv4
- table = 'routeview_routeorigin'
- sql = "INSERT INTO %s_new SET asn=%%s, prefix_min=%%s, prefix_max=%%s" % table
-
- try:
- logger.info('Dropping existing staging table...')
- cursor.execute('DROP TABLE IF EXISTS %s_new' % table)
- except _mysql_exceptions.Warning:
- pass
-
- logger.info('Creating staging table...')
- cursor.execute('CREATE TABLE %(table)s_new LIKE %(table)s' % {'table': table})
-
- logger.info('Disabling autocommit...')
- cursor.execute('SET autocommit=0')
-
- logger.info('Adding rows to table...')
- for row in itertools.islice(f, 5, None):
- cols = row.split()
-
- # index -1 is i/e/? for igp/egp
- origin_as = cols[-2]
- # FIXME: skip AS_SETs
- if origin_as[0] == '{':
- continue
-
- prefix = cols[1]
-
- # validate the prefix since the "sh ip bgp" output is sometimes
- # corrupt by no space between the prefix and the next hop IP
- # address.
- net, bits = prefix.split('/')
- if len(bits) > 2:
- s = ['mask for %s looks fishy...' % prefix]
- prefix = '%s/%s' % (net, bits[0:2])
- s.append('assuming it should be %s' % prefix)
- logger.warning(' '.join(s))
-
- # the output may contain multiple paths to the same origin.
- # if this is the same prefix as the last entry, we don't need
- # to validate it again.
- #
- # prefixes are sorted, but the origin_as is not, so we keep a set to
- # avoid duplicates, and insert into the db once we've seen all the
- # origin_as values for a given prefix
- if prefix != last_prefix:
- # output routes for previous prefix
- if last_prefix is not None:
- try:
- rng = range_class.parse_str(last_prefix)
- rmin = long(rng.min)
- rmax = long(rng.max)
- cursor.executemany(sql, [(asn, rmin, rmax) for asn in asns])
- except BadIPResource:
- logger.warning('skipping bad prefix: ' + last_prefix)
-
- asns = set()
- last_prefix = prefix
-
- try:
- asns.add(int(origin_as))
- except ValueError as err:
- logger.warning('\n'.join(
- ['unable to parse origin AS: ' + origin_as],
- ['ValueError: ' + str(err)]
- ['route entry was: ' + row],
- ))
-
- logger.info('Committing...')
- cursor.execute('COMMIT')
-
- try:
- logger.info('Dropping old table...')
- cursor.execute('DROP TABLE IF EXISTS %s_old' % table)
- except _mysql_exceptions.Warning:
- pass
-
- logger.info('Swapping staging table with live table...')
- cursor.execute('RENAME TABLE %(table)s TO %(table)s_old, %(table)s_new TO %(table)s' % {'table': table})
-
- transaction.commit_unless_managed()
-
- logger.info('Updating timestamp metadata...')
- rpki.gui.app.timestamp.update('bgp_v4_import')
-
-
-def parse_mrt(f):
- # filter input through bgpdump
- pipe = subprocess.Popen(['bgpdump', '-m', '-v', '-'], stdin=f,
- stdout=subprocess.PIPE)
-
- last_prefix = None
- last_as = None
- for e in pipe.stdout.readlines():
- a = e.split('|')
- prefix = a[5]
- try:
- origin_as = int(a[6].split()[-1])
- except ValueError:
- # skip AS_SETs
- continue
-
- if prefix != last_prefix:
- last_prefix = prefix
- elif last_as == origin_as:
- continue
- last_as = origin_as
-
- asns = PREFIXES.get(prefix)
- if not asns:
- asns = set()
- PREFIXES[prefix] = asns
- asns.add(origin_as)
-
- pipe.wait()
- if pipe.returncode:
- raise ProgException('bgpdump exited with code %d' % pipe.returncode)
-
-
-class ProgException(Exception):
- pass
-
-
-class UnknownInputType(ProgException):
- pass
-
-
-class PipeFailed(ProgException):
- pass
-
-
-def import_routeviews_dump(filename=DEFAULT_URL, filetype='auto'):
- """Load the oix-full-snapshot-latest.bz2 from routeview.org into the
- rpki.gui.routeview database.
-
- Arguments:
-
- filename [optional]: the full path to the downloaded file to parse
-
- filetype [optional]: 'text' or 'mrt'
-
- """
- start_time = time.time()
-
- if filename.startswith('http://'):
- #get filename from the basename of the URL
- u = urlparse.urlparse(filename)
- bname = os.path.basename(unquote(u.path))
- tmpname = os.path.join('/tmp', bname)
-
- logger.info("Downloading %s to %s" % (filename, tmpname))
- if os.path.exists(tmpname):
- os.remove(tmpname)
- # filename is replaced with a local filename containing cached copy of
- # URL
- filename, headers = urlretrieve(filename, tmpname)
-
- if filetype == 'auto':
- # try to determine input type from filename, based on the default
- # filenames from archive.routeviews.org
- bname = os.path.basename(filename)
- if bname.startswith('oix-full-snapshot-latest'):
- filetype = 'text'
- elif bname.startswith('rib.'):
- filetype = 'mrt'
- else:
- raise UnknownInputType('unable to automatically determine input file type')
- logging.info('Detected import format as "%s"' % filetype)
-
- pipe = None
- if filename.endswith('.bz2'):
- bunzip = 'bunzip2'
- logging.info('Decompressing input file on the fly...')
- pipe = subprocess.Popen([bunzip, '--stdout', filename],
- stdout=subprocess.PIPE)
- input_file = pipe.stdout
- else:
- input_file = open(filename)
-
- try:
- dispatch = {'text': parse_text, 'mrt': parse_mrt}
- dispatch[filetype](input_file)
- except KeyError:
- raise UnknownInputType('"%s" is an unknown input file type' % filetype)
-
- if pipe:
- logging.debug('Waiting for child to exit...')
- pipe.wait()
- if pipe.returncode:
- raise PipeFailed('Child exited code %d' % pipe.returncode)
- pipe = None
- else:
- input_file.close()
-
- logger.info('Elapsed time %d secs' % (time.time() - start_time))