blob: 20632e14608e37ba2ff7c5b3f467009cf315b51a [file] [log] [blame]
Don Newtone0d34a82019-11-14 10:58:06 -05001#!/usr/bin/env perl
2
3# Copyright 2011 The Go Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style
5# license that can be found in the LICENSE file.
6
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
15use strict;
16
17if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
18 print STDERR "GOARCH or GOOS not defined in environment\n";
19 exit 1;
20}
21
22my $debug = 0;
23my %ctls = ();
24
25my @headers = qw (
26 sys/sysctl.h
27 sys/socket.h
28 sys/tty.h
29 sys/malloc.h
30 sys/mount.h
31 sys/namei.h
32 sys/sem.h
33 sys/shm.h
34 sys/vmmeter.h
35 uvm/uvmexp.h
36 uvm/uvm_param.h
37 uvm/uvm_swap_encrypt.h
38 ddb/db_var.h
39 net/if.h
40 net/if_pfsync.h
41 net/pipex.h
42 netinet/in.h
43 netinet/icmp_var.h
44 netinet/igmp_var.h
45 netinet/ip_ah.h
46 netinet/ip_carp.h
47 netinet/ip_divert.h
48 netinet/ip_esp.h
49 netinet/ip_ether.h
50 netinet/ip_gre.h
51 netinet/ip_ipcomp.h
52 netinet/ip_ipip.h
53 netinet/pim_var.h
54 netinet/tcp_var.h
55 netinet/udp_var.h
56 netinet6/in6.h
57 netinet6/ip6_divert.h
58 netinet6/pim6_var.h
59 netinet/icmp6.h
60 netmpls/mpls.h
61);
62
63my @ctls = qw (
64 kern
65 vm
66 fs
67 net
68 #debug # Special handling required
69 hw
70 #machdep # Arch specific
71 user
72 ddb
73 #vfs # Special handling required
74 fs.posix
75 kern.forkstat
76 kern.intrcnt
77 kern.malloc
78 kern.nchstats
79 kern.seminfo
80 kern.shminfo
81 kern.timecounter
82 kern.tty
83 kern.watchdog
84 net.bpf
85 net.ifq
86 net.inet
87 net.inet.ah
88 net.inet.carp
89 net.inet.divert
90 net.inet.esp
91 net.inet.etherip
92 net.inet.gre
93 net.inet.icmp
94 net.inet.igmp
95 net.inet.ip
96 net.inet.ip.ifq
97 net.inet.ipcomp
98 net.inet.ipip
99 net.inet.mobileip
100 net.inet.pfsync
101 net.inet.pim
102 net.inet.tcp
103 net.inet.udp
104 net.inet6
105 net.inet6.divert
106 net.inet6.ip6
107 net.inet6.icmp6
108 net.inet6.pim6
109 net.inet6.tcp6
110 net.inet6.udp6
111 net.mpls
112 net.mpls.ifq
113 net.key
114 net.pflow
115 net.pfsync
116 net.pipex
117 net.rt
118 vm.swapencrypt
119 #vfsgenctl # Special handling required
120);
121
122# Node name "fixups"
123my %ctl_map = (
124 "ipproto" => "net.inet",
125 "net.inet.ipproto" => "net.inet",
126 "net.inet6.ipv6proto" => "net.inet6",
127 "net.inet6.ipv6" => "net.inet6.ip6",
128 "net.inet.icmpv6" => "net.inet6.icmp6",
129 "net.inet6.divert6" => "net.inet6.divert",
130 "net.inet6.tcp6" => "net.inet.tcp",
131 "net.inet6.udp6" => "net.inet.udp",
132 "mpls" => "net.mpls",
133 "swpenc" => "vm.swapencrypt"
134);
135
136# Node mappings
137my %node_map = (
138 "net.inet.ip.ifq" => "net.ifq",
139 "net.inet.pfsync" => "net.pfsync",
140 "net.mpls.ifq" => "net.ifq"
141);
142
143my $ctlname;
144my %mib = ();
145my %sysctl = ();
146my $node;
147
148sub debug() {
149 print STDERR "$_[0]\n" if $debug;
150}
151
152# Walk the MIB and build a sysctl name to OID mapping.
153sub build_sysctl() {
154 my ($node, $name, $oid) = @_;
155 my %node = %{$node};
156 my @oid = @{$oid};
157
158 foreach my $key (sort keys %node) {
159 my @node = @{$node{$key}};
160 my $nodename = $name.($name ne '' ? '.' : '').$key;
161 my @nodeoid = (@oid, $node[0]);
162 if ($node[1] eq 'CTLTYPE_NODE') {
163 if (exists $node_map{$nodename}) {
164 $node = \%mib;
165 $ctlname = $node_map{$nodename};
166 foreach my $part (split /\./, $ctlname) {
167 $node = \%{@{$$node{$part}}[2]};
168 }
169 } else {
170 $node = $node[2];
171 }
172 &build_sysctl($node, $nodename, \@nodeoid);
173 } elsif ($node[1] ne '') {
174 $sysctl{$nodename} = \@nodeoid;
175 }
176 }
177}
178
179foreach my $ctl (@ctls) {
180 $ctls{$ctl} = $ctl;
181}
182
183# Build MIB
184foreach my $header (@headers) {
185 &debug("Processing $header...");
186 open HEADER, "/usr/include/$header" ||
187 print STDERR "Failed to open $header\n";
188 while (<HEADER>) {
189 if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ ||
190 $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ ||
191 $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) {
192 if ($1 eq 'CTL_NAMES') {
193 # Top level.
194 $node = \%mib;
195 } else {
196 # Node.
197 my $nodename = lc($2);
198 if ($header =~ /^netinet\//) {
199 $ctlname = "net.inet.$nodename";
200 } elsif ($header =~ /^netinet6\//) {
201 $ctlname = "net.inet6.$nodename";
202 } elsif ($header =~ /^net\//) {
203 $ctlname = "net.$nodename";
204 } else {
205 $ctlname = "$nodename";
206 $ctlname =~ s/^(fs|net|kern)_/$1\./;
207 }
208 if (exists $ctl_map{$ctlname}) {
209 $ctlname = $ctl_map{$ctlname};
210 }
211 if (not exists $ctls{$ctlname}) {
212 &debug("Ignoring $ctlname...");
213 next;
214 }
215
216 # Walk down from the top of the MIB.
217 $node = \%mib;
218 foreach my $part (split /\./, $ctlname) {
219 if (not exists $$node{$part}) {
220 &debug("Missing node $part");
221 $$node{$part} = [ 0, '', {} ];
222 }
223 $node = \%{@{$$node{$part}}[2]};
224 }
225 }
226
227 # Populate current node with entries.
228 my $i = -1;
229 while (defined($_) && $_ !~ /^}/) {
230 $_ = <HEADER>;
231 $i++ if $_ =~ /{.*}/;
232 next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/;
233 $$node{$1} = [ $i, $2, {} ];
234 }
235 }
236 }
237 close HEADER;
238}
239
240&build_sysctl(\%mib, "", []);
241
242print <<EOF;
243// mksysctl_openbsd.pl
244// Code generated by the command above; DO NOT EDIT.
245
246// +build $ENV{'GOARCH'},$ENV{'GOOS'}
247
248package unix;
249
250type mibentry struct {
251 ctlname string
252 ctloid []_C_int
253}
254
255var sysctlMib = []mibentry {
256EOF
257
258foreach my $name (sort keys %sysctl) {
259 my @oid = @{$sysctl{$name}};
260 print "\t{ \"$name\", []_C_int{ ", join(', ', @oid), " } }, \n";
261}
262
263print <<EOF;
264}
265EOF