Diff for /libraries/libldap/result.c between versions 1.145 and 1.146

version 1.145, 2007/01/02 19:00:58 version 1.146, 2007/01/04 14:01:22
Line 1 Line 1
 /* result.c - wait for an ldap result */  /* result.c - wait for an ldap result */
 /* $OpenLDAP: pkg/ldap/libraries/libldap/result.c,v 1.144 2006/12/17 21:04:25 ando Exp $ */  /* $OpenLDAP: pkg/ldap/libraries/libldap/result.c,v 1.145 2007/01/02 19:00:58 kurt Exp $ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *   *
  * Copyright 1998-2007 The OpenLDAP Foundation.   * Copyright 1998-2007 The OpenLDAP Foundation.
Line 43 Line 43
  *      LDAPResult ::= SEQUENCE {   *      LDAPResult ::= SEQUENCE {
  *              resultCode                      ENUMERATED { ... },   *              resultCode                      ENUMERATED { ... },
  *              matchedDN                       LDAPDN,   *              matchedDN                       LDAPDN,
  *              diagnosticMessage       LDAPString,   *              diagnosticMessage               LDAPString,
  *              referral                        [3] Referral OPTIONAL   *              referral                        [3] Referral OPTIONAL
  *      }   *      }
  *      Referral ::= SEQUENCE OF LDAPURL        (one or more)   *      Referral ::= SEQUENCE OF LDAPURL        (one or more)
  *      LDAPURL ::= LDAPString                          (limited to URL chars)   *      LDAPURL ::= LDAPString                  (limited to URL chars)
  */   */
   
 #include "portable.h"  #include "portable.h"
Line 92  static LDAPMessage * chkResponseList LDA Line 92  static LDAPMessage * chkResponseList LDA
  * search references, followed by an ldap result).  An extension to   * search references, followed by an ldap result).  An extension to
  * LDAPv3 allows partial extended responses to be returned in response   * LDAPv3 allows partial extended responses to be returned in response
  * to any request.  The type of the first message received is returned.   * to any request.  The type of the first message received is returned.
  * When waiting, any messages that have been abandoned are discarded.   * When waiting, any messages that have been abandoned/discarded are 
    * discarded.
  *   *
  * Example:   * Example:
  *      ldap_result( s, msgid, all, timeout, result )   *      ldap_result( s, msgid, all, timeout, result )
