Exemple #1
0
static void
free_response(void* data)
{
	Response_free((Response*)data);
}
Exemple #2
0
/**
 * void Frame_responseSTD(Frame_T, Frame_T)
 * @param frame: A standard query to parse
 * @param response: filled with the standard response
 * @return None
 **/
static void Frame_responseSTD(Frame_T frame, Frame_T response) {
  Query_T query;
  Response_T resp;
  const uint16_t* protocols;
  uint16_t* protocolCopy;
  const uint16_t* proto;
  bool found = false;
  uint8_t respHead[SHA256_SIZE + sizeof(uint16_t)];
  int error, count;

  count = error = 0;

  /* Parse Query */
  query = Query_init(frame->payload, frame->sHeader.length);
  if (query == NULL) {
    response->sHeader.op = kMAL;
    return;
  }
  protocols = Query_protocols(query);

  /* Create Response */
  memset(respHead, 0x00, SHA256_SIZE + sizeof(uint16_t));
  memcpy(respHead, Query_id(query), SHA256_SIZE);
  
  resp = Response_init(respHead, SHA256_SIZE + sizeof(uint16_t));
  if (resp == NULL) {
    response->sHeader.op = kMAL;
    Query_free(query);
    return;
  }

  /* First, Check Local Database for Results */
  for (proto = protocols; *proto != 0; proto++) {
    size_t len;
    const char* encrypted;
    
    encrypted = Local_get((char*)respHead, *proto, &len);
    if (encrypted != NULL) {
      error = Response_buildRecord(resp, *proto, encrypted, (uint16_t)len, Local_getTTL((char*)respHead, *proto));
      if (error < 0) {
        Response_free(resp);
        Query_free(query);
        response->sHeader.op = kNTF;
        return;
      }
      found = true;
    }
    count++;
  }

  if (found) {
    /* Found in Local Database! Sign and Return */
    response->sHeader.length = Response_size(resp);
    /*error = Response_sign(resp, Local_getPrivkey()); */
    response->payload = calloc(response->sHeader.length, sizeof(uint8_t));
    if (response->payload == NULL || error < 0) {
      if (response->payload) free(response->payload);
      response->payload = NULL;
      response->sHeader.length = 0;
      response->sHeader.op = kNTF;
    } else {
      response->sHeader.aa = 1;
      Response_serialize(resp, response->payload);
    }

    Response_free(resp);
    Query_free(query);
    return;
  }

  /* Only do cache check if client is okay with non-authoritative responses. */

  if (!response->sHeader.aa) {
    
    /* Make a Defensive Copy of Protocol List */
    protocolCopy = calloc(count, sizeof(uint16_t));
    memcpy(protocolCopy, protocols, count * sizeof(uint16_t));
    
    /* Check Cache */
    for (proto = protocolCopy; *proto != 0; proto++) {
      size_t len;
      const void* record = NULL;
      record = Cache_get((char*)respHead, *proto, &len);
      if (record != NULL) {
        Response_addRecord(resp, *proto, record);
        Query_rmProtocol(query, *proto);
      }
    }

    /* If we covered all the protocols, return! */
    protocols = Query_protocols(query);
    if (*protocols == 0) {
      response->sHeader.length = Response_size(resp);
      response->payload = calloc(response->sHeader.length, sizeof(uint8_t));
      if (response->payload == NULL || error < 0) {
        if (response->payload) free(response->payload);
        response->payload = NULL;
        response->sHeader.length = 0;
        response->sHeader.op = kNTF;
      } else {
        Response_serialize(resp, response->payload);
      }

      Response_free(resp);
      Query_free(query);
      return;
    }
  }

  /* If not in the Local File or the Cache, recurse the request if requested */
  if (frame->sHeader.rd && frame->sHeader.recurse) {
    uint8_t* recBuf;
    size_t newRespLen;
    Recursor_T recursor;

    frame->sHeader.recurse--;
    frame->sHeader.length = Query_size(query);
    
    
    /* Serialize and Recurse */
    recBuf = calloc(sizeof(struct header) + frame->sHeader.length, sizeof(uint8_t));
    if (recBuf == NULL) {
      Response_free(resp);
      Query_free(query);
      response->sHeader.op = kNTF;
      return;
    }
    memcpy(recBuf, &(frame->sHeader), sizeof(struct header));
    Query_serialize(query, recBuf + sizeof(struct header));

    recursor = Recursor_init(recBuf, sizeof(struct header) + frame->sHeader.length, PEER_MAX, frame->sHeader.recurse + 1);
    free(recBuf);
    if (recursor == NULL) {
      Response_free(resp);
      Query_free(query);
      response->sHeader.op = kNTF;
      return;
    }
    while((recBuf = (uint8_t*)Recursor_poll(recursor, &newRespLen)) != NULL) {
      Frame_T f;
      Response_T src;
      f = calloc(1, sizeof(struct frame));
      if (f == NULL) continue;
      memcpy(recBuf, &(f->sHeader), sizeof(struct header));
      f->payload = recBuf + sizeof(struct header);
      if (f->sHeader.op != kSTD || f->sHeader.z || f->sHeader.qid != frame->sHeader.qid) {
        free(f); continue;
      }
      
      src = Response_init(f->payload, f->sHeader.length);
      if (src == NULL) {
        free(f); continue;
      }

      Response_merge(resp, src);
    }
  }

  /* If the Record Count is 0, Return NTF */
  if (Response_recordCount(resp) == 0) {
    Response_free(resp);
    Query_free(query);
    response->sHeader.op = kNTF;
    return;
  }

  /* Serialize Response, Cleanup, and Return */
  response->sHeader.length = Response_size(resp);
  response->payload = calloc(response->sHeader.length, sizeof(uint8_t));
  if (response->payload == NULL || error < 0) {
    if (response->payload) free(response->payload);
    response->payload = NULL;
    response->sHeader.length = 0;
    response->sHeader.op = kNTF;
  } else {
    Response_serialize(resp, response->payload);
  }

  Response_free(resp);
  Query_free(query);
  return;
}