summaryrefslogtreecommitdiff
path: root/tinc.go
diff options
context:
space:
mode:
Diffstat (limited to 'tinc.go')
-rw-r--r--tinc.go125
1 files changed, 125 insertions, 0 deletions
diff --git a/tinc.go b/tinc.go
new file mode 100644
index 0000000..76857cb
--- /dev/null
+++ b/tinc.go
@@ -0,0 +1,125 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "net"
+ "os"
+ "strings"
+)
+
+type Error struct {
+ File string
+ Line int
+ Err error
+}
+
+func (e Error) Error() string {
+ if e.Line > 0 {
+ return fmt.Sprintf("%v:%v: %v", e.File, e.Line, e.Err)
+ } else {
+ return fmt.Sprintf("%v: %v", e.File, e.Err)
+ }
+}
+
+func parseConfigLine(line string) (key, val string) {
+ line = strings.TrimRight(line, "\t ")
+ keylen := strings.IndexAny(line, "\t =")
+ if keylen < 0 {
+ keylen = len(line)
+ }
+
+ variable := line[:keylen]
+
+ value := strings.TrimLeft(line[keylen:], "\t ")
+ if strings.HasPrefix(value, "=") {
+ value = strings.TrimLeft(value[1:], "\t ")
+ }
+
+ return variable, value
+}
+
+func readConfigFile(fname string) (map[string][]string, error) {
+ config_tree := make(map[string][]string)
+
+ fp, err := os.Open(fname)
+ if err != nil {
+ return nil, Error{File: fname, Err: err}
+ }
+
+ buffer := bufio.NewScanner(fp)
+
+ lineno := 0
+ ignore := false
+ for buffer.Scan() {
+ line := buffer.Text()
+
+ lineno++
+
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+
+ if ignore {
+ if strings.HasPrefix(line, "-----END") {
+ ignore = false
+ }
+
+ continue
+ }
+
+ if strings.HasPrefix(line, "-----BEGIN") {
+ ignore = true
+ continue
+
+ }
+
+ variable, value := parseConfigLine(line)
+ if len(value) == 0 {
+ err = fmt.Errorf("No value for variable: %s", variable)
+ return nil, Error{File: fname, Line: lineno, Err: err}
+ }
+ variable = strings.ToLower(variable)
+ config_tree[variable] = append(config_tree[variable], value)
+ }
+
+ err = buffer.Err()
+ if err != nil {
+ return nil, Error{File: fname, Err: err}
+ }
+ return config_tree, nil
+}
+
+// Returns a list of public addresses for a host-config in Go
+// "net.Dial" format.
+func getAddresses(cfg map[string][]string) []string {
+ var result []string
+
+ for _, node := range cfg["address"] {
+ var port string
+ space := strings.IndexByte(node, ' ')
+ if space < 0 {
+ if ports, portsOk := cfg["port"]; portsOk {
+ port = ports[0]
+ } else {
+ port = "655"
+ }
+ } else {
+ port = node[space+1:]
+ node = node[:space]
+ }
+
+ if isIPv6(node) {
+ result = append(result, fmt.Sprintf("[%s]:%s", node, port))
+ } else {
+ result = append(result, fmt.Sprintf("%s:%s", node, port))
+ }
+ }
+
+ return result
+}
+
+func isIPv6(node string) bool {
+ ip := net.ParseIP(node)
+ return ip != nil && ip.To4() == nil
+}