Skip to content

Commit

Permalink
Add httpboot plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
5kt committed Jun 6, 2024
1 parent 1dd896e commit 0abbb3a
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
pl_sleep "github.com/coredhcp/coredhcp/plugins/sleep"
pl_staticroute "github.com/coredhcp/coredhcp/plugins/staticroute"
pl_bluefield "github.com/ironcore-dev/fedhcp/plugins/bluefield"
pl_httpboot "github.com/ironcore-dev/fedhcp/plugins/httpboot"
pl_ipam "github.com/ironcore-dev/fedhcp/plugins/ipam"
pl_onmetal "github.com/ironcore-dev/fedhcp/plugins/onmetal"
pl_oob "github.com/ironcore-dev/fedhcp/plugins/oob"
Expand Down Expand Up @@ -86,6 +87,7 @@ var desiredPlugins = []*plugins.Plugin{
&pl_onmetal.Plugin,
&pl_oob.Plugin,
&pl_pxeboot.Plugin,
&pl_httpboot.Plugin,
}

func main() {
Expand Down
103 changes: 103 additions & 0 deletions plugins/httpboot/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: MIT

package httpboot

import (
"fmt"
"github.com/coredhcp/coredhcp/handler"
"github.com/coredhcp/coredhcp/logger"
"github.com/coredhcp/coredhcp/plugins"
"github.com/insomniacslk/dhcp/dhcpv4"
"github.com/insomniacslk/dhcp/dhcpv6"
"net/url"
"strings"
)

var bootFile4 string
var bootFile6 string

var log = logger.GetLogger("plugins/httpboot")

var Plugin = plugins.Plugin{
Name: "httpboot",
Setup6: setup6,
Setup4: setup4,
}

func parseArgs(args ...string) (*url.URL, error) {
if len(args) != 1 {
return nil, fmt.Errorf("Exactly one argument must be passed to the httpboot plugin, got %d", len(args))
}
return url.Parse(args[0])
}

func setup6(args ...string) (handler.Handler6, error) {
u, err := parseArgs(args...)
if err != nil {
return nil, err
}
bootFile6 = u.String()
log.Printf("loaded httpboot plugin for DHCPv6.")
return Handler6, nil
}

func setup4(args ...string) (handler.Handler4, error) {
u, err := parseArgs(args...)
if err != nil {
return nil, err
}
bootFile4 = u.String()
log.Printf("loaded httpboot plugin for DHCPv4.")
return Handler4, nil
}

func Handler6(req, resp dhcpv6.DHCPv6) (dhcpv6.DHCPv6, bool) {
log.Debugf("Received DHCPv6 request: %s", req.Summary())
decap, err := req.GetInnerMessage()
if err != nil {
log.Errorf("Could not decapsulate request: %v", err)
return nil, true
}

if decap.GetOneOption(dhcpv6.OptionVendorClass) != nil {
vc := decap.GetOneOption(dhcpv6.OptionVendorClass).String()
if strings.Contains(vc, "HTTPClient") {
bf := &dhcpv6.OptionGeneric{
OptionCode: dhcpv6.OptionBootfileURL,
OptionData: []byte(bootFile6),
}
resp.AddOption(bf)
vid := &dhcpv6.OptionGeneric{
OptionCode: dhcpv6.OptionVendorClass,
// 0000 (4 bytes) Enterprise Identifier
// 0a (2 bytes) length of "HTTPClient"
// - rest with HTTPClient
OptionData: []byte("00000aHTTPClient"),
}
resp.AddOption(vid)
}
}

return resp, false
}

func Handler4(req, resp *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, bool) {
log.Debugf("Received DHCPv4 request: %s", req.Summary())
if req.GetOneOption(dhcpv4.OptionClassIdentifier) != nil {
vc := req.GetOneOption(dhcpv4.OptionClassIdentifier)
if strings.Contains(string(vc), "HTTPClient") {
bf := &dhcpv4.Option{
Code: dhcpv4.OptionBootfileName,
Value: dhcpv4.String(bootFile4),
}
resp.Options.Update(*bf)
vid := &dhcpv4.Option{
Code: dhcpv4.OptionClassIdentifier,
Value: dhcpv4.String("HTTPClient"),
}
resp.Options.Update(*vid)
}
}
return resp, false
}

0 comments on commit 0abbb3a

Please sign in to comment.