add support for prefix generation

This commit is contained in:
Nico Schottelius 2020-12-05 15:05:12 +01:00
commit 3a2d1481f2
7 changed files with 90 additions and 9 deletions

View file

@ -12,3 +12,8 @@ class ULAForm(forms.ModelForm):
validate_ula_prefix(prefix)
return prefix
class ULAGenerateForm(forms.ModelForm):
class Meta:
model = ULA
fields = [ 'name', 'organization', 'website' ]

View file

@ -22,7 +22,10 @@
<div class="collapse navbar-collapse"
id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item"> <a class="nav-link" href="/submit">Submit prefix</a></li>
<li class="nav-item"> <a class="nav-link"
href="/generate">Generate new prefix</a></li>
<li class="nav-item"> <a class="nav-link"
href="/submit">Submit existing prefix</a></li>
{% if user.is_authenticated %}
<span class="navbar-text">Logged in as {{ user }}.</span>

View file

@ -5,16 +5,31 @@
<div class="container">
<div class="row">
<div class="col">
<h1>
{% if method == 'submit' %}
<h1>Submitting existing prefix</h1>
<p>
You submit an existing prefix. Please follow the
<a href="https://tools.ietf.org/html/rfc4193">RFC4193</a>
rules for generation (basically: use a random network, do not
pick "cool numbers" as they will clash with somebody else in
the future).
</p>
{% elif method == 'generate' %}
<h1>Generate new prefix</h1>
<p>
A new random prefix will be generated for you.
</p>
{% endif %}
<p>
All ULA prefixes are /48 networks. Simply add the first IP address
(without any netmask, for instance fd23:2323:2323::).
You can choose the name of your liking and an optional
organization name.
You can choose the name of your liking and an organization name.
</p>
<p>
ULA prefixes must be part of the fd00::/8 network.
ULA prefixes are always subnets of the fd00::/8 network.
</p>
</div>

View file

@ -34,7 +34,15 @@
<a href="https://account.ungleich.ch">ungleich account</a>.
</p>
</div>
{% if messages %}
<div class="row">
{% for message in messages %}
<div class="alert alert-primary" role="alert">
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}
<div class="row">
<table class="table table-striped">
<thead>

View file

@ -23,6 +23,7 @@ from ipv6ula import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('submit/', views.SubmitView.as_view(), name='submit'),
path('generate/', views.GenerateView.as_view(), name='generate'),
path('login/', views.LoginView.as_view(), name='login'),
path('logout/', views.logout_view, name='logout'),
path('admin/', admin.site.urls),

24
ipv6ula/utils.py Normal file
View file

@ -0,0 +1,24 @@
import ipaddress
import random
def random_ula_net():
"""
Use fd00::/8 as a basis
We have 40 bit of address space to then generate /48 networks
We generate a random integer between 0 and (2**40)-1
We then shift that number by 80 bits to fit into the correct position
Example:
>>> ula_net = ipaddress.IPv6Network("fd00::/8")
>>> ula_net[(2**40)-1 << 80]
IPv6Address('fdff:ffff:ffff::')
>>>
"""
ula_net = ipaddress.IPv6Network("fd00::/8")
random_number = random.randrange(0, 2**40)
network = ula_net[random_number << 80]
return network

View file

@ -2,6 +2,7 @@ from django.views.generic.list import ListView
from django.views.generic.edit import CreateView
from django.contrib.auth import views as auth_views
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth import logout
from django.shortcuts import redirect
@ -11,23 +12,47 @@ import ipaddress
from django.conf import settings
from .models import *
from .forms import ULAForm
from .forms import *
from .utils import *
class IndexView(ListView):
model = ULA
queryset = ULA.objects.order_by('prefix')
class SubmitView(LoginRequiredMixin, CreateView):
class GenerateSubmitView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = ULA
form_class = ULAForm
login_url = '/login/'
success_url = '/'
success_message = "%(the_prefix)s/48 was created successfully"
gen_method = "undef"
def get_success_message(self, cleaned_data):
return self.success_message % dict(cleaned_data,
the_prefix = self.object.prefix)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['method'] = self.gen_method
return context
class GenerateView(GenerateSubmitView):
form_class = ULAGenerateForm
gen_method = "generate"
def form_valid(self, form):
form.instance.owner = self.request.user
return super(SubmitView, self).form_valid(form)
form.instance.prefix = str(random_ula_net())
return super(GenerateView, self).form_valid(form)
class SubmitView(GenerateSubmitView):
form_class = ULAForm
gen_method = "submit"
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
class LoginView(auth_views.LoginView):
template_name = 'ipv6ula/login.html'