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# @(#) $Id: makemib,v 1.3 2001/09/17 22:16:52 fenner Exp $ (jlv) 31 32# 33# This script will read either ASN.1-style MIB files or the ".defs" files 34# created by the ISODE "mosy" program on such files. 35# 36# The output of this script is the "mib.h" file used by tcpdumps' ASN.1/SNMP 37# decoding code. 38# 39# This script needs to be run by "gawk" (GNU awk). "nawk" will work, but 40# dump will get a recursion error if you process LARGE mibs. While it would 41# by farily easy to rewrite this not to use recursion (and also easy to 42# eliminate use of gsub and functions to use classic "awk"), you have to 43# order the structure declarations in defined-first order for the compiler 44# not to barf; too bad tsort doesn't take arguments. 45# 46 47cat << EOF 48/* 49 * This file was generated by tcpdump/makemib on `date` 50 * You probably don't want to edit this by hand! 51 * 52 * struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer 53}; 54 */ 55 56EOF 57 58awk ' 59BEGIN { 60 debug=0; 61 # for sanity, we prep the namespace with objects from RFC-1155 62 # (we manually establish the root) 63 oid["iso"]=1 64 oidadd("org", "iso", 3) 65 oidadd("dod", "org", 6) 66 oidadd("internet", "dod", 1) 67 oidadd("directory", "internet", 1) 68 oidadd("mgmt", "internet", 2) 69#XXX oidadd("mib", "mgmt", 1) 70 oidadd("mib-2", "mgmt", 1) 71 oidadd("experimental", "internet", 3) 72 oidadd("private", "internet", 4) 73 oidadd("enterprises", "private", 1) 74 oidadd("ip", "mib-2", 4) 75 oidadd("transmission", "mib-2", 10) 76 77 holddesc="none" 78} 79 80# 81# Read mosy "*.defs" file. mosy does all the parsing work; we just read 82# its simple and straightforward output. It would not be too hard to make 83# tcpdump directly read mosy output, but... 84# 85# Ignore these unless the current file is called something.defs; false 86# positives are too common in DESCRIPTIONs. 87 88NF > 1 && index($2,".")>0 && FILENAME ~ /\.defs/ { 89 # currently ignore items of the form "{ iso.3.6.1 }" 90 if (split($2, p, ".") == 2) { 91 oidadd($1, p[1], p[2]) 92 } 93 next 94} 95 96# 97# Must be a MIB file 98# Make it easier to parse - used to be done by sed 99{ sub(/--\*.*\*--/, ""); sub(/--.*/, ""); gsub(/[{}]/, " & "); } 100 101# 102# this next section is simple and naive, but does the job ok 103# 104 105# foo OBJECT IDENTIFIER ::= { baz 17 } 106# or 107# foo OBJECT IDENTIFIER ::= 108# { baz 17 } 109$2$3$4 == "OBJECTIDENTIFIER::=" { 110 holddesc="none" 111 if (NF == 8) 112 oidadd($1, $6, $7) 113 if (NF == 4) 114 holddesc=$1 115 next 116} 117$1 == "{" && holddesc != "none" && NF == 4 { 118 oidadd(holddesc, $2, $3) 119 holddesc="none" 120} 121# 122# foo OBJECT IDENTIFIER 123# ::= { bar 1 } 124$2$3 == "OBJECTIDENTIFIER" && $1 != "SYNTAX" && NF == 3 { 125 holddesc=$1 126} 127# 128# foo 129# OBJECT IDENTIFIER ::= { bar 1 } 130# a couple of heuristics to exclude single words in e.g. long 131# DESCRIPTION clauses 132NF == 1 && $1 ~ "[a-z][a-z]*[A-Z]" && $1 !~ /[(){}.,]/ && holddesc == "none" { 133 holddesc=$1 134} 135$1$2$3 == "OBJECTIDENTIFIER::=" && holddesc != "none" { 136 oidadd(holddesc, $5, $6) 137 holddesc="none" 138} 139# 140# "normal" style 141# foo OBJECT-TYPE ... 142# ... 143# ::= { baz 5 } 144$2 == "MODULE-IDENTITY" || $2 == "MODULE-COMPLIANCE" || 145 $2 == "OBJECT-IDENTITY" || $2 == "OBJECT-TYPE" || 146 $2 == "OBJECT-GROUP" || 147 $2 == "NOTIFICATION-TYPE" || $2 == "NOTIFICATION-GROUP" { 148 holddesc=$1 149} 150$1 == "::=" && holddesc != "none" && NF == 5 { 151 oidadd(holddesc, $3, $4) 152 holddesc="none" 153} 154# 155# foo ::= { baz 17 } 156$2$3 == "::={" { 157 oidadd($1,$4,$5) 158 holddesc="none" 159} 160 161 162# 163# End of the road - output the data. 164# 165 166END { 167 print "struct obj" 168 dump("iso") 169 print "*mibroot = &_iso_obj;" 170} 171 172function inn(file) { 173 if (file == "" || file == "-") 174 return "" 175 return " in " file 176} 177 178# 179# add a new object to the tree 180# 181# new OBJECT IDENTIFIER ::= { parent value } 182# 183 184function oidadd(new, parent, value) { 185 # Ignore 0.0 186 if (parent == "0" && value == 0) 187 return 188 if (debug) 189 print "/* oidadd" inn(FILENAME) ":", new, "in", parent, "as", value, "line", $0, "*/" 190 # use safe C identifiers 191 gsub(/[-&\/]/,"",new) 192 gsub(/[-&\/]/,"",parent) 193 # check if parent missing 194 if (oid[parent] == "") { 195 printf "/* parse problem%s: no parent for %s.%s(%d) */\n", \ 196 inn(FILENAME), parent, new, value 197 return 198 } 199 # check if parent.value already exists 200 if (oid[new] > 0 && oid[new] != value) { 201 printf "/* parse problem%s: dup %s.%s(%d) != old (%d) */\n", \ 202 inn(FILENAME), parent, new, value, oid[new] 203 return 204 } 205 # check for new name for parent.value 206 if (child[parent] != "") { 207 for (sib = child[parent]; sib != ""; sib = sibling[sib]) 208 if (oid[sib] == value) { 209 if (new != sib) 210 printf "/* parse problem%s: new name" \ 211 " \"%s\"" \ 212 " for %s.%s(%d) ignored */\n", \ 213 inn(FILENAME), new, parent, \ 214 sib, value 215 return 216 } 217 } 218 219 oid[new]=value 220 if (child[parent] == "") { 221 child[parent] = new 222 } else { 223 sibling[new] = child[parent] 224 child[parent] = new 225 } 226} 227 228# 229# old(?) routine to recurse down the tree (in postfix order for convenience) 230# 231 232function dump(item, c, s) { 233# newitem=sofar"."item"("oid[item]")" 234# printf "/* %s c=%s s=%s */\n", newitem, child[item], sibling[item] 235 c="NULL" 236 if (child[item] != "") { 237 dump(child[item]) 238 c = "&_"child[item]"_obj" 239 } 240 s="NULL" 241 if (sibling[item] != "") { 242 dump(sibling[item]) 243 s = "&_"sibling[item]"_obj" 244 } 245 printf "_%s_obj = {\n\t\"%s\", %d, 0,\n\t%s, %s\n},\n", \ 246 item, item, oid[item], c, s 247} 248' $@ 249exit 0 250