-
Notifications
You must be signed in to change notification settings - Fork 325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
introduce XLAT, native IPv4 for clients #1808
Changes from 4 commits
277d1bf
78f09e9
35a0e3f
ebbd407
5569a6d
b6616b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
gluon-464xlat-clat | ||
================== | ||
|
||
This package provides the kernel module and functionality required to support | ||
ipv4 clients on an ipv6-only backbone. | ||
rotanid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Assumptions | ||
----------- | ||
|
||
* Clients will be given IPv4 addresses by a dhcp daemon that runs on each node. | ||
rotanid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
gluon-ddhcpd is a great choice for this. | ||
* There is a component on the network that does plat on the default network | ||
64:ff9b::/96. https://github.com/FreifunkMD/jool-docker.git can do this. | ||
|
||
Limitations | ||
----------- | ||
* When roaming, clients will experience temporary loss of IPv4 connectivity | ||
|
||
site.conf | ||
--------- | ||
|
||
clat_range : mandatory | ||
- infrastructure net (ULA) from which a /96 clat prefix will be generated. | ||
- This must be a /48 prefix. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A short subclause, explaining why a /48, e.g. how it is partitioned, would go a long way. |
||
- This can be the same for each community and is pre-registered at https://wiki.freifunk.net/IP-Netze#IPv6 as part of fdff:ffff:ff00::/40 | ||
rotanid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Example:: | ||
|
||
{ | ||
clat_range = 'fdff:ffff:ffff::/48', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation |
||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
include $(TOPDIR)/rules.mk | ||
|
||
PKG_NAME:=gluon-464xlat-clat | ||
PKG_VERSION:=1 | ||
|
||
include ../gluon.mk | ||
|
||
PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||
rotanid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
define Package/gluon-464xlat-clat | ||
TITLE:=Support translating IPv4 addresses to IPv6 using 464xlat | ||
neocturne marked this conversation as resolved.
Show resolved
Hide resolved
|
||
DEPENDS:=+gluon-core +kmod-nat46 | ||
endef | ||
|
||
$(eval $(call BuildPackageGluon,gluon-464xlat-clat)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
need_string(in_domain({'clat_range'})) | ||
need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
net.ipv4.conf.clat.accept_local=1 | ||
net.ipv6.conf.clat.use_oif_addrs_only=1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
net.ipv4.conf.clat.accept_local=1 | ||
net.ipv6.conf.clat.use_oif_addrs_only=1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
#!/bin/sh | ||
# Copyright 2018 Vincent Wiemann <[email protected]> | ||
# | ||
# This program is free software; you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License version 2 | ||
# as published by the Free Software Foundation | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
CTR=/proc/net/nat46/control | ||
|
||
[ -n "$INCLUDE_ONLY" ] || { | ||
. /lib/functions.sh | ||
. ../netifd-proto.sh | ||
init_proto "$@" | ||
} | ||
|
||
proto_464xlatclat_init_config() { | ||
proto_config_add_string "zone" | ||
proto_config_add_string "zone4" | ||
proto_config_add_string "local_style" | ||
proto_config_add_string "local_v4" | ||
proto_config_add_string "local_v6" | ||
proto_config_add_string "local_ea_len" | ||
proto_config_add_string "local_psid" | ||
proto_config_add_boolean "local_fmr_flag" | ||
proto_config_add_string "remote_style" | ||
proto_config_add_string "remote_v4" | ||
proto_config_add_string "remote_v6" | ||
proto_config_add_string "remote_ea_len" | ||
proto_config_add_string "remote_psid" | ||
proto_config_add_string "ip4table" | ||
proto_config_add_boolean "debug" | ||
available=1 | ||
no_device=1 | ||
} | ||
|
||
proto_464xlatclat_setup() { | ||
local config="$1" | ||
local clat_cfg="config ${config}" | ||
local local_style | ||
local local_v4 | ||
local local_v6 | ||
local local_ea_len | ||
local local_psid | ||
local local_fmr | ||
local remote_style | ||
local remote_v4 | ||
local remote_v6 | ||
local remote_ea_len | ||
local remote_psid | ||
local zone | ||
local zone4 | ||
local ip4table | ||
|
||
config_load network | ||
config_get ip4table "${config}" "ip4table" | ||
config_get zone "${config}" "zone" | ||
config_get zone4 "${config}" "zone4" | ||
config_get_bool debug "${config}" "debug" 0 | ||
config_get local_style "${config}" "local_style" | ||
config_get local_v4 "${config}" "local_v4" | ||
config_get local_v6 "${config}" "local_v6" | ||
config_get local_ea_len "${config}" "local_ea_len" | ||
config_get local_psid "${config}" "local_psid_offset" | ||
config_get_bool local_fmr "${config}" "local_fmr_flag" 0 | ||
config_get remote_style "${config}" "remote_style" | ||
config_get remote_v4 "${config}" "remote_v4" | ||
config_get remote_v6 "${config}" "remote_v6" | ||
config_get remote_ea_len "${config}" "remote_ea_len" | ||
config_get remote_psid "${config}" "remote_psid_offset" | ||
config_get local_ip "${config}" "local_ip" | ||
|
||
zone="${zone:-wan}" | ||
zone4="${zone4:-lan}" | ||
local_v6="${local_v6:-fd00:13:37:13:37::/96}" | ||
remote_v4="${remote_v4:-0.0.0.0/0}" | ||
|
||
[ "$debug" -ne 0 ] && clat_cfg="$clat_cfg debug 1" | ||
[ "${local_fmr}" -ne 0 ] && clat_cfg="$clat_cfg local.fmr-flag 1" | ||
|
||
clat_cfg="${clat_cfg} local.style ${local_style:-RFC6052} local.v4 ${local_v4:-192.168.1.0/24} local.v6 ${local_v6}" | ||
clat_cfg="${clat_cfg} local.ea-len ${local_ea_len:-0} local.psid-offset ${local_psid:-0}" | ||
clat_cfg="${clat_cfg} remote.style ${remote_style:-RFC6052} remote.v4 ${remote_v4} remote.v6 ${remote_v6:-64:ff9b::/96}" | ||
clat_cfg="${clat_cfg} remote.ea-len ${remote_ea_len:-0} remote.psid-offset ${remote_psid:-0}" | ||
|
||
echo "add ${config}" > ${CTR} | ||
echo "${clat_cfg}" > ${CTR} | ||
|
||
[ "${ip4table}" ] && ip -4 rule add from "${local_v4}" lookup "${ip4table}" | ||
|
||
proto_init_update "${config}" 1 | ||
|
||
# add routes | ||
case "${local_v6}" in | ||
*:*/*) | ||
proto_add_ipv6_route "${local_v6%%/*}" "${local_v6##*/}" | ||
;; | ||
*:*) | ||
proto_add_ipv6_route "${local_v6%%/*}" "128" | ||
;; | ||
esac | ||
|
||
case "${remote_v4}" in | ||
*.*/*) | ||
proto_add_ipv4_route "${remote_v4%%/*}" "${remote_v4##*/}" "" "" 2048 | ||
;; | ||
*.*) | ||
proto_add_ipv4_route "${remote_v4%%/*}" "32" "" "" 2048 | ||
;; | ||
esac | ||
|
||
proto_add_data | ||
[ "${zone}" != "-" ] && json_add_string zone "${zone}" | ||
|
||
json_add_array firewall | ||
# if forwarding within "zone" and between zone<->zone4 is allowed you can set zone = "-" | ||
if [ "${zone}" != "-" ]; then | ||
json_add_object "" | ||
json_add_string type rule | ||
json_add_string family inet6 | ||
json_add_string proto all | ||
json_add_string direction in | ||
json_add_string dest "${zone}" | ||
json_add_string src "${zone}" | ||
json_add_string src_ip "$local_v6" | ||
json_add_string target ACCEPT | ||
json_close_object | ||
# if a forwarding between zone and zone4 exists (e.g. lan<->wan) you can set zone4 = "-" | ||
if [ "${zone4}" != "-" ]; then | ||
json_add_object "" | ||
json_add_string type rule | ||
json_add_string family inet | ||
json_add_string proto all | ||
json_add_string direction out | ||
json_add_string dest "${zone}" | ||
[ "$remote_v4" != "0.0.0.0/0" ] && json_add_string dest_ip "$remote_v4" | ||
json_add_string src "${zone4}" | ||
json_add_string src_ip "$local_v4" | ||
json_add_string target ACCEPT | ||
json_close_object | ||
fi | ||
fi | ||
|
||
json_close_array | ||
|
||
proto_close_data | ||
|
||
proto_send_update "$config" | ||
|
||
# this rule relies on the ll-address being set. This rule will set the | ||
# src-address for icmp packets to the ipv4 next-node address | ||
clat_ll_ip="$(ip -o a s dev clat |cut -d" " -f7|cut -d"/" -f1)/128" | ||
clat_cfg="insert $config local.v4 ${local_ip} local.v6 :: local.style NONE" | ||
clat_cfg="${clat_cfg} local.ea-len 0 local.psid-offset 0" | ||
clat_cfg="${clat_cfg} remote.v4 ${local_ip} remote.v6 $clat_ll_ip" | ||
clat_cfg="${clat_cfg} remote.style NONE remote.ea-len 0 remote.psid-offset 0" | ||
echo "${clat_cfg}" > ${CTR} | ||
} | ||
|
||
proto_464xlatclat_teardown() { | ||
local config="$1" | ||
echo "del ${config}" > ${CTR} | ||
} | ||
|
||
[ -n "$INCLUDE_ONLY" ] || { | ||
add_protocol 464xlatclat | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#!/usr/bin/lua | ||
local site = require 'gluon.site' | ||
local sysconfig = require 'gluon.sysconfig' | ||
local uci = require('simple-uci').cursor() | ||
|
||
local f = io.open("/etc/iproute2/rt_tables", "r") | ||
if f then | ||
if not f:read("*a"):find("10\tclat") then | ||
f:close() | ||
f = io.open("/etc/iproute2/rt_tables", "a") | ||
if f then | ||
f:write("\n10\tclat\n") | ||
end | ||
end | ||
f:close() | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could reuse |
||
|
||
local plat_prefix = uci:get('network', 'plat', 'local_v6') or "64:ff9b::/96" | ||
|
||
uci:set('network', 'local_node', 'ip4table', 'clat') | ||
|
||
local appendix = sysconfig.primary_mac:gsub('%:', '') | ||
appendix = string.format('%x:%x:%x', tonumber(appendix:sub(1, 4), 16), | ||
tonumber(appendix:sub(5, 8), 16), | ||
tonumber(appendix:sub(9, 12), 16)) | ||
local clat_prefix = string.format('%s%s::/96', site.clat_range():gsub(':/.+', ''), appendix) | ||
|
||
uci:delete('network', 'clat') | ||
uci:section('network', 'interface', 'clat', { | ||
proto = '464xlatclat', | ||
local_v4 = site.prefix4(), | ||
local_v6 = clat_prefix, | ||
remote_v6 = plat_prefix, | ||
zone = "local_client", | ||
zone4 = "local_client", | ||
ip4table = "clat", | ||
local_ip = site.next_node.ip4() .. '/32' | ||
}) | ||
uci:save('network') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
include $(TOPDIR)/rules.mk | ||
|
||
PKG_NAME:=gluon-ddhcpd | ||
PKG_VERSION:=1 | ||
|
||
include ../gluon.mk | ||
|
||
define Package/gluon-ddhcpd | ||
TITLE:=Distributed DHCP Daemon for Gluon | ||
DEPENDS:=+gluon-core +ddhcpd | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ddhcpd depends on a means to distribute multicast throughout the network. In babel networks this capability is provided by mmfd. in batman networks this is provided by the l2-property of batman. It could also be provided by bier or any other means. There is no way to model that currently and depending on mmfd is not the right thing to do for batman - as such a dependency was not placed. |
||
endef | ||
|
||
$(eval $(call BuildPackageGluon,gluon-ddhcpd)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. empty line? |
||
need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', true) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/bin/sh | ||
|
||
for i in /etc/ddhcpd.d/* | ||
do | ||
$i "$@" | ||
done |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#!/bin/sh /etc/rc.common | ||
|
||
START=90 | ||
USE_PROCD=1 | ||
NAME=ddhcpd | ||
DAEMON=/usr/sbin/ddhcpd | ||
MAXDELAY=10 | ||
|
||
validate_section_ddhcpd() { | ||
uci_validate_section "$NAME" ddhcpd settings \ | ||
'dhcp_interface:string:br-client' \ | ||
'server_interface:string:br-client' \ | ||
'block_size_pow:uinteger:2' \ | ||
'spare_blocks:uinteger:1' \ | ||
'timeout:uinteger:30' \ | ||
'block_network:cidr4' \ | ||
'dhcp_lease_time:uinteger:300' | ||
server_interface=$(ubus call network.interface dump | jsonfilter -e "@.interface[@.interface='$(cat /lib/gluon/respondd/client.dev 2>/dev/null)' && @.up=true].device") | ||
} | ||
|
||
start_service() { | ||
[ -x /lib/gluon/ddhcpd/arguments ] || exit 1 | ||
|
||
procd_open_instance | ||
procd_set_param command $DAEMON -D | ||
|
||
config_load "${NAME}" | ||
|
||
validate_section_ddhcpd || { | ||
echo "validation failed" | ||
return 1 | ||
} | ||
|
||
procd_append_param command -s "$spare_blocks" | ||
procd_append_param command -b "$block_size_pow" | ||
procd_append_param command -c "$dhcp_interface" | ||
procd_append_param command -i "$server_interface" | ||
procd_append_param command -N "$block_network" | ||
procd_append_param command -o "51:4:0.0.1.44" | ||
procd_append_param command -o "3:4:$(lua -e 'print(require("gluon.site").next_node.ip4())')" | ||
procd_append_param command -o "6:4:$(lua -e 'print(require("gluon.site").next_node.ip4())')" | ||
procd_append_param command $(/lib/gluon/ddhcpd/arguments) | ||
procd_set_param respawn | ||
procd_set_param netdev "$dhcp_interface" | ||
[ "$dhcp_interface" == "$server_interface" ] || procd_append_param netdev "$server_interface" | ||
procd_set_param stderr 1 | ||
procd_close_instance | ||
} | ||
|
||
service_triggers() { | ||
procd_add_config_trigger "config.change" "ddhcpd" /etc/init.d/ddhcpd restart | ||
procd_add_interface_trigger "interface.*" "$server_interface" /etc/init.d/ddhcpd restart | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
|
||
uci set ddhcpd.settings.enabled="0" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be merged into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done, please check if it was done correctly |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/usr/bin/lua | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WIth the mmfd rule it's probably appropriate to call the file |
||
|
||
local uci = require('simple-uci').cursor() | ||
|
||
uci:section('firewall', 'rule', 'local_node_dhcp', { | ||
src = 'local_client', | ||
name = 'allow_dhcp_local_client', | ||
dest_port = '67', | ||
proto = 'udp', | ||
target = 'ACCEPT' | ||
rotanid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
|
||
uci:section('firewall', 'rule', 'ddhcpd_mmfd', { | ||
dest_port = '1234', | ||
src = 'mmfd', | ||
src_ip = 'fe80::/64', | ||
name = 'allow_ddhcp_to_reserve_blocks', | ||
proto = 'udp', | ||
target = 'ACCEPT' | ||
}) | ||
|
||
uci:save('firewall') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/usr/bin/lua | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no need to sort this behind the firewall rules, both can be put at position 315. |
||
|
||
local site = require 'gluon.site' | ||
|
||
local uci = require('simple-uci').cursor() | ||
|
||
uci:set('ddhcpd', 'settings', 'block_network', site.prefix4()) | ||
|
||
uci:save('ddhcpd') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/sh | ||
if [ "$1" = "lease" ] | ||
then | ||
echo add_address "$2" "$3" | uc /var/run/l3roamd.sock | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lacking documentation for
gluon-ddhcpd
.