IP_STATUS_FILE and routing improvements (#130)
- Obtains VPN public IP address from routing table - Logs and writes VPN Public IP address to `/ip` as soon as VPN is up - Obtain port forward, logs it and writes it as soon as VPN is up - Routing fully refactored and tested - Routing reads from `/proc/net/route` - Routing mutates the routes using `ip route ...`
This commit is contained in:
93
internal/routing/entry.go
Normal file
93
internal/routing/entry.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"strings"
|
||||
)
|
||||
|
||||
type routingEntry struct {
|
||||
iface string
|
||||
destination net.IP
|
||||
gateway net.IP
|
||||
flags string
|
||||
refCount int
|
||||
use int
|
||||
metric int
|
||||
mask net.IPMask
|
||||
mtu int
|
||||
window int
|
||||
irtt int
|
||||
}
|
||||
|
||||
func parseRoutingEntry(s string) (r routingEntry, err error) {
|
||||
wrapError := func(err error) error {
|
||||
return fmt.Errorf("line %q: %w", s, err)
|
||||
}
|
||||
fields := strings.Fields(s)
|
||||
if len(fields) < 11 {
|
||||
return r, wrapError(fmt.Errorf("not enough fields"))
|
||||
}
|
||||
r.iface = fields[0]
|
||||
r.destination, err = reversedHexToIPv4(fields[1])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.gateway, err = reversedHexToIPv4(fields[2])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.flags = fields[3]
|
||||
r.refCount, err = strconv.Atoi(fields[4])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.use, err = strconv.Atoi(fields[5])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.metric, err = strconv.Atoi(fields[6])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.mask, err = hexToIPv4Mask(fields[7])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.mtu, err = strconv.Atoi(fields[8])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.window, err = strconv.Atoi(fields[9])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
r.irtt, err = strconv.Atoi(fields[10])
|
||||
if err != nil {
|
||||
return r, wrapError(err)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func reversedHexToIPv4(reversedHex string) (IP net.IP, err error) {
|
||||
bytes, err := hex.DecodeString(reversedHex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse reversed IP hex %q: %s", reversedHex, err)
|
||||
} else if len(bytes) != 4 {
|
||||
return nil, fmt.Errorf("hex string contains %d bytes instead of 4", len(bytes))
|
||||
}
|
||||
return []byte{bytes[3], bytes[2], bytes[1], bytes[0]}, nil
|
||||
}
|
||||
|
||||
func hexToIPv4Mask(hexString string) (mask net.IPMask, err error) {
|
||||
bytes, err := hex.DecodeString(hexString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse hex mask %q: %s", hexString, err)
|
||||
} else if len(bytes) != 4 {
|
||||
return nil, fmt.Errorf("hex string contains %d bytes instead of 4", len(bytes))
|
||||
}
|
||||
return []byte{bytes[3], bytes[2], bytes[1], bytes[0]}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user