package main import ( "bufio" "fmt" "log" "os" // "time" "strconv" "math/rand" "github.com/songgao/packets/ethernet" "github.com/songgao/water" "github.com/vishvananda/netlink" ) type Client struct { ifce *water.Interface hostname string addr *netlink.Addr } // -- funcs -- // writes out desired hostname to file. generates a small bash script for // the client to run //func generateNewClient() { // // var desired_hostname string // fmt.Printf("Please enter a desired hostname for the new client: ") // // scanner := bufio.NewScanner(os.Stdin) // scanner.Scan() // err := scanner.Err() // if err != nil { // log.Fatal(err) // panic(err) // } // desired_hostname = scanner.Text() // // //} // maps ip --> hostname // used to verify collisions var client_leases = make(map[string]string) func generateClientTUN(hn string) Client { // configure TUN interface config := water.Config{ DeviceType: water.TUN, } config.Name = "tun_"+hn cl_ifce, err := water.New(config) if err != nil { log.Fatal(err) } // Generate a free address to assign var cl_Addr_str string // This is a bad way of doing it, and only accounts for local conflicts // theres definitely a way to find if it conflicts somewhere else // ideally, it shouldnt be locked to this 16 block, either. eventually, // the allowed range (CIDR included) should be defined. // this is an alpha for now, just to get *something* nice working r := rand.New(rand.NewSource(255)) for { var b1 int = int(r.Int31n(255)) var b2 int = int(r.Int31n(255)) cl_Addr_str = "." + strconv.Itoa(b1) + "." + strconv.Itoa(b2) fmt.Println(cl_Addr_str) _, isLeased := client_leases[cl_Addr_str] if !isLeased { break } } cl_Link, err := netlink.LinkByName(config.Name) if err != nil { log.Fatal(err) } cl_Addr, err := netlink.ParseAddr("169.254"+cl_Addr_str+"/16") if err != nil { log.Fatal(err) } // register addr -> ifce with host netlink.AddrAdd(cl_Link, cl_Addr) return Client { ifce: cl_ifce, hostname: hn, addr: cl_Addr, } } func main() { var desired_hostname string fmt.Printf("your nosthanem is ") hn, _ := os.Hostname() fmt.Println(hn) fmt.Printf("Please enter a desired hostname for the new client: ") scanner := bufio.NewScanner(os.Stdin) scanner.Scan() err := scanner.Err() if err != nil { log.Fatal(err) } desired_hostname = scanner.Text() var registered_client Client = generateClientTUN(desired_hostname) log.Printf("interface name: %s\n", registered_client.ifce.Name()) var frame ethernet.Frame ifce := registered_client.ifce for { frame.Resize(1500) n, err := ifce.Read([]byte(frame)) if err != nil { log.Fatal(err) } frame = frame[:n] log.Printf("Dst: %s\n", frame.Destination()) log.Printf("Src: %s\n", frame.Source()) log.Printf("Ethertype: % x\n", frame.Ethertype()) log.Printf("Payload: % x\n", frame.Payload()) } // generateNewClient() }