github.com/Andyfoo/golang/x/sys@v0.0.0-20190901054642-57c1bf301704/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 // +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 // buildTags returns build tags. 35 func buildTags() 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/pim_var.h`, 167 `netinet/tcp_var.h`, 168 `netinet/udp_var.h`, 169 `netinet6/in6.h`, 170 `netinet6/ip6_divert.h`, 171 `netinet6/pim6_var.h`, 172 `netinet/icmp6.h`, 173 `netmpls/mpls.h`, 174 } 175 176 ctls := [...]string{ 177 `kern`, 178 `vm`, 179 `fs`, 180 `net`, 181 //debug /* Special handling required */ 182 `hw`, 183 //machdep /* Arch specific */ 184 `user`, 185 `ddb`, 186 //vfs /* Special handling required */ 187 `fs.posix`, 188 `kern.forkstat`, 189 `kern.intrcnt`, 190 `kern.malloc`, 191 `kern.nchstats`, 192 `kern.seminfo`, 193 `kern.shminfo`, 194 `kern.timecounter`, 195 `kern.tty`, 196 `kern.watchdog`, 197 `net.bpf`, 198 `net.ifq`, 199 `net.inet`, 200 `net.inet.ah`, 201 `net.inet.carp`, 202 `net.inet.divert`, 203 `net.inet.esp`, 204 `net.inet.etherip`, 205 `net.inet.gre`, 206 `net.inet.icmp`, 207 `net.inet.igmp`, 208 `net.inet.ip`, 209 `net.inet.ip.ifq`, 210 `net.inet.ipcomp`, 211 `net.inet.ipip`, 212 `net.inet.mobileip`, 213 `net.inet.pfsync`, 214 `net.inet.pim`, 215 `net.inet.tcp`, 216 `net.inet.udp`, 217 `net.inet6`, 218 `net.inet6.divert`, 219 `net.inet6.ip6`, 220 `net.inet6.icmp6`, 221 `net.inet6.pim6`, 222 `net.inet6.tcp6`, 223 `net.inet6.udp6`, 224 `net.mpls`, 225 `net.mpls.ifq`, 226 `net.key`, 227 `net.pflow`, 228 `net.pfsync`, 229 `net.pipex`, 230 `net.rt`, 231 `vm.swapencrypt`, 232 //vfsgenctl /* Special handling required */ 233 } 234 235 // Node name "fixups" 236 ctlMap := map[string]string{ 237 "ipproto": "net.inet", 238 "net.inet.ipproto": "net.inet", 239 "net.inet6.ipv6proto": "net.inet6", 240 "net.inet6.ipv6": "net.inet6.ip6", 241 "net.inet.icmpv6": "net.inet6.icmp6", 242 "net.inet6.divert6": "net.inet6.divert", 243 "net.inet6.tcp6": "net.inet.tcp", 244 "net.inet6.udp6": "net.inet.udp", 245 "mpls": "net.mpls", 246 "swpenc": "vm.swapencrypt", 247 } 248 249 // Node mappings 250 nodeMap = map[string]string{ 251 "net.inet.ip.ifq": "net.ifq", 252 "net.inet.pfsync": "net.pfsync", 253 "net.mpls.ifq": "net.ifq", 254 } 255 256 mCtls := make(map[string]bool) 257 for _, ctl := range ctls { 258 mCtls[ctl] = true 259 } 260 261 for _, header := range headers { 262 debug("Processing " + header) 263 file, err := os.Open(filepath.Join("/usr/include", header)) 264 if err != nil { 265 fmt.Fprintf(os.Stderr, "%v\n", err) 266 os.Exit(1) 267 } 268 s := bufio.NewScanner(file) 269 for s.Scan() { 270 var sub []string 271 if reMatch(ctlNames1RE, s.Text(), &sub) || 272 reMatch(ctlNames2RE, s.Text(), &sub) || 273 reMatch(ctlNames3RE, s.Text(), &sub) { 274 if sub[1] == `CTL_NAMES` { 275 // Top level. 276 node = &mib 277 } else { 278 // Node. 279 nodename := strings.ToLower(sub[2]) 280 ctlName := "" 281 if reMatch(netInetRE, header, &sub) { 282 ctlName = "net.inet." + nodename 283 } else if reMatch(netInet6RE, header, &sub) { 284 ctlName = "net.inet6." + nodename 285 } else if reMatch(netRE, header, &sub) { 286 ctlName = "net." + nodename 287 } else { 288 ctlName = nodename 289 ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`) 290 } 291 292 if val, ok := ctlMap[ctlName]; ok { 293 ctlName = val 294 } 295 if _, ok := mCtls[ctlName]; !ok { 296 debug("Ignoring " + ctlName + "...") 297 continue 298 } 299 300 // Walk down from the top of the MIB. 301 node = &mib 302 for _, part := range strings.Split(ctlName, ".") { 303 if _, ok := (*node)[part]; !ok { 304 debug("Missing node " + part) 305 (*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}} 306 } 307 node = (*node)[part].pE 308 } 309 } 310 311 // Populate current node with entries. 312 i := -1 313 for !strings.HasPrefix(s.Text(), "}") { 314 s.Scan() 315 if reMatch(bracesRE, s.Text(), &sub) { 316 i++ 317 } 318 if !reMatch(ctlTypeRE, s.Text(), &sub) { 319 continue 320 } 321 (*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}} 322 } 323 } 324 } 325 err = s.Err() 326 if err != nil { 327 fmt.Fprintf(os.Stderr, "%v\n", err) 328 os.Exit(1) 329 } 330 file.Close() 331 } 332 buildSysctl(&mib, "", []int{}) 333 334 sort.Strings(sysCtl) 335 text := strings.Join(sysCtl, "") 336 337 fmt.Printf(srcTemplate, cmdLine(), buildTags(), text) 338 } 339 340 const srcTemplate = `// %s 341 // Code generated by the command above; DO NOT EDIT. 342 343 // +build %s 344 345 package unix 346 347 type mibentry struct { 348 ctlname string 349 ctloid []_C_int 350 } 351 352 var sysctlMib = []mibentry { 353 %s 354 } 355 `