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