static void free_response(void* data) { Response_free((Response*)data); }
/** * 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; }