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