├── LICENCE
├── README.md
├── fold
└── utils
├── eui-64
├── exp6
├── lamac
├── mcmac4
├── mcmac6
├── solip6
└── solmac
/LICENCE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 David Halls
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fold
2 |
3 | **Note: I'm no longer maintaining this project. Let me know if you wish to contribute.**
4 |
5 | Run virtual machines on a virtual network created by [Weave](https://github.com/zettio/weave).
6 |
7 | - Requires Weave (of course).
8 | - Requires [my fork of nfdhcpd](https://github.com/davedoesdev/nfdhcpd) in order to provide each VM with address and configuration data.
9 | - Like Weave each subnet is fully isolated — Fold sets up the necessary firewall rules.
10 | - Supports custom configuration data per VM using DNS TXT records. Useful for service discovery in multi-VM applications.
11 | - Mix docker containers with VMs - they can talk to each other over the same Weave network.
12 | - Interoperates with weaveDNS: VMs can lookup Weave records and containers can lookup Fold records.
13 | - Full IPv6 support.
14 | - Supports [KVM](http://www.linux-kvm.org/page/Main_Page) and [Rumprun](https://github.com/rumpkernel/rumprun) for lightweight VMs.
15 |
16 | The motivation for Fold is to support applications you don't trust enough to run in containers. For example, multi-tenant environments or when you've pulled in many dependencies and haven't audited all the third party modules your application uses.
17 |
18 | # Usage
19 |
20 | ## Setting up Weave network
21 |
22 | You need to create a Weave network (`weave launch`) before running Fold. Please see the [Weave documentation](https://github.com/zettio/weave) for details.
23 |
24 | Fold supports Weave [automatic IP address management (IPAM)](http://docs.weave.works/weave/latest_release/ipam.html) and [mixed automatic and manual allocation](http://docs.weave.works/weave/latest_release/ipam.html#manual).
25 |
26 | When using IPAM, allocate an IP address using:
27 |
28 | ```shell
29 | fold -i -4 auto [net: | net:default]
30 | ```
31 |
32 | You must supply an interface name — Weave will assign the address to this name. Supply a CIDR if you don't want to use Weave's default subnet. The allocated IP address will be written to standard output.
33 |
34 | To release the IP address later, after running your VM, you can use:
35 |
36 | ```shell
37 | fold -i -4 release
38 | ```
39 |
40 | When using mixed allocation, give your VMs IP addresses from the manual allocation range.
41 |
42 | If you want your Weave containers to be able to make DNS queries against Fold, use the Docker `--dns` option when launching your containers. For example, if you're going to run a VM with IP address `10.0.1.100` and want to make DNS queries against it then use `docker run --dns=10.0.1.100 ...`
43 |
44 | ## Running VMs using Fold
45 |
46 | Once you've setup your Weave network, use the `fold` command to run virtual machines on the network:
47 |
48 | ```shell
49 | fold [-i ]
50 | [-4 /]
51 | [-6 ]
52 | [-s]
53 | [-m ]...
54 | [-k ]
55 | [-d ]
56 | [-b ]
57 | [-a ]
58 | [-A ]
59 |
60 | kvm|qemu-system-* [...]
61 | ```
62 |
63 | You should supply at least one of `-4` or `-6`.
64 |
65 | **`-i`** names the interface created for the VM and attached to the Weave network bridge. If you don't supply one then Fold makes a name up for you. If you're using IPAM then use the same name you used to allocate the IP address.
66 |
67 | **`-4`** gives the VM an IPv4 address and subnet on the Weave network. For example, `-4 10.0.1.100/24`. The VM will be able to communicate with other VMs on the same subnet. If you're using IPAM, use the IP allocated to the interface name.
68 |
69 | **`-6`** gives the VM an IPv6 address and prefix on the Weave network. For example, `-6 fde5:824d:d315:3bb1::/64`. The VM will be able to communicate with other VMs with the same prefix. Your VM's guest OS is assumed to be using [Modified EUI-64](http://tools.ietf.org/html/rfc4291#section-2.5.1), unless you specify the `-s` or `-k` options.
70 |
71 | **`-s`** sets the VM's IPv6 address to the full 128-bit value you specified with `-6` (i.e. with the prefix specifier removed).
72 |
73 | **`-m`** allows the VM to receive IPv4 or IPv6 multicast packets for a given address. You can repeat `-m` more than once, for example `-m 239.1.2.3 -m ff3e::4321:1234`.
74 |
75 | **`-k`** specifies that the VM should use an IPv6 [RFC 7217](https://tools.ietf.org/html/rfc7217) stable privacy address. Fold uses [rdiscd](https://github.com/AGWA/rdiscd) to generate the address. `rdiscd-mkaddress` should be available in your `PATH`.
76 |
77 | The argument to `-k` is the file containing the secret key used to generate the stable privacy address. Fold puts the stable privacy address into a file called `interface-id` on a temporary ext2fs disk image. The path to the image file will be substituted for `_rdiscd_img_file_` in the rest of the arguments. For example:
78 |
79 | ```shell
80 | fold ... -k keyfile ... kvm -fda _rdiscd_img_file_
81 | ```
82 |
83 | Note that Fold doesn't support IPv6 [RFC 4941](http://tools.ietf.org/html/rfc4941) temporary addresses so you should disable these in your VM's guest operating system.
84 |
85 | **`-d`** specifies the directory in which to write the file containing the stable privacy address (only if `-k` is specified). Defaults to the current directory.
86 |
87 | **`-b`** specifies a binding file containing configuration data for `nfdhcpd`. It will be used by `nfdhcpd` to supply information such as a hostname and DNS address and TXT records to the VM's guest OS. Please see the [nfdhcpd documentation](https://github.com/davedoesdev/nfdhcpd) for more information. Here's an example:
88 |
89 | ```ini
90 | HOSTNAME=test
91 | GATEWAY=10.0.1.90
92 | GATEWAY_MAC=7a:f4:96:e0:1c:a0
93 | GATEWAY6=fde5:824d:d315:3bb1::91
94 | GATEWAY6_MAC=7e:b7:70:3b:81:77
95 | NAMESERVERS=10.0.1.50
96 | NAMESERVERS6=fde5:824d:d315:3bb1::1
97 | ADDRESS:database.=10.0.1.1
98 | ADDRESS6:database.=fde5:824d:d315:3bb1::9
99 | TXT:table.=Users
100 | DNS_NAMESERVERS=172.17.42.1
101 | ```
102 |
103 | Fold will add `IPADDR`, `SUBNET`, `PREFIX`, `IP6ADDR` and `BRIDGE` to the settings in your binding file.
104 |
105 | Note that if you define an IPv4 gateway, Fold requires a setting which `nfdhcpd` doesn't use: `GATEWAY_MAC`. Fold needs the MAC of your gateway in order to make sure traffic coming in and out of the subnet (or prefix for IPv6) goes via the gateway only.
106 |
107 | One way to get a gateway on your Weave network is to use [Weave host network integration](http://docs.weave.works/weave/latest_release/features.html#host-network-integration). Use `weave expose` to get the gateway IP address and `weave ps weave:expose` to get the gateway MAC.
108 |
109 | If you want your VM to be able to make queries against weaveDNS, you need to set `DNS_NAMESERVERS` to the IP address of the _Docker_ bridge device (usually `docker0`). Use `ip addr show dev docker0` or `ifconfig docker0` and parse the output to find the IP address. For example:
110 |
111 | ```shell
112 | ifconfig docker0 | grep 'inet addr:' | cut -d: -f2 | awk '{print $1}'
113 | ```
114 |
115 | **`-a`** specifies the `iptables` action to take for packets outside the subnet coming from or going to the VM's IP address (via the gateway, if you defined one). The default is `-a "-j RETURN"` (resume with non-Fold processing) but you can use `-a "-g ..."` or `-a "-j ..."` to continue processing using a chain you've defined.
116 |
117 | **`-A`** does the same as `-a` but for `ip6tables` and IPv6 packets.
118 |
119 | **``** is a (mandatory) MAC address to give the VM. Note you can use the `utils/lamac` script to generate a random [locally administered address](http://en.wikipedia.org/wiki/MAC_address#Address_details).
120 |
121 | **`...`** should contain arguments necessary to load your VM, for example:
122 | - `-hda disk.qcow2` (KVM)
123 | - `-kernel myrumpkernel.bin -append '{"net": {"if": "vioif0",, "type": "inet",, "method":"dhcp"},, "cmdline": "myapp"}'` (Rumprun).
124 |
125 | ## Environment variables
126 |
127 | Fold uses `iptables`, `ip6tables` and `ebtables`. To change how Fold invokes these commands, set the `IPTABLES`, `IP6TABLES` and `EBTABLES` environment variables respectively. For example, to support concurrent use:
128 |
129 | ```shell
130 | IPTABLES='iptables --wait' IP6TABLES='ip6tables --wait' EBTABLES='ebtables --concurrent' fold ...
131 | ```
132 |
133 | By default, Fold expects to find the global `nfdhcpd` configuration file at `/etc/nfdhcpd/nfdhcpd.conf`. You can override this by setting `NFDHCPD_CFG`.
134 |
135 | # Examples
136 |
137 | Run a Ubuntu VM on the Weave network, with IPv4 and IPv6 addresses (IPv6 using EUI-64):
138 |
139 | ```shell
140 | fold -4 10.0.1.100/24 -6 fde5:824d:d315:3bb1::/64 -b test-binding 52:54:00:12:34:56 kvm -hda ubuntu.qcow2
141 | ```
142 |
143 | Run a Ubuntu VM on the Weave network, with IPv4 and IPv6 unicast and multicast addresses (IPv6 unicast address using stable privacy):
144 |
145 | ```shell
146 | fold -4 10.0.1.100/24 -6 fde5:824d:d315:3bb1::/64 -k keyfile -m 239.1.2.3 -b test-binding 52:54:00:12:34:56 kvm -hda ubuntu.qcow2 -fda _rdiscd_img_file_
147 | ```
148 |
149 | Run a Rumprun kernel on a Weave network (10.9.200.1/16):
150 |
151 | ```shell
152 | fold -4 10.9.200.1/16 52:54:00:12:34:56 kvm -kernel rumprun-packages/nodejs/build-4.3.0/out/Release/node-hello-world.bin -append '{"net": {"if": "vioif0",, "type": "inet",, "method":"dhcp"},, "cmdline": "node"}' -m 256
153 | ```
154 |
--------------------------------------------------------------------------------
/fold:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | BRIDGE=weave
5 | WEAVE_CONTAINER_NAME=weave
6 | WEAVE_HTTP_PORT=6784
7 | NFDHCPD_CFG="${NFDHCPD_CFG:-/etc/nfdhcpd/nfdhcpd.conf}"
8 | MTU=16384 # max TAP MTU
9 | let "MARK_GATEWAY=1<<0"
10 | let "MARK_GATEWAY6=1<<1"
11 | UTILS="$(dirname "$0")/utils"
12 | IPTABLES="${IPTABLES:-iptables}"
13 | IP6TABLES="${IP6TABLES:-ip6tables}"
14 | EBTABLES="${EBTABLES:-ebtables}"
15 |
16 | usage() {
17 | echo "Usage:"
18 | echo "fold -i -4 auto [net: | net:default]"
19 | echo "fold -i -4 release"
20 | echo "fold [-i ]"
21 | echo " [-4 /] [-6 ] [-s] [-m ]..."
22 | echo " [-k ] [-d ]"
23 | echo " [-b ]"
24 | echo " [-a ] [-A ]"
25 | echo " kvm|qemu-system-* ..."
26 | exit 1
27 | }
28 |
29 | [ "$(id -u)" = 0 ] || {
30 | echo "fold must be run as 'root'" >&2
31 | exit 1
32 | }
33 |
34 | unset IPSUB PREFIX PREFIX_AS_ADDR KEYFILE RDISCD_IMG_FILE TAP_IFNAME
35 | RDISCD_IMG_DIR=.
36 | MULTI4=()
37 | MULTI6=()
38 | NFDHCPD_BINDING_IN=/dev/null
39 | GATEWAY_ACTION="-j RETURN"
40 | GATEWAY6_ACTION="-j RETURN"
41 | while getopts 4:6:sm:k:d:b:i:a:A: opt
42 | do
43 | case $opt in
44 | 4)
45 | IPSUB="$OPTARG"
46 | ;;
47 | 6)
48 | PREFIX="$OPTARG"
49 | ;;
50 | s)
51 | PREFIX_AS_ADDR=1
52 | ;;
53 | m)
54 | if [[ "$OPTARG" == *.* ]]; then
55 | MULTI4=("${MULTI4[@]}" "$OPTARG")
56 | else
57 | MULTI6=("${MULTI6[@]}" "$OPTARG")
58 | fi
59 | ;;
60 | k)
61 | KEYFILE="$OPTARG"
62 | ;;
63 | d)
64 | RDISCD_IMG_DIR="$OPTARG"
65 | ;;
66 | b)
67 | NFDHCPD_BINDING_IN="$OPTARG"
68 | ;;
69 | i)
70 | TAP_IFNAME="$OPTARG"
71 | ;;
72 | a)
73 | GATEWAY_ACTION="$OPTARG"
74 | ;;
75 | A)
76 | GATEWAY6_ACTION="$OPTARG"
77 | ;;
78 | *)
79 | usage
80 | ;;
81 | esac
82 | done
83 |
84 | shift $((OPTIND-1))
85 |
86 | # IPAM functions taken from weave script
87 |
88 | IP_REGEXP="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
89 | CIDR_REGEXP="$IP_REGEXP/[0-9]{1,2}"
90 |
91 | is_cidr() {
92 | echo "$1" | grep -E "^$CIDR_REGEXP$" >/dev/null
93 | }
94 |
95 | container_ip() {
96 | if ! status=$(docker inspect --format='{{.State.Running}} {{.NetworkSettings.IPAddress}}' $1 2>/dev/null) ; then
97 | echo "$2" >&2
98 | return 1
99 | fi
100 | case "$status" in
101 | "true ")
102 | echo "$1 container has no IP address; is Docker networking enabled?" >&2
103 | return 1
104 | ;;
105 | true*)
106 | CONTAINER_IP="${status#true }"
107 | ;;
108 | *)
109 | echo "$3" >&2
110 | return 1
111 | ;;
112 | esac
113 | }
114 |
115 | http_call_ip() {
116 | ip="$1"
117 | port="$2"
118 | http_verb="$3"
119 | url="$4"
120 | shift 4
121 | curl --connect-timeout 3 -s -S -X $http_verb "$@" http://$ip:$port$url
122 | }
123 |
124 | # Call url $4 with http verb $3 on container $1 at port $2
125 | http_call() {
126 | HTTP_CALL_CONTAINER=$1
127 | container_ip $HTTP_CALL_CONTAINER \
128 | "$HTTP_CALL_CONTAINER container is not present. Have you launched it?" \
129 | "$HTTP_CALL_CONTAINER container is not running." \
130 | || return 1
131 | shift 1
132 | if ! http_call_ip $CONTAINER_IP "$@" ; then
133 | echo "Call to $HTTP_CALL_CONTAINER failed." >&2
134 | return 1
135 | fi
136 | }
137 |
138 | if [ "$IPSUB" = auto ]; then
139 | [ -n "$TAP_IFNAME" -a $# -le 1 ] || usage
140 | if [ $# -eq 0 -o "$1" = net:default ]; then
141 | IPAM_URL="/ip/$TAP_IFNAME"
142 | else
143 | IPAM_URL="/ip/$TAP_IFNAME/${1#net:}"
144 | fi
145 | if ! CIDR="$(http_call $WEAVE_CONTAINER_NAME $WEAVE_HTTP_PORT POST "$IPAM_URL")"; then
146 | exit 1
147 | fi
148 | if [ "$CIDR" = "404 page not found" ] ; then
149 | echo "IP address allocation must be enabled to use 'net:'" >&2
150 | exit 1
151 | fi
152 | if ! is_cidr "$CIDR" ; then
153 | echo "$CIDR" >&2
154 | exit 1
155 | fi
156 | echo "$CIDR"
157 | exit
158 | fi
159 |
160 | if [ "$IPSUB" = release ]; then
161 | [ -n "$TAP_IFNAME" -a $# -eq 0 ] || usage
162 | http_call $WEAVE_CONTAINER_NAME $WEAVE_HTTP_PORT DELETE "/ip/$TAP_IFNAME"
163 | exit
164 | fi
165 |
166 | TAP_IFNAME="${TAP_IFNAME:-vethfotp$$}"
167 | NFDHCPD_BINDING_OUT="/var/lib/nfdhcpd/$TAP_IFNAME"
168 |
169 | [ $# -gt 1 ] || usage
170 |
171 | MACADDR="$1"
172 | COMMAND="$2"
173 | shift 2
174 |
175 | trim() {
176 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' "$@"
177 | }
178 |
179 | config() {
180 | grep -i "^$1 *=" $2 | sed 's/^[^=]*=//' | sed 's/#.*$//' | trim
181 | }
182 |
183 | config1() {
184 | config "$1" "$2" | sed 's/,.*$//' | trim
185 | }
186 |
187 | run_prog() {
188 | local user="${SUDO_USER:-root}"
189 | if command -v sudo >& /dev/null; then
190 | sudo -u "$user" "$@"
191 | else
192 | su --preserve-environment -l -c 'exec "$0" "$@"' "$user" -- "$@"
193 | fi
194 | }
195 |
196 | DHCP_QUEUE="$(config dhcp_queue "$NFDHCPD_CFG")"
197 | DHCP6_QUEUE="$(config dhcp6_queue "$NFDHCPD_CFG")"
198 | RS_QUEUE="$(config rs_queue "$NFDHCPD_CFG")"
199 | NS_QUEUE="$(config ns_queue "$NFDHCPD_CFG")"
200 | DNS_QUEUE="$(config dns_queue "$NFDHCPD_CFG")"
201 | DNS6_QUEUE="$(config dns6_queue "$NFDHCPD_CFG")"
202 | NOTIFY_QUEUE="$(config notify_queue "$NFDHCPD_CFG")"
203 | NOTIFY6_QUEUE="$(config notify6_queue "$NFDHCPD_CFG")"
204 | NAMESERVER="$(config1 nameservers "$NFDHCPD_BINDING_IN")"
205 | GATEWAY="$(config gateway "$NFDHCPD_BINDING_IN")"
206 | GATEWAY_MAC="$(config gateway_mac "$NFDHCPD_BINDING_IN")"
207 | GATEWAY6="$(config gateway6 "$NFDHCPD_BINDING_IN")"
208 | GATEWAY6_MAC="$(config gateway6_mac "$NFDHCPD_BINDING_IN")"
209 |
210 | if [ "$IPSUB" ]; then
211 | # extract the IP address from an ipaddr/subnet spec
212 | IFS=/ read -a ipsub <<< "$IPSUB"
213 | IPADDR="${ipsub[0]}"
214 |
215 | # make a zero-ending subnet mask (CIDR) from an ipaddr/subnet spec
216 | IFS=. read -a ipaddr <<< "$IPADDR"
217 | ipnum=$(((ipaddr[0] << 24) + (ipaddr[1] << 16) + (ipaddr[2] << 8) + (ipaddr[3])))
218 | ipnum=$((ipnum & ~(2 ** (32 - ipsub[1]) - 1)))
219 | SUBNET=$((ipnum >> 24 & 255)).$((ipnum >> 16 & 255)).$((ipnum >> 8 & 255)).$((ipnum & 255))/${ipsub[1]}
220 | fi
221 |
222 | if [ "$PREFIX" ]; then
223 | if [ "$KEYFILE" ]; then
224 | # For RFC-7217 (stable privacy addresses), support rdiscd.
225 | # We generate an address using rdiscd-mkaddress here and write it into
226 | # a disk image which we attach to the VM. rdiscd can then pick this up
227 | # in the guest. We could generate a random address here but it's nice
228 | # to be able to know which IPv6 address relates to a MAC address.
229 | IP6ADDR="$(rdiscd-mkaddress -m "$MACADDR" -k "$KEYFILE" "$PREFIX" stable-privacy)"
230 | RDISCD_IMG_FILE="$RDISCD_IMG_DIR/rdiscd_$TAP_IFNAME.img"
231 | run_prog genext2fs -b 1440 "$RDISCD_IMG_FILE"
232 | echo "::$("$UTILS/exp6" "$IP6ADDR" 16 8)" | run_prog e2cp -P 400 - "$RDISCD_IMG_FILE:interface-id"
233 | echo 64 | run_prog e2cp -P 400 - "$RDISCD_IMG_FILE:interface-id-len"
234 | elif [ -n "$PREFIX_AS_ADDR" ]; then
235 | # Use the prefix as the address
236 | IP6ADDR="$("$UTILS/exp6" "${PREFIX%/*}")"
237 | else
238 | # Assume guest uses EUI-64.
239 | IP6ADDR="$("$UTILS/exp6" "$PREFIX" 8):$("$UTILS/eui-64" "$MACADDR")"
240 | fi
241 | # RFC-4941 (privacy extensions) aren't supported since we'd have no way
242 | # to tell nfdhcpd what to use when rewriting neighbour advertisement source
243 | # addresses. Also, allowing any VM to send/receive packets on any address
244 | # isn't desirable - we want to know a VM is only sending traffic on its
245 | # expected address (i.e. it's not impersonating another VM).
246 | fi
247 |
248 | unrule() {
249 | if $IPTABLES -t mangle -L "in$TAP_IFNAME" >& /dev/null; then
250 | $IPTABLES -t mangle -D PREROUTING -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
251 | $IPTABLES -t mangle -F "in$TAP_IFNAME"
252 | $IPTABLES -t mangle -X "in$TAP_IFNAME"
253 | fi
254 | if $IPTABLES -t mangle -L "out$TAP_IFNAME" >& /dev/null; then
255 | $IPTABLES -t mangle -D FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
256 | $IPTABLES -t mangle -F "out$TAP_IFNAME"
257 | $IPTABLES -t mangle -X "out$TAP_IFNAME"
258 | fi
259 | if $IPTABLES -L "in$TAP_IFNAME" >& /dev/null; then
260 | $IPTABLES -D FORWARD -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
261 | $IPTABLES -D INPUT -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
262 | $IPTABLES -F "in$TAP_IFNAME"
263 | $IPTABLES -X "in$TAP_IFNAME"
264 | fi
265 | if $IPTABLES -L "out$TAP_IFNAME" >& /dev/null; then
266 | $IPTABLES -D FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
267 | $IPTABLES -D FORWARD -o "$BRIDGE" -d "$IPADDR" -j "out$TAP_IFNAME"
268 | $IPTABLES -D OUTPUT -o "$BRIDGE" -d "$IPADDR" -j "out$TAP_IFNAME"
269 | $IPTABLES -F "out$TAP_IFNAME"
270 | $IPTABLES -X "out$TAP_IFNAME"
271 | fi
272 | if $IP6TABLES -t mangle -L "in$TAP_IFNAME" >& /dev/null; then
273 | $IP6TABLES -t mangle -D PREROUTING -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
274 | $IP6TABLES -t mangle -F "in$TAP_IFNAME"
275 | $IP6TABLES -t mangle -X "in$TAP_IFNAME"
276 | fi
277 | if $IP6TABLES -t mangle -L "out$TAP_IFNAME" >& /dev/null; then
278 | $IP6TABLES -t mangle -D FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
279 | $IP6TABLES -t mangle -F "out$TAP_IFNAME"
280 | $IP6TABLES -t mangle -X "out$TAP_IFNAME"
281 | fi
282 | if $IP6TABLES -L "in$TAP_IFNAME" >& /dev/null; then
283 | $IP6TABLES -D INPUT -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
284 | $IP6TABLES -D FORWARD -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
285 | $IP6TABLES -F "in$TAP_IFNAME"
286 | $IP6TABLES -X "in$TAP_IFNAME"
287 | fi
288 | if $IP6TABLES -L "out$TAP_IFNAME" >& /dev/null; then
289 | $IP6TABLES -D FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
290 | $IP6TABLES -D FORWARD -o "$BRIDGE" -d "$IP6ADDR" -j "out$TAP_IFNAME"
291 | $IP6TABLES -D OUTPUT -o "$BRIDGE" -d "$IP6ADDR" -j "out$TAP_IFNAME"
292 | $IP6TABLES -F "out$TAP_IFNAME"
293 | $IP6TABLES -X "out$TAP_IFNAME"
294 | fi
295 | if $EBTABLES -t nat -L "in$TAP_IFNAME" >& /dev/null; then
296 | $EBTABLES -t nat -D PREROUTING -i "$TAP_IFNAME" -j "in$TAP_IFNAME"
297 | $EBTABLES -t nat -F "in$TAP_IFNAME"
298 | $EBTABLES -t nat -X "in$TAP_IFNAME"
299 | fi
300 | #$EBTABLES -D FORWARD --log >& /dev/null || true
301 | if $EBTABLES -L "in$TAP_IFNAME" >& /dev/null; then
302 | $EBTABLES -D FORWARD -i "$TAP_IFNAME" -j "in$TAP_IFNAME"
303 | $EBTABLES -F "in$TAP_IFNAME"
304 | $EBTABLES -X "in$TAP_IFNAME"
305 | fi
306 | if $EBTABLES -L "out$TAP_IFNAME" >& /dev/null; then
307 | $EBTABLES -D FORWARD -o "$TAP_IFNAME" -j "out$TAP_IFNAME"
308 | $EBTABLES -F "out$TAP_IFNAME"
309 | $EBTABLES -X "out$TAP_IFNAME"
310 | fi
311 | }
312 |
313 | rule() {
314 | $EBTABLES -t nat -N "in$TAP_IFNAME" -P RETURN
315 | $EBTABLES -t nat -I PREROUTING -i "$TAP_IFNAME" -j "in$TAP_IFNAME"
316 |
317 | if [ "$IPSUB" ]; then
318 | $IPTABLES -t mangle -N "in$TAP_IFNAME"
319 | $IPTABLES -t mangle -I PREROUTING -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
320 | $IPTABLES -t mangle -A "in$TAP_IFNAME" -p udp --dport bootps -j NFQUEUE --queue-num "$DHCP_QUEUE"
321 | $IPTABLES -t mangle -A "in$TAP_IFNAME" -p udp --dport domain -j NFQUEUE --queue-num "$DNS_QUEUE"
322 |
323 | $IPTABLES -t mangle -N "out$TAP_IFNAME"
324 | $IPTABLES -t mangle -I FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
325 | $IPTABLES -t mangle -A "out$TAP_IFNAME" -p udp --dport domain -j NFQUEUE --queue-num "$DNS_QUEUE"
326 |
327 | #$IPTABLES -t mangle -L
328 |
329 | $IPTABLES -N "in$TAP_IFNAME"
330 | $IPTABLES -I FORWARD -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
331 | $IPTABLES -I INPUT -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
332 | if [ "$GATEWAY_MAC" ]; then
333 | $IPTABLES -A "in$TAP_IFNAME" -s "$IPADDR" -m mark --mark "$MARK_GATEWAY/$MARK_GATEWAY" $GATEWAY_ACTION
334 | fi
335 | $IPTABLES -A "in$TAP_IFNAME" -s "$IPADDR" -d "$SUBNET" -j RETURN
336 | for addr in "${MULTI4[@]}"; do
337 | $IPTABLES -A "in$TAP_IFNAME" -s "$IPADDR" -d "$addr" -j RETURN
338 | done
339 | $IPTABLES -A "in$TAP_IFNAME" -j REJECT
340 |
341 | $IPTABLES -N "out$TAP_IFNAME"
342 | $IPTABLES -I FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
343 | $IPTABLES -I FORWARD -o "$BRIDGE" -d "$IPADDR" -j "out$TAP_IFNAME"
344 | $IPTABLES -I OUTPUT -o "$BRIDGE" -d "$IPADDR" -j "out$TAP_IFNAME"
345 | if [ "$GATEWAY" ]; then
346 | $IPTABLES -A "out$TAP_IFNAME" ! -s "$SUBNET" -d "$IPADDR" $GATEWAY_ACTION
347 | $IPTABLES -A "out$TAP_IFNAME" -s "$GATEWAY" -d "$IPADDR" $GATEWAY_ACTION
348 | fi
349 | $IPTABLES -A "out$TAP_IFNAME" -s "$SUBNET" -d "$IPADDR" -j RETURN
350 | for addr in "${MULTI4[@]}"; do
351 | $IPTABLES -A "out$TAP_IFNAME" -s "$SUBNET" -d "$addr" -j RETURN
352 | done
353 | $IPTABLES -A "out$TAP_IFNAME" -j REJECT
354 | #$IPTABLES -L
355 |
356 | if [ "$NAMESERVER" ]; then
357 | $EBTABLES -t nat -A "in$TAP_IFNAME" -p arp --arp-opcode request --arp-ip-dst "$NAMESERVER" -j arpreply --arpreply-mac "$MACADDR"
358 | fi
359 | if [ "$GATEWAY_MAC" ]; then
360 | $EBTABLES -t nat -A "in$TAP_IFNAME" -d "$GATEWAY_MAC" -j mark --mark-or "$MARK_GATEWAY" --mark-target CONTINUE
361 | fi
362 | #$EBTABLES -t nat -L
363 | fi
364 |
365 | if [ "$PREFIX" ]; then
366 | $IP6TABLES -t mangle -N "in$TAP_IFNAME"
367 | $IP6TABLES -t mangle -I PREROUTING -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
368 | $IP6TABLES -t mangle -A "in$TAP_IFNAME" -p udp --dport dhcpv6-server -j NFQUEUE --queue-num "$DHCP6_QUEUE"
369 | $IP6TABLES -t mangle -A "in$TAP_IFNAME" -p udp --dport domain -j NFQUEUE --queue-num "$DNS6_QUEUE"
370 | $IP6TABLES -t mangle -A "in$TAP_IFNAME" -p ipv6-icmp --icmpv6-type router-solicitation -j NFQUEUE --queue-num "$RS_QUEUE"
371 | $IP6TABLES -t mangle -A "in$TAP_IFNAME" -p ipv6-icmp --icmpv6-type neighbour-solicitation -j NFQUEUE --queue-num "$NS_QUEUE"
372 |
373 | $IP6TABLES -t mangle -N "out$TAP_IFNAME"
374 | $IP6TABLES -t mangle -I FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
375 | $IP6TABLES -t mangle -A "out$TAP_IFNAME" -p udp --dport domain -j NFQUEUE --queue-num "$DNS6_QUEUE"
376 |
377 | #$IP6TABLES -t mangle -L
378 |
379 | $IP6TABLES -N "in$TAP_IFNAME"
380 | $IP6TABLES -I FORWARD -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
381 | $IP6TABLES -I INPUT -m physdev --physdev-in "$TAP_IFNAME" -j "in$TAP_IFNAME"
382 | if [ "$GATEWAY6_MAC" ]; then
383 | $IP6TABLES -A "in$TAP_IFNAME" -s "$IP6ADDR" -m mark --mark "$MARK_GATEWAY6/$MARK_GATEWAY6" $GATEWAY6_ACTION
384 | fi
385 | $IP6TABLES -A "in$TAP_IFNAME" -s "$IP6ADDR" -d "$PREFIX" -j RETURN
386 | for addr in "${MULTI6[@]}"; do
387 | $IP6TABLES -A "in$TAP_IFNAME" -s "$IP6ADDR" -d "$addr" -j RETURN
388 | done
389 | # Allow packets to solicited-node multicast addresses (for neighbour
390 | # solicitations). nfdhcpd checks if the request is for the allocated
391 | # prefix (and only intercepts if it's not). nfdhcp also sets the source
392 | # address to the non-link local address.
393 | # Note that we expect neighbour advertisements to have non-link local
394 | # source and destination.
395 | $IP6TABLES -A "in$TAP_IFNAME" -s "$IP6ADDR" -d ff02:0:0:0:0:1:ff00::/104 -p ipv6-icmp --icmpv6-type neighbour-solicitation -j RETURN
396 | $IP6TABLES -A "in$TAP_IFNAME" -j REJECT
397 |
398 | $IP6TABLES -N "out$TAP_IFNAME"
399 | $IP6TABLES -I FORWARD -m physdev --physdev-is-bridged --physdev-out "$TAP_IFNAME" -j "out$TAP_IFNAME"
400 | $IP6TABLES -I FORWARD -o "$BRIDGE" -d "$IP6ADDR" -j "out$TAP_IFNAME"
401 | $IP6TABLES -I OUTPUT -o "$BRIDGE" -d "$IP6ADDR" -j "out$TAP_IFNAME"
402 | if [ "$GATEWAY6_MAC" ]; then
403 | $IP6TABLES -A "out$TAP_IFNAME" ! -s "$PREFIX" -d "$IP6ADDR" $GATEWAY6_ACTION
404 | $IP6TABLES -A "out$TAP_IFNAME" -s "$GATEWAY6" -d "$IP6ADDR" $GATEWAY6_ACTION
405 | fi
406 | $IP6TABLES -A "out$TAP_IFNAME" -s "$PREFIX" -d "$IP6ADDR" -j RETURN
407 | for addr in "${MULTI6[@]}"; do
408 | $IP6TABLES -A "out$TAP_IFNAME" -s "$PREFIX" -d "$addr" -j RETURN
409 | done
410 | # Allow packets to our solicited-node multicast address (for neighbour
411 | # solicitations).
412 | # Note that we expect neighbour advertisements to have non-link local
413 | # source and destination.
414 | $IP6TABLES -A "out$TAP_IFNAME" -s "$PREFIX" -d "$("$UTILS/solip6" "$IP6ADDR")" -p ipv6-icmp --icmpv6-type neighbour-solicitation -j RETURN
415 | $IP6TABLES -A "out$TAP_IFNAME" -j REJECT
416 | #$IP6TABLES -L
417 |
418 | if [ "$GATEWAY6_MAC" ]; then
419 | $EBTABLES -t nat -A "in$TAP_IFNAME" -d "$GATEWAY6_MAC" -j mark --mark-or "$MARK_GATEWAY6" --mark-target CONTINUE
420 | fi
421 | fi
422 |
423 | NOTIFY_PORT="$(config notify_port "$NFDHCPD_BINDING_IN")"
424 | if [ "$NOTIFY_PORT" ]; then
425 | if [ "$IPSUB" ]; then
426 | NOTIFY_IP="$(config notify_ip "$NFDHCPD_BINDING_IN")"
427 | if [ "$NOTIFY_IP" ]; then
428 | $IPTABLES -t mangle -A "in$TAP_IFNAME" -p udp -d "$NOTIFY_IP" --dport "$NOTIFY_PORT" -j NFQUEUE --queue-num "$NOTIFY_QUEUE"
429 | $IPTABLES -t mangle -A "in$TAP_IFNAME" -p udp --dport "$NOTIFY_PORT" -j DROP
430 | $IPTABLES -t mangle -A "in$TAP_IFNAME" -p tcp --dport "$NOTIFY_PORT" -j DROP
431 | $IPTABLES -I "out$TAP_IFNAME" -p udp --dport "$NOTIFY_PORT" -j REJECT
432 | $IPTABLES -I "out$TAP_IFNAME" -p tcp --dport "$NOTIFY_PORT" -j REJECT
433 | $EBTABLES -t nat -A "in$TAP_IFNAME" -p arp --arp-opcode request --arp-ip-dst "$NOTIFY_IP" -j arpreply --arpreply-mac "$MACADDR"
434 | fi
435 | fi
436 | if [ "$PREFIX" ]; then
437 | NOTIFY_IP6="$(config notify_ip6 "$NFDHCPD_BINDING_IN")"
438 | if [ "$NOTIFY_IP6" ]; then
439 | $IP6TABLES -t mangle -A "in$TAP_IFNAME" -p udp -d "$NOTIFY_IP6" --dport "$NOTIFY_PORT" -j NFQUEUE --queue-num "$NOTIFY6_QUEUE"
440 | $IP6TABLES -t mangle -A "in$TAP_IFNAME" -p udp --dport "$NOTIFY_PORT" -j DROP
441 | $IP6TABLES -t mangle -A "in$TAP_IFNAME" -p tcp --dport "$NOTIFY_PORT" -j DROP
442 | $IP6TABLES -I "out$TAP_IFNAME" -p udp --dport "$NOTIFY_PORT" -j REJECT
443 | $IP6TABLES -I "out$TAP_IFNAME" -p tcp --dport "$NOTIFY_PORT" -j REJECT
444 | fi
445 | fi
446 | fi
447 |
448 | #$EBTABLES -I FORWARD --log
449 | $EBTABLES -N "in$TAP_IFNAME" -P DROP
450 | $EBTABLES -A FORWARD -i "$TAP_IFNAME" -j "in$TAP_IFNAME"
451 | # Stop any packets not from allocated MAC address
452 | $EBTABLES -A "in$TAP_IFNAME" -s ! "$MACADDR" -j DROP
453 | if [ "$IPSUB" ]; then
454 | # Allow ARP packets from this IP address to subnet
455 | $EBTABLES -A "in$TAP_IFNAME" -p arp --arp-ip-src "$IPADDR" --arp-ip-dst "$SUBNET" -j RETURN
456 | # Allow IPv4
457 | $EBTABLES -A "in$TAP_IFNAME" -p ipv4 -j RETURN
458 | fi
459 | if [ "$PREFIX" ]; then
460 | # Allow IPv6
461 | $EBTABLES -A "in$TAP_IFNAME" -p ipv6 -j RETURN
462 | fi
463 |
464 | $EBTABLES -N "out$TAP_IFNAME" -P DROP
465 | $EBTABLES -A FORWARD -o "$TAP_IFNAME" -j "out$TAP_IFNAME"
466 | if [ "$IPSUB" ]; then
467 | # Allow ARP requests for this IP address from subnet
468 | $EBTABLES -A "out$TAP_IFNAME" -p arp --arp-opcode request --arp-ip-src "$SUBNET" --arp-ip-dst "$IPADDR" -j RETURN
469 | # Allow IPv4 multicast
470 | for addr in "${MULTI4[@]}"; do
471 | $EBTABLES -A "out$TAP_IFNAME" -d "$("$UTILS/mcmac4" "$addr")" -j RETURN
472 | done
473 | fi
474 | if [ "$PREFIX" ]; then
475 | # Allow solicited-node multicast requests
476 | $EBTABLES -A "out$TAP_IFNAME" -d "$("$UTILS/solmac" "$IP6ADDR")" -j RETURN
477 | # Allow IPv6 multicast
478 | for addr in "${MULTI6[@]}"; do
479 | $EBTABLES -A "out$TAP_IFNAME" -d "$("$UTILS/mcmac6" "$addr")" -j RETURN
480 | done
481 | fi
482 | # Stop any packets not for allocated MAC address
483 | $EBTABLES -A "out$TAP_IFNAME" -d ! "$MACADDR" -j DROP
484 | if [ "$IPSUB" ]; then
485 | # Allow ARP replies to this IP address but only from subnet
486 | $EBTABLES -A "out$TAP_IFNAME" -p arp --arp-opcode reply --arp-ip-src "$SUBNET" --arp-ip-dst "$IPADDR" -j RETURN
487 | # Allow IPv4
488 | $EBTABLES -A "out$TAP_IFNAME" -p ipv4 -j RETURN
489 | fi
490 | if [ "$PREFIX" ]; then
491 | # Allow IPv6
492 | $EBTABLES -A "out$TAP_IFNAME" -p ipv6 -j RETURN
493 | fi
494 | #$EBTABLES -L
495 | }
496 |
497 | untap() {
498 | if ip link show dev "$TAP_IFNAME" >& /dev/null; then
499 | ip link del dev "$TAP_IFNAME"
500 | fi
501 | }
502 |
503 | tap() {
504 | ip tuntap add dev "$TAP_IFNAME" mode tap
505 | ip link set dev "$TAP_IFNAME" mtu "$MTU"
506 | ip link set dev "$TAP_IFNAME" master "$BRIDGE"
507 | ip link set dev "$TAP_IFNAME" up
508 | }
509 |
510 | cleanup() {
511 | trap - EXIT
512 | untap; unrule
513 | rm -f "$NFDHCPD_BINDING_OUT"
514 | [ "$RDISCD_IMG_FILE" ] && run_prog rm -f "$RDISCD_IMG_FILE"
515 | }
516 |
517 | trap cleanup EXIT # bash calls cleanup when exiting due to signals too
518 |
519 | unrule; rule
520 | untap; tap
521 |
522 | ( echo "MAC=$MACADDR"
523 | [ "$IPADDR" ] && echo "IP=$IPADDR"
524 | [ "$SUBNET" ] && echo "SUBNET=$SUBNET"
525 | [ "$PREFIX" ] && echo "SUBNET6=$PREFIX"
526 | [ "$IP6ADDR" ] && echo "IP6=$IP6ADDR"
527 | echo "BRIDGE=$BRIDGE"
528 | echo "MTU=$MTU"
529 | cat "$NFDHCPD_BINDING_IN" ) > "$NFDHCPD_BINDING_OUT"
530 |
531 | args=("${@//_rdiscd_img_file_/$RDISCD_IMG_FILE}")
532 |
533 | case "$COMMAND" in
534 | kvm|qemu-system-*)
535 | run_prog "$COMMAND" -netdev "tap,id=hn0,ifname=$TAP_IFNAME,script=no,downscript=no" -device "virtio-net-pci,netdev=hn0,id=nic1,mac=$MACADDR" "${args[@]}"
536 | ;;
537 | *)
538 | echo "Unknown fold command '$COMMAND'" >&2
539 | usage
540 | ;;
541 | esac
542 |
543 |
--------------------------------------------------------------------------------
/utils/eui-64:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # make an EUI-64 address from a MAC-48 address
3 | if test $# -ne 1; then
4 | echo "usage: $0 " 1>&2
5 | exit 1
6 | fi
7 | mac="$(echo "$1" | tr -d : | tr A-Z a-z)"
8 | mac="$(echo "$mac" | head -c 6)fffe$(echo "$mac" | tail -c +7)"
9 | let "b = 0x$(echo "$mac" | head -c 2)"
10 | let "b ^= 2"
11 | printf "%02x" "$b"
12 | echo "$mac" | tail -c +3 | head -c 2
13 | echo -n :
14 | echo "$mac" | tail -c +5 | head -c 4
15 | echo -n :
16 | echo "$mac" | tail -c +9 | head -c 4
17 | echo -n :
18 | echo "$mac" | tail -c +13
19 |
--------------------------------------------------------------------------------
/utils/exp6:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # expand an IPv6 address
3 | import argparse, socket, binascii, sys, re
4 | parser = argparse.ArgumentParser()
5 | parser.add_argument("ip6addr", help="IPv6 address")
6 | parser.add_argument("left", help="Number of leftmost bytes to output", type=int, nargs="?", default=16)
7 | parser.add_argument("right", help="Number of rightmost bytes to output", type=int, nargs="?", default=16)
8 | args = parser.parse_args()
9 | ip6addr = args.ip6addr.partition("/")
10 | exp = socket.inet_pton(socket.AF_INET6, ip6addr[0])
11 | if ip6addr[2]:
12 | prefix = int(ip6addr[2])
13 | n = long(exp.encode('hex'), 16)
14 | n &= ~(2 ** (128 - prefix) - 1)
15 | exp = ''.join([chr(n >> (i * 8) & 255) for i in xrange(15, -1, -1)])
16 | hex = binascii.hexlify(exp)
17 | out = hex[:args.left * 2][-args.right * 2:]
18 | if args.right < args.left:
19 | regex = re.compile(r'(.{1,4})(?=(.{4})+)')
20 | else:
21 | regex = re.compile(r'(.{4})(?!$)')
22 | sys.stdout.write(regex.sub(r'\1:', out))
23 |
--------------------------------------------------------------------------------
/utils/lamac:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # generate a random locally-administered MAC address
3 | read -a bytes < <(od -N 6 /dev/urandom -A n -t u1 -v)
4 | let "bytes[0] &= 0xfc"
5 | let "bytes[0] |= 0x2"
6 | for i in "${!bytes[@]}"; do
7 | bytes[$i]=$(printf "%02x" "${bytes[$i]}")
8 | done
9 | IFS=:
10 | echo "${bytes[*]}"
11 |
--------------------------------------------------------------------------------
/utils/mcmac4:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # convert an IPv4 address into a mulicast MAC address
3 | import argparse, socket, binascii, sys, re
4 |
5 | regex = re.compile(r'(.{2})(?!$)')
6 | def fmt(n):
7 | exp = ''.join([chr(n >> (i * 8) & 255) for i in xrange(5, -1, -1)])
8 | hex = binascii.hexlify(exp)
9 | return regex.sub(r'\1:', hex)
10 |
11 | parser = argparse.ArgumentParser()
12 | parser.add_argument("ip4addr", help="IPv4 address")
13 | args = parser.parse_args()
14 | ip4addr = args.ip4addr.partition("/")
15 | b = ip4addr[2]
16 | b = int(b) if b else 32
17 | exp = socket.inet_pton(socket.AF_INET, ip4addr[0])
18 | n = long(exp.encode('hex'), 16)
19 | n &= (2 ** 23 - 1)
20 | n |= 0x01005e000000
21 | m = ~(2 ** (23 - max(b - 9, 0)) - 1)
22 | n &= m
23 | sys.stdout.write(fmt(n))
24 | if b < 32:
25 | sys.stdout.write('/')
26 | sys.stdout.write(fmt(m))
27 |
--------------------------------------------------------------------------------
/utils/mcmac6:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # convert an IPv6 address into a mulicast MAC address
3 | import argparse, socket, binascii, sys, re
4 |
5 | regex = re.compile(r'(.{2})(?!$)')
6 | def fmt(n):
7 | exp = ''.join([chr(n >> (i * 8) & 255) for i in xrange(5, -1, -1)])
8 | hex = binascii.hexlify(exp)
9 | return regex.sub(r'\1:', hex)
10 |
11 | parser = argparse.ArgumentParser()
12 | parser.add_argument("ip6addr", help="IPv6 address")
13 | args = parser.parse_args()
14 | ip6addr = args.ip6addr.partition("/")
15 | b = ip6addr[2]
16 | b = int(b) if b else 128
17 | exp = socket.inet_pton(socket.AF_INET6, ip6addr[0])
18 | n = long(exp.encode('hex'), 16)
19 | n &= (2 ** 32 - 1)
20 | n |= 0x333300000000
21 | m = ~(2 ** (32 - max(b - 96, 0)) - 1)
22 | n &= m
23 | sys.stdout.write(fmt(n))
24 | if b < 128:
25 | sys.stdout.write('/')
26 | sys.stdout.write(fmt(m))
27 |
--------------------------------------------------------------------------------
/utils/solip6:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # make solicited-node multicast IPv6 address from IPv6 address
3 | if test $# -ne 1; then
4 | echo "usage: $0 " 1>&2
5 | exit 1
6 | fi
7 | echo -n ff02::1:ff$("$(dirname "$0")/exp6" "$1" 16 3)
8 |
--------------------------------------------------------------------------------
/utils/solmac:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # make solicited-node multicast MAC address from IPv6 address
3 | if test $# -ne 1; then
4 | echo "usage: $0 " 1>&2
5 | exit 1
6 | fi
7 | echo -n 33:33:ff:$("$(dirname "$0")/exp6" "$1" 16 3 | sed 's/\(.\{2\}\)$/:\1/')
8 |
--------------------------------------------------------------------------------