| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- // 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 redisplugin
- import (
- "errors"
- "fmt"
- "net"
- "strings"
- "time"
- "github.com/coredhcp/coredhcp/handler"
- "github.com/coredhcp/coredhcp/logger"
- "github.com/coredhcp/coredhcp/plugins"
- "github.com/gomodule/redigo/redis"
- "github.com/insomniacslk/dhcp/dhcpv4"
- "github.com/insomniacslk/dhcp/dhcpv6"
- )
- // various global variables
- var (
- log = logger.GetLogger("plugins/redis")
- pool *redis.Pool
- )
- func init() {
- plugins.RegisterPlugin("redis", setupRedis6, setupRedis4)
- }
- // Handler6 handles DHCPv6 packets for the redis plugin
- func Handler6(req, resp dhcpv6.DHCPv6) (dhcpv6.DHCPv6, bool) {
- // TODO add IPv6 support
- return nil, true
- }
- // Handler4 handles DHCPv4 packets for the redis plugin
- func Handler4(req, resp *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, bool) {
- // Get redis connection from pool
- conn := pool.Get()
- // defer redis connection close so we don't leak connections
- defer conn.Close()
- // Get all options for a MAC
- options, err := redis.StringMap(conn.Do("HGETALL", "mac:"+req.ClientHWAddr.String()))
- // Handle redis error
- if err != nil {
- log.Printf("Redis error: %s...dropping request", err)
- return nil, true
- }
- // Handle no hash found
- if len(options) == 0 {
- log.Printf("MAC %s not found...dropping request", req.ClientHWAddr.String())
- return nil, true
- }
- // Handle no ipv4 field
- if options["ipv4"] == "" {
- log.Printf("MAC %s has no ipv4 field...dropping request", req.ClientHWAddr.String())
- return nil, true
- }
- // Loop through options returned and assign as needed
- for option, value := range options {
- switch option {
- case "ipv4":
- ipaddr, ipnet, err := net.ParseCIDR(value)
- if err != nil {
- log.Printf("MAC %s malformed IP %s error: %s...dropping request", req.ClientHWAddr.String(), value, err)
- return nil, true
- }
- resp.YourIPAddr = ipaddr
- resp.Options.Update(dhcpv4.OptSubnetMask(ipnet.Mask))
- log.Printf("MAC %s assigned IPv4 address %s", req.ClientHWAddr.String(), value)
- case "router":
- router := net.ParseIP(value)
- if router.To4() == nil {
- log.Printf("MAC %s Invalid router option: %s...option skipped", req.ClientHWAddr.String(), value)
- break
- }
- resp.Options.Update(dhcpv4.OptRouter(router))
- case "dns":
- var dnsServers4 []net.IP
- servers := strings.Split(value, ",")
- for _, server := range servers {
- DNSServer := net.ParseIP(server)
- if DNSServer.To4() == nil {
- log.Printf("MAC %s Invalid dns server: %s...dropping request", req.ClientHWAddr.String(), server)
- return nil, true
- }
- dnsServers4 = append(dnsServers4, DNSServer)
- }
- if req.IsOptionRequested(dhcpv4.OptionDomainNameServer) {
- resp.Options.Update(dhcpv4.OptDNS(dnsServers4...))
- }
- case "leaseTime":
- lt, err := time.ParseDuration(value)
- if err != nil {
- log.Printf("MAC %s invalid lease time %s...option skipped", req.ClientHWAddr.String(), value)
- break
- }
- // Set lease time
- resp.Options.Update(dhcpv4.OptIPAddressLeaseTime(lt))
- default:
- log.Printf("MAC %s found un-handled option %s...option skipped", req.ClientHWAddr.String(), option)
- }
- }
- return resp, false
- }
- func setupRedis6(args ...string) (handler.Handler6, error) {
- // TODO setup function for IPv6
- log.Warning("not implemented for IPv6")
- return Handler6, nil
- }
- func setupRedis4(args ...string) (handler.Handler4, error) {
- _, h4, err := setupRedis(false, args...)
- return h4, err
- }
- func setupRedis(v6 bool, args ...string) (handler.Handler6, handler.Handler4, error) {
- if len(args) < 1 {
- return nil, nil, fmt.Errorf("invalid number of arguments, want: 1 (redis server:port), got: %d", len(args))
- }
- if args[0] == "" {
- return nil, nil, errors.New("Redis server can't be empty")
- }
- if v6 {
- log.Printf("Using redis server %s for DHCPv6 static leases", args[0])
- } else {
- log.Printf("Using redis server %s for DHCPv4 static leases", args[0])
- }
- // Initialize Redis Pool
- pool = &redis.Pool{
- MaxIdle: 10,
- IdleTimeout: 240 * time.Second,
- Dial: func() (redis.Conn, error) {
- return redis.Dial("tcp", args[0])
- },
- }
- return Handler6, Handler4, nil
- }
|