io.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. /* io.c - ber general i/o routines */
  2. /* $OpenLDAP$ */
  3. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  4. *
  5. * Copyright 1998-2024 The OpenLDAP Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted only as authorized by the OpenLDAP
  10. * Public License.
  11. *
  12. * A copy of this license is available in the file LICENSE in the
  13. * top-level directory of the distribution or, alternatively, at
  14. * <http://www.OpenLDAP.org/license.html>.
  15. */
  16. /* Portions Copyright (c) 1990 Regents of the University of Michigan.
  17. * All rights reserved.
  18. *
  19. * Redistribution and use in source and binary forms are permitted
  20. * provided that this notice is preserved and that due credit is given
  21. * to the University of Michigan at Ann Arbor. The name of the University
  22. * may not be used to endorse or promote products derived from this
  23. * software without specific prior written permission. This software
  24. * is provided ``as is'' without express or implied warranty.
  25. */
  26. /* ACKNOWLEDGEMENTS:
  27. * This work was originally developed by the University of Michigan
  28. * (as part of U-MICH LDAP).
  29. */
  30. #include "portable.h"
  31. #include <stdio.h>
  32. #include <ac/stdlib.h>
  33. #include <ac/ctype.h>
  34. #include <ac/errno.h>
  35. #include <ac/socket.h>
  36. #include <ac/string.h>
  37. #include <ac/unistd.h>
  38. #ifdef HAVE_IO_H
  39. #include <io.h>
  40. #endif
  41. #include "lber-int.h"
  42. #include "ldap_log.h"
  43. ber_slen_t
  44. ber_skip_data(
  45. BerElement *ber,
  46. ber_len_t len )
  47. {
  48. ber_len_t actuallen, nleft;
  49. assert( ber != NULL );
  50. assert( LBER_VALID( ber ) );
  51. nleft = ber_pvt_ber_remaining( ber );
  52. actuallen = nleft < len ? nleft : len;
  53. ber->ber_ptr += actuallen;
  54. ber->ber_tag = *(unsigned char *)ber->ber_ptr;
  55. return( (ber_slen_t) actuallen );
  56. }
  57. /*
  58. * Read from the ber buffer. The caller must maintain ber->ber_tag.
  59. * Do not use to read whole tags. See ber_get_tag() and ber_skip_data().
  60. */
  61. ber_slen_t
  62. ber_read(
  63. BerElement *ber,
  64. char *buf,
  65. ber_len_t len )
  66. {
  67. ber_len_t actuallen, nleft;
  68. assert( ber != NULL );
  69. assert( buf != NULL );
  70. assert( LBER_VALID( ber ) );
  71. nleft = ber_pvt_ber_remaining( ber );
  72. actuallen = nleft < len ? nleft : len;
  73. AC_MEMCPY( buf, ber->ber_ptr, actuallen );
  74. ber->ber_ptr += actuallen;
  75. return( (ber_slen_t) actuallen );
  76. }
  77. /*
  78. * Write to the ber buffer.
  79. * Note that ber_start_seqorset/ber_put_seqorset() bypass ber_write().
  80. */
  81. ber_slen_t
  82. ber_write(
  83. BerElement *ber,
  84. LDAP_CONST char *buf,
  85. ber_len_t len,
  86. int zero ) /* nonzero is unsupported from OpenLDAP 2.4.18 */
  87. {
  88. char **p;
  89. assert( ber != NULL );
  90. assert( buf != NULL );
  91. assert( LBER_VALID( ber ) );
  92. if ( zero != 0 ) {
  93. ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "%s",
  94. "ber_write: nonzero 4th argument not supported\n" );
  95. return( -1 );
  96. }
  97. p = ber->ber_sos_ptr == NULL ? &ber->ber_ptr : &ber->ber_sos_ptr;
  98. if ( len > (ber_len_t) (ber->ber_end - *p) ) {
  99. if ( ber_realloc( ber, len ) != 0 ) return( -1 );
  100. }
  101. AC_MEMCPY( *p, buf, len );
  102. *p += len;
  103. return( (ber_slen_t) len );
  104. }
  105. /* Resize the ber buffer */
  106. int
  107. ber_realloc( BerElement *ber, ber_len_t len )
  108. {
  109. ber_len_t total, offset, sos_offset, rw_offset;
  110. char *buf;
  111. assert( ber != NULL );
  112. assert( LBER_VALID( ber ) );
  113. /* leave room for ber_flatten() to \0-terminate ber_buf */
  114. if ( ++len == 0 ) {
  115. return( -1 );
  116. }
  117. total = ber_pvt_ber_total( ber );
  118. #define LBER_EXBUFSIZ 4060 /* a few words less than 2^N for binary buddy */
  119. #if defined( LBER_EXBUFSIZ ) && LBER_EXBUFSIZ > 0
  120. # ifndef notdef
  121. /* don't realloc by small amounts */
  122. total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len;
  123. # else
  124. { /* not sure what value this adds. reduce fragmentation? */
  125. ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ;
  126. ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ;
  127. total = ( have + need ) * LBER_EXBUFSIZ;
  128. }
  129. # endif
  130. #else
  131. total += len; /* realloc just what's needed */
  132. #endif
  133. if ( total < len || total > (ber_len_t)-1 / 2 /* max ber_slen_t */ ) {
  134. return( -1 );
  135. }
  136. buf = ber->ber_buf;
  137. offset = ber->ber_ptr - buf;
  138. sos_offset = ber->ber_sos_ptr ? ber->ber_sos_ptr - buf : 0;
  139. /* if ber_sos_ptr != NULL, it is > ber_buf so that sos_offset > 0 */
  140. rw_offset = ber->ber_rwptr ? ber->ber_rwptr - buf : 0;
  141. buf = (char *) ber_memrealloc_x( buf, total, ber->ber_memctx );
  142. if ( buf == NULL ) {
  143. return( -1 );
  144. }
  145. ber->ber_buf = buf;
  146. ber->ber_end = buf + total;
  147. ber->ber_ptr = buf + offset;
  148. if ( sos_offset )
  149. ber->ber_sos_ptr = buf + sos_offset;
  150. if ( ber->ber_rwptr )
  151. ber->ber_rwptr = buf + rw_offset;
  152. return( 0 );
  153. }
  154. void
  155. ber_free_buf( BerElement *ber )
  156. {
  157. assert( LBER_VALID( ber ) );
  158. if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx );
  159. ber->ber_buf = NULL;
  160. ber->ber_sos_ptr = NULL;
  161. ber->ber_valid = LBER_UNINITIALIZED;
  162. }
  163. void
  164. ber_free( BerElement *ber, int freebuf )
  165. {
  166. if( ber == NULL ) {
  167. LDAP_MEMORY_DEBUG_ASSERT( ber != NULL );
  168. return;
  169. }
  170. if( freebuf ) ber_free_buf( ber );
  171. ber_memfree_x( (char *) ber, ber->ber_memctx );
  172. }
  173. int
  174. ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
  175. {
  176. return ber_flush2( sb, ber,
  177. freeit ? LBER_FLUSH_FREE_ON_SUCCESS
  178. : LBER_FLUSH_FREE_NEVER );
  179. }
  180. int
  181. ber_flush2( Sockbuf *sb, BerElement *ber, int freeit )
  182. {
  183. ber_len_t towrite;
  184. ber_slen_t rc;
  185. assert( sb != NULL );
  186. assert( ber != NULL );
  187. assert( SOCKBUF_VALID( sb ) );
  188. assert( LBER_VALID( ber ) );
  189. if ( ber->ber_rwptr == NULL ) {
  190. ber->ber_rwptr = ber->ber_buf;
  191. }
  192. towrite = ber->ber_ptr - ber->ber_rwptr;
  193. if ( sb->sb_debug ) {
  194. ber_log_printf( LDAP_DEBUG_TRACE, sb->sb_debug,
  195. "ber_flush2: %ld bytes to sd %ld%s\n",
  196. towrite, (long) sb->sb_fd,
  197. ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" );
  198. ber_log_bprint( LDAP_DEBUG_BER, sb->sb_debug,
  199. ber->ber_rwptr, towrite );
  200. }
  201. while ( towrite > 0 ) {
  202. #ifdef LBER_TRICKLE
  203. sleep(1);
  204. rc = ber_int_sb_write( sb, ber->ber_rwptr, 1 );
  205. #else
  206. rc = ber_int_sb_write( sb, ber->ber_rwptr, towrite );
  207. #endif
  208. if ( rc <= 0 ) {
  209. if ( freeit & LBER_FLUSH_FREE_ON_ERROR ) ber_free( ber, 1 );
  210. return -1;
  211. }
  212. towrite -= rc;
  213. ber->ber_rwptr += rc;
  214. }
  215. if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 );
  216. return 0;
  217. }
  218. BerElement *
  219. ber_alloc_t( int options )
  220. {
  221. BerElement *ber;
  222. ber = (BerElement *) LBER_CALLOC( 1, sizeof(BerElement) );
  223. if ( ber == NULL ) {
  224. return NULL;
  225. }
  226. ber->ber_valid = LBER_VALID_BERELEMENT;
  227. ber->ber_tag = LBER_DEFAULT;
  228. ber->ber_options = options;
  229. ber->ber_debug = ber_int_debug;
  230. assert( LBER_VALID( ber ) );
  231. return ber;
  232. }
  233. BerElement *
  234. ber_alloc( void ) /* deprecated */
  235. {
  236. return ber_alloc_t( 0 );
  237. }
  238. BerElement *
  239. der_alloc( void ) /* deprecated */
  240. {
  241. return ber_alloc_t( LBER_USE_DER );
  242. }
  243. BerElement *
  244. ber_dup( BerElement *ber )
  245. {
  246. BerElement *new;
  247. assert( ber != NULL );
  248. assert( LBER_VALID( ber ) );
  249. if ( (new = ber_alloc_t( ber->ber_options )) == NULL ) {
  250. return NULL;
  251. }
  252. *new = *ber;
  253. assert( LBER_VALID( new ) );
  254. return( new );
  255. }
  256. void
  257. ber_init2( BerElement *ber, struct berval *bv, int options )
  258. {
  259. assert( ber != NULL );
  260. (void) memset( (char *)ber, '\0', sizeof( BerElement ));
  261. ber->ber_valid = LBER_VALID_BERELEMENT;
  262. ber->ber_tag = LBER_DEFAULT;
  263. ber->ber_options = (char) options;
  264. ber->ber_debug = ber_int_debug;
  265. if ( bv != NULL ) {
  266. ber->ber_buf = bv->bv_val;
  267. ber->ber_ptr = ber->ber_buf;
  268. ber->ber_end = ber->ber_buf + bv->bv_len;
  269. }
  270. assert( LBER_VALID( ber ) );
  271. }
  272. /* OLD U-Mich ber_init() */
  273. void
  274. ber_init_w_nullc( BerElement *ber, int options )
  275. {
  276. ber_init2( ber, NULL, options );
  277. }
  278. /* New C-API ber_init() */
  279. /* This function constructs a BerElement containing a copy
  280. ** of the data in the bv argument.
  281. */
  282. BerElement *
  283. ber_init( struct berval *bv )
  284. {
  285. BerElement *ber;
  286. assert( bv != NULL );
  287. if ( bv == NULL ) {
  288. return NULL;
  289. }
  290. ber = ber_alloc_t( 0 );
  291. if( ber == NULL ) {
  292. /* allocation failed */
  293. return NULL;
  294. }
  295. /* copy the data */
  296. if ( ((ber_len_t) ber_write ( ber, bv->bv_val, bv->bv_len, 0 ))
  297. != bv->bv_len )
  298. {
  299. /* write failed, so free and return NULL */
  300. ber_free( ber, 1 );
  301. return NULL;
  302. }
  303. ber_reset( ber, 1 ); /* reset the pointer to the start of the buffer */
  304. return ber;
  305. }
  306. /* New C-API ber_flatten routine */
  307. /* This routine allocates a struct berval whose contents are a BER
  308. ** encoding taken from the ber argument. The bvPtr pointer points to
  309. ** the returned berval.
  310. **
  311. ** ber_flatten2 is the same, but uses a struct berval passed by
  312. ** the caller. If alloc is 0 the returned bv uses the ber buf directly.
  313. */
  314. int ber_flatten2(
  315. BerElement *ber,
  316. struct berval *bv,
  317. int alloc )
  318. {
  319. assert( bv != NULL );
  320. if ( bv == NULL ) {
  321. return -1;
  322. }
  323. if ( ber == NULL ) {
  324. /* ber is null, create an empty berval */
  325. bv->bv_val = NULL;
  326. bv->bv_len = 0;
  327. } else if ( ber->ber_sos_ptr != NULL ) {
  328. /* unmatched "{" and "}" */
  329. return -1;
  330. } else {
  331. /* copy the berval */
  332. ber_len_t len = ber_pvt_ber_write( ber );
  333. if ( alloc ) {
  334. bv->bv_val = (char *) ber_memalloc_x( len + 1, ber->ber_memctx );
  335. if ( bv->bv_val == NULL ) {
  336. return -1;
  337. }
  338. AC_MEMCPY( bv->bv_val, ber->ber_buf, len );
  339. bv->bv_val[len] = '\0';
  340. } else if ( ber->ber_buf != NULL ) {
  341. bv->bv_val = ber->ber_buf;
  342. bv->bv_val[len] = '\0';
  343. } else {
  344. bv->bv_val = "";
  345. }
  346. bv->bv_len = len;
  347. }
  348. return 0;
  349. }
  350. int ber_flatten(
  351. BerElement *ber,
  352. struct berval **bvPtr)
  353. {
  354. struct berval *bv;
  355. int rc;
  356. assert( bvPtr != NULL );
  357. if(bvPtr == NULL) {
  358. return -1;
  359. }
  360. bv = ber_memalloc_x( sizeof(struct berval), ber->ber_memctx );
  361. if ( bv == NULL ) {
  362. return -1;
  363. }
  364. rc = ber_flatten2(ber, bv, 1);
  365. if (rc == -1) {
  366. ber_memfree_x(bv, ber->ber_memctx);
  367. } else {
  368. *bvPtr = bv;
  369. }
  370. return rc;
  371. }
  372. void
  373. ber_reset( BerElement *ber, int was_writing )
  374. {
  375. assert( ber != NULL );
  376. assert( LBER_VALID( ber ) );
  377. if ( was_writing ) {
  378. ber->ber_end = ber->ber_ptr;
  379. ber->ber_ptr = ber->ber_buf;
  380. } else {
  381. ber->ber_ptr = ber->ber_end;
  382. }
  383. ber->ber_rwptr = NULL;
  384. }
  385. /*
  386. * A rewrite of ber_get_next that can safely be called multiple times
  387. * for the same packet. It will simply continue where it stopped until
  388. * a full packet is read.
  389. */
  390. #define LENSIZE 4
  391. ber_tag_t
  392. ber_get_next(
  393. Sockbuf *sb,
  394. ber_len_t *len,
  395. BerElement *ber )
  396. {
  397. assert( sb != NULL );
  398. assert( len != NULL );
  399. assert( ber != NULL );
  400. assert( SOCKBUF_VALID( sb ) );
  401. assert( LBER_VALID( ber ) );
  402. if ( ber->ber_debug & LDAP_DEBUG_TRACE ) {
  403. ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
  404. "ber_get_next\n" );
  405. }
  406. /*
  407. * Any ber element looks like this: tag length contents.
  408. * Assuming everything's ok, we return the tag byte (we
  409. * can assume a single byte), return the length in len,
  410. * and the rest of the undecoded element in buf.
  411. *
  412. * Assumptions:
  413. * 1) small tags (less than 128)
  414. * 2) definite lengths
  415. * 3) primitive encodings used whenever possible
  416. *
  417. * The code also handles multi-byte tags. The first few bytes
  418. * of the message are read to check for multi-byte tags and
  419. * lengths. These bytes are temporarily stored in the ber_tag,
  420. * ber_len, and ber_usertag fields of the berelement until
  421. * tag/len parsing is complete. After this parsing, any leftover
  422. * bytes and the rest of the message are copied into the ber_buf.
  423. *
  424. * We expect tag and len to be at most 32 bits wide.
  425. */
  426. if (ber->ber_rwptr == NULL) {
  427. assert( ber->ber_buf == NULL );
  428. ber->ber_rwptr = (char *) &ber->ber_len-1;
  429. ber->ber_ptr = ber->ber_rwptr;
  430. ber->ber_tag = 0;
  431. }
  432. while (ber->ber_rwptr > (char *)&ber->ber_tag && ber->ber_rwptr <
  433. (char *)&ber->ber_len + LENSIZE*2) {
  434. ber_slen_t sblen;
  435. char buf[sizeof(ber->ber_len)-1];
  436. ber_len_t tlen = 0;
  437. /* The tag & len can be at most 9 bytes; we try to read up to 8 here */
  438. sock_errset(0);
  439. sblen=((char *)&ber->ber_len + LENSIZE*2 - 1)-ber->ber_rwptr;
  440. /* Trying to read the last len byte of a 9 byte tag+len */
  441. if (sblen<1)
  442. sblen = 1;
  443. sblen=ber_int_sb_read( sb, ber->ber_rwptr, sblen );
  444. if (sblen<=0) return LBER_DEFAULT;
  445. ber->ber_rwptr += sblen;
  446. /* We got at least one byte, try to parse the tag. */
  447. if (ber->ber_ptr == (char *)&ber->ber_len-1) {
  448. ber_tag_t tag;
  449. unsigned char *p = (unsigned char *)ber->ber_ptr;
  450. tag = *p++;
  451. if ((tag & LBER_BIG_TAG_MASK) == LBER_BIG_TAG_MASK) {
  452. ber_len_t i;
  453. for (i=1; (char *)p<ber->ber_rwptr; i++) {
  454. tag <<= 8;
  455. tag |= *p++;
  456. if (!(tag & LBER_MORE_TAG_MASK))
  457. break;
  458. /* Is the tag too big? */
  459. if (i == sizeof(ber_tag_t)-1) {
  460. sock_errset(ERANGE);
  461. return LBER_DEFAULT;
  462. }
  463. }
  464. /* Did we run out of bytes? */
  465. if ((char *)p == ber->ber_rwptr) {
  466. sock_errset(EWOULDBLOCK);
  467. return LBER_DEFAULT;
  468. }
  469. }
  470. ber->ber_tag = tag;
  471. ber->ber_ptr = (char *)p;
  472. }
  473. if ( ber->ber_ptr == ber->ber_rwptr ) {
  474. sock_errset(EWOULDBLOCK);
  475. return LBER_DEFAULT;
  476. }
  477. /* Now look for the length */
  478. if (*ber->ber_ptr & 0x80) { /* multi-byte */
  479. int i;
  480. unsigned char *p = (unsigned char *)ber->ber_ptr;
  481. int llen = *p++ & 0x7f;
  482. if (llen > LENSIZE) {
  483. sock_errset(ERANGE);
  484. return LBER_DEFAULT;
  485. }
  486. /* Not enough bytes? */
  487. if (ber->ber_rwptr - (char *)p < llen) {
  488. sock_errset(EWOULDBLOCK);
  489. return LBER_DEFAULT;
  490. }
  491. for (i=0; i<llen; i++) {
  492. tlen <<=8;
  493. tlen |= *p++;
  494. }
  495. ber->ber_ptr = (char *)p;
  496. } else {
  497. tlen = *(unsigned char *)ber->ber_ptr++;
  498. }
  499. /* Are there leftover data bytes inside ber->ber_len? */
  500. if (ber->ber_ptr < (char *)&ber->ber_usertag) {
  501. if (ber->ber_rwptr < (char *)&ber->ber_usertag) {
  502. sblen = ber->ber_rwptr - ber->ber_ptr;
  503. } else {
  504. sblen = (char *)&ber->ber_usertag - ber->ber_ptr;
  505. }
  506. AC_MEMCPY(buf, ber->ber_ptr, sblen);
  507. ber->ber_ptr += sblen;
  508. } else {
  509. sblen = 0;
  510. }
  511. ber->ber_len = tlen;
  512. /* now fill the buffer. */
  513. /* make sure length is reasonable */
  514. if ( ber->ber_len == 0 ) {
  515. sock_errset(ERANGE);
  516. return LBER_DEFAULT;
  517. }
  518. if ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ) {
  519. ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug,
  520. "ber_get_next: sockbuf_max_incoming exceeded "
  521. "(%ld > %ld)\n", ber->ber_len, sb->sb_max_incoming );
  522. sock_errset(ERANGE);
  523. return LBER_DEFAULT;
  524. }
  525. if (ber->ber_buf==NULL) {
  526. ber_len_t l = ber->ber_rwptr - ber->ber_ptr;
  527. /* ber->ber_ptr is always <= ber->ber->ber_rwptr.
  528. * make sure ber->ber_len agrees with what we've
  529. * already read.
  530. */
  531. if ( ber->ber_len < sblen + l ) {
  532. sock_errset(ERANGE);
  533. return LBER_DEFAULT;
  534. }
  535. ber->ber_buf = (char *) ber_memalloc_x( ber->ber_len + 1, ber->ber_memctx );
  536. if (ber->ber_buf==NULL) {
  537. return LBER_DEFAULT;
  538. }
  539. ber->ber_end = ber->ber_buf + ber->ber_len;
  540. if (sblen) {
  541. AC_MEMCPY(ber->ber_buf, buf, sblen);
  542. }
  543. if (l > 0) {
  544. AC_MEMCPY(ber->ber_buf + sblen, ber->ber_ptr, l);
  545. sblen += l;
  546. }
  547. *ber->ber_end = '\0';
  548. ber->ber_ptr = ber->ber_buf;
  549. ber->ber_usertag = 0;
  550. if ((ber_len_t)sblen == ber->ber_len) {
  551. goto done;
  552. }
  553. ber->ber_rwptr = ber->ber_buf + sblen;
  554. }
  555. }
  556. if ((ber->ber_rwptr>=ber->ber_buf) && (ber->ber_rwptr<ber->ber_end)) {
  557. ber_slen_t res;
  558. ber_slen_t to_go;
  559. to_go = ber->ber_end - ber->ber_rwptr;
  560. /* unsigned/signed overflow */
  561. if (to_go<0) return LBER_DEFAULT;
  562. sock_errset(0);
  563. res = ber_int_sb_read( sb, ber->ber_rwptr, to_go );
  564. if (res<=0) return LBER_DEFAULT;
  565. ber->ber_rwptr+=res;
  566. if (res<to_go) {
  567. sock_errset(EWOULDBLOCK);
  568. return LBER_DEFAULT;
  569. }
  570. done:
  571. ber->ber_rwptr = NULL;
  572. *len = ber->ber_len;
  573. if ( ber->ber_debug ) {
  574. ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
  575. "ber_get_next: tag 0x%lx len %ld contents:\n",
  576. ber->ber_tag, ber->ber_len );
  577. ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
  578. }
  579. return (ber->ber_tag);
  580. }
  581. /* invalid input */
  582. return LBER_DEFAULT;
  583. }
  584. char *
  585. ber_start( BerElement* ber )
  586. {
  587. return ber->ber_buf;
  588. }
  589. int
  590. ber_len( BerElement* ber )
  591. {
  592. return ( ber->ber_end - ber->ber_buf );
  593. }
  594. int
  595. ber_ptrlen( BerElement* ber )
  596. {
  597. return ( ber->ber_ptr - ber->ber_buf );
  598. }
  599. void
  600. ber_rewind ( BerElement * ber )
  601. {
  602. ber->ber_rwptr = NULL;
  603. ber->ber_sos_ptr = NULL;
  604. ber->ber_end = ber->ber_ptr;
  605. ber->ber_ptr = ber->ber_buf;
  606. #if 0 /* TODO: Should we add this? */
  607. ber->ber_tag = LBER_DEFAULT;
  608. ber->ber_usertag = 0;
  609. #endif
  610. }
  611. int
  612. ber_remaining( BerElement * ber )
  613. {
  614. return ber_pvt_ber_remaining( ber );
  615. }