asn1_8c-source.html from net-snmp at Krugle
Show asn1_8c-source.html syntax highlighted
<!--#set var="section" value="development" -->
<!--#include virtual="/page-top.html" -->
<!-- CONTENT START -->
<!-- Generated by Doxygen 1.3.9.1 -->
<div class="qindex">
<a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class=
"qindex" href="annotated.html">Data Structures</a> | <a class="qindex" href="files.html">File List</a> | <a class=
"qindex" href="functions.html">Data Fields</a> | <a class="qindex" href="pages.html">Related Pages</a> | <a class=
"qindex" href="examples.html">Examples</a>
</div>
<div class="nav">
<a class="el" href="dir_000005.html">snmplib</a>
</div>
<h1>asn1.c</h1>
<div class="fragment">
<pre class="fragment">
00001 <span class="comment">/*</span>
00002 <span class="comment"> * Abstract Syntax Notation One, ASN.1</span>
00003 <span class="comment"> * As defined in ISO/IS 8824 and ISO/IS 8825</span>
00004 <span class="comment"> * This implements a subset of the above International Standards that</span>
00005 <span class="comment"> * is sufficient to implement SNMP.</span>
00006 <span class="comment"> *</span>
00007 <span class="comment"> * Encodes abstract data types into a machine independent stream of bytes.</span>
00008 <span class="comment"> *</span>
00009 <span class="comment"> */</span>
00010 <span class="comment">/**********************************************************************</span>
00011 <span class="comment"> Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University</span>
00012
00013 <span class="comment"> All Rights Reserved</span>
00014
00015 <span class="comment">Permission to use, copy, modify, and distribute this software and its </span>
00016 <span class="comment">documentation for any purpose and without fee is hereby granted, </span>
00017 <span class="comment">provided that the above copyright notice appear in all copies and that</span>
00018 <span class="comment">both that copyright notice and this permission notice appear in </span>
00019 <span class="comment">supporting documentation, and that the name of CMU not be</span>
00020 <span class="comment">used in advertising or publicity pertaining to distribution of the</span>
00021 <span class="comment">software without specific, written prior permission. </span>
00022
00023 <span class="comment">CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING</span>
00024 <span class="comment">ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL</span>
00025 <span class="comment">CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR</span>
00026 <span class="comment">ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,</span>
00027 <span class="comment">WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,</span>
00028 <span class="comment">ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS</span>
00029 <span class="comment">SOFTWARE.</span>
00030 <span class="comment">******************************************************************/</span>
00156 <span class="preprocessor">#include <net-snmp/net-snmp-config.h></span>
00157
00158 <span class="preprocessor">#ifdef KINETICS</span>
00159 <span class="preprocessor">#include "gw.h"</span>
00160 <span class="preprocessor">#endif</span>
00161
00162 <span class="preprocessor">#if HAVE_STRING_H</span>
00163 <span class="preprocessor">#include <string.h></span>
00164 <span class="preprocessor">#else</span>
00165 <span class="preprocessor">#include <strings.h></span>
00166 <span class="preprocessor">#endif</span>
00167
00168 <span class="preprocessor">#include <sys/types.h></span>
00169 <span class="preprocessor">#include <stdio.h></span>
00170 <span class="preprocessor">#ifdef HAVE_STDLIB_H</span>
00171 <span class="preprocessor">#include <stdlib.h></span>
00172 <span class="preprocessor">#endif</span>
00173 <span class="preprocessor">#if HAVE_WINSOCK_H</span>
00174 <span class="preprocessor">#include <winsock.h></span>
00175 <span class="preprocessor">#endif</span>
00176 <span class="preprocessor">#if HAVE_NETINET_IN_H</span>
00177 <span class="preprocessor">#include <netinet/in.h></span>
00178 <span class="preprocessor">#endif</span>
00179
00180 <span class="preprocessor">#ifdef vms</span>
00181 <span class="preprocessor">#include <in.h></span>
00182 <span class="preprocessor">#endif</span>
00183
00184 <span class="preprocessor">#if HAVE_DMALLOC_H</span>
00185 <span class="preprocessor">#include <dmalloc.h></span>
00186 <span class="preprocessor">#endif</span>
00187
00188 <span class="preprocessor">#include <net-snmp/output_api.h></span>
00189 <span class="preprocessor">#include <net-snmp/utilities.h></span>
00190
00191 <span class="preprocessor">#include <net-snmp/library/asn1.h></span>
00192 <span class="preprocessor">#include <net-snmp/library/int64.h></span>
00193 <span class="preprocessor">#include <net-snmp/library/mib.h></span>
00194
00195 <span class="preprocessor">#ifndef NULL</span>
00196 <span class="preprocessor">#define NULL 0</span>
00197 <span class="preprocessor">#endif</span>
00198
00199 <span class="preprocessor">#include <net-snmp/library/snmp_api.h></span>
00200
00201 <span class="preprocessor">#ifndef INT32_MAX</span>
00202 <span class="preprocessor"># define INT32_MAX 2147483647</span>
00203 <span class="preprocessor">#endif</span>
00204
00205 <span class="preprocessor">#ifndef INT32_MIN</span>
00206 <span class="preprocessor"># define INT32_MIN (0 - INT32_MAX - 1)</span>
00207 <span class="preprocessor">#endif</span>
00208
00209
00210 <span class="preprocessor">#if SIZEOF_LONG == 4</span>
00211 <span class="preprocessor"># define CHECK_OVERFLOW_S(x,y)</span>
00212 <span class="preprocessor"># define CHECK_OVERFLOW_U(x,y)</span>
00213 <span class="preprocessor">#else</span>
00214 <span class="preprocessor"># define CHECK_OVERFLOW_S(x,y) do { int trunc = 0; \</span>
00215 <span class="preprocessor"> if (x > INT32_MAX) { \</span>
00216 <span class="preprocessor"> trunc = 1; \</span>
00217 <span class="preprocessor"> x &= 0xffffffff; \</span>
00218 <span class="preprocessor"> } else if (x < INT32_MIN) { \</span>
00219 <span class="preprocessor"> trunc = 1; \</span>
00220 <span class="preprocessor"> x = 0 - (x & 0xffffffff); \</span>
00221 <span class="preprocessor"> } \</span>
00222 <span class="preprocessor"> if (trunc) \</span>
00223 <span class="preprocessor"> snmp_log(LOG_ERR,"truncating signed value to 32 bits (%d)\n",y); \</span>
00224 <span class="preprocessor"> } while(0)</span>
00225
00226 <span class="preprocessor"># define CHECK_OVERFLOW_U(x,y) do { \</span>
00227 <span class="preprocessor"> if (x > UINT32_MAX) { \</span>
00228 <span class="preprocessor"> x &= 0xffffffff; \</span>
00229 <span class="preprocessor"> snmp_log(LOG_ERR,"truncating unsigned value to 32 bits (%d)\n",y); \</span>
00230 <span class="preprocessor"> } \</span>
00231 <span class="preprocessor"> } while(0)</span>
00232 <span class="preprocessor">#endif</span>
00233
00242 <span class="keyword">static</span>
00243 <span class="keywordtype">void</span>
00244 _asn_size_err(<span class="keyword">const</span> <span class=
"keywordtype">char</span> *str, size_t wrongsize, size_t rightsize)
00245 {
00246 <span class="keywordtype">char</span> ebuf[128];
00247
00248 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
00249 <span class="stringliteral">"%s size %lu: s/b %lu"</span>, str,
00250 (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)wrongsize, (<span class=
"keywordtype">unsigned</span> <span class="keywordtype">long</span>)rightsize);
00251 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
00252 ERROR_MSG(ebuf);
00253 }
00254
00263 <span class="keyword">static</span>
00264 <span class="keywordtype">void</span>
00265 _asn_length_err(<span class="keyword">const</span> <span class=
"keywordtype">char</span> *str, size_t wrongsize, size_t rightsize)
00266 {
00267 <span class="keywordtype">char</span> ebuf[128];
00268
00269 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
00270 <span class="stringliteral">"%s length %lu too large: exceeds %lu"</span>, str,
00271 (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)wrongsize, (<span class=
"keywordtype">unsigned</span> <span class="keywordtype">long</span>)rightsize);
00272 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
00273 ERROR_MSG(ebuf);
00274 }
00275
00288 <span class="keyword">static</span>
00289 <span class="keywordtype">int</span>
00290 _asn_parse_length_check(<span class="keyword">const</span> <span class="keywordtype">char</span> *str,
00291 <span class="keyword">const</span> u_char * bufp, <span class="keyword">const</span> u_char * data,
00292 u_long plen, size_t dlen)
00293 {
00294 <span class="keywordtype">char</span> ebuf[128];
00295 size_t header_len;
00296
00297 <span class="keywordflow">if</span> (bufp == NULL) {
00298 <span class="comment">/*</span>
00299 <span class="comment"> * error message is set </span>
00300 <span class="comment"> */</span>
00301 <span class="keywordflow">return</span> 1;
00302 }
00303 header_len = bufp - data;
00304 <span class="keywordflow">if</span> (plen > 0x7fffffff || header_len > 0x7fffffff ||
00305 ((size_t) plen + header_len) > dlen) {
00306 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
00307 <span class="stringliteral">"%s: message overflow: %d len + %d delta > %d len"</span>,
00308 str, (<span class="keywordtype">int</span>) plen, (<span class=
"keywordtype">int</span>) header_len, (<span class="keywordtype">int</span>) dlen);
00309 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
00310 ERROR_MSG(ebuf);
00311 <span class="keywordflow">return</span> 1;
00312 }
00313 <span class="keywordflow">return</span> 0;
00314 }
00315
00316
00328 <span class="keyword">static</span>
00329 <span class="keywordtype">int</span>
00330 _asn_build_header_check(<span class="keyword">const</span> <span class="keywordtype">char</span> *str, <span class=
"keyword">const</span> u_char * data,
00331 size_t datalen, size_t typedlen)
00332 {
00333 <span class="keywordtype">char</span> ebuf[128];
00334
00335 <span class="keywordflow">if</span> (data == NULL) {
00336 <span class="comment">/*</span>
00337 <span class="comment"> * error message is set </span>
00338 <span class="comment"> */</span>
00339 <span class="keywordflow">return</span> 1;
00340 }
00341 <span class="keywordflow">if</span> (datalen < typedlen) {
00342 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
00343 <span class="stringliteral">"%s: bad header, length too short: %lu < %lu"</span>, str,
00344 (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)datalen, (<span class=
"keywordtype">unsigned</span> <span class="keywordtype">long</span>)typedlen);
00345 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
00346 ERROR_MSG(ebuf);
00347 <span class="keywordflow">return</span> 1;
00348 }
00349 <span class="keywordflow">return</span> 0;
00350 }
00351
00363 <span class="keyword">static</span>
00364 <span class="keywordtype">int</span>
00365 _asn_realloc_build_header_check(<span class="keyword">const</span> <span class="keywordtype">char</span> *str,
00366 u_char ** pkt,
00367 <span class="keyword">const</span> size_t * pkt_len, size_t typedlen)
00368 {
00369 <span class="keywordtype">char</span> ebuf[128];
00370
00371 <span class="keywordflow">if</span> (pkt == NULL || *pkt == NULL) {
00372 <span class="comment">/*</span>
00373 <span class="comment"> * Error message is set. </span>
00374 <span class="comment"> */</span>
00375 <span class="keywordflow">return</span> 1;
00376 }
00377
00378 <span class="keywordflow">if</span> (*pkt_len < typedlen) {
00379 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
00380 <span class="stringliteral">"%s: bad header, length too short: %lu < %lu"</span>, str,
00381 (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)*pkt_len, (<span class=
"keywordtype">unsigned</span> <span class="keywordtype">long</span>)typedlen);
00382 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
00383 ERROR_MSG(ebuf);
00384 <span class="keywordflow">return</span> 1;
00385 }
00386 <span class="keywordflow">return</span> 0;
00387 }
00388
00398 <span class="keywordtype">int</span>
00399 asn_check_packet(u_char * pkt, size_t len)
00400 {
00401 u_long asn_length;
00402
00403 <span class="keywordflow">if</span> (len < 2)
00404 <span class="keywordflow">return</span> 0; <span class="comment">/* always too short */</span>
00405
00406 <span class="keywordflow">if</span> (*pkt != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR))
00407 <span class="keywordflow">return</span> -1; <span class="comment">/* wrong type */</span>
00408
00409 <span class="keywordflow">if</span> (*(pkt + 1) & 0x80) {
00410 <span class="comment">/*</span>
00411 <span class="comment"> * long length </span>
00412 <span class="comment"> */</span>
00413 <span class="keywordflow">if</span> ((int) len < (int) (*(pkt + 1) & ~0x80) + 2)
00414 <span class="keywordflow">return</span> 0; <span class=
"comment">/* still to short, incomplete length */</span>
00415 asn_parse_length(pkt + 1, &asn_length);
00416 <span class="keywordflow">return</span> (asn_length + 2 + (*(pkt + 1) & ~0x80));
00417 } <span class="keywordflow">else</span> {
00418 <span class="comment">/*</span>
00419 <span class="comment"> * short length </span>
00420 <span class="comment"> */</span>
00421 <span class="keywordflow">return</span> (*(pkt + 1) + 2);
00422 }
00423 }
00424
00425 <span class="keyword">static</span>
00426 <span class="keywordtype">int</span>
00427 _asn_bitstring_check(<span class="keyword">const</span> <span class=
"keywordtype">char</span> *str, size_t asn_length, u_char datum)
00428 {
00429 <span class="keywordtype">char</span> ebuf[128];
00430
00431 <span class="keywordflow">if</span> (asn_length < 1) {
00432 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
00433 <span class="stringliteral">"%s: length %d too small"</span>, str, (<span class=
"keywordtype">int</span>) asn_length);
00434 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
00435 ERROR_MSG(ebuf);
00436 <span class="keywordflow">return</span> 1;
00437 }
00438 <span class="comment">/*</span>
00439 <span class="comment"> * if (datum > 7){</span>
00440 <span class="comment"> * sprintf(ebuf,"%s: datum %d >7: too large", str, (int)(datum));</span>
00441 <span class="comment"> * ERROR_MSG(ebuf);</span>
00442 <span class="comment"> * return 1;</span>
00443 <span class="comment"> * }</span>
00444 <span class="comment"> */</span>
00445 <span class="keywordflow">return</span> 0;
00446 }
00447
00469 u_char *
00470 asn_parse_int(u_char * data,
00471 size_t * datalength,
00472 u_char * type, <span class="keywordtype">long</span> *intp, size_t intsize)
00473 {
00474 <span class="comment">/*</span>
00475 <span class="comment"> * ASN.1 integer ::= 0x02 asnlength byte {byte}*</span>
00476 <span class="comment"> */</span>
00477 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"parse int"</span>;
00478 <span class="keyword">register</span> u_char *bufp = data;
00479 u_long asn_length;
00480 <span class="keyword">register</span> <span class="keywordtype">long</span> value = 0;
00481
00482 <span class="keywordflow">if</span> (intsize != <span class="keyword">sizeof</span>(long)) {
00483 _asn_size_err(errpre, intsize, <span class="keyword">sizeof</span>(<span class="keywordtype">long</span>));
00484 <span class="keywordflow">return</span> NULL;
00485 }
00486 *type = *bufp++;
00487 bufp = asn_parse_length(bufp, &asn_length);
00488 <span class="keywordflow">if</span> (_asn_parse_length_check
00489 (errpre, bufp, data, asn_length, *datalength))
00490 <span class="keywordflow">return</span> NULL;
00491
00492 <span class="keywordflow">if</span> ((size_t) asn_length > intsize) {
00493 _asn_length_err(errpre, (size_t) asn_length, intsize);
00494 <span class="keywordflow">return</span> NULL;
00495 }
00496
00497 *datalength -= (int) asn_length + (bufp - data);
00498 <span class="keywordflow">if</span> (*bufp & 0x80)
00499 value = -1; <span class="comment">/* integer is negative */</span>
00500
00501 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data + asn_length);
00502
00503 <span class="keywordflow">while</span> (asn_length--)
00504 value = (value << 8) | *bufp++;
00505
00506 CHECK_OVERFLOW_S(value,1);
00507
00508 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">" Integer:\t%ld (0x%.2X)\n"</span>, value, value));
00509
00510 *intp = value;
00511 <span class="keywordflow">return</span> bufp;
00512 }
00513
00514
00536 u_char *
00537 asn_parse_unsigned_int(u_char * data,
00538 size_t * datalength,
00539 u_char * type, u_long * intp, size_t intsize)
00540 {
00541 <span class="comment">/*</span>
00542 <span class="comment"> * ASN.1 integer ::= 0x02 asnlength byte {byte}*</span>
00543 <span class="comment"> */</span>
00544 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"parse uint"</span>;
00545 <span class="keyword">register</span> u_char *bufp = data;
00546 u_long asn_length;
00547 <span class="keyword">register</span> u_long value = 0;
00548
00549 <span class="keywordflow">if</span> (intsize != <span class="keyword">sizeof</span>(long)) {
00550 _asn_size_err(errpre, intsize, <span class="keyword">sizeof</span>(<span class="keywordtype">long</span>));
00551 <span class="keywordflow">return</span> NULL;
00552 }
00553 *type = *bufp++;
00554 bufp = asn_parse_length(bufp, &asn_length);
00555 <span class="keywordflow">if</span> (_asn_parse_length_check
00556 (errpre, bufp, data, asn_length, *datalength))
00557 <span class="keywordflow">return</span> NULL;
00558
00559 <span class="keywordflow">if</span> (((int) asn_length > (intsize + 1)) ||
00560 (((int) asn_length == intsize + 1) && *bufp != 0x00)) {
00561 _asn_length_err(errpre, (size_t) asn_length, intsize);
00562 <span class="keywordflow">return</span> NULL;
00563 }
00564 *datalength -= (int) asn_length + (bufp - data);
00565 <span class="keywordflow">if</span> (*bufp & 0x80)
00566 value = ~value; <span class="comment">/* integer is negative */</span>
00567
00568 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data + asn_length);
00569
00570 <span class="keywordflow">while</span> (asn_length--)
00571 value = (value << 8) | *bufp++;
00572
00573 CHECK_OVERFLOW_U(value,2);
00574
00575 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">" UInteger:\t%ld (0x%.2X)\n"</span>, value, value));
00576
00577 *intp = value;
00578 <span class="keywordflow">return</span> bufp;
00579 }
00580
00581
00605 u_char *
00606 asn_build_int(u_char * data,
00607 size_t * datalength, u_char type, <span class="keyword">const</span> <span class=
"keywordtype">long</span> *intp, size_t intsize)
00608 {
00609 <span class="comment">/*</span>
00610 <span class="comment"> * ASN.1 integer ::= 0x02 asnlength byte {byte}*</span>
00611 <span class="comment"> */</span>
00612 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"build int"</span>;
00613 <span class="keyword">register</span> <span class="keywordtype">long</span> integer;
00614 <span class="keyword">register</span> u_long mask;
00615 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
00616 u_char *initdatap = data;
00617 <span class="preprocessor">#endif</span>
00618
00619 <span class="keywordflow">if</span> (intsize != <span class="keyword">sizeof</span>(long)) {
00620 _asn_size_err(errpre, intsize, <span class="keyword">sizeof</span>(<span class="keywordtype">long</span>));
00621 <span class="keywordflow">return</span> NULL;
00622 }
00623 integer = *intp;
00624 CHECK_OVERFLOW_S(integer,3);
00625 <span class="comment">/*</span>
00626 <span class="comment"> * Truncate "unnecessary" bytes off of the most significant end of this</span>
00627 <span class="comment"> * 2's complement integer. There should be no sequence of 9</span>
00628 <span class="comment"> * consecutive 1's or 0's at the most significant end of the</span>
00629 <span class="comment"> * integer.</span>
00630 <span class="comment"> */</span>
00631 mask = ((u_long) 0x1FF) << ((8 * (<span class="keyword">sizeof</span>(long) - 1)) - 1);
00632 <span class="comment">/*</span>
00633 <span class="comment"> * mask is 0xFF800000 on a big-endian machine </span>
00634 <span class="comment"> */</span>
00635 <span class="keywordflow">while</span> ((((integer & mask) == 0) || ((integer & mask) == mask))
00636 && intsize > 1) {
00637 intsize--;
00638 integer <<= 8;
00639 }
00640 data = asn_build_header(data, datalength, type, intsize);
00641 <span class="keywordflow">if</span> (_asn_build_header_check(errpre, data, *datalength, intsize))
00642 <span class="keywordflow">return</span> NULL;
00643
00644 *datalength -= intsize;
00645 mask = ((u_long) 0xFF) << (8 * (<span class="keyword">sizeof</span>(long) - 1));
00646 <span class="comment">/*</span>
00647 <span class="comment"> * mask is 0xFF000000 on a big-endian machine </span>
00648 <span class="comment"> */</span>
00649 <span class="keywordflow">while</span> (intsize--) {
00650 *data++ = (u_char) ((integer & mask) >> (8 * (<span class="keyword">sizeof</span>(long) - 1)));
00651 integer <<= 8;
00652 }
00653 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap);
00654 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class=
"stringliteral">" Integer:\t%ld (0x%.2X)\n"</span>, *intp, *intp));
00655 <span class="keywordflow">return</span> data;
00656 }
00657
00658
00659
00683 u_char *
00684 asn_build_unsigned_int(u_char * data,
00685 size_t * datalength,
00686 u_char type, <span class="keyword">const</span> u_long * intp, size_t intsize)
00687 {
00688 <span class="comment">/*</span>
00689 <span class="comment"> * ASN.1 integer ::= 0x02 asnlength byte {byte}*</span>
00690 <span class="comment"> */</span>
00691 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"build uint"</span>;
00692 <span class="keyword">register</span> u_long integer;
00693 <span class="keyword">register</span> u_long mask;
00694 <span class="keywordtype">int</span> add_null_byte = 0;
00695 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
00696 u_char *initdatap = data;
00697 <span class="preprocessor">#endif</span>
00698
00699 <span class="keywordflow">if</span> (intsize != <span class="keyword">sizeof</span>(long)) {
00700 _asn_size_err(errpre, intsize, <span class="keyword">sizeof</span>(<span class="keywordtype">long</span>));
00701 <span class="keywordflow">return</span> NULL;
00702 }
00703 integer = *intp;
00704 CHECK_OVERFLOW_U(integer,4);
00705
00706 mask = ((u_long) 0xFF) << (8 * (<span class="keyword">sizeof</span>(long) - 1));
00707 <span class="comment">/*</span>
00708 <span class="comment"> * mask is 0xFF000000 on a big-endian machine </span>
00709 <span class="comment"> */</span>
00710 <span class="keywordflow">if</span> ((u_char) ((integer & mask) >> (8 * (<span class=
"keyword">sizeof</span>(long) - 1))) & 0x80) {
00711 <span class="comment">/*</span>
00712 <span class="comment"> * if MSB is set </span>
00713 <span class="comment"> */</span>
00714 add_null_byte = 1;
00715 intsize++;
00716 } <span class="keywordflow">else</span> {
00717 <span class="comment">/*</span>
00718 <span class=
"comment"> * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer.</span>
00719 <span class=
"comment"> * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the</span>
00720 <span class="comment"> * integer.</span>
00721 <span class="comment"> */</span>
00722 mask = ((u_long) 0x1FF) << ((8 * (<span class="keyword">sizeof</span>(long) - 1)) - 1);
00723 <span class="comment">/*</span>
00724 <span class="comment"> * mask is 0xFF800000 on a big-endian machine </span>
00725 <span class="comment"> */</span>
00726 <span class="keywordflow">while</span> ((((integer & mask) == 0) || ((integer & mask) == mask))
00727 && intsize > 1) {
00728 intsize--;
00729 integer <<= 8;
00730 }
00731 }
00732 data = asn_build_header(data, datalength, type, intsize);
00733 <span class="keywordflow">if</span> (_asn_build_header_check(errpre, data, *datalength, intsize))
00734 <span class="keywordflow">return</span> NULL;
00735
00736 *datalength -= intsize;
00737 <span class="keywordflow">if</span> (add_null_byte == 1) {
00738 *data++ = <span class="charliteral">'\0'</span>;
00739 intsize--;
00740 }
00741 mask = ((u_long) 0xFF) << (8 * (<span class="keyword">sizeof</span>(long) - 1));
00742 <span class="comment">/*</span>
00743 <span class="comment"> * mask is 0xFF000000 on a big-endian machine </span>
00744 <span class="comment"> */</span>
00745 <span class="keywordflow">while</span> (intsize--) {
00746 *data++ = (u_char) ((integer & mask) >> (8 * (<span class="keyword">sizeof</span>(long) - 1)));
00747 integer <<= 8;
00748 }
00749 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap);
00750 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class=
"stringliteral">" UInteger:\t%ld (0x%.2X)\n"</span>, *intp, *intp));
00751 <span class="keywordflow">return</span> data;
00752 }
00753
00754
00783 u_char *
00784 asn_parse_string(u_char * data,
00785 size_t * datalength,
00786 u_char * type, u_char * str, size_t * strlength)
00787 {
00788 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"parse string"</span>;
00789 u_char *bufp = data;
00790 u_long asn_length;
00791
00792 *type = *bufp++;
00793 bufp = asn_parse_length(bufp, &asn_length);
00794 <span class="keywordflow">if</span> (_asn_parse_length_check
00795 (errpre, bufp, data, asn_length, *datalength)) {
00796 <span class="keywordflow">return</span> NULL;
00797 }
00798
00799 <span class="keywordflow">if</span> ((int) asn_length > *strlength) {
00800 _asn_length_err(errpre, (size_t) asn_length, *strlength);
00801 <span class="keywordflow">return</span> NULL;
00802 }
00803
00804 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data + asn_length);
00805
00806 memmove(str, bufp, asn_length);
00807 <span class="keywordflow">if</span> (*strlength > (int) asn_length)
00808 str[asn_length] = 0;
00809 *strlength = (int) asn_length;
00810 *datalength -= (int) asn_length + (bufp - data);
00811
00812 DEBUGIF(<span class="stringliteral">"dumpv_recv"</span>) {
00813 u_char *buf = (u_char *) malloc(1 + asn_length);
00814 size_t l = (buf != NULL) ? (1 + asn_length) : 0, ol = 0;
00815
00816 <span class="keywordflow">if</span> (<a class="code" href=
"group__mib__utilities.html#ga28">sprint_realloc_asciistring</a>
00817 (&buf, &l, &ol, 1, str, asn_length)) {
00818 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">" String:\t%s\n"</span>, buf));
00819 } <span class="keywordflow">else</span> {
00820 <span class="keywordflow">if</span> (buf == NULL) {
00821 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">" String:\t[TRUNCATED]\n"</span>));
00822 } <span class="keywordflow">else</span> {
00823 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">" String:\t%s [TRUNCATED]\n"</span>,
00824 buf));
00825 }
00826 }
00827 <span class="keywordflow">if</span> (buf != NULL) {
00828 free(buf);
00829 }
00830 }
00831
00832 <span class="keywordflow">return</span> bufp + asn_length;
00833 }
00834
00835
00858 u_char *
00859 asn_build_string(u_char * data,
00860 size_t * datalength,
00861 u_char type, <span class="keyword">const</span> u_char * str, size_t strlength)
00862 {
00863 <span class="comment">/*</span>
00864 <span class="comment"> * ASN.1 octet string ::= primstring | cmpdstring</span>
00865 <span class="comment"> * primstring ::= 0x04 asnlength byte {byte}*</span>
00866 <span class="comment"> * cmpdstring ::= 0x24 asnlength string {string}*</span>
00867 <span class="comment"> * This code will never send a compound string.</span>
00868 <span class="comment"> */</span>
00869 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
00870 u_char *initdatap = data;
00871 <span class="preprocessor">#endif</span>
00872 data = asn_build_header(data, datalength, type, strlength);
00873 <span class="keywordflow">if</span> (_asn_build_header_check
00874 (<span class="stringliteral">"build string"</span>, data, *datalength, strlength))
00875 <span class="keywordflow">return</span> NULL;
00876
00877 <span class="keywordflow">if</span> (strlength) {
00878 <span class="keywordflow">if</span> (str == NULL) {
00879 memset(data, 0, strlength);
00880 } <span class="keywordflow">else</span> {
00881 memmove(data, str, strlength);
00882 }
00883 }
00884 *datalength -= strlength;
00885 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap + strlength);
00886 DEBUGIF(<span class="stringliteral">"dumpv_send"</span>) {
00887 u_char *buf = (u_char *) malloc(1 + strlength);
00888 size_t l = (buf != NULL) ? (1 + strlength) : 0, ol = 0;
00889
00890 <span class="keywordflow">if</span> (<a class="code" href=
"group__mib__utilities.html#ga28">sprint_realloc_asciistring</a>
00891 (&buf, &l, &ol, 1, str, strlength)) {
00892 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class=
"stringliteral">" String:\t%s\n"</span>, buf));
00893 } <span class="keywordflow">else</span> {
00894 <span class="keywordflow">if</span> (buf == NULL) {
00895 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class=
"stringliteral">" String:\t[TRUNCATED]\n"</span>));
00896 } <span class="keywordflow">else</span> {
00897 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class=
"stringliteral">" String:\t%s [TRUNCATED]\n"</span>,
00898 buf));
00899 }
00900 }
00901 <span class="keywordflow">if</span> (buf != NULL) {
00902 free(buf);
00903 }
00904 }
00905 <span class="keywordflow">return</span> data + strlength;
00906 }
00907
00908
00909
00929 u_char *
00930 asn_parse_header(u_char * data, size_t * datalength, u_char * type)
00931 {
00932 <span class="keyword">register</span> u_char *bufp;
00933 u_long asn_length;
00934
00935 <span class="keywordflow">if</span> (!data || !datalength || !type) {
00936 ERROR_MSG(<span class="stringliteral">"parse header: NULL pointer"</span>);
00937 <span class="keywordflow">return</span> NULL;
00938 }
00939 bufp = data;
00940 <span class="comment">/*</span>
00941 <span class="comment"> * this only works on data types < 30, i.e. no extension octets </span>
00942 <span class="comment"> */</span>
00943 <span class="keywordflow">if</span> (IS_EXTENSION_ID(*bufp)) {
00944 ERROR_MSG(<span class="stringliteral">"can't process ID >= 30"</span>);
00945 <span class="keywordflow">return</span> NULL;
00946 }
00947 *type = *bufp;
00948 bufp = asn_parse_length(bufp + 1, &asn_length);
00949
00950 <span class="keywordflow">if</span> (_asn_parse_length_check
00951 (<span class="stringliteral">"parse header"</span>, bufp, data, asn_length, *datalength))
00952 <span class="keywordflow">return</span> NULL;
00953
00954 <span class="preprocessor">#ifdef DUMP_PRINT_HEADERS</span>
00955 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, (bufp - data));
00956 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">" Header: 0x%.2X, len = %d (0x%X)\n"</span>, *data,
00957 asn_length, asn_length));
00958 <span class="preprocessor">#else</span>
00959 <span class="comment">/*</span>
00960 <span class="comment"> * DEBUGMSGHEXTLI(("recv",data,(bufp-data)));</span>
00961 <span class="comment"> * DEBUGMSG(("dumpH_recv","\n"));</span>
00962 <span class="comment"> */</span>
00963 <span class="preprocessor">#endif</span>
00964
00965 <span class="preprocessor">#ifdef OPAQUE_SPECIAL_TYPES</span>
00966
00967 <span class="keywordflow">if</span> ((*type == ASN_OPAQUE) && (*bufp == ASN_OPAQUE_TAG1)) {
00968
00969 <span class="comment">/*</span>
00970 <span class="comment"> * check if 64-but counter </span>
00971 <span class="comment"> */</span>
00972 <span class="keywordflow">switch</span> (*(bufp + 1)) {
00973 <span class="keywordflow">case</span> ASN_OPAQUE_COUNTER64:
00974 <span class="keywordflow">case</span> ASN_OPAQUE_U64:
00975 <span class="keywordflow">case</span> ASN_OPAQUE_FLOAT:
00976 <span class="keywordflow">case</span> ASN_OPAQUE_DOUBLE:
00977 <span class="keywordflow">case</span> ASN_OPAQUE_I64:
00978 *type = *(bufp + 1);
00979 <span class="keywordflow">break</span>;
00980
00981 <span class="keywordflow">default</span>:
00982 <span class="comment">/*</span>
00983 <span class="comment"> * just an Opaque </span>
00984 <span class="comment"> */</span>
00985 *datalength = (int) asn_length;
00986 <span class="keywordflow">return</span> bufp;
00987 }
00988 <span class="comment">/*</span>
00989 <span class="comment"> * value is encoded as special format </span>
00990 <span class="comment"> */</span>
00991 bufp = asn_parse_length(bufp + 2, &asn_length);
00992 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse opaque header"</span>, bufp, data,
00993 asn_length, *datalength))
00994 <span class="keywordflow">return</span> NULL;
00995 }
00996 <span class="preprocessor">#endif </span><span class="comment">/* OPAQUE_SPECIAL_TYPES */</span>
00997
00998 *datalength = (int) asn_length;
00999
01000 <span class="keywordflow">return</span> bufp;
01001 }
01002
01017 u_char *
01018 asn_parse_sequence(u_char * data, size_t * datalength, u_char * type, u_char expected_type, <span class=
"comment">/* must be this type */</span>
01019 <span class="keyword">const</span> <span class="keywordtype">char</span> *estr)
01020 { <span class="comment">/* error message prefix */</span>
01021 data = asn_parse_header(data, datalength, type);
01022 <span class="keywordflow">if</span> (data && (*type != expected_type)) {
01023 <span class="keywordtype">char</span> ebuf[128];
01024 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01025 <span class="stringliteral">"%s header type %02X: s/b %02X"</span>, estr,
01026 (u_char) * type, (u_char) expected_type);
01027 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01028 ERROR_MSG(ebuf);
01029 <span class="keywordflow">return</span> NULL;
01030 }
01031 <span class="keywordflow">return</span> data;
01032 }
01033
01034
01035
01058 u_char *
01059 asn_build_header(u_char * data,
01060 size_t * datalength, u_char type, size_t length)
01061 {
01062 <span class="keywordtype">char</span> ebuf[128];
01063
01064 <span class="keywordflow">if</span> (*datalength < 1) {
01065 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01066 <span class="stringliteral">"bad header length < 1 :%lu, %lu"</span>,
01067 (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)*datalength, (<span class=
"keywordtype">unsigned</span> <span class="keywordtype">long</span>)length);
01068 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01069 ERROR_MSG(ebuf);
01070 <span class="keywordflow">return</span> NULL;
01071 }
01072 *data++ = type;
01073 (*datalength)--;
01074 <span class="keywordflow">return</span> asn_build_length(data, datalength, length);
01075 }
01076
01100 u_char *
01101 asn_build_sequence(u_char * data,
01102 size_t * datalength, u_char type, size_t length)
01103 {
01104 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"build seq"</span>;
01105 <span class="keywordtype">char</span> ebuf[128];
01106
01107 <span class="keywordflow">if</span> (*datalength < 4) {
01108 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01109 <span class="stringliteral">"%s: length %d < 4: PUNT"</span>, errpre,
01110 (<span class="keywordtype">int</span>) *datalength);
01111 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01112 ERROR_MSG(ebuf);
01113 <span class="keywordflow">return</span> NULL;
01114 }
01115 *datalength -= 4;
01116 *data++ = type;
01117 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
01118 *data++ = (u_char) ((length >> 8) & 0xFF);
01119 *data++ = (u_char) (length & 0xFF);
01120 <span class="keywordflow">return</span> data;
01121 }
01122
01140 u_char *
01141 asn_parse_length(u_char * data, u_long * length)
01142 {
01143 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"parse length"</span>;
01144 <span class="keywordtype">char</span> ebuf[128];
01145 <span class="keyword">register</span> u_char lengthbyte;
01146
01147 <span class="keywordflow">if</span> (!data || !length) {
01148 ERROR_MSG(<span class="stringliteral">"parse length: NULL pointer"</span>);
01149 <span class="keywordflow">return</span> NULL;
01150 }
01151 lengthbyte = *data;
01152
01153 <span class="keywordflow">if</span> (lengthbyte & ASN_LONG_LEN) {
01154 lengthbyte &= ~ASN_LONG_LEN; <span class="comment">/* turn MSb off */</span>
01155 <span class="keywordflow">if</span> (lengthbyte == 0) {
01156 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01157 <span class="stringliteral">"%s: indefinite length not supported"</span>, errpre);
01158 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01159 ERROR_MSG(ebuf);
01160 <span class="keywordflow">return</span> NULL;
01161 }
01162 <span class="keywordflow">if</span> (lengthbyte > <span class="keyword">sizeof</span>(long)) {
01163 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01164 <span class="stringliteral">"%s: data length %d > %lu not supported"</span>, errpre,
01165 lengthbyte, (<span class="keywordtype">unsigned</span> <span class=
"keywordtype">long</span>)<span class="keyword">sizeof</span>(<span class="keywordtype">long</span>));
01166 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01167 ERROR_MSG(ebuf);
01168 <span class="keywordflow">return</span> NULL;
01169 }
01170 data++;
01171 *length = 0; <span class="comment">/* protect against short lengths */</span>
01172 <span class="keywordflow">while</span> (lengthbyte--) {
01173 *length <<= 8;
01174 *length |= *data++;
01175 }
01176 <span class="keywordflow">if</span> ((long) *length < 0) {
01177 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01178 <span class="stringliteral">"%s: negative data length %ld\n"</span>, errpre,
01179 (<span class="keywordtype">long</span>) *length);
01180 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01181 ERROR_MSG(ebuf);
01182 <span class="keywordflow">return</span> NULL;
01183 }
01184 <span class="keywordflow">return</span> data;
01185 } <span class="keywordflow">else</span> { <span class="comment">/* short asnlength */</span>
01186 *length = (long) lengthbyte;
01187 <span class="keywordflow">return</span> data + 1;
01188 }
01189 }
01190
01211 u_char *
01212 asn_build_length(u_char * data, size_t * datalength, size_t length)
01213 {
01214 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"build length"</span>;
01215 <span class="keywordtype">char</span> ebuf[128];
01216
01217 u_char *start_data = data;
01218
01219 <span class="comment">/*</span>
01220 <span class="comment"> * no indefinite lengths sent </span>
01221 <span class="comment"> */</span>
01222 <span class="keywordflow">if</span> (length < 0x80) {
01223 <span class="keywordflow">if</span> (*datalength < 1) {
01224 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01225 <span class="stringliteral">"%s: bad length < 1 :%lu, %lu"</span>, errpre,
01226 (<span class="keywordtype">unsigned</span> <span class=
"keywordtype">long</span>)*datalength, (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)length);
01227 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01228 ERROR_MSG(ebuf);
01229 <span class="keywordflow">return</span> NULL;
01230 }
01231 *data++ = (u_char) length;
01232 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (length <= 0xFF) {
01233 <span class="keywordflow">if</span> (*datalength < 2) {
01234 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01235 <span class="stringliteral">"%s: bad length < 2 :%lu, %lu"</span>, errpre,
01236 (<span class="keywordtype">unsigned</span> <span class=
"keywordtype">long</span>)*datalength, (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)length);
01237 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01238 ERROR_MSG(ebuf);
01239 <span class="keywordflow">return</span> NULL;
01240 }
01241 *data++ = (u_char) (0x01 | ASN_LONG_LEN);
01242 *data++ = (u_char) length;
01243 } <span class="keywordflow">else</span> { <span class=
"comment">/* 0xFF < length <= 0xFFFF */</span>
01244 <span class="keywordflow">if</span> (*datalength < 3) {
01245 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
01246 <span class="stringliteral">"%s: bad length < 3 :%lu, %lu"</span>, errpre,
01247 (<span class="keywordtype">unsigned</span> <span class=
"keywordtype">long</span>)*datalength, (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>)length);
01248 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
01249 ERROR_MSG(ebuf);
01250 <span class="keywordflow">return</span> NULL;
01251 }
01252 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
01253 *data++ = (u_char) ((length >> 8) & 0xFF);
01254 *data++ = (u_char) (length & 0xFF);
01255 }
01256 *datalength -= (data - start_data);
01257 <span class="keywordflow">return</span> data;
01258
01259 }
01260
01286 u_char *
01287 asn_parse_objid(u_char * data,
01288 size_t * datalength,
01289 u_char * type, oid * objid, size_t * objidlength)
01290 {
01291 <span class="comment">/*</span>
01292 <span class="comment"> * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*</span>
01293 <span class="comment"> * subidentifier ::= {leadingbyte}* lastbyte</span>
01294 <span class="comment"> * leadingbyte ::= 1 7bitvalue</span>
01295 <span class="comment"> * lastbyte ::= 0 7bitvalue</span>
01296 <span class="comment"> */</span>
01297 <span class="keyword">register</span> u_char *bufp = data;
01298 <span class="keyword">register</span> oid *oidp = objid + 1;
01299 <span class="keyword">register</span> u_long subidentifier;
01300 <span class="keyword">register</span> <span class="keywordtype">long</span> length;
01301 u_long asn_length;
01302
01303 *type = *bufp++;
01304 bufp = asn_parse_length(bufp, &asn_length);
01305 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse objid"</span>, bufp, data,
01306 asn_length, *datalength))
01307 <span class="keywordflow">return</span> NULL;
01308
01309 *datalength -= (int) asn_length + (bufp - data);
01310
01311 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data + asn_length);
01312
01313 <span class="comment">/*</span>
01314 <span class="comment"> * Handle invalid object identifier encodings of the form 06 00 robustly </span>
01315 <span class="comment"> */</span>
01316 <span class="keywordflow">if</span> (asn_length == 0)
01317 objid[0] = objid[1] = 0;
01318
01319 length = asn_length;
01320 (*objidlength)--; <span class="comment">/* account for expansion of first byte */</span>
01321
01322 <span class="keywordflow">while</span> (length > 0 && (*objidlength)-- > 0) {
01323 subidentifier = 0;
01324 <span class="keywordflow">do</span> { <span class=
"comment">/* shift and add in low order 7 bits */</span>
01325 subidentifier =
01326 (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8);
01327 length--;
01328 } <span class="keywordflow">while</span> (*(u_char *) bufp++ & ASN_BIT8); <span class=
"comment">/* last byte has high bit clear */</span>
01329
01330 <span class="preprocessor">#if defined(EIGHTBIT_SUBIDS) || (SIZEOF_LONG != 4)</span>
01331 <span class="keywordflow">if</span> (subidentifier > (u_long) MAX_SUBID) {
01332 ERROR_MSG(<span class="stringliteral">"subidentifier too large"</span>);
01333 <span class="keywordflow">return</span> NULL;
01334 }
01335 <span class="preprocessor">#endif</span>
01336 *oidp++ = (oid) subidentifier;
01337 }
01338
01339 <span class="keywordflow">if</span> (0 != length) {
01340 ERROR_MSG(<span class="stringliteral">"OID length exceeds buffer size"</span>);
01341 <span class="keywordflow">return</span> NULL;
01342 }
01343
01344 <span class="comment">/*</span>
01345 <span class="comment"> * The first two subidentifiers are encoded into the first component</span>
01346 <span class="comment"> * with the value (X * 40) + Y, where:</span>
01347 <span class="comment"> * X is the value of the first subidentifier.</span>
01348 <span class="comment"> * Y is the value of the second subidentifier.</span>
01349 <span class="comment"> */</span>
01350 subidentifier = (u_long) objid[1];
01351 <span class="keywordflow">if</span> (subidentifier == 0x2B) {
01352 objid[0] = 1;
01353 objid[1] = 3;
01354 } <span class="keywordflow">else</span> {
01355 <span class="keywordflow">if</span> (subidentifier < 40) {
01356 objid[0] = 0;
01357 objid[1] = subidentifier;
01358 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (subidentifier < 80) {
01359 objid[0] = 1;
01360 objid[1] = subidentifier - 40;
01361 } <span class="keywordflow">else</span> {
01362 objid[0] = 2;
01363 objid[1] = subidentifier - 80;
01364 }
01365 }
01366
01367 *objidlength = (int) (oidp - objid);
01368
01369 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class="stringliteral">" ObjID: "</span>));
01370 DEBUGMSGOID((<span class="stringliteral">"dumpv_recv"</span>, objid, *objidlength));
01371 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class="stringliteral">"\n"</span>));
01372 <span class="keywordflow">return</span> bufp;
01373 }
01374
01398 u_char *
01399 asn_build_objid(u_char * data,
01400 size_t * datalength,
01401 u_char type, oid * objid, size_t objidlength)
01402 {
01403 <span class="comment">/*</span>
01404 <span class="comment"> * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*</span>
01405 <span class="comment"> * subidentifier ::= {leadingbyte}* lastbyte</span>
01406 <span class="comment"> * leadingbyte ::= 1 7bitvalue</span>
01407 <span class="comment"> * lastbyte ::= 0 7bitvalue</span>
01408 <span class="comment"> */</span>
01409 size_t asnlength;
01410 <span class="keyword">register</span> oid *op = objid;
01411 u_char objid_size[MAX_OID_LEN];
01412 <span class="keyword">register</span> u_long objid_val;
01413 u_long first_objid_val;
01414 <span class="keyword">register</span> <span class="keywordtype">int</span> i;
01415 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
01416 u_char *initdatap = data;
01417 <span class="preprocessor">#endif</span>
01418
01419 <span class="comment">/*</span>
01420 <span class="comment"> * check if there are at least 2 sub-identifiers </span>
01421 <span class="comment"> */</span>
01422 <span class="keywordflow">if</span> (objidlength == 0) {
01423 <span class="comment">/*</span>
01424 <span class="comment"> * there are not, so make OID have two with value of zero </span>
01425 <span class="comment"> */</span>
01426 objid_val = 0;
01427 objidlength = 2;
01428 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (objid[0] > 2) {
01429 ERROR_MSG(<span class="stringliteral">"build objid: bad first subidentifier"</span>);
01430 <span class="keywordflow">return</span> NULL;
01431 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (objidlength == 1) {
01432 <span class="comment">/*</span>
01433 <span class="comment"> * encode the first value </span>
01434 <span class="comment"> */</span>
01435 objid_val = (op[0] * 40);
01436 objidlength = 2;
01437 op++;
01438 } <span class="keywordflow">else</span> {
01439 <span class="comment">/*</span>
01440 <span class="comment"> * combine the first two values </span>
01441 <span class="comment"> */</span>
01442 <span class="keywordflow">if</span> ((op[1] > 40) &&
01443 (op[0] < 2)) {
01444 ERROR_MSG(<span class="stringliteral">"build objid: bad second subidentifier"</span>);
01445 <span class="keywordflow">return</span> NULL;
01446 }
01447 objid_val = (op[0] * 40) + op[1];
01448 op += 2;
01449 }
01450 first_objid_val = objid_val;
01451
01452 <span class="comment">/*</span>
01453 <span class="comment"> * ditch illegal calls now </span>
01454 <span class="comment"> */</span>
01455 <span class="keywordflow">if</span> (objidlength > MAX_OID_LEN)
01456 <span class="keywordflow">return</span> NULL;
01457
01458 <span class="comment">/*</span>
01459 <span class="comment"> * calculate the number of bytes needed to store the encoded value </span>
01460 <span class="comment"> */</span>
01461 <span class="keywordflow">for</span> (i = 1, asnlength = 0;;) {
01462
01463 CHECK_OVERFLOW_U(objid_val,5);
01464 <span class="keywordflow">if</span> (objid_val < (unsigned) 0x80) {
01465 objid_size[i] = 1;
01466 asnlength += 1;
01467 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (objid_val < (unsigned) 0x4000) {
01468 objid_size[i] = 2;
01469 asnlength += 2;
01470 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (objid_val < (unsigned) 0x200000) {
01471 objid_size[i] = 3;
01472 asnlength += 3;
01473 } <span class="keywordflow">else</span> <span class=
"keywordflow">if</span> (objid_val < (unsigned) 0x10000000) {
01474 objid_size[i] = 4;
01475 asnlength += 4;
01476 } <span class="keywordflow">else</span> {
01477 objid_size[i] = 5;
01478 asnlength += 5;
01479 }
01480 i++;
01481 <span class="keywordflow">if</span> (i >= (int) objidlength)
01482 <span class="keywordflow">break</span>;
01483 objid_val = *op++; <span class="comment">/* XXX - doesn't handle 2.X (X > 40) */</span>
01484 }
01485
01486 <span class="comment">/*</span>
01487 <span class="comment"> * store the ASN.1 tag and length </span>
01488 <span class="comment"> */</span>
01489 data = asn_build_header(data, datalength, type, asnlength);
01490 <span class="keywordflow">if</span> (_asn_build_header_check
01491 (<span class="stringliteral">"build objid"</span>, data, *datalength, asnlength))
01492 <span class="keywordflow">return</span> NULL;
01493
01494 <span class="comment">/*</span>
01495 <span class="comment"> * store the encoded OID value </span>
01496 <span class="comment"> */</span>
01497 <span class="keywordflow">for</span> (i = 1, objid_val = first_objid_val, op = objid + 2;
01498 i < (int) objidlength; i++) {
01499 <span class="keywordflow">if</span> (i != 1) {
01500 objid_val = *op++;
01501 <span class="preprocessor">#if SIZEOF_LONG != 4</span>
01502 <span class="keywordflow">if</span> (objid_val > 0xffffffff) <span class=
"comment">/* already logged warning above */</span>
01503 objid_val &= 0xffffffff;
01504 <span class="preprocessor">#endif</span>
01505 }
01506 <span class="keywordflow">switch</span> (objid_size[i]) {
01507 <span class="keywordflow">case</span> 1:
01508 *data++ = (u_char) objid_val;
01509 <span class="keywordflow">break</span>;
01510
01511 <span class="keywordflow">case</span> 2:
01512 *data++ = (u_char) ((objid_val >> 7) | 0x80);
01513 *data++ = (u_char) (objid_val & 0x07f);
01514 <span class="keywordflow">break</span>;
01515
01516 <span class="keywordflow">case</span> 3:
01517 *data++ = (u_char) ((objid_val >> 14) | 0x80);
01518 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01519 *data++ = (u_char) (objid_val & 0x07f);
01520 <span class="keywordflow">break</span>;
01521
01522 <span class="keywordflow">case</span> 4:
01523 *data++ = (u_char) ((objid_val >> 21) | 0x80);
01524 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
01525 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01526 *data++ = (u_char) (objid_val & 0x07f);
01527 <span class="keywordflow">break</span>;
01528
01529 <span class="keywordflow">case</span> 5:
01530 *data++ = (u_char) ((objid_val >> 28) | 0x80);
01531 *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80);
01532 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
01533 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01534 *data++ = (u_char) (objid_val & 0x07f);
01535 <span class="keywordflow">break</span>;
01536 }
01537 }
01538
01539 <span class="comment">/*</span>
01540 <span class="comment"> * return the length and data ptr </span>
01541 <span class="comment"> */</span>
01542 *datalength -= asnlength;
01543 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap);
01544 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class="stringliteral">" ObjID: "</span>));
01545 DEBUGMSGOID((<span class="stringliteral">"dumpv_send"</span>, objid, objidlength));
01546 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class="stringliteral">"\n"</span>));
01547 <span class="keywordflow">return</span> data;
01548 }
01549
01569 u_char *
01570 asn_parse_null(u_char * data, size_t * datalength, u_char * type)
01571 {
01572 <span class="comment">/*</span>
01573 <span class="comment"> * ASN.1 null ::= 0x05 0x00</span>
01574 <span class="comment"> */</span>
01575 <span class="keyword">register</span> u_char *bufp = data;
01576 u_long asn_length;
01577
01578 *type = *bufp++;
01579 bufp = asn_parse_length(bufp, &asn_length);
01580 <span class="keywordflow">if</span> (bufp == NULL) {
01581 ERROR_MSG(<span class="stringliteral">"parse null: bad length"</span>);
01582 <span class="keywordflow">return</span> NULL;
01583 }
01584 <span class="keywordflow">if</span> (asn_length != 0) {
01585 ERROR_MSG(<span class="stringliteral">"parse null: malformed ASN.1 null"</span>);
01586 <span class="keywordflow">return</span> NULL;
01587 }
01588
01589 *datalength -= (bufp - data);
01590
01591 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data);
01592 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class="stringliteral">" NULL\n"</span>));
01593
01594 <span class="keywordflow">return</span> bufp + asn_length;
01595 }
01596
01597
01618 u_char *
01619 asn_build_null(u_char * data, size_t * datalength, u_char type)
01620 {
01621 <span class="comment">/*</span>
01622 <span class="comment"> * ASN.1 null ::= 0x05 0x00</span>
01623 <span class="comment"> */</span>
01624 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
01625 u_char *initdatap = data;
01626 <span class="preprocessor">#endif</span>
01627 data = asn_build_header(data, datalength, type, 0);
01628 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap);
01629 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class="stringliteral">" NULL\n"</span>));
01630 <span class="keywordflow">return</span> data;
01631 }
01632
01656 u_char *
01657 asn_parse_bitstring(u_char * data,
01658 size_t * datalength,
01659 u_char * type, u_char * str, size_t * strlength)
01660 {
01661 <span class="comment">/*</span>
01662 <span class="comment"> * bitstring ::= 0x03 asnlength unused {byte}*</span>
01663 <span class="comment"> */</span>
01664 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"parse bitstring"</span>;
01665 <span class="keyword">register</span> u_char *bufp = data;
01666 u_long asn_length;
01667
01668 *type = *bufp++;
01669 bufp = asn_parse_length(bufp, &asn_length);
01670 <span class="keywordflow">if</span> (_asn_parse_length_check(errpre, bufp, data,
01671 asn_length, *datalength))
01672 <span class="keywordflow">return</span> NULL;
01673
01674 <span class="keywordflow">if</span> ((size_t) asn_length > *strlength) {
01675 _asn_length_err(errpre, (size_t) asn_length, *strlength);
01676 <span class="keywordflow">return</span> NULL;
01677 }
01678 <span class="keywordflow">if</span> (_asn_bitstring_check(errpre, asn_length, *bufp))
01679 <span class="keywordflow">return</span> NULL;
01680
01681 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data);
01682 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class="stringliteral">" Bitstring: "</span>));
01683 DEBUGMSGHEX((<span class="stringliteral">"dumpv_recv"</span>, data, asn_length));
01684 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class="stringliteral">"\n"</span>));
01685
01686 memmove(str, bufp, asn_length);
01687 *strlength = (int) asn_length;
01688 *datalength -= (int) asn_length + (bufp - data);
01689 <span class="keywordflow">return</span> bufp + asn_length;
01690 }
01691
01692
01715 u_char *
01716 asn_build_bitstring(u_char * data,
01717 size_t * datalength,
01718 u_char type, <span class="keyword">const</span> u_char * str, size_t strlength)
01719 {
01720 <span class="comment">/*</span>
01721 <span class="comment"> * ASN.1 bit string ::= 0x03 asnlength unused {byte}*</span>
01722 <span class="comment"> */</span>
01723 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"build bitstring"</span>;
01724 <span class="keywordflow">if</span> (_asn_bitstring_check
01725 (errpre, strlength, (u_char)((str) ? *str : 0)))
01726 <span class="keywordflow">return</span> NULL;
01727
01728 data = asn_build_header(data, datalength, type, strlength);
01729 <span class="keywordflow">if</span> (_asn_build_header_check(errpre, data, *datalength, strlength))
01730 <span class="keywordflow">return</span> NULL;
01731
01732 <span class="keywordflow">if</span> (strlength > 0 && str)
01733 memmove(data, str, strlength);
01734 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (strlength > 0 && !str) {
01735 ERROR_MSG(<span class="stringliteral">"no string passed into asn_build_bitstring\n"</span>);
01736 <span class="keywordflow">return</span> NULL;
01737 }
01738
01739 *datalength -= strlength;
01740 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, data, strlength);
01741 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class="stringliteral">" Bitstring: "</span>));
01742 DEBUGMSGHEX((<span class="stringliteral">"dumpv_send"</span>, data, strlength));
01743 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class="stringliteral">"\n"</span>));
01744 <span class="keywordflow">return</span> data + strlength;
01745 }
01746
01769 u_char *
01770 asn_parse_unsigned_int64(u_char * data,
01771 size_t * datalength,
01772 u_char * type,
01773 <span class="keyword">struct</span> counter64 * cp, size_t countersize)
01774 {
01775 <span class="comment">/*</span>
01776 <span class="comment"> * ASN.1 integer ::= 0x02 asnlength byte {byte}*</span>
01777 <span class="comment"> */</span>
01778 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"parse uint64"</span>;
01779 <span class="keyword">const</span> <span class="keywordtype">int</span> uint64sizelimit = (4 * 2) + 1;
01780 <span class="keyword">register</span> u_char *bufp = data;
01781 u_long asn_length;
01782 <span class="keyword">register</span> u_long low = 0, high = 0;
01783
01784 <span class="keywordflow">if</span> (countersize != <span class="keyword">sizeof</span>(<span class=
"keyword">struct </span>counter64)) {
01785 _asn_size_err(errpre, countersize, <span class="keyword">sizeof</span>(<span class=
"keyword">struct</span> counter64));
01786 <span class="keywordflow">return</span> NULL;
01787 }
01788 *type = *bufp++;
01789 bufp = asn_parse_length(bufp, &asn_length);
01790 <span class="keywordflow">if</span> (_asn_parse_length_check
01791 (errpre, bufp, data, asn_length, *datalength))
01792 <span class="keywordflow">return</span> NULL;
01793
01794 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data);
01795 <span class="preprocessor">#ifdef OPAQUE_SPECIAL_TYPES</span>
01796 <span class="comment">/*</span>
01797 <span class="comment"> * 64 bit counters as opaque </span>
01798 <span class="comment"> */</span>
01799 <span class="keywordflow">if</span> ((*type == ASN_OPAQUE) &&
01800 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
01801 (*bufp == ASN_OPAQUE_TAG1) &&
01802 ((*(bufp + 1) == ASN_OPAQUE_COUNTER64) ||
01803 (*(bufp + 1) == ASN_OPAQUE_U64))) {
01804 <span class="comment">/*</span>
01805 <span class="comment"> * change type to Counter64 or U64 </span>
01806 <span class="comment"> */</span>
01807 *type = *(bufp + 1);
01808 <span class="comment">/*</span>
01809 <span class="comment"> * value is encoded as special format </span>
01810 <span class="comment"> */</span>
01811 bufp = asn_parse_length(bufp + 2, &asn_length);
01812 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse opaque uint64"</span>, bufp, data,
01813 asn_length, *datalength))
01814 <span class="keywordflow">return</span> NULL;
01815 }
01816 <span class="preprocessor">#endif </span><span class="comment">/* OPAQUE_SPECIAL_TYPES */</span>
01817 <span class="keywordflow">if</span> (((int) asn_length > uint64sizelimit) ||
01818 (((int) asn_length == uint64sizelimit) && *bufp != 0x00)) {
01819 _asn_length_err(errpre, (size_t) asn_length, uint64sizelimit);
01820 <span class="keywordflow">return</span> NULL;
01821 }
01822 *datalength -= (int) asn_length + (bufp - data);
01823 <span class="keywordflow">if</span> (*bufp & 0x80) {
01824 low = 0xFFFFFF; <span class="comment">/* first byte bit 1 means start the data with 1s */</span>
01825 high = 0xFFFFFF;
01826 }
01827
01828 <span class="keywordflow">while</span> (asn_length--) {
01829 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24);
01830 low = ((low & 0x00FFFFFF) << 8) | *bufp++;
01831 }
01832
01833 CHECK_OVERFLOW_U(high,6);
01834 CHECK_OVERFLOW_U(low,6);
01835
01836 cp->low = low;
01837 cp->high = high;
01838
01839 DEBUGIF(<span class="stringliteral">"dumpv_recv"</span>) {
01840 <span class="keywordtype">char</span> i64buf[I64CHARSZ + 1];
01841 printU64(i64buf, cp);
01842 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">"Counter64: %s"</span>, i64buf));
01843 }
01844
01845 <span class="keywordflow">return</span> bufp;
01846 }
01847
01848
01870 u_char *
01871 asn_build_unsigned_int64(u_char * data,
01872 size_t * datalength,
01873 u_char type,
01874 <span class="keyword">const</span> <span class=
"keyword">struct</span> counter64 * cp, size_t countersize)
01875 {
01876 <span class="comment">/*</span>
01877 <span class="comment"> * ASN.1 integer ::= 0x02 asnlength byte {byte}*</span>
01878 <span class="comment"> */</span>
01879
01880 <span class="keyword">register</span> u_long low, high;
01881 <span class="keyword">register</span> u_long mask, mask2;
01882 <span class="keywordtype">int</span> add_null_byte = 0;
01883 size_t intsize;
01884 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
01885 u_char *initdatap = data;
01886 <span class="preprocessor">#endif</span>
01887
01888 <span class="keywordflow">if</span> (countersize != <span class="keyword">sizeof</span>(<span class=
"keyword">struct </span>counter64)) {
01889 _asn_size_err(<span class="stringliteral">"build uint64"</span>, countersize,
01890 <span class="keyword">sizeof</span>(<span class="keyword">struct</span> counter64));
01891 <span class="keywordflow">return</span> NULL;
01892 }
01893 intsize = 8;
01894 low = cp->low;
01895 high = cp->high;
01896
01897 CHECK_OVERFLOW_U(high,7);
01898 CHECK_OVERFLOW_U(low,7);
01899
01900 mask = ((u_long) 0xFF) << (8 * (<span class="keyword">sizeof</span>(long) - 1));
01901 <span class="comment">/*</span>
01902 <span class="comment"> * mask is 0xFF000000 on a big-endian machine </span>
01903 <span class="comment"> */</span>
01904 <span class="keywordflow">if</span> ((u_char) ((high & mask) >> (8 * (<span class=
"keyword">sizeof</span>(long) - 1))) & 0x80) {
01905 <span class="comment">/*</span>
01906 <span class="comment"> * if MSB is set </span>
01907 <span class="comment"> */</span>
01908 add_null_byte = 1;
01909 intsize++;
01910 } <span class="keywordflow">else</span> {
01911 <span class="comment">/*</span>
01912 <span class="comment"> * Truncate "unnecessary" bytes off of the most significant end of this 2's</span>
01913 <span class="comment"> * complement integer.</span>
01914 <span class="comment"> * There should be no sequence of 9 consecutive 1's or 0's at the most</span>
01915 <span class="comment"> * significant end of the integer.</span>
01916 <span class="comment"> */</span>
01917 mask2 = ((u_long) 0x1FF) << ((8 * (<span class="keyword">sizeof</span>(long) - 1)) - 1);
01918 <span class="comment">/*</span>
01919 <span class="comment"> * mask2 is 0xFF800000 on a big-endian machine </span>
01920 <span class="comment"> */</span>
01921 <span class="keywordflow">while</span> ((((high & mask2) == 0) || ((high & mask2) == mask2))
01922 && intsize > 1) {
01923 intsize--;
01924 high = (high << 8)
01925 | ((low & mask) >> (8 * (<span class="keyword">sizeof</span>(long) - 1)));
01926 low <<= 8;
01927 }
01928 }
01929 <span class="preprocessor">#ifdef OPAQUE_SPECIAL_TYPES</span>
01930 <span class="comment">/*</span>
01931 <span class="comment"> * encode a Counter64 as an opaque (it also works in SNMPv1) </span>
01932 <span class="comment"> */</span>
01933 <span class="comment">/*</span>
01934 <span class="comment"> * turn into Opaque holding special tagged value </span>
01935 <span class="comment"> */</span>
01936 <span class="keywordflow">if</span> (type == ASN_OPAQUE_COUNTER64) {
01937 <span class="comment">/*</span>
01938 <span class="comment"> * put the tag and length for the Opaque wrapper </span>
01939 <span class="comment"> */</span>
01940 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
01941 <span class="keywordflow">if</span> (_asn_build_header_check
01942 (<span class="stringliteral">"build counter u64"</span>, data, *datalength, intsize + 3))
01943 <span class="keywordflow">return</span> NULL;
01944
01945 <span class="comment">/*</span>
01946 <span class="comment"> * put the special tag and length </span>
01947 <span class="comment"> */</span>
01948 *data++ = ASN_OPAQUE_TAG1;
01949 *data++ = ASN_OPAQUE_COUNTER64;
01950 *data++ = (u_char) intsize;
01951 *datalength = *datalength - 3;
01952 } <span class="keywordflow">else</span>
01953 <span class="comment">/*</span>
01954 <span class="comment"> * Encode the Unsigned int64 in an opaque </span>
01955 <span class="comment"> */</span>
01956 <span class="comment">/*</span>
01957 <span class="comment"> * turn into Opaque holding special tagged value </span>
01958 <span class="comment"> */</span>
01959 <span class="keywordflow">if</span> (type == ASN_OPAQUE_U64) {
01960 <span class="comment">/*</span>
01961 <span class="comment"> * put the tag and length for the Opaque wrapper </span>
01962 <span class="comment"> */</span>
01963 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
01964 <span class="keywordflow">if</span> (_asn_build_header_check
01965 (<span class="stringliteral">"build opaque u64"</span>, data, *datalength, intsize + 3))
01966 <span class="keywordflow">return</span> NULL;
01967
01968 <span class="comment">/*</span>
01969 <span class="comment"> * put the special tag and length </span>
01970 <span class="comment"> */</span>
01971 *data++ = ASN_OPAQUE_TAG1;
01972 *data++ = ASN_OPAQUE_U64;
01973 *data++ = (u_char) intsize;
01974 *datalength = *datalength - 3;
01975 } <span class="keywordflow">else</span> {
01976 <span class="preprocessor">#endif </span><span class="comment">/* OPAQUE_SPECIAL_TYPES */</span>
01977 data = asn_build_header(data, datalength, type, intsize);
01978 <span class="keywordflow">if</span> (_asn_build_header_check
01979 (<span class="stringliteral">"build uint64"</span>, data, *datalength, intsize))
01980 <span class="keywordflow">return</span> NULL;
01981
01982 <span class="preprocessor">#ifdef OPAQUE_SPECIAL_TYPES</span>
01983 }
01984 <span class="preprocessor">#endif </span><span class="comment">/* OPAQUE_SPECIAL_TYPES */</span>
01985 *datalength -= intsize;
01986 <span class="keywordflow">if</span> (add_null_byte == 1) {
01987 *data++ = <span class="charliteral">'\0'</span>;
01988 intsize--;
01989 }
01990 <span class="keywordflow">while</span> (intsize--) {
01991 *data++ = (u_char) ((high & mask) >> (8 * (<span class="keyword">sizeof</span>(long) - 1)));
01992 high = (high << 8)
01993 | ((low & mask) >> (8 * (<span class="keyword">sizeof</span>(long) - 1)));
01994 low <<= 8;
01995
01996 }
01997 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap);
01998 DEBUGIF(<span class="stringliteral">"dumpv_send"</span>) {
01999 <span class="keywordtype">char</span> i64buf[I64CHARSZ + 1];
02000 printU64(i64buf, cp);
02001 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, i64buf));
02002 }
02003 <span class="keywordflow">return</span> data;
02004 }
02005
02006 <span class="preprocessor">#ifdef OPAQUE_SPECIAL_TYPES</span>
02007
02008
02032 u_char *
02033 asn_parse_signed_int64(u_char * data,
02034 size_t * datalength,
02035 u_char * type,
02036 <span class="keyword">struct</span> counter64 * cp, size_t countersize)
02037 {
02038 <span class="keyword">static</span> <span class="keyword">const</span> <span class=
"keywordtype">char</span> *errpre = <span class="stringliteral">"parse int64"</span>;
02039 <span class="keyword">const</span> <span class="keywordtype">int</span> int64sizelimit = (4 * 2) + 1;
02040 <span class="keywordtype">char</span> ebuf[128];
02041 <span class="keyword">register</span> u_char *bufp = data;
02042 u_long asn_length;
02043 <span class="keyword">register</span> u_int low = 0, high = 0;
02044
02045 <span class="keywordflow">if</span> (countersize != <span class="keyword">sizeof</span>(<span class=
"keyword">struct </span>counter64)) {
02046 _asn_size_err(errpre, countersize, <span class="keyword">sizeof</span>(<span class=
"keyword">struct</span> counter64));
02047 <span class="keywordflow">return</span> NULL;
02048 }
02049 *type = *bufp++;
02050 bufp = asn_parse_length(bufp, &asn_length);
02051 <span class="keywordflow">if</span> (_asn_parse_length_check
02052 (errpre, bufp, data, asn_length, *datalength))
02053 <span class="keywordflow">return</span> NULL;
02054
02055 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data);
02056 <span class="keywordflow">if</span> ((*type == ASN_OPAQUE) &&
02057 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
02058 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_I64)) {
02059 <span class="comment">/*</span>
02060 <span class="comment"> * change type to Int64 </span>
02061 <span class="comment"> */</span>
02062 *type = *(bufp + 1);
02063 <span class="comment">/*</span>
02064 <span class="comment"> * value is encoded as special format </span>
02065 <span class="comment"> */</span>
02066 bufp = asn_parse_length(bufp + 2, &asn_length);
02067 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse opaque int64"</span>, bufp, data,
02068 asn_length, *datalength))
02069 <span class="keywordflow">return</span> NULL;
02070 }
02071 <span class="comment">/*</span>
02072 <span class="comment"> * this should always have been true until snmp gets int64 PDU types </span>
02073 <span class="comment"> */</span>
02074 <span class="keywordflow">else</span> {
02075 snprintf(ebuf, <span class="keyword">sizeof</span>(ebuf),
02076 <span class="stringliteral">"%s: wrong type: %d, len %d, buf bytes (%02X,%02X)"</span>,
02077 errpre, *type, (<span class="keywordtype">int</span>) asn_length, *bufp, *(bufp + 1));
02078 ebuf[ <span class="keyword">sizeof</span>(ebuf)-1 ] = 0;
02079 ERROR_MSG(ebuf);
02080 <span class="keywordflow">return</span> NULL;
02081 }
02082 <span class="keywordflow">if</span> (((int) asn_length > int64sizelimit) ||
02083 (((int) asn_length == int64sizelimit) && *bufp != 0x00)) {
02084 _asn_length_err(errpre, (size_t) asn_length, int64sizelimit);
02085 <span class="keywordflow">return</span> NULL;
02086 }
02087 *datalength -= (int) asn_length + (bufp - data);
02088 <span class="keywordflow">if</span> (*bufp & 0x80) {
02089 low = 0xFFFFFF; <span class="comment">/* first byte bit 1 means start the data with 1s */</span>
02090 high = 0xFFFFFF;
02091 }
02092
02093 <span class="keywordflow">while</span> (asn_length--) {
02094 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24);
02095 low = ((low & 0x00FFFFFF) << 8) | *bufp++;
02096 }
02097
02098 CHECK_OVERFLOW_U(high,8);
02099 CHECK_OVERFLOW_U(low,8);
02100
02101 cp->low = low;
02102 cp->high = high;
02103
02104 DEBUGIF(<span class="stringliteral">"dumpv_recv"</span>) {
02105 <span class="keywordtype">char</span> i64buf[I64CHARSZ + 1];
02106 printI64(i64buf, cp);
02107 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">"Integer64: %s"</span>, i64buf));
02108 }
02109
02110 <span class="keywordflow">return</span> bufp;
02111 }
02112
02113
02114
02136 u_char *
02137 asn_build_signed_int64(u_char * data,
02138 size_t * datalength,
02139 u_char type,
02140 <span class="keyword">const</span> <span class=
"keyword">struct</span> counter64 * cp, size_t countersize)
02141 {
02142 <span class="comment">/*</span>
02143 <span class="comment"> * ASN.1 integer ::= 0x02 asnlength byte {byte}*</span>
02144 <span class="comment"> */</span>
02145
02146 <span class="keyword">struct </span>counter64 c64;
02147 <span class="keyword">register</span> u_int mask, mask2;
02148 u_long low, high;
02149 size_t intsize;
02150 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
02151 u_char *initdatap = data;
02152 <span class="preprocessor">#endif</span>
02153
02154 <span class="keywordflow">if</span> (countersize != <span class="keyword">sizeof</span>(<span class=
"keyword">struct </span>counter64)) {
02155 _asn_size_err(<span class="stringliteral">"build int64"</span>, countersize,
02156 <span class="keyword">sizeof</span>(<span class="keyword">struct</span> counter64));
02157 <span class="keywordflow">return</span> NULL;
02158 }
02159 intsize = 8;
02160 memcpy(&c64, cp, <span class="keyword">sizeof</span>(<span class="keyword">struct</span> counter64)); <span class=
"comment">/* we're may modify it */</span>
02161 low = c64.low;
02162 high = c64.high;
02163
02164 CHECK_OVERFLOW_S(high,9);
02165 CHECK_OVERFLOW_U(low,9);
02166
02167 <span class="comment">/*</span>
02168 <span class="comment"> * Truncate "unnecessary" bytes off of the most significant end of this</span>
02169 <span class="comment"> * 2's complement integer. There should be no sequence of 9</span>
02170 <span class="comment"> * consecutive 1's or 0's at the most significant end of the</span>
02171 <span class="comment"> * integer.</span>
02172 <span class="comment"> */</span>
02173 mask = ((u_int) 0xFF) << (8 * (<span class="keyword">sizeof</span>(u_int) - 1));
02174 mask2 = ((u_int) 0x1FF) << ((8 * (<span class="keyword">sizeof</span>(u_int) - 1)) - 1);
02175 <span class="comment">/*</span>
02176 <span class="comment"> * mask is 0xFF800000 on a big-endian machine </span>
02177 <span class="comment"> */</span>
02178 <span class="keywordflow">while</span> ((((high & mask2) == 0) || ((high & mask2) == mask2))
02179 && intsize > 1) {
02180 intsize--;
02181 high = (high << 8)
02182 | ((low & mask) >> (8 * (<span class="keyword">sizeof</span>(u_int) - 1)));
02183 low <<= 8;
02184 }
02185 <span class="comment">/*</span>
02186 <span class="comment"> * until a real int64 gets incorperated into SNMP, we are going to</span>
02187 <span class="comment"> * encode it as an opaque instead. First, we build the opaque</span>
02188 <span class="comment"> * header and then the int64 tag type we use to mark it as an</span>
02189 <span class="comment"> * int64 in the opaque string. </span>
02190 <span class="comment"> */</span>
02191 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
02192 <span class="keywordflow">if</span> (_asn_build_header_check
02193 (<span class="stringliteral">"build int64"</span>, data, *datalength, intsize + 3))
02194 <span class="keywordflow">return</span> NULL;
02195
02196 *data++ = ASN_OPAQUE_TAG1;
02197 *data++ = ASN_OPAQUE_I64;
02198 *data++ = (u_char) intsize;
02199 *datalength -= (3 + intsize);
02200
02201 <span class="keywordflow">while</span> (intsize--) {
02202 *data++ = (u_char) ((high & mask) >> (8 * (<span class="keyword">sizeof</span>(u_int) - 1)));
02203 high = (high << 8)
02204 | ((low & mask) >> (8 * (<span class="keyword">sizeof</span>(u_int) - 1)));
02205 low <<= 8;
02206 }
02207 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap);
02208 DEBUGIF(<span class="stringliteral">"dumpv_send"</span>) {
02209 <span class="keywordtype">char</span> i64buf[I64CHARSZ + 1];
02210 printU64(i64buf, cp);
02211 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, i64buf));
02212 }
02213 <span class="keywordflow">return</span> data;
02214 }
02215
02216
02238 u_char *
02239 asn_parse_float(u_char * data,
02240 size_t * datalength,
02241 u_char * type, <span class="keywordtype">float</span> *floatp, size_t floatsize)
02242 {
02243 <span class="keyword">register</span> u_char *bufp = data;
02244 u_long asn_length;
02245 <span class="keyword">union </span>{
02246 <span class="keywordtype">float</span> floatVal;
02247 <span class="keywordtype">long</span> longVal;
02248 u_char c[<span class="keyword">sizeof</span>(float)];
02249 } fu;
02250
02251 <span class="keywordflow">if</span> (floatsize != <span class="keyword">sizeof</span>(float)) {
02252 _asn_size_err(<span class="stringliteral">"parse float"</span>, floatsize, <span class=
"keyword">sizeof</span>(<span class="keywordtype">float</span>));
02253 <span class="keywordflow">return</span> NULL;
02254 }
02255 *type = *bufp++;
02256 bufp = asn_parse_length(bufp, &asn_length);
02257 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse float"</span>, bufp, data,
02258 asn_length, *datalength))
02259 <span class="keywordflow">return</span> NULL;
02260
02261 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data + asn_length);
02262 <span class="comment">/*</span>
02263 <span class="comment"> * the float is encoded as an opaque </span>
02264 <span class="comment"> */</span>
02265 <span class="keywordflow">if</span> ((*type == ASN_OPAQUE) &&
02266 (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) &&
02267 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_FLOAT)) {
02268
02269 <span class="comment">/*</span>
02270 <span class="comment"> * value is encoded as special format </span>
02271 <span class="comment"> */</span>
02272 bufp = asn_parse_length(bufp + 2, &asn_length);
02273 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse opaque float"</span>, bufp, data,
02274 asn_length, *datalength))
02275 <span class="keywordflow">return</span> NULL;
02276
02277 <span class="comment">/*</span>
02278 <span class="comment"> * change type to Float </span>
02279 <span class="comment"> */</span>
02280 *type = ASN_OPAQUE_FLOAT;
02281 }
02282
02283 <span class="keywordflow">if</span> (asn_length != <span class="keyword">sizeof</span>(float)) {
02284 _asn_size_err(<span class="stringliteral">"parse seq float"</span>, asn_length, <span class=
"keyword">sizeof</span>(<span class="keywordtype">float</span>));
02285 <span class="keywordflow">return</span> NULL;
02286 }
02287
02288 *datalength -= (int) asn_length + (bufp - data);
02289 memcpy(&fu.c[0], bufp, asn_length);
02290
02291 <span class="comment">/*</span>
02292 <span class="comment"> * correct for endian differences </span>
02293 <span class="comment"> */</span>
02294 fu.longVal = ntohl(fu.longVal);
02295
02296 *floatp = fu.floatVal;
02297
02298 DEBUGMSG((<span class="stringliteral">"dumpv_recv"</span>, <span class=
"stringliteral">"Opaque float: %f\n"</span>, *floatp));
02299 <span class="keywordflow">return</span> bufp;
02300 }
02301
02325 u_char *
02326 asn_build_float(u_char * data,
02327 size_t * datalength,
02328 u_char type, <span class="keyword">const</span> <span class=
"keywordtype">float</span> *floatp, size_t floatsize)
02329 {
02330 <span class="keyword">union </span>{
02331 <span class="keywordtype">float</span> floatVal;
02332 <span class="keywordtype">int</span> intVal;
02333 u_char c[<span class="keyword">sizeof</span>(float)];
02334 } fu;
02335 <span class="preprocessor">#ifndef SNMP_NO_DEBUGGING</span>
02336 u_char *initdatap = data;
02337 <span class="preprocessor">#endif</span>
02338
02339 <span class="keywordflow">if</span> (floatsize != <span class="keyword">sizeof</span>(float)) {
02340 _asn_size_err(<span class="stringliteral">"build float"</span>, floatsize, <span class=
"keyword">sizeof</span>(<span class="keywordtype">float</span>));
02341 <span class="keywordflow">return</span> NULL;
02342 }
02343 <span class="comment">/*</span>
02344 <span class="comment"> * encode the float as an opaque </span>
02345 <span class="comment"> */</span>
02346 <span class="comment">/*</span>
02347 <span class="comment"> * turn into Opaque holding special tagged value </span>
02348 <span class="comment"> */</span>
02349
02350 <span class="comment">/*</span>
02351 <span class="comment"> * put the tag and length for the Opaque wrapper </span>
02352 <span class="comment"> */</span>
02353 data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize + 3);
02354 <span class="keywordflow">if</span> (_asn_build_header_check
02355 (<span class="stringliteral">"build float"</span>, data, *datalength, (floatsize + 3)))
02356 <span class="keywordflow">return</span> NULL;
02357
02358 <span class="comment">/*</span>
02359 <span class="comment"> * put the special tag and length </span>
02360 <span class="comment"> */</span>
02361 *data++ = ASN_OPAQUE_TAG1;
02362 *data++ = ASN_OPAQUE_FLOAT;
02363 *data++ = (u_char) floatsize;
02364 *datalength = *datalength - 3;
02365
02366 fu.floatVal = *floatp;
02367 <span class="comment">/*</span>
02368 <span class="comment"> * correct for endian differences </span>
02369 <span class="comment"> */</span>
02370 fu.intVal = htonl(fu.intVal);
02371
02372 *datalength -= floatsize;
02373 memcpy(data, &fu.c[0], floatsize);
02374
02375 DEBUGDUMPSETUP(<span class="stringliteral">"send"</span>, initdatap, data - initdatap);
02376 DEBUGMSG((<span class="stringliteral">"dumpv_send"</span>, <span class=
"stringliteral">"Opaque float: %f\n"</span>, *floatp));
02377 data += floatsize;
02378 <span class="keywordflow">return</span> data;
02379 }
02380
02381
02403 u_char *
02404 asn_parse_double(u_char * data,
02405 size_t * datalength,
02406 u_char * type, <span class="keywordtype">double</span> *doublep, size_t doublesize)
02407 {
02408 <span class="keyword">register</span> u_char *bufp = data;
02409 u_long asn_length;
02410 <span class="keywordtype">long</span> tmp;
02411 <span class="keyword">union </span>{
02412 <span class="keywordtype">double</span> doubleVal;
02413 <span class="keywordtype">int</span> intVal[2];
02414 u_char c[<span class="keyword">sizeof</span>(double)];
02415 } fu;
02416
02417
02418 <span class="keywordflow">if</span> (doublesize != <span class="keyword">sizeof</span>(double)) {
02419 _asn_size_err(<span class="stringliteral">"parse double"</span>, doublesize, <span class=
"keyword">sizeof</span>(<span class="keywordtype">double</span>));
02420 <span class="keywordflow">return</span> NULL;
02421 }
02422 *type = *bufp++;
02423 bufp = asn_parse_length(bufp, &asn_length);
02424 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse double"</span>, bufp, data,
02425 asn_length, *datalength))
02426 <span class="keywordflow">return</span> NULL;
02427
02428 DEBUGDUMPSETUP(<span class="stringliteral">"recv"</span>, data, bufp - data + asn_length);
02429 <span class="comment">/*</span>
02430 <span class="comment"> * the double is encoded as an opaque </span>
02431 <span class="comment"> */</span>
02432 <span class="keywordflow">if</span> ((*type == ASN_OPAQUE) &&
02433 (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) &&
02434 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_DOUBLE)) {
02435
02436 <span class="comment">/*</span>
02437 <span class="comment"> * value is encoded as special format </span>
02438 <span class="comment"> */</span>
02439 bufp = asn_parse_length(bufp + 2, &asn_length);
02440 <span class="keywordflow">if</span> (_asn_parse_length_check(<span class=
"stringliteral">"parse opaque double"</span>, bufp, dat