- Add directory information with Unicode table borders - Add network information with professional formatting - Add version command - Add comprehensive documentation (README.md, DEVELOPMENT.md) - Improve table output with proper borders and alignment - Add project structure (cmd/, pkg/ directories)
231 lines
5.3 KiB
Go
231 lines
5.3 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/zemenawi/zutils/pkg/colors"
|
|
)
|
|
|
|
func NetworkInfoCommand(args []string) error {
|
|
PrintBoxHeader("NETWORK INFORMATION", colors.Cyan)
|
|
|
|
PrintSectionHeader("IP ADDRESSES")
|
|
|
|
interfaces, err := net.Interfaces()
|
|
if err == nil {
|
|
for _, iface := range interfaces {
|
|
if iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagLoopback == 0 {
|
|
addrs, err := iface.Addrs()
|
|
if err == nil {
|
|
for _, addr := range addrs {
|
|
var ip net.IP
|
|
switch v := addr.(type) {
|
|
case *net.IPNet:
|
|
ip = v.IP
|
|
case *net.IPAddr:
|
|
ip = v.IP
|
|
}
|
|
|
|
if ip != nil && !ip.IsLoopback() {
|
|
fmt.Printf("%s%s🌐%s %s%-18s%s %s\n",
|
|
colors.Green, colors.Bold, colors.Reset,
|
|
colors.Cyan, iface.Name, colors.Reset,
|
|
ip.String())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
fmt.Printf("%sError getting network interfaces: %v%s\n", colors.Red, err, colors.Reset)
|
|
}
|
|
fmt.Println()
|
|
|
|
PrintSectionHeader("PUBLIC IP")
|
|
publicIP := getPublicIP()
|
|
if publicIP != "" {
|
|
fmt.Printf("%s%s🌍%s Public IP: %s%s%s\n",
|
|
colors.Green, colors.Bold, colors.Reset,
|
|
colors.Cyan, publicIP, colors.Reset)
|
|
} else {
|
|
fmt.Printf("%sUnable to determine public IP%s\n", colors.Yellow, colors.Reset)
|
|
}
|
|
fmt.Println()
|
|
|
|
PrintSectionHeader("DNS INFO")
|
|
dnsServers := getDNSServers()
|
|
for i, dns := range dnsServers {
|
|
fmt.Printf("%s%s🔗%s DNS Server %d: %s%s%s\n",
|
|
colors.Green, colors.Bold, colors.Reset,
|
|
i+1,
|
|
colors.Cyan, dns, colors.Reset)
|
|
}
|
|
fmt.Println()
|
|
|
|
PrintSectionHeader("ACTIVE CONNECTIONS")
|
|
connections := getNetworkConnections()
|
|
if len(connections) > 0 {
|
|
maxShow := 10
|
|
if len(connections) < maxShow {
|
|
maxShow = len(connections)
|
|
}
|
|
|
|
headers := []string{"#", "Proto", "State", "Local Address", "Remote Address"}
|
|
data := make([][]string, 0, maxShow)
|
|
|
|
for i := 0; i < maxShow; i++ {
|
|
parsed := parseConnection(connections[i])
|
|
row := []string{
|
|
fmt.Sprintf("%d", i+1),
|
|
parsed.proto,
|
|
parsed.state,
|
|
parsed.local,
|
|
parsed.remote,
|
|
}
|
|
data = append(data, row)
|
|
}
|
|
|
|
printSimpleTable(headers, data)
|
|
|
|
if len(connections) > maxShow {
|
|
fmt.Printf("%s%s...and %d more connections%s\n",
|
|
colors.Gray, colors.Bold, len(connections)-maxShow, colors.Reset)
|
|
}
|
|
fmt.Println()
|
|
} else {
|
|
fmt.Printf("%sNo active connections detected%s\n", colors.Yellow, colors.Reset)
|
|
fmt.Println()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func getPublicIP() string {
|
|
var cmd *exec.Cmd
|
|
|
|
if runtime.GOOS == "windows" {
|
|
cmd = exec.Command("curl", "-s", "ifconfig.me")
|
|
} else {
|
|
cmd = exec.Command("curl", "-s", "ifconfig.me")
|
|
}
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err == nil {
|
|
return strings.TrimSpace(string(output))
|
|
}
|
|
|
|
cmd = exec.Command("wget", "-qO-", "ifconfig.me")
|
|
output, err = cmd.CombinedOutput()
|
|
if err == nil {
|
|
return strings.TrimSpace(string(output))
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func getDNSServers() []string {
|
|
var dnsServers []string
|
|
|
|
if runtime.GOOS == "linux" {
|
|
cmd := exec.Command("sh", "-c", "grep '^nameserver' /etc/resolv.conf | awk '{print $2}'")
|
|
output, err := cmd.CombinedOutput()
|
|
if err == nil {
|
|
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
|
|
for _, line := range lines {
|
|
if line != "" {
|
|
dnsServers = append(dnsServers, line)
|
|
}
|
|
}
|
|
}
|
|
} else if runtime.GOOS == "darwin" {
|
|
cmd := exec.Command("scutil", "--dns")
|
|
output, err := cmd.CombinedOutput()
|
|
if err == nil {
|
|
lines := strings.Split(string(output), "\n")
|
|
for _, line := range lines {
|
|
if strings.Contains(line, "nameserver[") {
|
|
parts := strings.Fields(line)
|
|
if len(parts) >= 3 {
|
|
dnsServers = append(dnsServers, parts[2])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(dnsServers) == 0 {
|
|
dnsServers = append(dnsServers, "8.8.8.8 (Google DNS)")
|
|
dnsServers = append(dnsServers, "1.1.1.1 (Cloudflare DNS)")
|
|
}
|
|
|
|
return dnsServers
|
|
}
|
|
|
|
func getNetworkConnections() []string {
|
|
var connections []string
|
|
|
|
if runtime.GOOS == "linux" {
|
|
cmd := exec.Command("ss", "-tun")
|
|
output, err := cmd.CombinedOutput()
|
|
if err == nil {
|
|
lines := strings.Split(string(output), "\n")
|
|
for i := 1; i < len(lines) && i < 12; i++ {
|
|
line := strings.TrimSpace(lines[i])
|
|
if line != "" {
|
|
connections = append(connections, line)
|
|
}
|
|
}
|
|
}
|
|
} else if runtime.GOOS == "darwin" {
|
|
cmd := exec.Command("netstat", "-an")
|
|
output, err := cmd.CombinedOutput()
|
|
if err == nil {
|
|
lines := strings.Split(string(output), "\n")
|
|
for i := 0; i < len(lines) && i < 11; i++ {
|
|
line := strings.TrimSpace(lines[i])
|
|
if strings.Contains(line, "ESTABLISHED") {
|
|
connections = append(connections, line)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return connections
|
|
}
|
|
|
|
type connectionInfo struct {
|
|
proto string
|
|
state string
|
|
local string
|
|
remote string
|
|
}
|
|
|
|
func parseConnection(conn string) connectionInfo {
|
|
parts := strings.Fields(conn)
|
|
result := connectionInfo{}
|
|
|
|
if len(parts) >= 5 {
|
|
result.proto = parts[0]
|
|
result.state = parts[1]
|
|
|
|
// ss output format: proto state recv-q send-q local remote
|
|
// Try to find addresses by position
|
|
for i := 4; i < len(parts); i++ {
|
|
part := parts[i]
|
|
// Look for IP:port patterns
|
|
if strings.Contains(part, ":") && (strings.Contains(part, ".") || strings.Contains(part, ":")) {
|
|
if result.local == "" {
|
|
result.local = part
|
|
} else {
|
|
result.remote = part
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|