265 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			265 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
|   | #!/usr/bin/env perl | ||
|  | 
 | ||
|  | # Copyright 2011 The Go Authors. All rights reserved. | ||
|  | # Use of this source code is governed by a BSD-style | ||
|  | # license that can be found in the LICENSE file. | ||
|  | 
 | ||
|  | # | ||
|  | # Parse the header files for OpenBSD and generate a Go usable sysctl MIB. | ||
|  | # | ||
|  | # Build a MIB with each entry being an array containing the level, type and | ||
|  | # a hash that will contain additional entries if the current entry is a node. | ||
|  | # We then walk this MIB and create a flattened sysctl name to OID hash. | ||
|  | # | ||
|  | 
 | ||
|  | use strict; | ||
|  | 
 | ||
|  | if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") { | ||
|  | 	print STDERR "GOARCH or GOOS not defined in environment\n"; | ||
|  | 	exit 1; | ||
|  | } | ||
|  | 
 | ||
|  | my $debug = 0; | ||
|  | my %ctls = (); | ||
|  | 
 | ||
|  | my @headers = qw ( | ||
|  | 	sys/sysctl.h | ||
|  | 	sys/socket.h | ||
|  | 	sys/tty.h | ||
|  | 	sys/malloc.h | ||
|  | 	sys/mount.h | ||
|  | 	sys/namei.h | ||
|  | 	sys/sem.h | ||
|  | 	sys/shm.h | ||
|  | 	sys/vmmeter.h | ||
|  | 	uvm/uvm_param.h | ||
|  | 	uvm/uvm_swap_encrypt.h | ||
|  | 	ddb/db_var.h | ||
|  | 	net/if.h | ||
|  | 	net/if_pfsync.h | ||
|  | 	net/pipex.h | ||
|  | 	netinet/in.h | ||
|  | 	netinet/icmp_var.h | ||
|  | 	netinet/igmp_var.h | ||
|  | 	netinet/ip_ah.h | ||
|  | 	netinet/ip_carp.h | ||
|  | 	netinet/ip_divert.h | ||
|  | 	netinet/ip_esp.h | ||
|  | 	netinet/ip_ether.h | ||
|  | 	netinet/ip_gre.h | ||
|  | 	netinet/ip_ipcomp.h | ||
|  | 	netinet/ip_ipip.h | ||
|  | 	netinet/pim_var.h | ||
|  | 	netinet/tcp_var.h | ||
|  | 	netinet/udp_var.h | ||
|  | 	netinet6/in6.h | ||
|  | 	netinet6/ip6_divert.h | ||
|  | 	netinet6/pim6_var.h | ||
|  | 	netinet/icmp6.h | ||
|  | 	netmpls/mpls.h | ||
|  | ); | ||
|  | 
 | ||
