Explorar o código

added staticroute plugin

for configuring one or more classless static routes with DHCP option 121

Signed-off-by: Reinier Schoof <reinier@skoef.nl>
Signed-off-by: Reinier Schoof <reinier.schoof@nl.team.blue>
Reinier Schoof %!s(int64=4) %!d(string=hai) anos
pai
achega
2176f33418

+ 1 - 0
cmds/coredhcp-generator/core-plugins.txt

@@ -9,3 +9,4 @@ github.com/coredhcp/coredhcp/plugins/router
 github.com/coredhcp/coredhcp/plugins/serverid
 github.com/coredhcp/coredhcp/plugins/searchdomains
 github.com/coredhcp/coredhcp/plugins/sleep
+github.com/coredhcp/coredhcp/plugins/staticroute

+ 7 - 0
cmds/coredhcp/config.yml.example

@@ -156,3 +156,10 @@ server4:
         # * lease duration can be given in any format understood by go's
         # "ParseDuration": https://golang.org/pkg/time/#ParseDuration
         - range: leases.txt 10.10.10.100 10.10.10.200 60s
+
+        # staticroute advertises additional routes the client should install in
+        # its routing table as described in RFC3442
+        # - staticroute: <destination>,<gateway> [<destination>,<gateway> ...]
+        # where destination should be in CIDR notation and gateway should be
+        # the IP address of the router through which the destination is reachable
+        # - staticroute: 10.20.20.0/24,10.10.10.1

+ 2 - 0
cmds/coredhcp/main.go

@@ -28,6 +28,7 @@ import (
 	pl_searchdomains "github.com/coredhcp/coredhcp/plugins/searchdomains"
 	pl_serverid "github.com/coredhcp/coredhcp/plugins/serverid"
 	pl_sleep "github.com/coredhcp/coredhcp/plugins/sleep"
+	pl_staticroute "github.com/coredhcp/coredhcp/plugins/staticroute"
 
 	"github.com/sirupsen/logrus"
 	flag "github.com/spf13/pflag"
@@ -70,6 +71,7 @@ var desiredPlugins = []*plugins.Plugin{
 	&pl_searchdomains.Plugin,
 	&pl_serverid.Plugin,
 	&pl_sleep.Plugin,
+	&pl_staticroute.Plugin,
 }
 
 func main() {

+ 73 - 0
plugins/staticroute/plugin.go

@@ -0,0 +1,73 @@
+// Copyright 2018-present the CoreDHCP Authors. All rights reserved
+// This source code is licensed under the MIT license found in the
+// LICENSE file in the root directory of this source tree.
+
+package staticroute
+
+import (
+	"errors"
+	"net"
+	"strings"
+
+	"github.com/coredhcp/coredhcp/handler"
+	"github.com/coredhcp/coredhcp/logger"
+	"github.com/coredhcp/coredhcp/plugins"
+	"github.com/insomniacslk/dhcp/dhcpv4"
+)
+
+var log = logger.GetLogger("plugins/staticroute")
+
+// Plugin wraps the information necessary to register a plugin.
+var Plugin = plugins.Plugin{
+	Name:   "staticroute",
+	Setup4: setup4,
+}
+
+var routes dhcpv4.Routes
+
+func setup4(args ...string) (handler.Handler4, error) {
+	log.Printf("loaded plugin for DHCPv4.")
+	routes = make(dhcpv4.Routes, 0)
+
+	if len(args) < 1 {
+		return nil, errors.New("need at least one static route")
+	}
+
+	var err error
+	for _, arg := range args {
+		fields := strings.Split(arg, ",")
+		if len(fields) != 2 {
+			return Handler4, errors.New("expected a destination/gateway pair, got: " + arg)
+		}
+
+		route := &dhcpv4.Route{}
+		_, route.Dest, err = net.ParseCIDR(fields[0])
+		if err != nil {
+			return Handler4, errors.New("expected a destination subnet, got: " + fields[0])
+		}
+
+		route.Router = net.ParseIP(fields[1])
+		if route.Router == nil {
+			return Handler4, errors.New("expected a gateway address, got: " + fields[1])
+		}
+
+		routes = append(routes, route)
+		log.Debugf("adding static route %s", route)
+	}
+
+	log.Printf("loaded %d static routes.", len(routes))
+
+	return Handler4, nil
+}
+
+// Handler4 handles DHCPv4 packets for the static routes plugin
+func Handler4(req, resp *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, bool) {
+	if len(routes) > 0 {
+		resp.Options.Update(dhcpv4.Option{
+			Code:  dhcpv4.OptionCode(dhcpv4.OptionClasslessStaticRoute),
+			Value: routes,
+		})
+	}
+
+	return resp, false
+}

+ 60 - 0
plugins/staticroute/plugin_test.go

@@ -0,0 +1,60 @@
+// Copyright 2018-present the CoreDHCP Authors. All rights reserved
+// This source code is licensed under the MIT license found in the
+// LICENSE file in the root directory of this source tree.
+
+package staticroute
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestSetup4(t *testing.T) {
+	assert.Empty(t, routes)
+
+	var err error
+	// no args
+	_, err = setup4()
+	if assert.Error(t, err) {
+		assert.Equal(t, "need at least one static route", err.Error())
+	}
+
+	// invalid arg
+	_, err = setup4("foo")
+	if assert.Error(t, err) {
+		assert.Equal(t, "expected a destination/gateway pair, got: foo", err.Error())
+	}
+
+	// invalid destination
+	_, err = setup4("foo,")
+	if assert.Error(t, err) {
+		assert.Equal(t, "expected a destination subnet, got: foo", err.Error())
+	}
+
+	// invalid gateway
+	_, err = setup4("10.0.0.0/8,foo")
+	if assert.Error(t, err) {
+		assert.Equal(t, "expected a gateway address, got: foo", err.Error())
+	}
+
+	// valid route
+	_, err = setup4("10.0.0.0/8,192.168.1.1")
+	if assert.NoError(t, err) {
+		if assert.Equal(t, 1, len(routes)) {
+			assert.Equal(t, "10.0.0.0/8", routes[0].Dest.String())
+			assert.Equal(t, "192.168.1.1", routes[0].Router.String())
+		}
+	}
+
+	// multiple valid routes
+	_, err = setup4("10.0.0.0/8,192.168.1.1", "192.168.2.0/24,192.168.1.100")
+	if assert.NoError(t, err) {
+		if assert.Equal(t, 2, len(routes)) {
+			assert.Equal(t, "10.0.0.0/8", routes[0].Dest.String())
+			assert.Equal(t, "192.168.1.1", routes[0].Router.String())
+			assert.Equal(t, "192.168.2.0/24", routes[1].Dest.String())
+			assert.Equal(t, "192.168.1.100", routes[1].Router.String())
+		}
+	}
+}