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 47 cat << 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 56 EOF 57 58 awk ' 59 BEGIN { 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 88 NF > 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 132 NF == 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 166 END { 167 print "struct obj" 168 dump("iso") 169 print "*mibroot = &_iso_obj;" 170 } 171 172 function 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 184 function 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 232 function 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 ' $@ 249 exit 0 250