1// Copyright 2019 The GoPacket Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the LICENSE file in the root of the source
5// tree.
6
7// +build ignore
8
9package main
10
11// This file generates the godefs needed for the windows version.
12// Rebuild is only necessary if additional libpcap functionality is implemented, or a new arch is implemented in golang.
13// Call with go run generate_windows.go [-I includepath]
14// Needs npcap sdk, go tool cgo, and gofmt to work. Location of npcap includes can be specified with -I
15
16import (
17	"bytes"
18	"flag"
19	"fmt"
20	"io/ioutil"
21	"log"
22	"os"
23	"os/exec"
24	"path/filepath"
25	"strings"
26)
27
28const header = `// Copyright 2019 The GoPacket Authors. All rights reserved.
29//
30// Use of this source code is governed by a BSD-style license
31// that can be found in the LICENSE file in the root of the source
32// tree.
33
34// This file contains necessary structs/constants generated from libpcap headers with cgo -godefs
35// generated with: %s
36// DO NOT MODIFY
37
38`
39
40const source = `
41package pcap
42
43//#include <pcap.h>
44import "C"
45
46import "syscall" // needed for RawSockaddr
47
48const errorBufferSize = C.PCAP_ERRBUF_SIZE
49
50const (
51	pcapErrorNotActivated    = C.PCAP_ERROR_NOT_ACTIVATED
52	pcapErrorActivated       = C.PCAP_ERROR_ACTIVATED
53	pcapWarningPromisc       = C.PCAP_WARNING_PROMISC_NOTSUP
54	pcapErrorNoSuchDevice    = C.PCAP_ERROR_NO_SUCH_DEVICE
55	pcapErrorDenied          = C.PCAP_ERROR_PERM_DENIED
56	pcapErrorNotUp           = C.PCAP_ERROR_IFACE_NOT_UP
57	pcapError                = C.PCAP_ERROR
58	pcapWarning              = C.PCAP_WARNING
59	pcapDIN                  = C.PCAP_D_IN
60	pcapDOUT                 = C.PCAP_D_OUT
61	pcapDINOUT               = C.PCAP_D_INOUT
62	pcapNetmaskUnknown       = C.PCAP_NETMASK_UNKNOWN
63	pcapTstampPrecisionMicro = C.PCAP_TSTAMP_PRECISION_MICRO
64	pcapTstampPrecisionNano  = C.PCAP_TSTAMP_PRECISION_NANO
65)
66
67type timeval C.struct_timeval
68type pcapPkthdr C.struct_pcap_pkthdr
69type pcapTPtr uintptr
70type pcapBpfInstruction C.struct_bpf_insn
71type pcapBpfProgram C.struct_bpf_program
72type pcapStats C.struct_pcap_stat
73type pcapCint C.int
74type pcapIf C.struct_pcap_if
75// +godefs map struct_sockaddr syscall.RawSockaddr
76type pcapAddr C.struct_pcap_addr
77`
78
79var includes = flag.String("I", "C:\\npcap-sdk-1.01\\Include", "Include path containing libpcap headers")
80
81func main() {
82	flag.Parse()
83
84	infile, err := ioutil.TempFile(".", "defs.*.go")
85	if err != nil {
86		log.Fatal("Couldn't create temporary source file: ", err)
87	}
88	defer infile.Close()
89	defer os.Remove(infile.Name())
90
91	_, err = infile.WriteString(source)
92	if err != nil {
93		log.Fatalf("Couldn't write definitions to temporary file %s: %s", infile.Name(), err)
94	}
95	err = infile.Close()
96	if err != nil {
97		log.Fatalf("Couldn't close temporary source file %s: %s", infile.Name(), err)
98	}
99
100	archs := []string{"386", "amd64"}
101	for _, arch := range archs {
102		env := append(os.Environ(), "GOARCH="+arch)
103		cmd := exec.Command("go", "tool", "cgo", "-godefs", "--", "-I", *includes, infile.Name())
104		cmd.Env = env
105		cmd.Stderr = os.Stderr
106		var generated bytes.Buffer
107		cmd.Stdout = &generated
108		err := cmd.Run()
109		if err != nil {
110			log.Fatalf("Couldn't generated defs for %s: %s\n", arch, err)
111		}
112
113		cmd = exec.Command("gofmt")
114		cmd.Env = env
115		cmd.Stderr = os.Stderr
116		outName := fmt.Sprintf("defs_windows_%s.go", arch)
117		out, err := os.Create(outName)
118		if err != nil {
119			log.Fatalf("Couldn't open file %s: %s", outName, err)
120		}
121		cmd.Stdout = out
122		in, err := cmd.StdinPipe()
123		if err != nil {
124			log.Fatal("Couldn't create input pipe for gofmt: ", err)
125		}
126		err = cmd.Start()
127		if err != nil {
128			log.Fatal("Couldn't start gofmt: ", err)
129		}
130
131		_, err = fmt.Fprintf(in, header, strings.Join(append([]string{filepath.Base(os.Args[0])}, os.Args[1:]...), " "))
132		if err != nil {
133			log.Fatal("Couldn't write header to gofmt: ", err)
134		}
135
136		for {
137			line, err := generated.ReadBytes('\n')
138			if err != nil {
139				break
140			}
141			// remove godefs comments
142			if bytes.HasPrefix(line, []byte("//")) {
143				continue
144			}
145			_, err = in.Write(line)
146			if err != nil {
147				log.Fatal("Couldn't write line to gofmt: ", err)
148			}
149		}
150		in.Close()
151		err = cmd.Wait()
152		if err != nil {
153			log.Fatal("gofmt failed: ", err)
154		}
155		out.Close()
156	}
157}
158