Browse Source

updating with added test, opted for not doing netmask conversion with recursion

AETH-erial 10 months ago
parent
commit
7bc3e0d258
4 changed files with 146 additions and 10 deletions
  1. 2 2
      Makefile
  2. 18 4
      cmd/kyoketsu/kyoketsu.go
  3. 98 4
      pkg/local.go
  4. 28 0
      pkg/local_test.go

+ 2 - 2
Makefile

@@ -30,8 +30,8 @@ KYOKETSU = kyoketsu
 KYOKETSU_WEB = kyoketsu-web
 
 build:
-	go build -x -v -cover -o ./build/linux/$(KYOKETSU)/$(KYOKETSU) ./cmd/$(KYOKETSU)/$(KYOKETSU).go && \
-	go build -x -v -cover -o ./build/linux/$(KYOKETSU_WEB)/$(KYOKETSU_WEB) ./cmd/$(KYOKETSU_WEB)/$(KYOKETSU_WEB).go
+	go build -o ./build/linux/$(KYOKETSU)/$(KYOKETSU) ./cmd/$(KYOKETSU)/$(KYOKETSU).go && \
+	go build -o ./build/linux/$(KYOKETSU_WEB)/$(KYOKETSU_WEB) ./cmd/$(KYOKETSU_WEB)/$(KYOKETSU_WEB).go
 
 format:
 	go fmt ./...

+ 18 - 4
cmd/kyoketsu/kyoketsu.go

@@ -37,17 +37,17 @@ import (
 	"sync"
 
 	kyoketsu "git.aetherial.dev/aeth/kyoketsu/pkg"
+	"github.com/manifoldco/promptui"
 )
 
-var licenseMsg = "\n	http-wokou  Copyright (C) 2024  Russell Hrubesky, ChiralWorks Software LLC\n	This program comes with ABSOLUTELY NO WARRANTY; for details type `http-wokou --license`\n	This is free software, and you are welcome to redistribute it\n	under certain conditions; type `http-wokou --redist` for details.\n\n"
+var licenseMsg = "\n	kyoketsu  Copyright (C) 2024  Russell Hrubesky, ChiralWorks Software LLC\n	This program comes with ABSOLUTELY NO WARRANTY; for details type `kyoketsu --license`\n	This is free software, and you are welcome to redistribute it\n	under certain conditions; type `kyoketsu --redist` for details.\n\n"
 
 var redistMsg = "\n	This program is free software: you can redistribute it and/or modify\n	it under the terms of the GNU General Public License as published by\n	the Free Software Foundation, either version 3 of the License, or\n	(at your option) any later version.\n\n"
 
