Example #1
0
func main() {
	// Uncomment the following lines if you need to time the options parsing
	//log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
	//log.Println(": Program started")

	// Configure Command Line Options
	var useUDP, quiet, debug bool
	var maxRTT time.Duration
	var numPing int
	getopt.BoolVarLong(&useUDP, "udp", 'u', "use UDP instead of ICMP")
	getopt.BoolVarLong(&quiet, "quiet", 'q', "only display host data")
	getopt.BoolVarLong(&debug, "debug", 'v', "print additional messages")
	maxRTT = defaultMaxRTT
	getopt.DurationVarLong(&maxRTT, "rtt", 't', "max RTT for each ping")
	numPing = defaultPingCount
	getopt.IntVarLong(&numPing, "count", 'n', "max number of pings per target")
	getopt.SetParameters("startIP endIP")
	getopt.Parse()

	// Verify arguments
	if getopt.NArgs() != 2 {
		log.Println("Incorrect number of arguments!")
		getopt.PrintUsage(os.Stderr)
		os.Exit(1)
	}
	startIPString := getopt.Arg(0)
	endIPString := getopt.Arg(1)

	// Test for incompatible options
	if quiet && debug {
		log.Println("`quiet` and `debug` are incompatible")
		getopt.PrintUsage(os.Stderr)
		os.Exit(1)
	}

	if debug {
		log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
		log.Println(": Command Line Parsing complete")
	}

	// Convert to IP object
	startIP := net.ParseIP(startIPString)
	if startIP == nil {
		log.Fatal("Start IP,", startIPString, ", is not a valid IP address")
	}
	if debug {
		log.Println(": Start IP\t", startIPString)
	}
	endIP := net.ParseIP(endIPString)
	if endIP == nil {
		log.Fatal("End IP,", endIPString, ", is not a valid IP address")
	}
	if debug {
		log.Println(": End IP  \t", endIPString)
	}

	netProto := "ip4:icmp"
	if strings.Index(startIPString, ":") != -1 {
		netProto = "ip6:ipv6-icmp"
	}

	p := fastping.NewPinger()
	p.MaxRTT = maxRTT
	p.OnRecv = func(addr *net.IPAddr, rtt time.Duration) {
		var device resultData
		device.PingResult = addr.String() + "\t" + roundDuration(baseRTT+rtt, time.Millisecond).String()
		ips = append(ips, device)
		p.RemoveIPAddr(addr)
	}

	currentIP := make(net.IP, len(startIP))
	for copy(currentIP, startIP); bytes.Compare(currentIP, endIP) <= 0; inc(currentIP) {
		ra, err := net.ResolveIPAddr(netProto, currentIP.String())
		if err != nil {
			log.Fatal(err)
		}
		p.AddIPAddr(ra)
	}

	if useUDP {
		p.Network("udp")
	}

	if debug {
		log.Println(": Start Scan")
	}

	for index := 0; index < numPing; index++ {
		baseRTT = time.Duration(index) * maxRTT
		err := p.Run()
		if err != nil {
			log.Fatal("Pinger returns error: ", err)
		}
	}

	if debug {
		log.Println(": Scan complete")
	}

	if !quiet {
		fmt.Println()
		fmt.Printf("%d devices found\n", len(ips))
		fmt.Println()
	}

	if debug {
		log.Println(": Start Host Lookup")
	}

	// Query DNS for the name of each device found by the ping scan
	var ipAndTime []string
	var hostname string
	var wg sync.WaitGroup
	for index, ip := range ips {
		ipAndTime = strings.SplitN(ip.PingResult, "\t", 2)
		wg.Add(1)
		go func(ipString string, localIndex int) {
			hosts, err := net.LookupAddr(ipString)
			if err != nil {
				hostname = "Error: " + err.Error()
			} else {
				hostname = strings.Join(hosts, ", ")
			}
			ips[localIndex].HostResult = hostname
			wg.Done()
		}(ipAndTime[0], index)
	}
	wg.Wait()

	if debug {
		log.Println(": DNS complete")
	}

	sort.Sort(byIP(ips))

	if debug {
		log.Println(": Sort complete")
	}

	for _, ip := range ips {
		fmt.Printf("%-25s\t--> %s\n", ip.PingResult, ip.HostResult)
	}

	if !quiet {
		fmt.Println()
	}

	if debug {
		log.Println(": Program complete")
	}
}
Example #2
0
// main program
func main() {
	// local variables
	var err error

	// parse commandline argiments
	getopt.Parse()

	// show help screen and exit in case of -h or --help option
	if *fHelp {
		getopt.Usage()
		os.Exit(1)
	}

	// look for mandatory positional arguments
	if getopt.NArgs() < 1 {
		log.Fatal("Nothing to do. Use -h for help.")
	}

	// by default, read server list from stdin
	ServerListFile := os.Stdin

	// read server names from file if a file name is supplied
	if *fFile != "" {
		ServerListFile, err = os.Open(*fFile)
		if err != nil {
			log.Fatal(fmt.Sprintf("ServerListFile: Error: %v", err))
		}
		defer ServerListFile.Close()
	}
	AddrPadding, ServerList := LoadServerList(ServerListFile)

	// command to run on servers
	fCommand = getopt.Arg(0)

	// make new group
	group := &SshGroup{
		Active:   0,
		Total:    len(ServerList),
		Complete: 0,
	}

	// no point to display more processes than
	if *fProcs > group.Total {
		*fProcs = group.Total
	}

	// print heading text
	fmt.Fprintln(os.Stderr, "gssh - group ssh, ver. 0.6")
	fmt.Fprintln(os.Stderr, "(c)2014 Bozhin Zafirov <*****@*****.**>")
	fmt.Fprintln(os.Stderr)
	fmt.Fprintf(os.Stderr, "  [*] read (%d) hosts from the list\n", group.Total)
	fmt.Fprintf(os.Stderr, "  [*] executing '%s' as user '%s'\n", fCommand, *fUser)
	fmt.Fprintf(os.Stderr, "  [*] spawning %d parallel ssh sessions\n\n", *fProcs)

	// spawn ssh processes
	for i, Server := range ServerList {
		ssh := &SshServer{
			Username: *fUser,
			Address:  Server,
		}
		group.Servers = append(group.Servers, ssh)
		// run command
		group.mu.Lock()
		group.Active++
		group.mu.Unlock()
		go group.Command(ssh, AddrPadding, fCommand)
		// show progless after new process spawn
		group.UpdateProgress()
		if i < group.Total {
			// time delay and max procs wait between spawn
			time.Sleep(time.Duration(*fDelay) * time.Millisecond)
			group.Wait(*fProcs)
		}
	}
	// wait for ssh processes to exit
	group.Wait(0)
	group.mu.Lock()
	group.ClearProgress()
	group.mu.Unlock()

	// calculate stats
	var StdoutServersCount int
	var StderrServersCount int
	var AllServersCount int
	var StdoutLinesCount int
	var StderrLinesCount int
	var AllLinesCount int
	for _, ssh := range group.Servers {
		if ssh.StdoutLineCount > 0 {
			StdoutLinesCount += ssh.StdoutLineCount
			StdoutServersCount++
		}
		if ssh.StderrLineCount > 0 {
			StderrLinesCount += ssh.StderrLineCount
			StderrServersCount++
		}
		if ssh.StdoutLineCount > 0 || ssh.StderrLineCount > 0 {
			AllLinesCount += ssh.StdoutLineCount + ssh.StderrLineCount
			AllServersCount++
		}
	}

	fmt.Fprintln(os.Stderr)
	fmt.Fprintf(os.Stderr, "  Done. Processed: %d / Output: %d (%d) / \033[01;32m->\033[0m %d (%d) / \033[01;31m=>\033[0m %d (%d)\n",
		group.Total,
		AllServersCount,
		AllLinesCount,
		StdoutServersCount,
		StdoutLinesCount,
		StderrServersCount,
		StderrLinesCount,
	)
}