Line 451  try_read1msg( Line 452  try_read1msg(
         ber_tag_t       tag;          ber_tag_t       tag;
         ber_len_t       len;          ber_len_t       len;
         int             foundit = 0;          int             foundit = 0;
         LDAPRequest     *lr, *tmplr;          LDAPRequest     *lr, *tmplr, dummy_lr = { 0 };
         LDAPConn        *lc;          LDAPConn        *lc;
         BerElement      tmpber;          BerElement      tmpber;
         int             rc, refer_cnt, hadref, simple_request;          int             rc, refer_cnt, hadref, simple_request;
Line 533  nextresp3: Line 534  nextresp3:
                 return( -1 );                  return( -1 );
         }          }
   
           /* id == 0 iff unsolicited notification message (RFC 4511) */
   
         /* if it's been abandoned, toss it */          /* if it's been abandoned, toss it */
         if ( ldap_abandoned( ld, id, &idx ) ) {          if ( id > 0 ) {
                 /* the message type */                  if ( ldap_abandoned( ld, id, &idx ) ) {
                 tag = ber_peek_tag( ber, &len );                          /* the message type */
                 switch ( tag ) {                          tag = ber_peek_tag( ber, &len );
                 case LDAP_RES_SEARCH_ENTRY:                          switch ( tag ) {
                 case LDAP_RES_SEARCH_REFERENCE:                          case LDAP_RES_SEARCH_ENTRY:
                 case LDAP_RES_INTERMEDIATE:                          case LDAP_RES_SEARCH_REFERENCE:
                 case LBER_ERROR:                          case LDAP_RES_INTERMEDIATE:
                         break;                          case LBER_ERROR:
                                   break;
   
                 default:                          default:
                         /* there's no need to keep the id                                  /* there's no need to keep the id
                          * in the abandoned list any longer */                                   * in the abandoned list any longer */
                         ldap_mark_abandoned( ld, id, idx );                                  ldap_mark_abandoned( ld, id, idx );
                         break;                                  break;
                 }                          }
   
                 Debug( LDAP_DEBUG_ANY,                          Debug( LDAP_DEBUG_ANY,
                         "abandoned/discarded ld %p msgid %ld message type %s\n",                                  "abandoned/discarded ld %p msgid %ld message type %s\n",
                         (void *)ld, (long)id, ldap_int_msgtype2str( tag ) );                                  (void *)ld, (long)id, ldap_int_msgtype2str( tag ) );
   
 retry_ber:  retry_ber:
                 ber_free( ber, 1 );                          ber_free( ber, 1 );
                 if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) {                          if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_DATA_READY, NULL ) ) {
                         goto retry;                                  goto retry;
                           }
                           return( LDAP_MSG_X_KEEP_LOOKING );      /* continue looking */
                 }                  }
                 return( LDAP_MSG_X_KEEP_LOOKING );      /* continue looking */  
         }  
   
         lr = ldap_find_request_by_msgid( ld, id );                  lr = ldap_find_request_by_msgid( ld, id );
         if ( lr == NULL ) {                  if ( lr == NULL ) {
                 const char      *msg = "unknown";                          const char      *msg = "unknown";
   
                           /* the message type */
                           tag = ber_peek_tag( ber, &len );
                           switch ( tag ) {
                           case LBER_ERROR:
                                   break;
   
                 /* the message type */                          default:
                 tag = ber_peek_tag( ber, &len );                                  msg = ldap_int_msgtype2str( tag );
                 switch ( tag ) {                                  break;
                 case LBER_ERROR:                          }
                         break;  
   
                 default:                          Debug( LDAP_DEBUG_ANY,
                         msg = ldap_int_msgtype2str( tag );                                  "no request for response on ld %p msgid %ld message type %s (tossing)\n",
                         break;                                  (void *)ld, (long)id, msg );
                 }  
   
                 Debug( LDAP_DEBUG_ANY,                          goto retry_ber;
                         "no request for response on ld %p msgid %ld message type %s (tossing)\n",                  }
                         (void *)ld, (long)id, msg );  
   
                 goto retry_ber;  
         }  
 #ifdef LDAP_CONNECTIONLESS  #ifdef LDAP_CONNECTIONLESS
         if ( LDAP_IS_UDP(ld) && isv2 ) {                  if ( LDAP_IS_UDP(ld) && isv2 ) {
                 ber_scanf(ber, "x{");                          ber_scanf(ber, "x{");
         }                  }
 nextresp2:  nextresp2:
 #endif  #endif
           }
   
         /* the message type */          /* the message type */
         tag = ber_peek_tag( ber, &len );          tag = ber_peek_tag( ber, &len );
         if ( tag == LBER_ERROR ) {          if ( tag == LBER_ERROR ) {
Line 602  nextresp2: Line 609  nextresp2:
                 "read1msg: ld %p msgid %ld message type %s\n",                  "read1msg: ld %p msgid %ld message type %s\n",
                 (void *)ld, (long)lr->lr_msgid, ldap_int_msgtype2str( tag ) );                  (void *)ld, (long)lr->lr_msgid, ldap_int_msgtype2str( tag ) );
   
           if ( id == 0 ) {
                   /* unsolicited notification message (RFC 4511) */
                   if ( tag != LDAP_RES_EXTENDED ) {
                           /* toss it */
                           goto retry_ber;
   
                           /* strictly speaking, it's an error; from RFC 4511:
   
   4.4.  Unsolicited Notification
   
      An unsolicited notification is an LDAPMessage sent from the server to
      the client that is not in response to any LDAPMessage received by the
      server.  It is used to signal an extraordinary condition in the
      server or in the LDAP session between the client and the server.  The
      notification is of an advisory nature, and the server will not expect
      any response to be returned from the client.
   
      The unsolicited notification is structured as an LDAPMessage in which
      the messageID is zero and protocolOp is set to the extendedResp
      choice using the ExtendedResponse type (See Section 4.12).  The
      responseName field of the ExtendedResponse always contains an LDAPOID
      that is unique for this notification.
   
                            * however, since unsolicited responses
                            * are of advisory nature, better
                            * toss it, right now
                            */
   
   #if 0
                           ld->ld_errno = LDAP_DECODING_ERROR;
                           ber_free( ber, 1 );
                           return( -1 );
   #endif
                   }
   
                   lr = &dummy_lr;
           }
   
         id = lr->lr_origid;          id = lr->lr_origid;
         refer_cnt = 0;          refer_cnt = 0;
         hadref = simple_request = 0;          hadref = simple_request = 0;
