Beispiel #1
0
struct list_res
res_walk_parents (const struct res *out, const struct hs *hs, int in_port,
		  array_t* out_arr)
{
  struct res *curr_res = (struct res*) out;
  struct list_res currq = {0};

  // set up initial result to start inversion
  struct hs int_hs;
  hs_isect_arr (&int_hs, &out->hs, out_arr);
  list_append (&currq, res_extend (out, &int_hs, out->port, true));

  struct res *cur;

  while (curr_res) {
    if (curr_res->rules.cur) {
      for (int i = curr_res->rules.cur - 1; i >= 0; i--) {
	struct list_res nextq = {0};
	struct res_rule r = curr_res->rules.arr[i];
	while ((cur = currq.head)) {
	  list_pop (&currq);
	  struct list_res tmp = rule_inv_apply (r.tf_tf, r.tf_rule, cur, false);
	  list_concat (&nextq, &tmp);
	  res_free (cur);
	} // for each current result from rule inversion
	currq = nextq;
      } // for each rule
    }
    else return currq;

    // set (hs,port) which the inverted (hs,port) results must intersect
    struct res *parent = curr_res->parent;
    struct hs *next_hs = hs_create (curr_res->hs.len);
    int next_port;
    if (parent) {
      hs_copy (next_hs, &parent->hs);
      next_port = parent->port;
    }
    else {
      hs_copy (next_hs, hs);
      next_port = in_port;
    }

    // Intersect the results in `currq` with the target (hs,port)
    struct list_res nextq = {0};
    while ((cur = currq.head)) {
      list_pop (&currq);
      struct hs *new_hs = hs_isect_a (&cur->hs, next_hs);
      if (cur->port == next_port && new_hs)
	list_append (&nextq, res_extend (cur, new_hs, next_port, false));
      else
	res_free (cur);
    }
    currq = nextq;
    curr_res = parent;
  }

  return currq;
}
/**
 * vmw_simple_resource_init - Initialize a simple resource object.
 *
 * @dev_priv: Pointer to a struct device private.
 * @simple: The struct vmw_simple_resource to initialize.
 * @data: Data passed to the information initialization function.
 * @res_free: Function pointer to destroy the simple resource.
 *
 * Returns:
 *   0 if succeeded.
 *   Negative error value if error, in which case the resource will have been
 * freed.
 */
static int vmw_simple_resource_init(struct vmw_private *dev_priv,
				    struct vmw_simple_resource *simple,
				    void *data,
				    void (*res_free)(struct vmw_resource *res))
{
	struct vmw_resource *res = &simple->res;
	int ret;

	ret = vmw_resource_init(dev_priv, res, false, res_free,
				&simple->func->res_func);

	if (ret) {
		res_free(res);
		return ret;
	}

	ret = simple->func->init(res, data);
	if (ret) {
		vmw_resource_unreference(&res);
		return ret;
	}

	simple->res.hw_destroy = simple->func->hw_destroy;

	return 0;
}
Beispiel #3
0
Datei: 4.c Projekt: rednuk/Temp
void *run()
{
    res_t res;
    res_init();
    res = res_allocate();
    sleep(1);
    res_free(res);
    return 0;
}
Beispiel #4
0
result plan_free(Plan plan) {
  if (plan == NULL) return FAIL;

  for (int i=0; i < plan->nb_res; i++)
    if (res_free(plan->res[i]) == FAIL) return FAIL;

  free(plan->res);
  free(plan);

  return OK;
}
Beispiel #5
0
void
res_free (struct res *res)
{
  if (res->refs) { res->next = NULL; return; }

  hs_destroy (&res->hs);
  pthread_mutex_destroy (&res->lock);
  struct res *parent = res->parent;
  free (res);
  if (parent) { parent->refs--; res_free (parent); }
}
Beispiel #6
0
Plan plan_create(Prob prob) {
  Plan plan = plan_create_empty(prob_res_count(prob));
  if (plan == NULL) return NULL;

  for (int i=0; i < plan->nb_res; i++) {
    plan->res[i] = res_create(prob_job_count(prob));
    if (plan->res[i] == NULL) {
      for (; i >= 0; i--) res_free(plan->res[i]);
      free(plan->res);
      free(plan);
      return NULL;
    }
  }

  return plan;
}
Beispiel #7
0
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
  struct unicorn_fh *fh = priv;
  struct unicorn_dev *dev = fh->dev;
  int err, res;

  if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    return -EINVAL;
  if (i != fh->type)
    return -EINVAL;

  res = get_resource(fh,  0x01 << fh->channel);
  err = videobuf_streamoff(&fh->vidq);
  if (err < 0)
    return err;
  res_free(dev, fh, res);
  return 0;
}
Beispiel #8
0
/***********************************************************************
 *           I_RpcSendReceive [RPCRT4.@]
 *
 * Sends a message to the server and receives the response.
 *
 * PARAMS
 *  pMsg [I/O] RPC message information.
 *
 * RETURNS
 *  Success: RPC_S_OK.
 *  Failure: Any error code.
 *
 * NOTES
 *  The buffer must have been allocated with I_RpcGetBuffer().
 *
 * SEE ALSO
 *  I_RpcGetBuffer(), I_RpcSend(), I_RpcReceive().
 */
RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
{
	RpcBinding* bind = (RpcBinding*)pMsg->Handle;
	RpcConnection * conn = (RpcConnection *)pMsg->ReservedForRuntime;
	ITgmRpcConnection* theConn = conn->rpc_connection;
	void* res_buf = 0;
	ULONG res_len = 0;
	ipc_client_memory_free_fun_t res_free = NULL;


	RpcPktHdr *hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation,
		pMsg->BufferLength,
		pMsg->ProcNum & ~RPC_FLAGS_VALID_BIT,
		&bind->ObjectUuid);

	hdr->common.frag_len += pMsg->BufferLength;

	char* pkt =  (char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,hdr->common.frag_len+1);
	memcpy(pkt,hdr,hdr->common.frag_len-pMsg->BufferLength);
	memcpy(pkt+hdr->common.frag_len-pMsg->BufferLength,pMsg->Buffer,pMsg->BufferLength);


	HRESULT hr = theConn->SendSyncRequestEx(pkt,hdr->common.frag_len,&res_buf,&res_len,&res_free,0);
	HeapFree(GetProcessHeap(),0,pkt);
	HeapFree(GetProcessHeap(),0,hdr);
	HeapFree(GetProcessHeap(),0,pMsg->Buffer);

	if(SUCCEEDED(hr))
	{
		CRpcUnpacker theUnPacket(res_buf,res_len);
		pMsg->BufferLength = theUnPacket.get_BufferLength();
		pMsg->Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,pMsg->BufferLength);
		memcpy(pMsg->Buffer,theUnPacket.get_BufferPtr(),pMsg->BufferLength);
		res_free(res_buf);
	}else {
		RPCRT4_DestroyConnection(conn);
		pMsg->ReservedForRuntime = NULL;
	}

	return RPC_S_OK;
}
Beispiel #9
0
void add_common_resource(resp r)
{
    char outTemp[256];
    strp outType;
    NAMEINFO_NODE   *new_nameinfo;

    if (!r || !r->b || !r->b->buffer)
        return; /* Refuse to add a resource without data */

    ALLOC(new_nameinfo, NAMEINFO_NODE);
    new_nameinfo->next = NULL;
    new_nameinfo->data.rcslength = r->b->len;
    new_nameinfo->data.rcsdata = (LPBYTE)buff_ind(r->b);
    r->b = NULL;
    new_nameinfo->data.rcsflags = r->flags;
    if (!HIWORD(r->name))
    {
        if (LOWORD(r->name) > 0x7fff)
            FATAL(("Resource identifier %d is too large", (int)(LOWORD(r->name))));
        new_nameinfo->data.rcsitemname = (char *)(LOWORD(r->name) | (r->type == RT_STRING ? 0x0000 : 0x8000));
    }
    else
        new_nameinfo->data.rcsitemname = (char *)(r->name);
    if (HIWORD(r->type))
        new_nameinfo->data.wType = (WORD)(RT_USER_DEF);
    else
        new_nameinfo->data.wType = LOWORD(r->type);
    incr_res_count((char *)r->type, new_nameinfo);
    if (!HIWORD(r->name))
        sprintf(outTemp, "%d", (int)r->name);
    else
        sprintf(outTemp, "%s", r->name);
    outType = resource_type_name(r->type);
    VPRINT(("Added resource: %s %s", outType, outTemp));
    str_free(outType);
    res_free(r);
}
Beispiel #10
0
// Perform a DNS query and parse the results.  Follows CNAME records.
void SipSrvLookup::res_query_and_parse(const char* in_name,
                                       int type,
                                       res_response* in_response,
                                       const char*& out_name,
                                       res_response*& out_response
   )
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSrvLookup::res_query_and_parse in_name = '%s', "
                 "type = %d (%s)",
                 in_name,type,
                 type == T_CNAME ? "CNAME" :
                 type == T_SRV ? "SRV" :
                 type == T_A ? "A" :
                 type == T_NAPTR ? "NAPTR" :
                 "unknown");

   // The number of CNAMEs we have followed.
   int cname_count = 0;
   // The response currently being examined.
   res_response* response = in_response;
   // The name currently being examined.
   const char* name = in_name;
   // TRUE if 'response' was a lookup for 'name' and 'type'.
   UtlBoolean response_for_this_name = FALSE;
   // Buffer into which to read DNS replies.
   char answer[DNS_RESPONSE_SIZE];
   union u_rdata* p;

   // Loop until we find a reason to exit.  Each turn around the loop does
   // another DNS lookup.
   while (1)
   {
      // While response != NULL and there is a CNAME record for name
      // in response.
      while (response != NULL &&
             (p = look_for(response, name, T_CNAME)) != NULL)
      {
         cname_count++;
         if (cname_count > SipSrvLookup::getOption(SipSrvLookup::OptionCodeCNAMELimit))
         {
            break;
         }
         // If necessary, free the current 'name'.
         if (name != in_name)
         {
            free((void*) name);
         }
         // Copy the canonical name from the CNAME record into 'name', so
         // we can still use it after freeing 'response'.
         name = strdup(p->string);
         // Remember that we are now looking for a name that was not the one
         // that we searched for to produce this response.  Hence, if we don't
         // find any RRs for it, that is not authoritative and we have to do
         // another DNS query.
         response_for_this_name = FALSE;
         // Go back and check whether the result name of the CNAME is listed
         // in this response.
      }
      // This response does not contain a CNAME for 'name'.  So it is either
      // a final response that gives us the RRs we are looking for, or
      // we need to do a lookup on 'name'.

      // Check whether the response was for this name, or contains records
      // of the type we are looking for.  If either, then any records we
      // are looking for are in this response, so we can return.
      if (response_for_this_name ||
          (response != NULL && look_for(response, name, type) != NULL))
      {
         break;
      }

      // We must do another lookup.
      // Start by freeing 'response' if we need to.
      if (response != in_response)
      {
         res_free(response);
      }
      response = NULL;
      // Now, 'response' will be from a query for 'name'.
      response_for_this_name = TRUE;
      // Debugging print.
      if (SipSrvLookup::getOption(SipSrvLookup::OptionCodePrintAnswers))
      {
         printf("res_nquery(\"%s\", class = %d, type = %d)\n",
                name, C_IN, type);
      }

      // Initialize the res state struct and set the timeout to
      // 3 secs and retries to 2
      struct __res_state res;
      res_ninit(&res);
      res.retrans = mTimeout;
      res.retry = mRetries;

      if (!mNameserverIP.isNull())
      {
          res.nscount = 1;
          inet_aton(mNameserverIP.data(), &res.nsaddr_list[0].sin_addr);

          if (mNameserverPort > 1)
          {
             res.nsaddr_list[0].sin_port = htons(mNameserverPort);
          }
      }

      // Use res_nquery, not res_search or res_query, so defaulting rules are not
      // applied to the domain, and so that the query is thread-safe.
      int r = res_nquery(&res, name, C_IN, type,
                         (unsigned char*) answer, sizeof (answer));
      // Done with res state struct, so cleanup.
      // Must close once and only once per res_ninit, after res_nquery.
      res_nclose(&res);

      if (r == -1)
      {
         // res_query failed, return.
         OsSysLog::add(FAC_SIP, PRI_WARNING,
                       "DNS query for name '%s', "
                       "type = %d (%s): returned error",
                       name, type,
                       type == T_CNAME ? "CNAME" :
                       type == T_SRV ? "SRV" :
                       type == T_A ? "A" :
                       type == T_NAPTR ? "NAPTR" :
                       "unknown");
         break;
      }

      response = res_parse((char*) &answer);
      if (response == NULL)
      {
         // res_parse failed, return.
         OsSysLog::add(FAC_SIP, PRI_WARNING,
                       "DNS query for name '%s', "
                       "type = %d (%s): response could not be parsed",
                       name, type,
                       type == T_CNAME ? "CNAME" :
                       type == T_SRV ? "SRV" :
                       type == T_A ? "A" :
                       type == T_NAPTR ? "NAPTR" :
                       "unknown");
         break;
      }
      // If requested for testing purposes, sort the query and print it.
      // Sort first, so we see how sorting came out.
      if (SipSrvLookup::getOption(SipSrvLookup::OptionCodeSortAnswers))
      {
         sort_answers(response);
      }
      if (SipSrvLookup::getOption(SipSrvLookup::OptionCodePrintAnswers))
      {
         res_print(response);
      }
      // Now that we have a fresh DNS query to analyze, go back and check it
      // for a CNAME for 'name' and then for records of the requested type.
   }

   // Final processing:  Copy the working name and response to the output
   // variables.
   out_name = name;
   out_response = response;
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSrvLookup::res_query_and_parse out_name = '%s', out_response = %p",
                 out_name, out_response);

}
Beispiel #11
0
/*
 * Look up A records for a domain name, and insert them into the list
 * of servers.
 */
