forked from coredhcp/coredhcp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
160 lines (144 loc) · 4.31 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main
import (
"errors"
"log"
"net"
"time"
"github.com/coredhcp/coredhcp/config"
"github.com/coredhcp/coredhcp/handler"
"github.com/coredhcp/coredhcp/plugins"
_ "github.com/coredhcp/coredhcp/plugins/file"
_ "github.com/coredhcp/coredhcp/plugins/server_id"
"github.com/insomniacslk/dhcp/dhcpv4"
"github.com/insomniacslk/dhcp/dhcpv6"
)
// Application variables
var (
AppName = "CoreDHCP"
AppVersion = "v0.1"
)
// Server is a CoreDHCP server structure that holds information about
// DHCPv6 and DHCPv4 servers, and their respective handlers.
type Server struct {
Handlers6 []handler.Handler6
Handlers4 []handler.Handler4
Config *config.Config
Server6 *dhcpv6.Server
Server4 *dhcpv4.Server
errors chan error
}
// LoadPlugins reads a Viper configuration and loads the plugins
// as specified in the `plugins` section, in order. For a plugin to
// be available, it must have been previously registered with
// plugins.RegisterPlugin. This is normally done at plugin import.
func (s *Server) LoadPlugins(conf *config.Config) ([]*plugins.Plugin, error) {
log.Print("Loading plugins...")
loadedPlugins := make([]*plugins.Plugin, 0)
if conf.Server4 != nil {
return nil, errors.New("plugin loading for DHCPv4 not implemented yet")
}
// load v6 plugins
if conf.Server6 == nil {
return nil, errors.New("no configuration found for DHCPv6 server")
}
// now load the plugins. We need to call its setup function with
// the arguments extracted above. The setup function is mapped in
// plugins.RegisteredPlugins .
for _, pluginConf := range conf.Server6.Plugins {
if plugin, ok := plugins.RegisteredPlugins[pluginConf.Name]; ok {
log.Printf("Loading plugin `%s`", pluginConf.Name)
h6, err := plugin.Setup6(pluginConf.Args...)
if err != nil {
return nil, err
}
loadedPlugins = append(loadedPlugins, plugin)
if h6 == nil {
return nil, config.ConfigErrorFromString("no DHCPv6 handler for plugin %s", pluginConf.Name)
}
s.Handlers6 = append(s.Handlers6, h6)
//s.Handlers4 = append(s.Handlers4, h4)
} else {
return nil, config.ConfigErrorFromString("unknown plugin `%s`", pluginConf.Name)
}
}
return loadedPlugins, nil
}
// MainHandler6 runs for every received DHCPv6 packet. It will run every
// registered handler in sequence, and reply with the resulting response.
// It will not reply if the resulting response is `nil`.
func (s *Server) MainHandler6(conn net.PacketConn, peer net.Addr, req dhcpv6.DHCPv6) {
var (
resp dhcpv6.DHCPv6
stop bool
)
for _, handler := range s.Handlers6 {
resp, stop = handler(req, resp)
if stop {
break
}
}
if resp != nil {
if _, err := conn.WriteTo(resp.ToBytes(), peer); err != nil {
log.Printf("conn.Write to %v failed: %v", peer, err)
}
} else {
log.Print("Dropping request because response is nil")
}
}
// MainHandler4 is like MainHandler6, but for DHCPv4 packets.
func (s *Server) MainHandler4(conn net.PacketConn, peer net.Addr, d *dhcpv4.DHCPv4) {
log.Print(d.Summary())
}
// Start will start the server asynchronously. See `Wait` to wait until
// the execution ends.
func (s *Server) Start() error {
_, err := s.LoadPlugins(s.Config)
if err != nil {
return err
}
// listen
if s.Config.Server6 != nil {
log.Printf("Starting DHCPv6 listener on %v", s.Config.Server6.Listener)
s.Server6 = dhcpv6.NewServer(*s.Config.Server6.Listener, s.MainHandler6)
go func() {
s.errors <- s.Server6.ActivateAndServe()
}()
}
if s.Config.Server4 != nil {
log.Printf("Starting DHCPv4 listener on %v", s.Config.Server6.Listener)
s.Server4 = dhcpv4.NewServer(*s.Config.Server4.Listener, s.MainHandler4)
go func() {
s.errors <- s.Server4.ActivateAndServe()
}()
}
return nil
}
// Wait waits until the end of the execution of the server.
func (s *Server) Wait() error {
log.Print("Waiting")
if s.Server6 != nil {
s.Server6.Close()
}
if s.Server4 != nil {
s.Server4.Close()
}
return <-s.errors
}
// NewServer creates a Server instance with the provided configuration.
func NewServer(config *config.Config) *Server {
return &Server{Config: config, errors: make(chan error, 1)}
}
func main() {
config, err := config.Parse()
if err != nil {
log.Fatal(err)
}
server := NewServer(config)
if err := server.Start(); err != nil {
log.Fatal(err)
}
if err := server.Wait(); err != nil {
log.Print(err)
}
time.Sleep(time.Second)
}