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