|  | my @ctls = qw ( | ||
|  | 	kern | ||
|  | 	vm | ||
|  | 	fs | ||
|  | 	net | ||
|  | 	#debug				# Special handling required | ||
|  | 	hw | ||
|  | 	#machdep			# Arch specific | ||
|  | 	user | ||
|  | 	ddb | ||
|  | 	#vfs				# Special handling required | ||
|  | 	fs.posix | ||
|  | 	kern.forkstat | ||
|  | 	kern.intrcnt | ||
|  | 	kern.malloc | ||
|  | 	kern.nchstats | ||
|  | 	kern.seminfo | ||
|  | 	kern.shminfo | ||
|  | 	kern.timecounter | ||
|  | 	kern.tty | ||
|  | 	kern.watchdog | ||
|  | 	net.bpf | ||
|  | 	net.ifq | ||
|  | 	net.inet | ||
|  | 	net.inet.ah | ||
|  | 	net.inet.carp | ||
|  | 	net.inet.divert | ||
|  | 	net.inet.esp | ||
|  | 	net.inet.etherip | ||
|  | 	net.inet.gre | ||
|  | 	net.inet.icmp | ||
|  | 	net.inet.igmp | ||
|  | 	net.inet.ip | ||
|  | 	net.inet.ip.ifq | ||
|  | 	net.inet.ipcomp | ||
|  | 	net.inet.ipip | ||
|  | 	net.inet.mobileip | ||
|  | 	net.inet.pfsync | ||
|  | 	net.inet.pim | ||
|  | 	net.inet.tcp | ||
|  | 	net.inet.udp | ||
|  | 	net.inet6 | ||
|  | 	net.inet6.divert | ||
|  | 	net.inet6.ip6 | ||
|  | 	net.inet6.icmp6 | ||
|  | 	net.inet6.pim6 | ||
|  | 	net.inet6.tcp6 | ||
|  | 	net.inet6.udp6 | ||
|  | 	net.mpls | ||
|  | 	net.mpls.ifq | ||
|  | 	net.key | ||
|  | 	net.pflow | ||
|  | 	net.pfsync | ||
|  | 	net.pipex | ||
|  | 	net.rt | ||
|  | 	vm.swapencrypt | ||
|  | 	#vfsgenctl			# Special handling required | ||
|  | ); | ||
|  | 
 | ||
|  | # Node name "fixups" | ||
|  | my %ctl_map = ( | ||
|  | 	"ipproto" => "net.inet", | ||
|  | 	"net.inet.ipproto" => "net.inet", | ||
|  | 	"net.inet6.ipv6proto" => "net.inet6", | ||
|  | 	"net.inet6.ipv6" => "net.inet6.ip6", | ||
|  | 	"net.inet.icmpv6" => "net.inet6.icmp6", | ||
|  | 	"net.inet6.divert6" => "net.inet6.divert", | ||
|  | 	"net.inet6.tcp6" => "net.inet.tcp", | ||
|  | 	"net.inet6.udp6" => "net.inet.udp", | ||
|  | 	"mpls" => "net.mpls", | ||
|  | 	"swpenc" => "vm.swapencrypt" | ||
|  | ); | ||
|  | 
 | ||
|  | # Node mappings | ||
|  | my %node_map = ( | ||
|  | 	"net.inet.ip.ifq" => "net.ifq", | ||
|  | 	"net.inet.pfsync" => "net.pfsync", | ||
|  | 	"net.mpls.ifq" => "net.ifq" | ||
|  | ); | ||
|  | 
 | ||
|  | my $ctlname; | ||
|  | my %mib = (); | ||
|  | my %sysctl = (); | ||
|  | my $node; | ||
|  | 
 | ||
|  | sub debug() { | ||
|  | 	print STDERR "$_[0]\n" if $debug; | ||
|  | } | ||
|  | 
 | ||
