diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..3553527 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,86 @@ +version: 2.1 + +jobs: + build: + docker: + - image: cimg/go:1.20 + steps: + - run: + name: Install upx + command: sudo apt update && sudo apt install upx -y + - checkout + - restore_cache: + keys: + - go-mod-v1-{{ checksum "go.sum" }} + - go-mod-v1 + - run: + name: Install Dependencies + command: go get ./... + - save_cache: + key: go-mod-v1-{{ checksum "go.sum" }} + paths: + - "/go/pkg/mod" + - run: + name: Build + command: go build -C cmd/gowake/ -v -ldflags="-w -s" + - run: + name: Upx + command: upx ./cmd/gowake/gowake + - persist_to_workspace: + root: ~/project + paths: + - cmd/gowake/gowake + release: + docker: + - image: cimg/base:current + steps: + - attach_workspace: + at: ./ + - run: + name: Package + command: tar cvfz ${CIRCLE_PROJECT_REPONAME}_${CIRCLE_TAG}_linux_amd64.tar.gz cmd/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_PROJECT_REPONAME} + - run: + name: Release + command: | + curl -v \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/lupinelab/${CIRCLE_PROJECT_REPONAME}/releases \ + -d '{"tag_name":"'$CIRCLE_TAG'","draft":false,"prerelease":false}' + + RELEASE_ID=$(curl -s \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/lupinelab/${CIRCLE_PROJECT_REPONAME}/releases/tags/${CIRCLE_TAG} \ + | jq '.id') + + curl -v \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $GITHUB_TOKEN"\ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -H "Content-Type: $(file -b --mime-type ${CIRCLE_PROJECT_REPONAME}_${CIRCLE_TAG}_linux_amd64.tar.gz)" \ + https://uploads.github.com/repos/lupinelab/${CIRCLE_PROJECT_REPONAME}/releases/$RELEASE_ID/assets?name=$(basename ${CIRCLE_PROJECT_REPONAME}_${CIRCLE_TAG}_linux_amd64.tar.gz) \ + --data-binary @${CIRCLE_PROJECT_REPONAME}_${CIRCLE_TAG}_linux_amd64.tar.gz + +workflows: + build_and_release: + jobs: + - build: + filters: + tags: + only: /v\d+\.\d+\.\d+/ + - release: + context: + - github + requires: + - build + filters: + branches: + ignore: /.*/ + tags: + only: /v\d+\.\d+\.\d+/ + diff --git a/.gitignore b/.gitignore index 6bd3c26..57c4a40 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -gowake +./gowake \ No newline at end of file diff --git a/cmd/gowake/gowake b/cmd/gowake/gowake new file mode 100755 index 0000000..3279243 Binary files /dev/null and b/cmd/gowake/gowake differ diff --git a/cmd/gowake.go b/cmd/gowake/gowake.go similarity index 72% rename from cmd/gowake.go rename to cmd/gowake/gowake.go index 37da6fe..82ed0e8 100644 --- a/cmd/gowake.go +++ b/cmd/gowake/gowake.go @@ -1,9 +1,11 @@ -package cmd +package main import ( "fmt" "regexp" - "github.com/lupinelab/gowake/pkg" + + "github.com/lupinelab/gowake" + "github.com/lupinelab/gowake/cmd/listen" "github.com/spf13/cobra" ) @@ -31,32 +33,34 @@ var gowakeCmd = &cobra.Command{ } // Build packet - mp, err := pkg.BuildMagicPacket(args[0]) + mp, err := gowake.NewMagicPacket(args[0]) if err != nil { + fmt.Println(err.Error()) return } - sendoptions := pkg.SendOptions{Mp: mp, Port: port, IP: ip} - // Send packet - pkg.SendMagicPacket(sendoptions) + err = gowake.SendMagicPacket(*mp, ip, port) + if err != nil { + fmt.Println(err.Error()) + } + fmt.Printf("Sent magic packet to %v\n", args[0]) }, } -func Execute() error { - return gowakeCmd.Execute() -} - func init() { var port int var ip string + gowakeCmd.AddCommand(listen.ListenCmd) gowakeCmd.PersistentFlags().IntVarP(&port, "port", "p", 9, "Port to send or listen for magic packet") gowakeCmd.Flags().StringVarP(&ip, "ip", "i", "255.255.255.255", "Destination (IP or broadcast address) for the magic packet") - gowakeCmd.PersistentFlags().BoolP("help", "h", false, "Print help") - gowakeCmd.SetHelpCommand(&cobra.Command{ - Hidden: true, - }) + gowakeCmd.PersistentFlags().BoolP("help", "h", false, "Print help for command") cobra.EnableCommandSorting = false - gowakeCmd.CompletionOptions.DisableDefaultCmd = true + gowakeCmd.InitDefaultCompletionCmd() + gowakeCmd.CompletionOptions.DisableDescriptions = true +} + +func main() { + gowakeCmd.Execute() } diff --git a/cmd/listen.go b/cmd/listen/listen.go similarity index 74% rename from cmd/listen.go rename to cmd/listen/listen.go index 8ea9f3d..0a12c54 100644 --- a/cmd/listen.go +++ b/cmd/listen/listen.go @@ -1,21 +1,21 @@ -package cmd +package listen import ( "fmt" - "github.com/lupinelab/gowake/pkg" + "github.com/lupinelab/gowake" "github.com/spf13/cobra" ) -var listenCmd = &cobra.Command{ +var ListenCmd = &cobra.Command{ Use: "listen", Short: "Listen for a magic packet", Run: func(cmd *cobra.Command, args []string) { port, _ := cmd.Flags().GetInt("port") cont, _ := cmd.Flags().GetBool("continuous") fmt.Printf("Listening for magic packets on port %d:\n", port) - for true { - remote, macaddr, err := pkg.ListenMagicPacket(port) + for { + remote, macaddr, err := gowake.Listen(port) if err != nil { if err.Error() == fmt.Sprintf("listen udp 0.0.0.0:%d: bind: permission denied", port) { fmt.Println("Please run as elevated user") @@ -35,6 +35,5 @@ var listenCmd = &cobra.Command{ func init() { var continuous bool - listenCmd.Flags().BoolVarP(&continuous, "continuous", "c", false, "Listen continuously for magic packets") - gowakeCmd.AddCommand(listenCmd) + ListenCmd.Flags().BoolVarP(&continuous, "continuous", "c", false, "Listen continuously for magic packets") } diff --git a/go.mod b/go.mod index 6ea80c8..912002e 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/lupinelab/gowake -go 1.19 +go 1.20 -require github.com/spf13/cobra v1.5.0 +require github.com/spf13/cobra v1.7.0 require ( - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect ) diff --git a/go.sum b/go.sum index c0305ca..f3366a9 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,10 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/listen.go b/listen.go new file mode 100644 index 0000000..a0566b2 --- /dev/null +++ b/listen.go @@ -0,0 +1,29 @@ +package gowake + +import ( + "net" +) + +func Listen(port int) (*net.UDPAddr, string, error) { + addr := net.UDPAddr{ + IP: net.ParseIP("0.0.0.0"), + Port: port, + } + + listener, err := net.ListenUDP("udp", &addr) + if err != nil { + return nil, "", err + } + defer listener.Close() + + magicPacket := MagicPacket{} + remote := &net.UDPAddr{} + for { + _, remote, err = listener.ReadFromUDP(magicPacket[:]) + if err != nil { + return remote, "", err + } else { + return remote, net.HardwareAddr.String(magicPacket[96:]), err + } + } +} diff --git a/magicpacket.go b/magicpacket.go new file mode 100644 index 0000000..e10c942 --- /dev/null +++ b/magicpacket.go @@ -0,0 +1,32 @@ +package gowake + +import ( + "fmt" + "net" +) + +type MagicPacket [102]byte + +func NewMagicPacket(mac string) (mp *MagicPacket, err error) { + // Parse mac address + hwAddr, err := net.ParseMAC(mac) + if err != nil { + return nil, err + } + + if len(hwAddr) != 6 { + return nil, fmt.Errorf("invalid EUI-48 MAC address") + } + + // Build magicpacket + magicPacket := MagicPacket{} + copy(magicPacket[:], []byte{255, 255, 255, 255, 255, 255}) + + offset := 6 + for i := 0; i < 16; i++ { + copy(magicPacket[offset:], hwAddr[:]) + offset += 6 + } + + return &magicPacket, err +} diff --git a/main.go b/main.go deleted file mode 100644 index 06f3db8..0000000 --- a/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "github.com/lupinelab/gowake/cmd" -) - -func main() { - cmd.Execute() -} diff --git a/pkg/listener.go b/pkg/listener.go deleted file mode 100644 index 710b774..0000000 --- a/pkg/listener.go +++ /dev/null @@ -1,30 +0,0 @@ -package pkg - -import ( - "fmt" - "net" -) - -func ListenMagicPacket(port int) (*net.UDPAddr, string, error) { - var magicpacket magicPacket - - network := net.UDPAddr{ - IP: net.ParseIP("0.0.0.0"), - Port: port, - } - - listener, err := net.ListenUDP("udp", &network) - if err != nil { - return nil, "", err - } - defer listener.Close() - - for { - _, remote, err := listener.ReadFromUDP(magicpacket[:]) - if err != nil { - fmt.Printf("Some error %v", err) - continue - } - return remote, net.HardwareAddr.String(magicpacket[96:]), err - } -} diff --git a/pkg/magicpacket.go b/pkg/magicpacket.go deleted file mode 100644 index dc0e335..0000000 --- a/pkg/magicpacket.go +++ /dev/null @@ -1,33 +0,0 @@ -package pkg - -import ( - "fmt" - "net" -) - -type magicPacket [102]byte - -func BuildMagicPacket(mac string) (packet magicPacket, err error) { - // Parse mac address - hwAddr, err := net.ParseMAC(mac) - if err != nil { - fmt.Println("invalid MAC address") - return packet, err - } - - if len(hwAddr) != 6 { - fmt.Println("invalid EUI-48 MAC address") - return packet, err - } - - // Build magicpacket - copy(packet[:], []byte{255, 255, 255, 255, 255, 255}) - - offset := 6 - for i := 0; i < 16; i++ { - copy(packet[offset:], hwAddr[:]) - offset += 6 - } - - return packet, err -} diff --git a/pkg/send.go b/pkg/send.go deleted file mode 100644 index f456ec0..0000000 --- a/pkg/send.go +++ /dev/null @@ -1,22 +0,0 @@ -package pkg - -import ( - "fmt" - "net" -) - -type SendOptions struct { - Mp magicPacket - IP string - Port int -} - -func SendMagicPacket(options SendOptions) { - conn, _ := net.Dial("udp", fmt.Sprintf("%s:%d", options.IP, options.Port)) - _, err := conn.Write(options.Mp[:]) - if err != nil { - fmt.Println("Could not send magic packet") - return - } - defer conn.Close() -} diff --git a/send.go b/send.go new file mode 100644 index 0000000..28304e9 --- /dev/null +++ b/send.go @@ -0,0 +1,22 @@ +package gowake + +import ( + "fmt" + "net" + +) + +func SendMagicPacket(packet MagicPacket, ip string, port int) error{ + conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", ip, port)) + if err != nil { + return err + } + defer conn.Close() + + _, err = conn.Write(packet[:]) + if err != nil { + return err + } + + return err +}