void lookup_A(server_t*& list,
              int& list_length_allocated,
              int& list_length_used,
              const char* domain,
              ///< domain name
              OsSocket::IpProtocolSocketType proto_code,
              ///< protocol code for result list
              res_response* in_response,
              ///< current DNS response, or NULL
              int port,
              ///< port
              unsigned int priority,
              ///< priority
              unsigned int weight
              ///< weight
   )
{
   // To hold the return of res_query_and_parse.
   res_response* response;
   const char* canonical_name;

   // Make the query and parse the response.
   SipSrvLookup::res_query_and_parse(domain, T_A, in_response, canonical_name,
                                     response);

   OsLock lock(SipSrvLookupThread::slookupThreadMutex);

   // Search the list of RRs.
   // For each answer that is an A record for this domain name.
   if (response != NULL)
   {
       unsigned int i;
      // Search the answer list.
      for (i = 0; i < response->header.ancount; i++)
      {
         if (response->answer[i]->rclass == C_IN &&
             response->answer[i]->type == T_A &&
             // Note we look for the canonical name now.
             strcasecmp(canonical_name, response->answer[i]->name) == 0)
         {
            // An A record has been found.
            // Assemble the needed information and add it to the server list.
            struct sockaddr_in sin;
	    memset(&sin, 0, sizeof(struct sockaddr_in));
            sin.sin_addr = response->answer[i]->rdata.address;
            sin.sin_family = AF_INET;
            sin.sin_port = htons(port);
            server_insert_addr(list, list_length_allocated,
                               list_length_used,
                               (const char*) domain,
                               proto_code, sin, priority, weight);
         }
      }
      // Search the additional list.
      for (i = 0; i < response->header.arcount; i++)
      {
         if (response->additional[i]->rclass == C_IN &&
             response->additional[i]->type == T_A &&
             // Note we look for the canonical name now.
             strcasecmp(canonical_name, response->additional[i]->name) == 0)
         {
            // An A record has been found.
            // Assemble the needed information and add it to the server list.
            struct sockaddr_in sin;
	    memset(&sin, 0, sizeof(struct sockaddr_in));
            sin.sin_addr = response->additional[i]->rdata.address;
            sin.sin_family = AF_INET;
            sin.sin_port = htons(port);
            server_insert_addr(list, list_length_allocated,
                               list_length_used,
                               (const char*) domain,
                               proto_code, sin, priority, weight);
         }
      }
   }

   // Free the result of res_parse if necessary.
   if (response != NULL && response != in_response)
   {
      res_free(response);
   }
   if (canonical_name != NULL && canonical_name != domain)
   {
      free((void*) canonical_name);
   }
}
Beispiel #12
0
/*
 * Look up SRV records for a domain name, and from them find server
 * addresses to insert into the list of servers.
 */