Line 643  nextresp2: Line 688  nextresp2:
                                 }                                  }
                         }                          }
                 }                  }
         } else   
         if ( tag != LDAP_RES_SEARCH_ENTRY && tag != LDAP_RES_INTERMEDIATE ) {          } else if ( tag != LDAP_RES_SEARCH_ENTRY && tag != LDAP_RES_INTERMEDIATE ) {
         /* All results that just return a status, i.e. don't return data                  /* All results that just return a status, i.e. don't return data
          * go through the following code.  This code also chases V2 referrals                   * go through the following code.  This code also chases V2 referrals
          * and checks if all referrals have been chased.                   * and checks if all referrals have been chased.
          */                   */
                 char            *lr_res_error = NULL;                  char            *lr_res_error = NULL;
   
                 tmpber = *ber;  /* struct copy */                  tmpber = *ber;  /* struct copy */
Line 711  nextresp2: Line 756  nextresp2:
                                                 break;                                                  break;
   
                                         default:                                          default:
                                                 if ( lr->lr_res_error == NULL ||                                                  if ( lr->lr_res_error == NULL ) {
                                                         lr->lr_res_error[ 0 ] == '\0' )  
                                                 {  
                                                         break;                                                          break;
                                                 }                                                  }
   
                                                   /* pedantic, should never happen */
                                                   if ( lr->lr_res_error[ 0 ] == '\0' ) {
                                                           LDAP_FREE( lr->lr_res_error );
                                                           lr->lr_res_error = NULL;
                                                           break;  
                                                   }
   
                                                 /* V2 referrals are in error string */                                                  /* V2 referrals are in error string */
                                                 refer_cnt = ldap_chase_referrals( ld, lr,                                                  refer_cnt = ldap_chase_referrals( ld, lr,
                                                         &lr->lr_res_error, -1, &hadref );                                                          &lr->lr_res_error, -1, &hadref );
Line 822  nextresp2: Line 872  nextresp2:
                                         }                                          }
                                 }                                  }
   
                                 ldap_return_request( ld, lr, 1 );                                  if ( lr != &dummy_lr ) {
                                           ldap_return_request( ld, lr, 1 );
                                   }
                                 lr = NULL;                                  lr = NULL;
                         }                          }
   
Line 840  nextresp2: Line 892  nextresp2:
         }          }
   
         if ( lr != NULL ) {          if ( lr != NULL ) {
                 ldap_return_request( ld, lr, 0 );                  if ( lr != &dummy_lr ) {
                           ldap_return_request( ld, lr, 0 );
                   }
                 lr = NULL;                  lr = NULL;
         }          }
   
Line 848  nextresp2: Line 902  nextresp2:
                 return( rc );                  return( rc );
         }          }
   
           /* try to handle unsolicited responses as appropriate */
           if ( id == 0 && msgid != LDAP_RES_UNSOLICITED ) {
                   int     is_nod = 0;
   
                   tag = ber_peek_tag( ber, &len );
   
                   /* we have a res oid */
                   if ( tag == LDAP_TAG_EXOP_RES_OID ) {
                           char    *resoid = NULL;
   
                           if ( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
                                   ld->ld_errno = LDAP_DECODING_ERROR;
                                   ber_free( ber, 1 );
                                   return -1;
                           }
   
                           assert( resoid[ 0 ] != '\0' );
   
                           is_nod = strcmp( resoid, LDAP_NOTICE_OF_DISCONNECTION ) == 0;
                           LDAP_FREE( resoid );
   
                           tag = ber_peek_tag( ber, &len );
                   }
   
                   /* we have a res value */
                   if ( tag == LDAP_TAG_EXOP_RES_VALUE ) {
                           /* don't need right now */
                   }
   
                   /* handle RFC 4511 "Notice of Disconnection" locally */
   
                   if ( is_nod ) {
                           if ( tag == LDAP_TAG_EXOP_RES_VALUE ) {
                                   ld->ld_errno = LDAP_DECODING_ERROR;
                                   ber_free( ber, 1 );
                                   return -1;
                           }
   
                           /* get rid of the connection... */
                           if ( lc != NULL ) {
   #ifdef LDAP_R_COMPILE
                                   ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
   #endif
                                   ldap_free_connection( ld, lc, 0, 1 );
   #ifdef LDAP_R_COMPILE
                                   ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
   #endif
                                   *lcp = NULL;
                           }
   
                           return LDAP_RES_EXTENDED;
                   }
           }
   
         /* make a new ldap message */          /* make a new ldap message */
         newmsg = (LDAPMessage *) LDAP_CALLOC( 1, sizeof(LDAPMessage) );          newmsg = (LDAPMessage *) LDAP_CALLOC( 1, sizeof(LDAPMessage) );
         if ( newmsg == NULL ) {          if ( newmsg == NULL ) {
Line 968  nextresp2: Line 1076  nextresp2:
   
         prev = NULL;          prev = NULL;
         for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) {          for ( l = ld->ld_responses; l != NULL; l = l->lm_next ) {
                 if ( l->lm_msgid == newmsg->lm_msgid )                  if ( l->lm_msgid == newmsg->lm_msgid ) {
                         break;                          break;
                   }
                 prev = l;                  prev = l;
         }          }
   
Line 994  nextresp2: Line 1103  nextresp2:
   
         /* return the whole chain if that's what we were looking for */          /* return the whole chain if that's what we were looking for */
         if ( foundit ) {          if ( foundit ) {
                 if ( prev == NULL )                  if ( prev == NULL ) {
                         ld->ld_responses = l->lm_next;                          ld->ld_responses = l->lm_next;
                 else                  } else {
                         prev->lm_next = l->lm_next;                          prev->lm_next = l->lm_next;
                   }
                 *result = l;                  *result = l;
         }          }
   

Removed from v.1.145  
changed lines
  Added in v.1.146


______________
© Copyright 1998-2020, OpenLDAP Foundation, info@OpenLDAP.org