forked from akrennmair/dyndnscd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fetch.go
105 lines (88 loc) · 2.18 KB
/
fetch.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
package main
import (
"bufio"
"github.com/akrennmair/goconf"
"net"
"net/http"
"os"
"syscall"
"unsafe"
)
type Fetcher interface {
FetchIP() (net.IP, error)
Source() string
}
func NewFetcher(c *conf.ConfigFile, section string) (f Fetcher, e error) {
sectiontype, err := c.GetString(section, "type")
if err != nil {
return nil, err
}
switch sectiontype {
case "ipbouncer":
bouncer_url, e1 := c.GetString(section, "bouncer_url")
if e1 != nil {
return nil, NewConfigMissingError("bouncer_url")
}
return NewIPBouncerFetcher(bouncer_url), nil
case "device":
device, e1 := c.GetString(section, "device")
if e1 != nil {
return nil, NewConfigMissingError("device")
}
return NewDeviceFetcher(device), nil
}
return nil, NewUnknownSectionTypeError(sectiontype)
}
type IPBouncerFetcher struct {
bouncer_url string
}
func NewIPBouncerFetcher(bouncer_url string) Fetcher {
f := &IPBouncerFetcher{}
f.bouncer_url = bouncer_url
return f
}
func (f IPBouncerFetcher) Source() string {
return f.bouncer_url
}
func (f IPBouncerFetcher) FetchIP() (ip net.IP, e error) {
httpclient := &http.Client{}
resp, err := httpclient.Get(f.bouncer_url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
httpdata := bufio.NewReader(resp.Body)
ipdata, _, err2 := httpdata.ReadLine()
if err2 != nil {
return nil, err2
}
return net.ParseIP(string(ipdata)), nil
}
type DeviceFetcher struct {
device string
}
func NewDeviceFetcher(device string) Fetcher {
f := &DeviceFetcher{}
f.device = device
return f
}
func (f DeviceFetcher) Source() string {
return f.device
}
func (f DeviceFetcher) FetchIP() (ip net.IP, err error) {
var ifreqbuf [40]byte
for i := 0; i < 40; i++ {
ifreqbuf[i] = 0
}
for i := 0; i < len(f.device); i++ {
ifreqbuf[i] = f.device[i]
}
socketfd, _, _ := syscall.Syscall(syscall.SYS_SOCKET, syscall.AF_INET, syscall.SOCK_DGRAM, 0)
defer syscall.Close(int(socketfd))
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(socketfd), uintptr(syscall.SIOCGIFADDR), uintptr(unsafe.Pointer(&ifreqbuf)))
if err = os.NewSyscallError("SYS_IOCTL", errno); err != nil {
return
}
ip = net.IPv4(ifreqbuf[20], ifreqbuf[21], ifreqbuf[22], ifreqbuf[23])
return
}