dhcp4: Don't use the non-binding DHCP Conn silently on linux.

pixiecore: Plumb NewSnooperConn into Server as an advanced option.
pixiecore/cli: Plumb DHCPNoBind to the CLI.

Now, by default, Pixiecore will bind() to the DHCP server port in a way
that shows up in `netstat` by default. If you want to enable the "coexist
with my existing DHCP server" mode, you need to explicitly pass
--dhcp-no-bind.
This commit is contained in:
David Anderson 2016-08-28 16:16:47 -07:00
parent 7bde0dde1b
commit f061a783a7
5 changed files with 61 additions and 17 deletions

View File

@ -26,7 +26,6 @@ import (
// defined as a var so tests can override it.
var (
dhcpClientPort = 68
platformConn func(string) (conn, error)
)
// txType describes how a Packet should be sent on the wire.
@ -68,13 +67,6 @@ type Conn struct {
// NewConn creates a Conn bound to the given UDP ip:port.
func NewConn(addr string) (*Conn, error) {
if platformConn != nil {
c, err := platformConn(addr)
if err == nil {
return &Conn{c}, nil
}
}
// Always try falling back to the portable implementation
c, err := newPortableConn(addr)
if err != nil {
return nil, err

View File

@ -36,8 +36,16 @@ type linuxConn struct {
conn *ipv4.RawConn
}
func init() {
platformConn = newLinuxConn
// NewSnooperConn creates a Conn that listens on the given UDP ip:port.
//
// Unlike NewConn, NewSnooperConn does not bind to the ip:port,
// enabling the Conn to coexist with other services on the machine.
func NewSnooperConn(addr string) (*Conn, error) {
c, err := newLinuxConn(addr)
if err != nil {
return nil, err
}
return &Conn{c}, nil
}
func newLinuxConn(addr string) (conn, error) {

27
dhcp4/conn_unsupported.go Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//+build !linux
package dhcp4
import "errors"
// NewSnooperConn creates a Conn that listens on the given UDP ip:port.
//
// Unlike NewConn, NewSnooperConn does not bind to the ip:port,
// enabling the Conn to coexist with other services on the machine.
func NewSnooperConn(addr string) (*Conn, error) {
return nil, errors.New("snooper Conns not supported on this OS")
}

View File

@ -73,9 +73,10 @@ func serverConfigFlags(cmd *cobra.Command) {
cmd.Flags().BoolP("log-timestamps", "t", false, "Add a timestamp to each log line")
cmd.Flags().IPP("listen-addr", "l", net.IPv4zero, "IPv4 address to listen on")
cmd.Flags().IntP("port", "p", 80, "Port to listen on for HTTP")
cmd.Flags().String("ipxe-bios", "", "path to an iPXE binary for BIOS/UNDI")
cmd.Flags().String("ipxe-efi32", "", "path to an iPXE binary for 32-bit UEFI")
cmd.Flags().String("ipxe-efi64", "", "path to an iPXE binary for 64-bit UEFI")
cmd.Flags().Bool("dhcp-no-bind", false, "Handle DHCP traffic without binding to the DHCP server port")
cmd.Flags().String("ipxe-bios", "", "Path to an iPXE binary for BIOS/UNDI")
cmd.Flags().String("ipxe-efi32", "", "Path to an iPXE binary for 32-bit UEFI")
cmd.Flags().String("ipxe-efi64", "", "Path to an iPXE binary for 64-bit UEFI")
}
func mustFile(path string) []byte {
@ -104,6 +105,10 @@ func serverFromFlags(cmd *cobra.Command) *pixiecore.Server {
if err != nil {
fatalf("Error reading flag: %s", err)
}
dhcpNoBind, err := cmd.Flags().GetBool("dhcp-no-bind")
if err != nil {
fatalf("Error reading flag: %s", err)
}
ipxeBios, err := cmd.Flags().GetString("ipxe-bios")
if err != nil {
fatalf("Error reading flag: %s", err)
@ -125,9 +130,10 @@ func serverFromFlags(cmd *cobra.Command) *pixiecore.Server {
}
ret := &pixiecore.Server{
Ipxe: map[pixiecore.Firmware][]byte{},
Log: logWithStdFmt,
HTTPPort: httpPort,
Ipxe: map[pixiecore.Firmware][]byte{},
Log: logWithStdFmt,
HTTPPort: httpPort,
DHCPNoBind: dhcpNoBind,
}
for fwtype, bs := range Ipxe {
ret.Ipxe[fwtype] = bs

View File

@ -154,6 +154,12 @@ type Server struct {
TFTPPort int
PXEPort int
// Listen for DHCP traffic without binding to the DHCP port. This
// enables coexistence of Pixiecore with another DHCP server.
//
// Currently only supported on Linux.
DHCPNoBind bool
errs chan error
}
@ -173,7 +179,12 @@ func (s *Server) Serve() error {
s.HTTPPort = portHTTP
}
dhcp, err := dhcp4.NewConn(fmt.Sprintf("%s:%d", s.Address, s.DHCPPort))
newDHCP := dhcp4.NewConn
if s.DHCPNoBind {
newDHCP = dhcp4.NewSnooperConn
}
dhcp, err := newDHCP(fmt.Sprintf("%s:%d", s.Address, s.DHCPPort))
if err != nil {
return err
}