mksysctl_openbsd.pl raw

   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  // Code generated by the command above; 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