-var licenseMsgLong = "\n		GNU GENERAL PUBLIC LICENSE\n		Version 3, 29 June 2007\n	Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n	Everyone is permitted to copy and distribute verbatim copies\n	of this license document, but changing it is not allowed.\n\n	http-wokou, An HTTP Proxying framework for bypassing DNS Security\n	Copyright (C) 2024 Russell Hrubesky, ChiralWorks Software LLC\n\n	This program is free software: you can redistribute it and/or modify\n	it under the terms of the GNU General Public License as published by\n	the Free Software Foundation, either version 3 of the License, or\n	(at your option) any later version.\n\n	This program is distributed in the hope that it will be useful,\n	but WITHOUT ANY WARRANTY; without even the implied warranty of\n	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n	GNU General Public License for more details.\n\n	You should have received a copy of the GNU General Public License\n	along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n"
+var licenseMsgLong = "\n		GNU GENERAL PUBLIC LICENSE\n		Version 3, 29 June 2007\n	Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n	Everyone is permitted to copy and distribute verbatim copies\n	of this license document, but changing it is not allowed.\n\n	kyoketsu, An HTTP Proxying framework for bypassing DNS Security\n	Copyright (C) 2024 Russell Hrubesky, ChiralWorks Software LLC\n\n	This program is free software: you can redistribute it and/or modify\n	it under the terms of the GNU General Public License as published by\n	the Free Software Foundation, either version 3 of the License, or\n	(at your option) any later version.\n\n	This program is distributed in the hope that it will be useful,\n	but WITHOUT ANY WARRANTY; without even the implied warranty of\n	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n	GNU General Public License for more details.\n\n	You should have received a copy of the GNU General Public License\n	along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n"
 
 func main() {
 
-	ip := flag.String("ips", "", "single ip address with CIDR notation to gather info about")
 	licenseInfo := flag.Bool("license", false, "Pass this flag to display license and warantee information.")
 	redistInfo := flag.Bool("redist", false, "Pass this flag to display redistribution information.")
 	flag.Parse()
@@ -61,9 +61,23 @@ func main() {
 		os.Exit(0)
 	}
 	fmt.Println(licenseMsg)
+
 	var err error
+	localAddr, err := kyoketsu.RetrieveLocalAddresses()
+	if err != nil {
+		log.Fatal(err)
+	}
+	prompt := promptui.Select{
+		Label: "Select the network you wish to scan.",
+		Items: localAddr.Choice,
+	}
+	choice, _, err := prompt.Run()
+	if err != nil {
+		log.Fatal(err)
+	}
 	var addr *kyoketsu.IpSubnetMapper
-	addr, err = kyoketsu.GetNetworkAddresses(*ip)
+	targetNet := fmt.Sprintf("%s/%s", localAddr.Choice[choice].HostAddress, localAddr.Choice[choice].Cidr)
+	addr, err = kyoketsu.GetNetworkAddresses(targetNet)
 	if err != nil {
 		log.Fatal(err)
 	}

+ 98 - 4
pkg/local.go

@@ -30,12 +30,15 @@ package kyoketsu
 import (
 	"fmt"
 	"log"
+	"math"
 	"net"
 	"net/netip"
 	"strconv"
 	"strings"
 )
 
+const IPV4_BITLEN = 32
+
 type NetworkInterfaceNotFound struct{ Passed string }
 
 // Implementing error interface
@@ -134,24 +137,115 @@ func GetNetworkAddresses(addr string) (*IpSubnetMapper, error) {
 type PromptEntry struct {
 	HostAddress    string
 	NetworkAddress string
-	Cidr           int
+	Cidr           string
 	SubnetMask     string
 	InterfaceName  string
+	MacAddress     string
 }
 
 type TuiSelectionFeed struct {
 	Choice []PromptEntry
 }
 
+func matchAddressToMac(ip string, intfs []net.Interface) (*PromptEntry, error) {
+	for i := range intfs {
+		intfsAddr, err := intfs[i].Addrs()
+		if err != nil {
+			return nil, err
+		}
+		for x := range intfsAddr {
+			fmt.Println(intfsAddr[x].String())
+		}
+
+	}
+	return nil, nil
+}
+
+func bitsToMask(ones int, bits int) string {
+	var bitmask []int
+
+	for i := 0; i < ones; i++ {
+		bitmask = append(bitmask, 1)
+	}
+	for i := ones; i < bits; i++ {
+		bitmask = append(bitmask, 0)
+	}
+
+	octets := []string{
+		strconv.Itoa(base2to10(bitmask[0:8])),
+		strconv.Itoa(base2to10(bitmask[8:16])),
+		strconv.Itoa(base2to10(bitmask[16:24])),
+		strconv.Itoa(base2to10(bitmask[24:32])),
+	}
+	return strings.Join(octets, ".")
+}
+
+/*
+convert a base 2 number (represented as an array) to a base 10 integer
+
+	:param bits: the slice of ints split into an array, e.g. '11110000' would be [1 1 1 1 0 0 0 0]
+*/
+func base2to10(bits []int) int {
+	var sum int
+	sum = 0
+	for i := range bits {
+		bits[i] = bits[i] * powerInt(2, len(bits)-1-i)
+	}
+	for i := range bits {
+		sum = sum + bits[i]
+	}
+	return sum
+
+}
+
+/*
+	 Wrapper func for getting the value of x to the power of y, as int opposed to float64
+	    :param x: the base number to operate on
+		:param y: the exponent
+*/
+func powerInt(x int, y int) int {
+	return int(math.Pow(float64(x), float64(y)))
+}
+
 func RetrieveLocalAddresses() (TuiSelectionFeed, error) {
 	var tuidata TuiSelectionFeed
+	intf, err := net.Interfaces()
+	if err != nil {
+		return tuidata, err
+	}
 
-	ifaces, err := net.Interfaces()
+	addrs, err := net.InterfaceAddrs()
 	if err != nil {
 		return tuidata, err
 	}
-	for i := range ifaces {
-		fmt.Printf("%+v\n", ifaces[i])
+	for x := range addrs {
+		var mac string
+		var interfacename string
+		ip, net, err := net.ParseCIDR(addrs[x].String())
+		if err != nil {
+			return tuidata, err
+		}
+		for i := range intf {
+			intfAddrs, err := intf[i].Addrs()
+			if err != nil {
+				return tuidata, err
+			}
+			for y := range intfAddrs {
+				if strings.Contains(intfAddrs[y].String(), strings.Split(ip.String(), "/")[0]) {
+					interfacename = intf[i].Name
+					mac = intf[i].HardwareAddr.String()
+				}
+			}
+		}
+		tuidata.Choice = append(tuidata.Choice, PromptEntry{
+			HostAddress:    ip.String(),
+			NetworkAddress: ip.Mask(net.Mask).String(),
+			Cidr:           strings.Split(addrs[x].String(), "/")[1],
+			SubnetMask:     bitsToMask(net.Mask.Size()),
+			MacAddress:     mac,
+			InterfaceName:  interfacename,
+		})
+
 	}
 
 	return tuidata, nil

+ 28 - 0
pkg/local_test.go

@@ -240,3 +240,31 @@ func TestGetNetworkAddresses(t *testing.T) {
 	}
 
 }
+
+func TestBitsToMask(t *testing.T) {
+	type TestCase struct {
+		Name  string
+		Gets  string
+		Wants string
+	}
+
+	tc := []TestCase{
+		TestCase{
+			Name:  "Function gets valid IP with cidr",
+			Gets:  "192.168.50.1/28",
+			Wants: "255.255.255.240",
+		},
+	}
+
+	for i := range tc {
+		_, net, err := net.ParseCIDR(tc[i].Gets)
+		if err != nil {
+			log.Fatal(err)
+		}
+		want := tc[i].Wants
+		got := bitsToMask(net.Mask.Size())
+		if got != want {
+			t.Errorf("test '%s' failed! got: %s\nwanted: %s\n", tc[i].Name, got, want)
+		}
+	}
+}