dns.c

Go to the documentation of this file.
00001 /* libspf - Sender Policy Framework library 00002 * 00003 * ANSI C implementation of draft-mengwong-spf-02.9.7.txt 00004 * 00005 * Author: James Couzens <jcouzens@6o4.ca> 00006 * Author: Sean Comeau <scomeau@obscurity.org> 00007 * 00008 * File: dns.c 00009 * Desc: DNS related functions 00010 * 00011 * License: 00012 * 00013 * The libspf Software License, Version 1.0 00014 * 00015 * Copyright (c) 2004 James Couzens & Sean Comeau All rights 00016 * reserved. 00017 * 00018 * Redistribution and use in source and binary forms, with or without 00019 * modification, are permitted provided that the following conditions 00020 * are met: 00021 * 00022 * 1. Redistributions of source code must retain the above copyright 00023 * notice, this list of conditions and the following disclaimer. 00024 * 00025 * 2. Redistributions in binary form must reproduce the above copyright 00026 * notice, this list of conditions and the following disclaimer in 00027 * the documentation and/or other materials provided with the 00028 * distribution. 00029 * 00030 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 00031 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00032 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00033 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS MAKING USE OF THIS LICESEN 00034 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00035 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00036 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 00037 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00038 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00039 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00040 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00041 * SUCH DAMAGE. 00042 * 00043 */ 00044 00045 #include "spf.h" 00046 #include "util.h" 00047 #include "dns.h" 00048 #include "error.h" 00049 00174 /* DNS_query 00175 * 00176 * Author: James Couzens <jcouzens@6o4.ca>\n 00177 * Author: Travis Anderson <travis@anthrax.ca>\n 00178 * 00179 * Date: 12/10/03 00180 * Date: 02/20/04 - Added cache by Travis Anderson <travis@anthrax.ca> 00181 * 00182 * Desc: 00183 * Executes a DNS query of type T_TYPE and then calls the 00184 * appropriate answer parsing function based on that type. Returns 00185 * a pointer to allocated memory (a string of space delimited 00186 * records). Upon failure returns NULL. 00187 * 00188 */ 00189 char *DNS_query(peer_info_t *peer_info, const char *s, const int T_TYPE, 00190 const char *mta) 00191 { 00192 int16_t r_len; /* res_search return code & packet len */ 00193 int16_t rc; /* generic return code / length of */ 00194 00195 u_char *msg_ptr; /* pointer to beginning of the message */ 00196 u_char *eom_ptr; /* pointer to the end of the message */ 00197 00198 u_char *rd_ptr; /* pointer to uncompressed message */ 00199 00200 int8_t ancount; /* number of answers */ 00201 00202 HEADER *hdr; /* pointer to the header of the packet */ 00203 00204 char buf[SPF_MAXDNAME]; /* record extraction buffer */ 00205 char answer[SPF_PACKETSZ]; /* answer buffer */ 00206 00207 char *rr_data = NULL; /* record */ 00208 00209 int ttl; /* answer TTL */ 00210 00211 if (s == NULL) 00212 { 00213 xeprintf("Passed a NULL char. Aborting.\n"); 00214 return(NULL); 00215 } 00216 00217 xvprintf("Called with (%s) and type: %i\n", s, T_TYPE); 00218 00219 memset(answer, '\0', SPF_PACKETSZ); 00220 memset(buf, '\0', SPF_MAXDNAME); 00221 r_len = res_search(s, C_IN, T_TYPE, (u_char *)answer, SPF_PACKETSZ); 00222 00223 if (r_len <= 0) 00224 { 00225 switch (h_errno) 00226 { 00227 case HOST_NOT_FOUND: 00228 snprintf(peer_info->error, MAX_ERROR, "DNS failure (Host not found)"); 00229 UTIL_assoc_prefix(peer_info, SPF_NONE, NULL); 00230 xvprintf("%s", peer_info->error); 00231 00232 return(NULL); 00233 00234 case TRY_AGAIN: 00235 snprintf(peer_info->error, MAX_ERROR, "DNS failure (Non-Authoritative Host not " 00236 "found, or SERFAIL.)"); 00237 UTIL_assoc_prefix(peer_info, SPF_NONE, NULL); 00238 xvprintf("%s", peer_info->error); 00239 00240 return(NULL); 00241 00242 case NO_RECOVERY: 00243 snprintf(peer_info->error, MAX_ERROR, "DNS failure (Non recoverable errors, " 00244 "FORMERR, REFUSED, NOTIMP.)"); 00245 UTIL_assoc_prefix(peer_info, SPF_ERROR, NULL); 00246 xvprintf("%s", peer_info->error); 00247 00248 return(NULL); 00249 00250 case NO_DATA: 00251 snprintf(peer_info->error, MAX_ERROR, "DNS failure (Valid name, no data record " 00252 "of requested type.)"); 00253 UTIL_assoc_prefix(peer_info, SPF_NONE, NULL); 00254 xvprintf("%s", peer_info->error); 00255 00256 return(NULL); 00257 00258 default: 00259 snprintf(peer_info->error, MAX_ERROR, "DNS failure (internal error)"); 00260 UTIL_assoc_prefix(peer_info, SPF_ERROR, NULL); 00261 xvprintf("%s", peer_info->error); 00262 return(NULL); 00263 } /* switch */ 00264 } 00265 00266 hdr = (HEADER *)&answer; 00267 ancount = ntohs(hdr->ancount); 00268 00269 xvprintf("Received packet size of %i bytes which contains %i answers.\n", 00270 r_len, ancount); 00271 xvprintf("ANSWERS: %i\n", ancount); 00272 xvprintf("QUESTIONS: %i\n", ntohs(hdr->qdcount)); 00273 00274 if (ancount > 0) 00275 { 00276 msg_ptr = (u_char *)&answer; /* point to start of message */ 00277 eom_ptr = (u_char *)&answer + r_len; /* point to end of message */ 00278 rd_ptr = (u_char *)&answer + HFIXEDSZ; /* point to start of RDATA */ 00279 00280 if ((rc = dn_skipname(rd_ptr, eom_ptr)) < 0) 00281 { 00282 xeprintf("Error obtaining QUESTION!\n"); 00283 return(NULL); 00284 } 00285 00286 rd_ptr += rc + QFIXEDSZ; /* jump to start of ANSWER */ 00287 00288 switch (T_TYPE) 00289 { 00290 case T_A: 00291 return((char *)TRUE); 00292 00293 case T_TXT: 00294 if ((rr_data = DNS_txt_answer(ancount, (u_char *)msg_ptr, (u_char *)eom_ptr, 00295 (u_char *)rd_ptr, buf, &ttl)) == NULL) 00296 { 00297 00298 return(NULL); 00299 } 00300 break; 00301 00302 case T_MX: 00303 if ((rr_data = DNS_mx_answer(ancount, (u_char *)msg_ptr, (u_char *)eom_ptr, 00304 (u_char *)rd_ptr, buf, &ttl)) == NULL) 00305 { 00306 00307 return(NULL); 00308 } 00309 break; 00310 00311 case T_PTR: 00312 00313 /* Comment: James Couzens <jcouzens@6o4.ca> 00314 * Date: 01/04/04 00315 * 00316 * DNS_ptr_answer doesn't allocate any memory and simply returns TRUE or FALSE, 00317 * however, this function returns a char so we return a cast TRUE or FALSE 00318 * depending on the outcome. 00319 * 00320 */ 00321 if (DNS_ptr_answer(peer_info, ancount, (u_char *)msg_ptr, (u_char *)eom_ptr, 00322 (u_char *)rd_ptr, buf, mta, &ttl) == FALSE) 00323 { 00324 return((char *)FALSE); 00325 } 00326 else 00327 { 00328 return((char *)TRUE); 00329 } 00330 break; 00331 case T_CNAME: 00332 if ((rr_data = DNS_cname_answer(ancount, (u_char *)msg_ptr, (u_char *)eom_ptr, 00333 (u_char *)rd_ptr, buf, &ttl)) == NULL) 00334 { 00335 00336 return(NULL); 00337 } 00338 break; 00339 } 00340 00341 return(rr_data); 00342 } 00343 00344 return(NULL); 00345 } 00346 00347 00348 /* DNS_txt_answer 00349 * 00350 * Author: James Couzens <jcouzens@6o4.ca> 00351 * 00352 * Date: 01/02/04 00353 * Date: 02/23/04 - Bugfix from Albert Weichselbraun <albert@atnet.at> 00354 * Date: 02/20/04 - Added cache by Travis Anderson <travis@anthrax.ca> 00355 * 00356 * Desc: 00357 * SPF_PACKETSZ bytes are allocated and then filled with \0 chars. 00358 * This buffer is then used in a TXT DNS query using data from the passed 00359 * peer_info_t structure. Upon success this buffer is re-cast as a char * 00360 * and then a pointer to this memory is returned. Upon failure a NULL 00361 * pointer is returned. 00362 * 00363 */ 00364 char *DNS_txt_answer(int16_t ancount, const u_char *msg_ptr, 00365 const u_char *eom_ptr, u_char *rd_ptr, char *buf, int *ttl) 00366 { 00367 int16_t i; /* utility */ 00368 int16_t j; /* utility */ 00369 int16_t rc; /* generic return code / length of */ 00370 int16_t rd_type; /* answer type */ 00371 int16_t rd_len; /* res_search return code & packet len */ 00372 int32_t rd_ttl; /* TTL */ 00373 00374 char *rr_data = NULL; /* data pointer */ 00375 char *r_buf = NULL; /* return buffer */ 00376 char *pos = NULL; /* utility pointer */ 00377 00378 if (msg_ptr == NULL || eom_ptr == NULL || rd_ptr == NULL || buf == NULL) 00379 { 00380 xeprintf("Called with NULL pointers\n"); 00381 return(NULL); 00382 } 00383 00384 i = 0; 00385 j = ancount; 00386 while (ancount > 0 && rd_ptr < eom_ptr) 00387 { 00388 if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf, SPF_MAXCDNAME)) < 0) 00389 { 00390 xeprintf("Error obtaining ANSWER!\n"); 00391 return(NULL); 00392 } 00393 00394 /* dname, type, class, TTL, rdata len, rdata */ 00395 rd_ptr += rc; /* jump to start of ANSWER data */ 00396 GETSHORT(rd_type, rd_ptr); /* get response type */ 00397 rd_ptr += INT16SZ; /* skip class */ 00398 /*rd_ptr += INT32SZ;*/ /* skip TTL */ 00399 GETLONG(rd_ttl, rd_ptr); /* get TTL */ 00400 GETSHORT(rd_len, rd_ptr); /* get data length */ 00401 00402 *ttl = rd_ttl; /* TTL working pointer */ 00403 00404 if (rd_type != T_TXT) 00405 { 00406 xvprintf("Ignoring record not of T_TXT type. (%i)\n", rd_type); 00407 rd_ptr += rd_len; 00408 continue; 00409 } 00410 00411 rd_ptr++; /* skip */ 00412 rd_ptr[rd_len] = '\0'; 00413 rd_ptr[rd_len - 1] = ' '; 00414 i += rd_len; 00415 00416 xvprintf("Answer %i has length %i. (%i)\n", ancount, rd_len, i); 00417 00418 /* Only received one answer, so this MUST start with v=spf1 or its 00419 * not a valid SPFv1 record 00420 */ 00421 if (j == 1 && (*rd_ptr != 'v' && *(rd_ptr + 1) != '=')) 00422 { 00423 xvprintf("INVALID Answer Data: (%s) len: %i\n", rd_ptr, rd_len); 00424 return(NULL); 00425 } 00426 00427 xvprintf("Answer Data: (%s) len: %i\n", rd_ptr, rd_len); 00428 00429 if (rd_len <= SPF_MAXDNAME) 00430 { 00431 if (rr_data == NULL) 00432 { 00433 rr_data = xmalloc(i + 1); 00434 memset(rr_data, '\0', (i + 1)); 00435 } 00436 else 00437 { 00438 rr_data = xrealloc(rr_data, (i + 1)); 00439 } 00440 00441 xvprintf("REALLOCATE memory: %i bytes\n", i); 00442 00443 strncat(rr_data, (char *)rd_ptr, rd_len); 00444 rr_data[i - 1] = ' '; 00445 rr_data[i] = '\0'; 00446 } 00447 00448 rd_ptr += rd_len; 00449 ancount--; 00450 } 00451 00452 if (rr_data == NULL) 00453 { 00454 return(NULL); 00455 } 00456 00457 rr_data[i] = '\0'; 00458 00459 xvprintf("RR_DATA: (%s)\n", rr_data); 00460 00461 if (*rr_data == 'v' && *(rr_data + 1) == '=' && *(rr_data + 2) == 's' && 00462 *(rr_data + 3) == 'p' && *(rr_data + 4) == 'f' && *(rr_data + 5) == '1') 00463 { 00464 xvprintf("Returning with valid SPFv1 record\n", rr_data); 00465 return(rr_data); 00466 } 00467 else 00468 { 00469 /* search the buffer for a valid SPFv1 version mechanism */ 00470 if ((pos = strstr(rr_data, "v=spf1")) != NULL) 00471 { 00472 xvprintf("Found SPFv1 version mechanism: (%s)\n", pos); 00473 r_buf = xstrndup(pos, strlen(pos) + 1); 00474 r_buf[strlen(pos)] = '\0'; 00475 xvprintf("Old buffer: (%s)\n", rr_data); 00476 xvprintf("New buffer: (%s)\n", r_buf); 00477 xfree(rr_data); 00478 pos = NULL; 00479 } 00480 /* no valid SPFv1 record here */ 00481 return(r_buf); 00482 } 00483 00484 xeprintf("Returning NULL\n"); 00485 return(NULL); 00486 } 00487 00488 00489 /* DNS_mx_answer 00490 * 00491 * Author: James Couzens <jcouzens@6o4.ca> 00492 * 00493 * Date: 01/02/04 00494 * Date: 02/20/04 - Added cache by Travis Anderson <travis@anthrax.ca> 00495 * 00496 * Desc: 00497 * SPF_PACKETSZ bytes are allocated and then filled with \0 chars. 00498 * This buffer is then used in an MX DNS query using data from the passed 00499 * peer_info_t structure. Upon success this buffer is re-cast as a char * 00500 * and then a pointer to this memory is returned. Upon failure a NULL 00501 * pointer is returned. 00502 * 00503 */ 00504 char *DNS_mx_answer(int16_t ancount, const u_char *msg_ptr, 00505 const u_char *eom_ptr, u_char *rd_ptr, char *buf, int *ttl) 00506 { 00507 int16_t i; /* utility */ 00508 int16_t rc; /* generic return code / length of */ 00509 int16_t rd_len = 0; /* res_search return code & packet len */ 00510 int16_t rd_pref; /* MX preference */ 00511 int16_t rd_type; /* answer type */ 00512 int32_t rd_ttl; /* TTL */ 00513 size_t buf_len; /* buffer length */ 00514 00515 char *rr_data = NULL; /* data pointer */ 00516 00517 i = 0; 00518 while ((ancount > 0) && (rd_ptr < eom_ptr)) 00519 { 00520 if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf, SPF_MAXCDNAME)) < 0) 00521 { 00522 xeprintf("Error obtaining ANSWER!\n"); 00523 return(NULL); 00524 } 00525 00526 /* dname, type, class, TTL, rdata len, rdata */ 00527 rd_ptr += rc; /* jump to start of ANSWER data */ 00528 GETSHORT(rd_type, rd_ptr); /* get response type */ 00529 rd_ptr += INT16SZ; /* skip class */ 00530 /*rd_ptr += INT32SZ;*/ /* skip TTL */ 00531 GETLONG(rd_ttl, rd_ptr); /* get TTL */ 00532 GETSHORT(rd_len, rd_ptr); /* get data length */ 00533 00534 *ttl = rd_ttl; 00535 00536 if (rd_type != T_MX) 00537 { 00538 xprintf("Forged packet?! We requested T_MX (15) but got %i\n", rd_type); 00539 rd_ptr += rd_len; 00540 continue; 00541 } 00542 00543 GETSHORT(rd_pref, rd_ptr); /* get MX preference */ 00544 00545 if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf, SPF_MAXCDNAME)) < 0) 00546 { 00547 xeprintf("Error obtaining ANSWER!\n"); 00548 return(NULL); 00549 } 00550 00551 xvprintf("MX: %s Preference: %i\n", buf, rd_pref); 00552 00553 buf_len = strlen(buf); 00554 i += (buf_len + 1); 00555 00556 if (rd_len <= SPF_MAXDNAME) 00557 { 00558 if (rr_data == NULL) 00559 { 00560 rr_data = xmalloc(i + 1); 00561 memset(rr_data, '\0', (i + 1)); 00562 } 00563 else 00564 { 00565 rr_data = xrealloc(rr_data, (i + 1)); 00566 } 00567 00568 xvprintf("REALLOCATE memory: %i bytes\n", (i + 1)); 00569 00570 strncat(rr_data, buf, buf_len); 00571 rr_data[i - 1] = ' '; 00572 rr_data[i] = '\0'; 00573 } 00574 00575 rd_ptr += rc; 00576 ancount--; 00577 } 00578 00579 rr_data[i - 1] = '\0'; 00580 return(rr_data); 00581 } 00582 00583 00584 /* DNS_ptr_answer 00585 * 00586 * Author: James Couzens <jcouzens@6o4.ca> 00587 * 00588 * Date: 01/02/04 00589 * Date: 02/20/04 - Added cache by Travis Anderson <travis@anthrax.ca> 00590 * 00591 * Desc: 00592 * A reverse lookup on an IP address leads to a lookup per returned 00593 * PTR answer to see if the returned answer matches. The forward lookups are 00594 * handled by a separate function which calls gethostbyname. Upon a single 00595 * successful match of a forward lookup with a reverse lookup, returns TRUE. 00596 * Returns FALSE upon failure. 00597 * 00598 */ 00599 SPF_BOOL DNS_ptr_answer(peer_info_t *peer_info, int16_t ancount, 00600 const u_char *msg_ptr, const u_char *eom_ptr, u_char *rd_ptr, char *buf, 00601 const char *mta, int *ttl) 00602 { 00603 int16_t rc; /* generic return code / length of */ 00604 int16_t rd_len = 0; /* res_search return code & packet len */ 00605 int16_t rd_type; /* answer type */ 00606 int32_t rd_ttl; /* TTL */ 00607 00608 char *cp = NULL; /* working pointer for copy of mta */ 00609 char *copy = NULL; /* copy of mta */ 00610 char *ptr_dom = NULL; /* stores domain from buf's (ptr res) hostname */ 00611 char *cur_dom = NULL; /* stores domain from rpeer's hostname */ 00612 00613 while ((ancount > 0) && (rd_ptr < eom_ptr)) 00614 { 00615 if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf, SPF_MAXCDNAME)) < 0) 00616 { 00617 xeprintf("Error obtaining ANSWER!\n"); 00618 return(FALSE); 00619 } 00620 00621 /* dname, type, class, TTL, rdata len, rdata */ 00622 rd_ptr += rc; /* jump to start of ANSWER data */ 00623 GETSHORT(rd_type, rd_ptr); /* get response type */ 00624 rd_ptr += INT16SZ; /* skip class */ 00625 /*rd_ptr += INT32SZ;*/ /* skip TTL */ 00626 GETLONG(rd_ttl, rd_ptr); /* get TTL */ 00627 GETSHORT(rd_len, rd_ptr); /* get data length */ 00628 00629 *ttl = rd_ttl; 00630 00631 if (rd_type != T_PTR) 00632 { 00633 xvprintf("Forged packet?! We requested T_PTR (12) but got %i\n", 00634 rd_type); 00635 rd_ptr += rd_len; 00636 continue; 00637 } 00638 00639 if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf, SPF_MAXCDNAME)) < 0) 00640 { 00641 xeprintf("Error obtaining ANSWER!\n"); 00642 return(FALSE); 00643 } 00644 00645 xvprintf("Answer %i has length %i.\n", ancount, rd_len); 00646 xvprintf("Answer Data: (%s) len: %i\n", buf, strlen(buf)); 00647 00648 if (rd_len <= SPF_MAXDNAME) 00649 { 00650 if ((ptr_dom = UTIL_get_dname(buf)) == NULL) 00651 { 00652 xvprintf("Invalid hostname (%s)\n", buf); 00653 return(FALSE); 00654 } 00655 00656 cp = copy = xstrndup(mta, (strlen(mta) + 1)); 00657 00658 if ((cp = strstr(mta, ":")) != NULL) 00659 { 00660 cp++; 00661 } 00662 else 00663 { 00664 cp = (char *)mta; /* stfu compiler */ 00665 } 00666 00667 if ((cur_dom = UTIL_get_dname(cp)) == NULL) 00668 { 00669 xvprintf("Invalid hostname (%s)\n", mta); 00670 xfree(ptr_dom); 00671 xfree(copy); 00672 return(FALSE); 00673 } 00674 00675 if (UTIL_validate_hostname(peer_info, buf, 32) == FALSE) 00676 { 00677 xvprintf("Unable to validate hostname (%s [%s]) with (%s [%s])\n", 00678 buf, ptr_dom, mta, cur_dom); 00679 00680 xfree(ptr_dom); 00681 xfree(cur_dom); 00682 xfree(copy); 00683 return(FALSE); 00684 } 00685 00686 if (strcasecmp(ptr_dom, cur_dom) == 0) 00687 { 00688 xprintf("Validated (%s [%s]) against(%s [%s])\n", buf, ptr_dom, 00689 mta, cur_dom); 00690 00691 peer_info->r_vhname = xstrndup(mta, (strlen(mta) + 1)); 00692 xfree(ptr_dom); 00693 xfree(cur_dom); 00694 xfree(copy); 00695 return(TRUE); 00696 } 00697 else 00698 { 00699 xprintf("Unable to validate (%s : %s)\n", buf, mta); 00700 xfree(ptr_dom); 00701 xfree(cur_dom); 00702 xfree(copy); 00703 } 00704 } 00705 else 00706 { 00707 xeprintf("Answer length is too long!\n"); 00708 } 00709 00710 rd_ptr += rc; 00711 ancount--; 00712 } 00713 00714 return(FALSE); 00715 } 00716 00717 00718 /* DNS_cname_answer 00719 * 00720 * Author: Teddy <teddy@teddy.ch> 00721 * 00722 * Date: 29/04/04 00723 * Date: 02/20/04 - Added cache by Travis Anderson <travis@anthrax.ca> 00724 * 00725 * Desc: 00726 * SPF_PACKETSZ bytes are allocated and then filled with \0 chars. 00727 * This buffer is then used in a TXT DNS query using data from the passed 00728 * peer_info_t structure. Upon success this buffer is re-cast as a char * 00729 * and then a pointer to this memory is returned. Upon failure a NULL 00730 * pointer is returned. 00731 * 00732 */ 00733 char *DNS_cname_answer(int16_t ancount, const u_char *msg_ptr, 00734 const u_char *eom_ptr, u_char *rd_ptr, char *buf, int *ttl) 00735 { 00736 int16_t i; /* utility */ 00737 int16_t rc; /* generic return code / length of */ 00738 int16_t rd_type; /* answer type */ 00739 int16_t rd_len; /* res_search return code & packet len */ 00740 int32_t rd_ttl; /* TTL */ 00741 size_t buf_len; /* buffer length */ 00742 00743 char *rr_data = NULL; /* data pointer */ 00744 00745 if (msg_ptr == NULL || eom_ptr == NULL || rd_ptr == NULL || buf == NULL) 00746 { 00747 xeprintf("Called with NULL pointers\n"); 00748 return(NULL); 00749 } 00750 00751 i = 0; 00752 while (ancount > 0 && rd_ptr < eom_ptr) 00753 { 00754 if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf, SPF_MAXCDNAME)) < 0) 00755 { 00756 xeprintf("Error obtaining ANSWER!\n"); 00757 return(NULL); 00758 } 00759 00760 /* dname, type, class, TTL, rdata len, rdata */ 00761 rd_ptr += rc; /* jump to start of ANSWER data */ 00762 GETSHORT(rd_type, rd_ptr); /* get response type */ 00763 rd_ptr += INT16SZ; /* skip class */ 00764 /*rd_ptr += INT32SZ;*/ /* skip TTL */ 00765 GETLONG(rd_ttl, rd_ptr); /* get TTL */ 00766 GETSHORT(rd_len, rd_ptr); /* get data length */ 00767 00768 *ttl = rd_ttl; 00769 00770 if (rd_type != T_CNAME) 00771 { 00772 xvprintf("Ignoring record not of T_CNAME type. (%i)\n", rd_type); 00773 rd_ptr += rd_len; 00774 continue; 00775 } 00776 00777 if ((rc = dn_expand(msg_ptr, eom_ptr, rd_ptr, buf, SPF_MAXCDNAME)) < 0) 00778 { 00779 xeprintf("Error obtaining ANSWER!\n"); 00780 return(NULL); 00781 } 00782 00783 buf_len = strlen(buf); 00784 i += (buf_len + 1); 00785 00786 if (rd_len <= SPF_MAXDNAME) 00787 { 00788 if (rr_data == NULL) 00789 { 00790 rr_data = xmalloc(i + 1); 00791 memset(rr_data, '\0', (i + 1)); 00792 } 00793 else 00794 { 00795 rr_data = xrealloc(rr_data, (i + 1)); 00796 } 00797 00798 xvprintf("REALLOCATE memory: %i bytes\n", (i + 1)); 00799 00800 strncat(rr_data, buf, buf_len); 00801 rr_data[i - 1] = ' '; 00802 rr_data[i] = '\0'; 00803 } 00804 00805 rd_ptr += rc; 00806 ancount--; 00807 } 00808 00809 rr_data[i - 1] = '\0'; 00810 return(rr_data); 00811 } 00812 00813 /* end dns.c */

Generated on Thu Jul 1 14:05:44 2004 for libspf v1.0 by doxygen 1.3.7