Example #1
0
// Reads the configuration file specified in global variable File
// and sets the admin credentials
func readConfig() (conf *config.Config, err error) {
	conf, err = config.LoadMinConfig(File)
	if err != nil || len(conf.Admin.Password) == 0 {
		return
	}

	AdminPassword = conf.Admin.Password
	AdminBind = conf.Admin.Bind

	return
}
Example #2
0
func main() {
	//Define the flags, and parse them
	//Clearly a hack but it works for now
	//TODO(inhies): Re-implement flag parsing so flags can have multiple meanings based on the base command (ping, route, etc)
	if len(os.Args) <= 1 {
		usage()
		return
	} else if len(os.Args) == 2 {
		if string(os.Args[1]) == "--help" {
			fs.PrintDefaults()
			return
		}
	} else {
		fs.Parse(os.Args[2:])
	}

	//TODO(inhies): check argv[0] for trailing commands.
	//For example, to run ctraceroute:
	//ln -s /path/to/cjdcmd /usr/bin/ctraceroute like things
	command := os.Args[1]

	if AdminPassword == defaultPass {
		conf, err := config.LoadMinConfig(File)
		fmt.Printf("\nReading config file from %v\n", File)
		if err != nil || len(conf.Admin.Password) == 0 {
			fmt.Printf("Error: %v\n", err)
			return
		}

		AdminPassword = conf.Admin.Password
		AdminBind = conf.Admin.Bind
	} else {
		AdminBind = defaultAdminBind
	}

	fmt.Printf("Attempting to connect to cjdns...")
	user, err := admin.Connect(AdminBind, AdminPassword)
	if err != nil {
		if e, ok := err.(net.Error); ok {
			if e.Timeout() {
				fmt.Println("\nConnection timed out")
			} else if e.Temporary() {
				fmt.Println("\nTemporary error (not sure what that means!)")
			} else {
				fmt.Println("\nUnable to connect to cjdns:", e)
			}
		} else {
			fmt.Println("\nError:", err)
		}
		return
	}

	println("Connected")
	defer user.Conn.Close()
	arguments := fs.Args()
	data := arguments[fs.NFlag()-fs.NFlag():]

	//Setup variables now so that if the program is killed we can still finish what we're doing
	ping := &Ping{}
	var loggingStreamID string

	// capture ctrl+c
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for _ = range c {
			fmt.Printf("\n")
			if command == "log" {
				//unsubscribe from logging
				_, err := admin.AdminLog_unsubscribe(user, loggingStreamID)
				if err != nil {
					fmt.Printf("%v\n", err)
					return
				}
			}
			if command == "ping" {
				//stop pinging and print results
				outputPing(ping)
			}
			//close all the channels
			for _, c := range user.Channels {
				close(c)
			}
			user.Conn.Close()
			return
		}
	}()

	switch command {

	case traceCmd:
		target, err := setTarget(data, false)
		if err != nil {
			fmt.Println(err)
			return
		}
		doTraceroute(user, target)

	case routeCmd:
		target, err := setTarget(data, true)
		if err != nil {
			fmt.Println(err)
			return
		}
		table := getTable(user)
		sort.Sort(ByQuality{table})
		count := 0
		for _, v := range table {
			if v.IP == target || v.Path == target {
				if v.Link > 1 {
					fmt.Printf("IP: %v -- Version: %d -- Path: %s -- Link: %.0f\n", v.IP, v.Version, v.Path, v.Link)
					count++
				}
			}
		}
		fmt.Println("Found", count, "routes")

	case pingCmd:
		// TODO: allow input of IP, hex path with and without dots and leading zeros, and binary path
		// TODO: allow pinging of entire routing table
		target, err := setTarget(data, true)
		if err != nil {
			fmt.Println(err)
			return
		}
		ping.Target = target
		if PingCount != defaultPingCount {
			// ping only as much as the user asked for
			for i := 1; i <= PingCount; i++ {
				err := pingNode(user, ping)
				if err != nil {
					fmt.Println(err)
					return
				}
				println(ping.Response)
			}
		} else {
			// ping until we're told otherwise
			for {
				err := pingNode(user, ping)
				if err != nil {
					fmt.Println(err)
					return
				}
				println(ping.Response)
			}
		}
		outputPing(ping)

	case logCmd:
		var response chan map[string]interface{}
		response, loggingStreamID, err = admin.AdminLog_subscribe(user, LogFile, LogLevel, LogFileLine)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			return
		}
		format := "%d %d %s %s:%d %s\n" // TODO: add user formatted output
		counter := 1
		for {
			input, ok := <-response
			if !ok {
				break
			}
			fmt.Printf(format, counter, input["time"], input["level"], input["file"], input["line"], input["message"])
			counter++
		}

	case peerCmd:
		peers := make([]*Route, 0)
		table := getTable(user)
		sort.Sort(ByQuality{table})
		fmt.Println("Finding all connected peers")

		for i := range table {

			if table[i].Link < 1 {
				continue
			}
			if table[i].RawPath == 1 {
				continue
			}
			response, err := getHops(table, table[i].RawPath)
			if err != nil {
				fmt.Println(err)
			}

			sort.Sort(ByPath{response})

			var peer *Route
			if len(response) > 1 {
				peer = response[1]
			} else {
				peer = response[0]
			}

			found := false
			for _, p := range peers {
				if p == peer {
					found = true
					break
				}
			}

			if !found {
				peers = append(peers, peer)
			}
		}
		for _, p := range peers {
			fmt.Printf("IP: %v -- Path: %s -- Link: %.0f\n", p.IP, p.Path, p.Link)
		}
	case versionCmd:
		// TODO(inhies): Ping a specific node and return it's cjdns version, or
		// ping all nodes in the routing table and get their versions
		// git log -1 --date=iso --pretty=format:"%ad" <hash>

	case killCmd:
		_, err := admin.Core_exit(user)
		if err != nil {
			fmt.Printf("%v\n", err)
			return
		}
		alive := true
		for ; alive; alive, _ = admin.SendPing(user, 1000) {
			runtime.Gosched() //play nice
		}
		println("cjdns is shutting down...")

	case dumpCmd:
		// TODO: add flag to show zero link quality routes, by default hide them
		table := getTable(user)
		sort.Sort(ByQuality{table})
		k := 1
		for _, v := range table {
			if v.Link >= 1 {
				fmt.Printf("%d IP: %v -- Version: %d -- Path: %s -- Link: %.0f\n", k, v.IP, v.Version, v.Path, v.Link)
				k++
			}
		}
	case "memory":
		println("Bye bye cjdns! This command causes a crash. Keep trying and maybe one day cjd will fix it :)")
		response, err := admin.Memory(user)
		if err != nil {
			fmt.Printf("%v\n", err)
			return
		}
		fmt.Println(response)
	default:
		fmt.Println("Invalid command", command)
		usage()
	}
}