1#!/bin/sh 2# 3# Copyright (c) 1990, 1996 4# John Robert LoVerso. All rights reserved. 5# SMIv2 parsing copyright (c) 1999 6# William C. Fenner. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 12# 1. Redistributions of source code must retain the above copyright 13# notices, this list of conditions and the following disclaimer. 14# 15# 2. Redistributions in binary form must reproduce the above copyright 16# notices, this list of conditions and the following disclaimer in the 17# documentation and/or other materials provided with the distribution. 18# 19# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 20# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30# 31# This script will read either ASN.1-style MIB files or the ".defs" files 32# created by the ISODE "mosy" program on such files. 33# 34# The output of this script is the "mib.h" file used by tcpdumps' ASN.1/SNMP 35# decoding code. 36# 37# This script needs to be run by "gawk" (GNU awk). "nawk" will work, but 38# dump will get a recursion error if you process LARGE mibs. While it would 39# by farily easy to rewrite this not to use recursion (and also easy to 40# eliminate use of gsub and functions to use classic "awk"), you have to 41# order the structure declarations in defined-first order for the compiler 42# not to barf; too bad tsort doesn't take arguments. 43# 44 45cat << EOF 46/* 47 * This file was generated by tcpdump/makemib on `date` 48 * You probably don't want to edit this by hand! 49 * 50 * struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer 51}; 52 */ 53 54EOF 55 56awk ' 57BEGIN { 58 debug=0; 59 # for sanity, we prep the namespace with objects from RFC-1155 60 # (we manually establish the root) 61 oid["iso"]=1 62 oidadd("org", "iso", 3) 63 oidadd("dod", "org", 6) 64 oidadd("internet", "dod", 1) 65 oidadd("directory", "internet", 1) 66 oidadd("mgmt", "internet", 2) 67#XXX oidadd("mib", "mgmt", 1) 68 oidadd("mib-2", "mgmt", 1) 69 oidadd("experimental", "internet", 3) 70 oidadd("private", "internet", 4) 71 oidadd("enterprises", "private", 1) 72 oidadd("ip", "mib-2", 4) 73 oidadd("transmission", "mib-2", 10) 74 75 holddesc="none" 76} 77 78# 79# Read mosy "*.defs" file. mosy does all the parsing work; we just read 80# its simple and straightforward output. It would not be too hard to make 81# tcpdump directly read mosy output, but... 82# 83# Ignore these unless the current file is called something.defs; false 84# positives are too common in DESCRIPTIONs. 85 86NF > 1 && index($2,".")>0 && FILENAME ~ /\.defs/ { 87 # currently ignore items of the form "{ iso.3.6.1 }" 88 if (split($2, p, ".") == 2) { 89 oidadd($1, p[1], p[2]) 90 } 91 next 92} 93 94# 95# Must be a MIB file 96# Make it easier to parse - used to be done by sed 97{ sub(/--\*.*\*--/, ""); sub(/--.*/, ""); gsub(/[{}]/, " & "); } 98 99# 100# this next section is simple and naive, but does the job ok 101# 102 103# foo OBJECT IDENTIFIER ::= { baz 17 } 104# or 105# foo OBJECT IDENTIFIER ::= 106# { baz 17 } 107$2$3$4 == "OBJECTIDENTIFIER::=" { 108 holddesc="none" 109 if (NF == 8) 110 oidadd($1, $6, $7) 111 if (NF == 4) 112 holddesc=$1 113 next 114} 115$1 == "{" && holddesc != "none" && NF == 4 { 116 oidadd(holddesc, $2, $3) 117 holddesc="none" 118} 119# 120# foo OBJECT IDENTIFIER 121# ::= { bar 1 } 122$2$3 == "OBJECTIDENTIFIER" && $1 != "SYNTAX" && NF == 3 { 123 holddesc=$1 124} 125# 126# foo 127# OBJECT IDENTIFIER ::= { bar 1 } 128# a couple of heuristics to exclude single words in e.g. long 129# DESCRIPTION clauses 130NF == 1 && $1 ~ "[a-z][a-z]*[A-Z]" && $1 !~ /[(){}.,]/ && holddesc == "none" { 131 holddesc=$1 132} 133$1$2$3 == "OBJECTIDENTIFIER::=" && holddesc != "none" { 134 oidadd(holddesc, $5, $6) 135 holddesc="none" 136} 137# 138# "normal" style 139# foo OBJECT-TYPE ... 140# ... 141# ::= { baz 5 } 142$2 == "MODULE-IDENTITY" || $2 == "MODULE-COMPLIANCE" || 143 $2 == "OBJECT-IDENTITY" || $2 == "OBJECT-TYPE" || 144 $2 == "OBJECT-GROUP" || 145 $2 == "NOTIFICATION-TYPE" || $2 == "NOTIFICATION-GROUP" { 146 holddesc=$1 147} 148$1 == "::=" && holddesc != "none" && NF == 5 { 149 oidadd(holddesc, $3, $4) 150 holddesc="none" 151} 152# 153# foo ::= { baz 17 } 154$2$3 == "::={" { 155 oidadd($1,$4,$5) 156 holddesc="none" 157} 158 159 160# 161# End of the road - output the data. 162# 163 164END { 165 print "struct obj" 166 dump("iso") 167 print "*mibroot = &_iso_obj;" 168} 169 170function inn(file) { 171 if (file == "" || file == "-") 172 return "" 173 return " in " file 174} 175 176# 177# add a new object to the tree 178# 179# new OBJECT IDENTIFIER ::= { parent value } 180# 181 182function oidadd(new, parent, value) { 183 # Ignore 0.0 184 if (parent == "0" && value == 0) 185 return 186 if (debug) 187 print "/* oidadd" inn(FILENAME) ":", new, "in", parent, "as", value, "line", $0, "*/" 188 # use safe C identifiers 189 gsub(/[-&\/]/,"",new) 190 gsub(/[-&\/]/,"",parent) 191 # check if parent missing 192 if (oid[parent] == "") { 193 printf "/* parse problem%s: no parent for %s.%s(%d) */\n", \ 194 inn(FILENAME), parent, new, value 195 return 196 } 197 # check if parent.value already exists 198 if (oid[new] > 0 && oid[new] != value) { 199 printf "/* parse problem%s: dup %s.%s(%d) != old (%d) */\n", \ 200 inn(FILENAME), parent, new, value, oid[new] 201 return 202 } 203 # check for new name for parent.value 204 if (child[parent] != "") { 205 for (sib = child[parent]; sib != ""; sib = sibling[sib]) 206 if (oid[sib] == value) { 207 if (new != sib) 208 printf "/* parse problem%s: new name" \ 209 " \"%s\"" \ 210 " for %s.%s(%d) ignored */\n", \ 211 inn(FILENAME), new, parent, \ 212 sib, value 213 return 214 } 215 } 216 217 oid[new]=value 218 if (child[parent] == "") { 219 child[parent] = new 220 } else { 221 sibling[new] = child[parent] 222 child[parent] = new 223 } 224} 225 226# 227# old(?) routine to recurse down the tree (in postfix order for convenience) 228# 229 230function dump(item, c, s) { 231# newitem=sofar"."item"("oid[item]")" 232# printf "/* %s c=%s s=%s */\n", newitem, child[item], sibling[item] 233 c="NULL" 234 if (child[item] != "") { 235 dump(child[item]) 236 c = "&_"child[item]"_obj" 237 } 238 s="NULL" 239 if (sibling[item] != "") { 240 dump(sibling[item]) 241 s = "&_"sibling[item]"_obj" 242 } 243 printf "_%s_obj = {\n\t\"%s\", %d, 0,\n\t%s, %s\n},\n", \ 244 item, item, oid[item], c, s 245} 246' $@ 247exit 0 248