summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvuko <vuko@hackerspace.pl>2021-01-04 20:52:42 +0100
committervuko <vuko@hackerspace.pl>2021-01-04 20:52:42 +0100
commita27d3d8dfeb296a77ab49359f1279f44c11610a2 (patch)
treea69a865c604105eb5daf78153c9d4d79209bfdb4
parent74a4a02ada1c3a9a4fde40cd12ced1351824e84d (diff)
downloadcheckinator-a27d3d8dfeb296a77ab49359f1279f44c11610a2.tar.gz
checkinator-a27d3d8dfeb296a77ab49359f1279f44c11610a2.tar.bz2
checkinator-a27d3d8dfeb296a77ab49359f1279f44c11610a2.zip
initial IPv6 support
-rw-r--r--at/web.py27
-rw-r--r--at/webapp.py21
-rw-r--r--web-config.dist.yaml5
3 files changed, 43 insertions, 10 deletions
diff --git a/at/web.py b/at/web.py
index a1a7fc2..f2445c8 100644
--- a/at/web.py
+++ b/at/web.py
@@ -2,7 +2,7 @@ import json
import sqlite3
from pathlib import Path
from datetime import datetime
-from typing import NamedTuple, Iterable, Iterator
+from typing import NamedTuple, Iterable, Iterator, List
from functools import wraps
from flask import Flask, render_template, abort, g, \
redirect, request, url_for, make_response
@@ -35,6 +35,7 @@ def get_device_info(conn: sqlite3.Connection, hwaddr: str) -> DeviceInfo:
def get_device_infos(conn: sqlite3.Connection, hwaddrs: Iterable[str]) -> Iterator[DeviceInfo]:
+ hwaddrs = list(hwaddrs)
in_clause = '({})'.format(', '.join(['?'] * len(hwaddrs)))
stmt = '''select hwaddr, name, ignored, owner from
devices where devices.hwaddr in ''' + in_clause
@@ -56,12 +57,19 @@ def app(instance_path, devices_api, config):
app.space_auth = SpaceAuth(app)
- def restrict_ip(prefix='', exclude=[]):
+ def restrict_ip(prefixes : List[str] = [], exclude : List[str] = []):
def decorator(f):
@wraps(f)
def func(*a, **kw):
r_addr = v4addr()
- if not r_addr.startswith(prefix) or r_addr in exclude:
+ if r_addr in exclude:
+ app.logger.info('got IP %s, rejecting', r_addr)
+ abort(403)
+
+ for prefix in prefixes:
+ if r_addr.startswith(prefix):
+ break
+ else:
app.logger.info('got IP %s, rejecting', r_addr)
abort(403)
@@ -151,7 +159,7 @@ def app(instance_path, devices_api, config):
return result
- restrict_to_hs = restrict_ip(prefix=app.config['CLAIMABLE_PREFIX'],
+ restrict_to_hs = restrict_ip(prefixes=app.config['CLAIMABLE_PREFIXES'],
exclude=app.config['CLAIMABLE_EXCLUDE'])
@@ -161,7 +169,12 @@ def app(instance_path, devices_api, config):
def claim_form():
hwaddr, name = app.updater.get_device(v4addr())
return render_template('claim.html', hwaddr=hwaddr, name=name)
-
+
+ @app.route('/my_ip', methods=['GET'])
+ def get_my_ip():
+ ip = v4addr()
+ hwaddr, name = app.updater.get_device(ip)
+ return f'ip: {ip!r}\nhwaddr: {hwaddr!r}\nhostname: {name!r}\n'
@app.route('/claim', methods=['POST'])
@restrict_to_hs
@@ -232,5 +245,5 @@ def app(instance_path, devices_api, config):
return app
-if __name__ == '__main__':
- app(Path.cwd().absolute()).run('0.0.0.0', 8080, debug=True)
+#if __name__ == '__main__':
+# app(Path.cwd().absolute()).run('0.0.0.0', 8080, debug=True)
diff --git a/at/webapp.py b/at/webapp.py
index a9d9949..cbb282e 100644
--- a/at/webapp.py
+++ b/at/webapp.py
@@ -5,7 +5,8 @@ from at.dhcp import DhcpdUpdater
from pathlib import Path
import yaml
import os
-from typing import Tuple, Optional
+import ipaddress
+from typing import Tuple, Optional, Dict
import grpc
from at.tracker_pb2 import ClientsRequest
@@ -13,15 +14,25 @@ from at.tracker_pb2_grpc import DhcpTrackerStub
from at.dhcp import DhcpLease
from datetime import datetime
+
def format_mac(raw: bytes) -> str:
return ':'.join(f'{b:02x}' for b in raw)
+def mac_from_ipv6(address : ipaddress.IPv6Address):
+ if not isinstance(address, ipaddress.IPv6Address):
+ raise ValueError(f"not an IPv6 address: {address}")
+ raw = address.packed[8:]
+ if raw[3:5] != bytes([0xff, 0xfe]):
+ raise ValueError(f"not MAC based IPv6 Address: {address}")
+ mac = bytes([raw[0] ^ 0x02, *raw[1:3], *raw[5:]])
+ return mac
+
class DevicesApi:
def __init__(self, grpc_channel):
self._api = DhcpTrackerStub(grpc_channel)
- def get_active_devices(self) -> DhcpLease:
+ def get_active_devices(self) -> Dict[str, DhcpLease]:
devices = self._api.GetClients(ClientsRequest())
return {
format_mac(d.hw_address): DhcpLease(
@@ -39,6 +50,12 @@ class DevicesApi:
return (
format_mac(device.hw_address), device.client_hostname
)
+
+ address = ipaddress.ip_address(ip)
+ if isinstance(address, ipaddress.IPv6Address):
+ mac = mac_from_ipv6(address)
+ return ( format_mac(mac), "" )
+
return None, None
diff --git a/web-config.dist.yaml b/web-config.dist.yaml
index 12ef918..39a8de7 100644
--- a/web-config.dist.yaml
+++ b/web-config.dist.yaml
@@ -8,7 +8,10 @@ DEBUG: true
# "${login}" string is replaced by member login (uid)
WIKI_URL: 'https://wiki.hackerspace.pl/people:%(login)s:start'
-CLAIMABLE_PREFIX: '10.8.0.'
+CLAIMABLE_PREFIXES:
+ - '10.8.0.'
+ - '2a0d:eb00:4242:0:'
+
CLAIMABLE_EXCLUDE: [ ]
SECRETS_FILE: "web-secrets.yaml"