void lookup_SRV(server_t*& list,
                int& list_length_allocated,
                int& list_length_used,
                const char* domain,
                ///< domain name
                const char* service,
                ///< "sip" or "sips"
                const char* proto_string,
                ///< protocol string for DNS lookup
                OsSocket::IpProtocolSocketType proto_code
                ///< protocol code for result list
   )
{
   // To hold the return of res_query_and_parse.
   res_response* response;
   const char* canonical_name;

   // Construct buffer to hold the key string for the lookup:
   //    _service._protocol.domain
   // 5 bytes suffices for the added components and the ending NUL.
   char* lookup_name = (char*) malloc(strlen(service) + strlen(proto_string) +
                                      strlen(domain) + 5);

   // Construct the domain name to search on.
   sprintf(lookup_name, "_%s._%s.%s", service, proto_string, domain);

   // Make the query and parse the response.
   SipSrvLookup::res_query_and_parse(lookup_name, T_SRV, NULL, canonical_name,
                                     response);
   if (response != NULL)
   {
       unsigned int i;
      // For each answer that is an SRV record for this domain name.

      // Search the answer list of RRs.
      for (i = 0; i < response->header.ancount; i++)
      {
         if (response->answer[i]->rclass == C_IN &&
             response->answer[i]->type == T_SRV &&
             // Note we look for the canonical name now.
             strcasecmp(canonical_name, response->answer[i]->name) == 0)
         {
            // Call lookup_A to get the A records for the target host
            // name.  Give it the pointer to our current response,
            // because it might have the A records.  If not, lookup_A
            // will do a DNS lookup to get them.
            lookup_A(list, list_length_allocated, list_length_used,
                     response->answer[i]->rdata.srv.target, proto_code,
                     response,
                     response->answer[i]->rdata.srv.port,
                     response->answer[i]->rdata.srv.priority,
                     response->answer[i]->rdata.srv.weight);
         }
      }
      // Search the additional list of RRs.
      for (i = 0; i < response->header.arcount; i++)
      {
         if (response->additional[i]->rclass == C_IN &&
             response->additional[i]->type == T_SRV &&
             // Note we look for the canonical name now.
             strcasecmp(canonical_name, response->additional[i]->name) == 0)
         {
            // Call lookup_A to get the A records for the target host
            // name.  Give it the pointer to our current response,
            // because it might have the A records.  If not, lookup_A
            // will do a DNS lookup to get them.
            lookup_A(list, list_length_allocated, list_length_used,
                     response->additional[i]->rdata.srv.target, proto_code,
                     response,
                     response->additional[i]->rdata.srv.port,
                     response->additional[i]->rdata.srv.priority,
                     response->additional[i]->rdata.srv.weight);
         }
      }
   }

   // Free the result of res_parse.
   if (response != NULL)
   {
      res_free(response);
   }
   if (canonical_name != NULL && canonical_name != lookup_name)
   {
      free((void*) canonical_name);
   }
   free((void*) lookup_name);
}
Beispiel #13
0
static void *
reach_thread (void *vdata)
{
  struct tdata *data = vdata;
  int sw = data->sw;
  struct list_res *res = &data->res;

  const uint32_t *out = g_out;
  int nout = g_nout;
  int ntfs = data_file->ntfs - 1;

  //int count = 0, loops = 0;
  while (true) {
    struct list_res queue = {0};
    pthread_mutex_lock (&wait_lock);
    //fprintf (stderr, "%d %d\n", sw, queues[sw].n);
    while (!queues[sw].head) {
      waiters |= 1 << sw;
      if (waiters + 1 == 1 << ntfs) {
        for (int i = 0; i < ntfs; i++) {
          if (i == sw) continue;
          pthread_cond_broadcast (&conds[i]);
        }
        pthread_mutex_unlock (&wait_lock);
        return NULL;
      }

      pthread_cond_wait (&conds[sw], &wait_lock);

      if (waiters + 1 == 1 << ntfs) {
        pthread_mutex_unlock (&wait_lock);
        return NULL;
      }
      assert (waiters | (1 << sw));
    }
    queue = queues[sw];
    memset (&queues[sw], 0, sizeof queues[sw]);
    pthread_mutex_unlock (&wait_lock);

    struct res *cur;
    while ((cur = queue.head)) {
      list_pop (&queue);

      bool new_res = false;
      struct list_res nextqs[ntfs];
      memset (nextqs, 0, sizeof nextqs);

      struct list_res ntf_res = ntf_apply (cur, sw);
      struct res *ntf_cur = ntf_res.head;
      while (ntf_cur) {
        struct res *ntf_next = ntf_cur->next;
        if (!out || int_find (ntf_cur->port, out, nout)) {
          list_append (res, ntf_cur);
          ref_add (ntf_cur, cur);
          if (out) {
            ntf_cur = ntf_next;
            continue;
          }
        }

        struct list_res ttf_res = tf_apply (tf_get (0), ntf_cur, true);
        struct res *ttf_cur = ttf_res.head;
        while (ttf_cur) {
          struct res *ttf_next = ttf_cur->next;
          if (is_loop (ttf_cur->port, cur)) {
            res_free (ttf_cur);
            ttf_cur = ttf_next;
            //loops++;
            continue;
          }

          ref_add (ttf_cur, cur);
          if (out && int_find (ttf_cur->port, out, nout)) list_append (res, ttf_cur);
          else {
            int new_sw = ntf_get_sw (ttf_cur->port);
            list_append (&nextqs[new_sw], ttf_cur);
            //count++;
            new_res = true;
          }
          ttf_cur = ttf_next;
        }
        if (out) res_free (ntf_cur);
        ntf_cur = ntf_next;
      }
      res_free_mt (cur, true);

      if (!new_res) continue;
      pthread_mutex_lock (&wait_lock);
      unsigned int wake = 0;
      for (int i = 0; i < ntfs; i++) {
        if (!nextqs[i].head) continue;
        list_concat (&queues[i], &nextqs[i]);
        pthread_cond_broadcast (&conds[i]);
        wake |= 1 << i;
      }
      waiters &= ~wake;
      pthread_mutex_unlock (&wait_lock);
    }
  }
}
Beispiel #14
0
RedirectPlugin::LookUpStatus
SipRedirectorISN::lookUp(
   const SipMessage& message,
   const UtlString& requestString,
   const Url& requestUri,
   const UtlString& method,
   ContactList& contactList,
   RequestSeqNo requestSeqNo,
   int redirectorNo,
   SipRedirectorPrivateStorage*& privateStorage,
   ErrorDescriptor& errorDescriptor)
{
   bool status = false;

   // Get the user part.
   UtlString userId;
   requestUri.getUserId(userId);

   // Test if the user part is in the right format -- prefix followed by digits*digits
   const char* user = userId.data();
   int prefix_length = mPrefix.length();
   // Compare the prefix.
   int i;                       // Length of the extension part.
   if (strncmp(user, mPrefix.data(), prefix_length) == 0)
   {
      // Effectively delete the prefix from the user part.
      user += prefix_length;
      // Check the syntax of the remainder of the user.
      i = strspn(user, "0123456789");
      int j = 0;
      if (i > 0)
      {
         if (user[i] == '*')
         {
            j = strspn(user + i + 1, "0123456789");
            if (user[i + 1 + j] == '\0')
            {
               status = true;
            }
         }
      }
   }

   if (status)
   {
      // Format of user part is correct.  Look for NAPTR records.

      // Create the domain to look up.
      char domain[2 * strlen(user) + mBaseDomain.length()];
      {
         char* p = &domain[0];
         // Copy the extension, reversing it and following each digit with a period.
         for (int k = i; --k >= 0; )
         {
            *p++ = user[k];
            *p++ = '.';
         }
         // Append the ITAD and a period.
         strcpy(p, user + i + 1);
         strcat(p, ".");
         // Append the ITAD root domain.
         strcat(p, mBaseDomain.data());
      }
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "%s::lookUp user '%s' has ISN format, domain is '%s'",
                    mLogName.data(), user, domain);

      // To hold the return of res_query_and_parse.
      res_response* dns_response;
      const char* canonical_name;

      // Make the query and parse the response.
      SipSrvLookup::res_query_and_parse(domain, T_NAPTR, NULL, canonical_name, dns_response);

      if (dns_response != NULL)
      {
         // Search the list of RRs for the 'best' answer.
         // Initialize to values at least 2**16.
         int lowest_order_seen = 1 << 16, lowest_preference_seen = 1 << 16;
         int best_response = -1; // No response found..
         // Search the answer list.
         for (unsigned int i = 0; i < dns_response->header.ancount; i++)
         {
            if (dns_response->answer[i]->rclass == C_IN &&
                dns_response->answer[i]->type == T_NAPTR &&
                // Note we look for the canonical name now.
                strcasecmp(canonical_name, dns_response->answer[i]->name) == 0)
            {
               // A NAPTR record has been found.
               OsSysLog::add(FAC_SIP, PRI_DEBUG,
                             "%s::LookUp "
                             "NAPTR record found '%s' %d %d %d %d '%s' '%s' '%s' '%s'",
                             mLogName.data(),
                             dns_response->answer[i]->name,
                             dns_response->answer[i]->rclass,
                             dns_response->answer[i]->type,
                             dns_response->answer[i]->rdata.naptr.order,
                             dns_response->answer[i]->rdata.naptr.preference,
                             dns_response->answer[i]->rdata.naptr.flags,
                             dns_response->answer[i]->rdata.naptr.services,
                             dns_response->answer[i]->rdata.naptr.regexp,
                             dns_response->answer[i]->rdata.naptr.replacement);
               // Accept the record if flags are 'u' and services are 'E2U+sip'.
               // Note that the value 'E2U+sip' is defined by RFC 3764
               // (SIP enumservice) not RFC 2915 (the original NAPTR RFC).
               if (strcasecmp(dns_response->answer[i]->rdata.naptr.flags, "u") == 0 &&
                   strcasecmp(dns_response->answer[i]->rdata.naptr.services, "E2U+sip") == 0)
               {
                  // Check that it has the lowest order and preference values seen so far.
                  if (dns_response->answer[i]->rdata.naptr.order < lowest_order_seen ||
                      (dns_response->answer[i]->rdata.naptr.order == lowest_order_seen &&
                       dns_response->answer[i]->rdata.naptr.preference < lowest_preference_seen))
                  {
                     best_response = i;
                     lowest_order_seen = dns_response->answer[i]->rdata.naptr.order;
                     lowest_preference_seen = dns_response->answer[i]->rdata.naptr.preference;
                  }
               }
            }
         }

         // At this point, best_response (if any) is the response we chose.
         if (best_response != -1)
         {
            char* p = dns_response->answer[best_response]->rdata.naptr.regexp;
            OsSysLog::add(FAC_SIP, PRI_DEBUG,
                          "%s::LookUp Using NAPTR rewrite '%s' for '%s'",
                          mLogName.data(), p, domain);
            // Enough space for the 'match' part of the regexp field.
            char match[strlen(p) + 1];
            // Pointer to the 'replace' part of the regexp field.
            char delim;
            const char* replace;
            int i_flag;
            if (res_naptr_split_regexp(p, &delim, match, &replace, &i_flag))
            {
               OsSysLog::add(FAC_SIP, PRI_DEBUG,
                             "%s::LookUp match = '%s', replace = '%s', i_flag = %d",
                             mLogName.data(), match, replace, i_flag);
               // Split operation was successful.  Try to match.
               regex_t reg;
               int ret = regcomp(&reg, match, REG_EXTENDED | (i_flag ? REG_ICASE : 0));
               if (ret == 0)
               {
                  // NAPTR matches can have only 9 substitutions.
                  regmatch_t pmatch[9];
                  // regexec returns 0 for success.
                  // Though RFC 3761 and the ISN Cookbook don't say, it appears
                  // that the regexp is matched against the user-part of the SIP URI.
                  if (regexec(&reg, user, 9, pmatch, 0) == 0)
                  {
                     // Match was successful.  Construct the replacement string.
                     // Current usage is that the replacement string is the resulting URI,
                     // not the replacement into the original application-string.
                     char* result = res_naptr_replace(replace, delim, pmatch, user, 0);
                     OsSysLog::add(FAC_SIP, PRI_DEBUG,
                                   "%s::LookUp result = '%s'",
                                   mLogName.data(), result);
                     // Note that the replacement string is not
                     // substituted back into the original string, but used
                     // alone as the destination URI.
                     // Parse result string into URI.
                     Url contact(result, TRUE);
                     // Almost all strings are parsable as SIP URIs with a sufficient
                     // number of components missing.  But we can check that a scheme
                     // was identified, and that a host name was found.
                     // (A string with sufficiently few punctuation characters appears to
                     // be a sip: URI with the scheme missing and only a host name, but
                     // the legal character set for host names is fairly narrow.)
                     UtlString h;
                     contact.getHostAddress(h);
                     if (contact.getScheme() != Url::UnknownUrlScheme && !h.isNull())
                     {
                        contactList.add(contact, *this);
                     }
                     else
                     {
                        OsSysLog::add(FAC_SIP, PRI_ERR,
                                      "%s::LookUp Bad result string '%s' - "
                                      "could not identify URI scheme and/or host name is null - "
                                      "for ISN translation of '%s'",
                                      mLogName.data(), result, requestString.data());
                     }
                     // Free the result string.
                     free(result);
                  }
                  else
                  {
                     OsSysLog::add(FAC_SIP, PRI_WARNING,
                                   "%s::LookUp NAPTR regexp '%s' does not match "
                                   "for ISN translation of '%s' - no contact generated",
                                   mLogName.data(), match, requestString.data());
                  }
                  // Free the parsed regexp structure.
                  regfree(&reg);
               }
               else
               {
                  OsSysLog::add(FAC_SIP, PRI_WARNING,
                                "%s::LookUp NAPTR regexp '%s' is syntactially invalid "
                                   "for ISN translation of '%s'",
                                mLogName.data(), match, requestString.data());
               }
            }
            else
            {
               OsSysLog::add(FAC_SIP, PRI_ERR,
                             "%s::LookUp cannot parse NAPTR regexp field '%s' "
                             "for ISN translation of '%s'",
                             mLogName.data(), p, requestString.data());
            }
         }
         else
         {
            OsSysLog::add(FAC_SIP, PRI_WARNING,
                          "%s::LookUp No usable NAPTR found for '%s'"
                          "for ISN translation of '%s'",
                          mLogName.data(), domain, requestString.data());
         }
      }
      else
      {
         OsSysLog::add(FAC_SIP, PRI_WARNING,
                       "%s::LookUp no NAPTR record found for domain '%s' "
                       "for ISN translation of '%s'",
                       mLogName.data(), domain, requestString.data());
      }

      // Free the result of res_parse if necessary.
      if (dns_response != NULL)
      {
         res_free(dns_response);
      }
      if (canonical_name != NULL && canonical_name != domain)
      {
         free((void*) canonical_name);
      }
   }

   return RedirectPlugin::SUCCESS;
}