|  | # Walk the MIB and build a sysctl name to OID mapping. | ||
|  | sub build_sysctl() { | ||
|  | 	my ($node, $name, $oid) = @_; | ||
|  | 	my %node = %{$node}; | ||
|  | 	my @oid = @{$oid}; | ||
|  | 
 | ||
|  | 	foreach my $key (sort keys %node) { | ||
|  | 		my @node = @{$node{$key}}; | ||
|  | 		my $nodename = $name.($name ne '' ? '.' : '').$key; | ||
|  | 		my @nodeoid = (@oid, $node[0]); | ||
|  | 		if ($node[1] eq 'CTLTYPE_NODE') { | ||
|  | 			if (exists $node_map{$nodename}) { | ||
|  | 				$node = \%mib; | ||
|  | 				$ctlname = $node_map{$nodename}; | ||
|  | 				foreach my $part (split /\./, $ctlname) { | ||
|  | 					$node = \%{@{$$node{$part}}[2]}; | ||
|  | 				} | ||
|  | 			} else { | ||
|  | 				$node = $node[2]; | ||
|  | 			} | ||
|  | 			&build_sysctl($node, $nodename, \@nodeoid); | ||
|  | 		} elsif ($node[1] ne '') { | ||
|  | 			$sysctl{$nodename} = \@nodeoid; | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | foreach my $ctl (@ctls) { | ||
|  | 	$ctls{$ctl} = $ctl; | ||
|  | } | ||
|  | 
 | ||
|  | # Build MIB | ||
|  | foreach my $header (@headers) { | ||
|  | 	&debug("Processing $header..."); | ||
|  | 	open HEADER, "/usr/include/$header" || | ||
|  | 	    print STDERR "Failed to open $header\n"; | ||
|  | 	while (<HEADER>) { | ||
|  | 		if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ || | ||
|  | 		    $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ || | ||
|  | 		    $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) { | ||
|  | 			if ($1 eq 'CTL_NAMES') { | ||
|  | 				# Top level. | ||
|  | 				$node = \%mib; | ||
|  | 			} else { | ||
|  | 				# Node. | ||
|  | 				my $nodename = lc($2); | ||
|  | 				if ($header =~ /^netinet\//) { | ||
|  | 					$ctlname = "net.inet.$nodename"; | ||
|  | 				} elsif ($header =~ /^netinet6\//) { | ||
|  | 					$ctlname = "net.inet6.$nodename"; | ||
|  | 				} elsif ($header =~ /^net\//) { | ||
|  | 					$ctlname = "net.$nodename"; | ||
|  | 				} else { | ||
|  | 					$ctlname = "$nodename"; | ||
|  | 					$ctlname =~ s/^(fs|net|kern)_/$1\./; | ||
|  | 				} | ||
|  | 				if (exists $ctl_map{$ctlname}) { | ||
|  | 					$ctlname = $ctl_map{$ctlname}; | ||
|  | 				} | ||
|  | 				if (not exists $ctls{$ctlname}) { | ||
|  | 					&debug("Ignoring $ctlname..."); | ||
|  | 					next; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				# Walk down from the top of the MIB. | ||
|  | 				$node = \%mib; | ||
|  | 				foreach my $part (split /\./, $ctlname) { | ||
|  | 					if (not exists $$node{$part}) { | ||
|  | 						&debug("Missing node $part"); | ||
|  | 						$$node{$part} = [ 0, '', {} ]; | ||
|  | 					} | ||
|  | 					$node = \%{@{$$node{$part}}[2]}; | ||
|  | 				} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			# Populate current node with entries. | ||
|  | 			my $i = -1; | ||
|  | 			while (defined($_) && $_ !~ /^}/) { | ||
|  | 				$_ = <HEADER>; | ||
|  | 				$i++ if $_ =~ /{.*}/; | ||
|  | 				next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/; | ||
|  | 				$$node{$1} = [ $i, $2, {} ]; | ||
|  | 			} | ||
|  | 		} | ||
|  | 	} | ||
|  | 	close HEADER; | ||
|  | } | ||
|  | 
 | ||
|  | &build_sysctl(\%mib, "", []); | ||
|  | 
 | ||
|  | print <<EOF; | ||
|  | // mksysctl_openbsd.pl | ||
|  | // MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT | ||
|  | 
 | ||
|  | // +build $ENV{'GOARCH'},$ENV{'GOOS'} | ||
|  | 
 | ||
|  | package unix; | ||
|  | 
 | ||
|  | type mibentry struct { | ||
|  | 	ctlname string | ||
|  | 	ctloid []_C_int | ||
|  | } | ||
|  | 
 | ||
|  | var sysctlMib = []mibentry { | ||
|  | EOF | ||
|  | 
 | ||
|  | foreach my $name (sort keys %sysctl) { | ||
|  | 	my @oid = @{$sysctl{$name}}; | ||
|  | 	print "\t{ \"$name\", []_C_int{ ", join(', ', @oid), " } }, \n"; | ||
|  | } | ||
|  | 
 | ||
|  | print <<EOF; | ||
|  | } | ||
|  | EOF |