github.com/giovannyortegon/go@v0.0.0-20220115155912-8890063f5bdd/src/pkg/mod/golang.org/x/sys@v0.0.0-20210927094055-39ccf1dd6fa6/unix/mksysctl_openbsd.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  // +build ignore
     7  
     8  // Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
     9  //
    10  // Build a MIB with each entry being an array containing the level, type and
    11  // a hash that will contain additional entries if the current entry is a node.
    12  // We then walk this MIB and create a flattened sysctl name to OID hash.
    13  
    14  package main
    15  
    16  import (
    17  	"bufio"
    18  	"fmt"
    19  	"os"
    20  	"path/filepath"
    21  	"regexp"
    22  	"sort"
    23  	"strings"
    24  )
    25  
    26  var (
    27  	goos, goarch string
    28  )
    29  
    30  // cmdLine returns this programs's commandline arguments.
    31  func cmdLine() string {
    32  	return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ")
    33  }
    34  
    35  // goBuildTags returns build tags in the go:build format.
    36  func goBuildTags() string {
    37  	return fmt.Sprintf("%s && %s", goarch, goos)
    38  }
    39  
    40  // plusBuildTags returns build tags in the +build format.
    41  func plusBuildTags() string {
    42  	return fmt.Sprintf("%s,%s", goarch, goos)
    43  }
    44  
    45  // reMatch performs regular expression match and stores the substring slice to value pointed by m.
    46  func reMatch(re *regexp.Regexp, str string, m *[]string) bool {
    47  	*m = re.FindStringSubmatch(str)
    48  	if *m != nil {
    49  		return true
    50  	}
    51  	return false
    52  }
    53  
    54  type nodeElement struct {
    55  	n  int
    56  	t  string
    57  	pE *map[string]nodeElement
    58  }
    59  
    60  var (
    61  	debugEnabled bool
    62  	mib          map[string]nodeElement
    63  	node         *map[string]nodeElement
    64  	nodeMap      map[string]string
    65  	sysCtl       []string
    66  )
    67  
    68  var (
    69  	ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`)
    70  	ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`)
    71  	ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`)
    72  	netInetRE   = regexp.MustCompile(`^netinet/`)
    73  	netInet6RE  = regexp.MustCompile(`^netinet6/`)
    74  	netRE       = regexp.MustCompile(`^net/`)
    75  	bracesRE    = regexp.MustCompile(`{.*}`)
    76  	ctlTypeRE   = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`)
    77  	fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`)
    78  )
    79  
    80  func debug(s string) {
    81  	if debugEnabled {
    82  		fmt.Fprintln(os.Stderr, s)
    83  	}
    84  }
    85  
    86  // Walk the MIB and build a sysctl name to OID mapping.
    87  func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) {
    88  	lNode := pNode // local copy of pointer to node
    89  	var keys []string
    90  	for k := range *lNode {
    91  		keys = append(keys, k)
    92  	}
    93  	sort.Strings(keys)
    94  
    95  	for _, key := range keys {
    96  		nodename := name
    97  		if name != "" {
    98  			nodename += "."
    99  		}
   100  		nodename += key
   101  
   102  		nodeoid := append(oid, (*pNode)[key].n)
   103  
   104  		if (*pNode)[key].t == `CTLTYPE_NODE` {
   105  			if _, ok := nodeMap[nodename]; ok {
   106  				lNode = &mib
   107  				ctlName := nodeMap[nodename]
   108  				for _, part := range strings.Split(ctlName, ".") {
   109  					lNode = ((*lNode)[part]).pE
   110  				}
   111  			} else {
   112  				lNode = (*pNode)[key].pE
   113  			}
   114  			buildSysctl(lNode, nodename, nodeoid)
   115  		} else if (*pNode)[key].t != "" {
   116  			oidStr := []string{}
   117  			for j := range nodeoid {
   118  				oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j]))
   119  			}
   120  			text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n"
   121  			sysCtl = append(sysCtl, text)
   122  		}
   123  	}
   124  }
   125  
   126  func main() {
   127  	// Get the OS (using GOOS_TARGET if it exist)
   128  	goos = os.Getenv("GOOS_TARGET")
   129  	if goos == "" {
   130  		goos = os.Getenv("GOOS")
   131  	}
   132  	// Get the architecture (using GOARCH_TARGET if it exists)
   133  	goarch = os.Getenv("GOARCH_TARGET")
   134  	if goarch == "" {
   135  		goarch = os.Getenv("GOARCH")
   136  	}
   137  	// Check if GOOS and GOARCH environment variables are defined
   138  	if goarch == "" || goos == "" {
   139  		fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
   140  		os.Exit(1)
   141  	}
   142  
   143  	mib = make(map[string]nodeElement)
   144  	headers := [...]string{
   145  		`sys/sysctl.h`,
   146  		`sys/socket.h`,
   147  		`sys/tty.h`,
   148  		`sys/malloc.h`,
   149  		`sys/mount.h`,
   150  		`sys/namei.h`,
   151  		`sys/sem.h`,
   152  		`sys/shm.h`,
   153  		`sys/vmmeter.h`,
   154  		`uvm/uvmexp.h`,
   155  		`uvm/uvm_param.h`,
   156  		`uvm/uvm_swap_encrypt.h`,
   157  		`ddb/db_var.h`,
   158  		`net/if.h`,
   159  		`net/if_pfsync.h`,
   160  		`net/pipex.h`,
   161  		`netinet/in.h`,
   162  		`netinet/icmp_var.h`,
   163  		`netinet/igmp_var.h`,
   164  		`netinet/ip_ah.h`,
   165  		`netinet/ip_carp.h`,
   166  		`netinet/ip_divert.h`,
   167  		`netinet/ip_esp.h`,
   168  		`netinet/ip_ether.h`,
   169  		`netinet/ip_gre.h`,
   170  		`netinet/ip_ipcomp.h`,
   171  		`netinet/ip_ipip.h`,
   172  		`netinet/tcp_var.h`,
   173  		`netinet/udp_var.h`,
   174  		`netinet6/in6.h`,
   175  		`netinet6/ip6_divert.h`,
   176  		`netinet/icmp6.h`,
   177  		`netmpls/mpls.h`,
   178  	}
   179  
   180  	ctls := [...]string{
   181  		`kern`,
   182  		`vm`,
   183  		`fs`,
   184  		`net`,
   185  		//debug			/* Special handling required */
   186  		`hw`,
   187  		//machdep		/* Arch specific */
   188  		`user`,
   189  		`ddb`,
   190  		//vfs			/* Special handling required */
   191  		`fs.posix`,
   192  		`kern.forkstat`,
   193  		`kern.intrcnt`,
   194  		`kern.malloc`,
   195  		`kern.nchstats`,
   196  		`kern.seminfo`,
   197  		`kern.shminfo`,
   198  		`kern.timecounter`,
   199  		`kern.tty`,
   200  		`kern.watchdog`,
   201  		`net.bpf`,
   202  		`net.ifq`,
   203  		`net.inet`,
   204  		`net.inet.ah`,
   205  		`net.inet.carp`,
   206  		`net.inet.divert`,
   207  		`net.inet.esp`,
   208  		`net.inet.etherip`,
   209  		`net.inet.gre`,
   210  		`net.inet.icmp`,
   211  		`net.inet.igmp`,
   212  		`net.inet.ip`,
   213  		`net.inet.ip.ifq`,
   214  		`net.inet.ipcomp`,
   215  		`net.inet.ipip`,
   216  		`net.inet.mobileip`,
   217  		`net.inet.pfsync`,
   218  		`net.inet.tcp`,
   219  		`net.inet.udp`,
   220  		`net.inet6`,
   221  		`net.inet6.divert`,
   222  		`net.inet6.ip6`,
   223  		`net.inet6.icmp6`,
   224  		`net.inet6.tcp6`,
   225  		`net.inet6.udp6`,
   226  		`net.mpls`,
   227  		`net.mpls.ifq`,
   228  		`net.key`,
   229  		`net.pflow`,
   230  		`net.pfsync`,
   231  		`net.pipex`,
   232  		`net.rt`,
   233  		`vm.swapencrypt`,
   234  		//vfsgenctl		/* Special handling required */
   235  	}
   236  
   237  	// Node name "fixups"
   238  	ctlMap := map[string]string{
   239  		"ipproto":             "net.inet",
   240  		"net.inet.ipproto":    "net.inet",
   241  		"net.inet6.ipv6proto": "net.inet6",
   242  		"net.inet6.ipv6":      "net.inet6.ip6",
   243  		"net.inet.icmpv6":     "net.inet6.icmp6",
   244  		"net.inet6.divert6":   "net.inet6.divert",
   245  		"net.inet6.tcp6":      "net.inet.tcp",
   246  		"net.inet6.udp6":      "net.inet.udp",
   247  		"mpls":                "net.mpls",
   248  		"swpenc":              "vm.swapencrypt",
   249  	}
   250  
   251  	// Node mappings
   252  	nodeMap = map[string]string{
   253  		"net.inet.ip.ifq": "net.ifq",
   254  		"net.inet.pfsync": "net.pfsync",
   255  		"net.mpls.ifq":    "net.ifq",
   256  	}
   257  
   258  	mCtls := make(map[string]bool)
   259  	for _, ctl := range ctls {
   260  		mCtls[ctl] = true
   261  	}
   262  
   263  	for _, header := range headers {
   264  		debug("Processing " + header)
   265  		file, err := os.Open(filepath.Join("/usr/include", header))
   266  		if err != nil {
   267  			fmt.Fprintf(os.Stderr, "%v\n", err)
   268  			os.Exit(1)
   269  		}
   270  		s := bufio.NewScanner(file)
   271  		for s.Scan() {
   272  			var sub []string
   273  			if reMatch(ctlNames1RE, s.Text(), &sub) ||
   274  				reMatch(ctlNames2RE, s.Text(), &sub) ||
   275  				reMatch(ctlNames3RE, s.Text(), &sub) {
   276  				if sub[1] == `CTL_NAMES` {
   277  					// Top level.
   278  					node = &mib
   279  				} else {
   280  					// Node.
   281  					nodename := strings.ToLower(sub[2])
   282  					ctlName := ""
   283  					if reMatch(netInetRE, header, &sub) {
   284  						ctlName = "net.inet." + nodename
   285  					} else if reMatch(netInet6RE, header, &sub) {
   286  						ctlName = "net.inet6." + nodename
   287  					} else if reMatch(netRE, header, &sub) {
   288  						ctlName = "net." + nodename
   289  					} else {
   290  						ctlName = nodename
   291  						ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`)
   292  					}
   293  
   294  					if val, ok := ctlMap[ctlName]; ok {
   295  						ctlName = val
   296  					}
   297  					if _, ok := mCtls[ctlName]; !ok {
   298  						debug("Ignoring " + ctlName + "...")
   299  						continue
   300  					}
   301  
   302  					// Walk down from the top of the MIB.
   303  					node = &mib
   304  					for _, part := range strings.Split(ctlName, ".") {
   305  						if _, ok := (*node)[part]; !ok {
   306  							debug("Missing node " + part)
   307  							(*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}}
   308  						}
   309  						node = (*node)[part].pE
   310  					}
   311  				}
   312  
   313  				// Populate current node with entries.
   314  				i := -1
   315  				for !strings.HasPrefix(s.Text(), "}") {
   316  					s.Scan()
   317  					if reMatch(bracesRE, s.Text(), &sub) {
   318  						i++
   319  					}
   320  					if !reMatch(ctlTypeRE, s.Text(), &sub) {
   321  						continue
   322  					}
   323  					(*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}}
   324  				}
   325  			}
   326  		}
   327  		err = s.Err()
   328  		if err != nil {
   329  			fmt.Fprintf(os.Stderr, "%v\n", err)
   330  			os.Exit(1)
   331  		}
   332  		file.Close()
   333  	}
   334  	buildSysctl(&mib, "", []int{})
   335  
   336  	sort.Strings(sysCtl)
   337  	text := strings.Join(sysCtl, "")
   338  
   339  	fmt.Printf(srcTemplate, cmdLine(), goBuildTags(), plusBuildTags(), text)
   340  }
   341  
   342  const srcTemplate = `// %s
   343  // Code generated by the command above; DO NOT EDIT.
   344  
   345  //go:build %s
   346  // +build %s
   347  
   348  package unix
   349  
   350  type mibentry struct {
   351  	ctlname string
   352  	ctloid []_C_int
   353  }
   354  
   355  var sysctlMib = []mibentry {
   356  %s
   357  }
   358  `