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