static int parse_answer(querybuf_t *ans, int len, struct in_addr *addr) { char buf[MAXPACKET]; HEADER *ahp; u_char *cp, *eoa; int type, n; ahp = &ans->hdr; eoa = ans->buf + len; cp = ans->buf + sizeof(HEADER); while (ahp->qdcount > 0) { ahp->qdcount--; cp += dn_skipname(cp, eoa) + QFIXEDSZ; } while (ahp->ancount > 0 && cp < eoa) { ahp->ancount--; if ((n = dn_expand(ans->buf, eoa, cp, buf, sizeof(buf))) < 0) break; cp += n; type = _getshort(cp); cp += 8; n = _getshort(cp); cp += 2; if (type == T_CNAME) { cp += n; continue; } memcpy(addr, cp, n); return 0; } h_errno = TRY_AGAIN; return -1; }
/* * int res_queriesmatch(buf1, eom1, buf2, eom2) * is there a 1:1 mapping of (name,type,Class) * in (buf1,eom1) and (buf2,eom2)? * returns: * -1 : format error * 0 : not a 1:1 mapping * >0 : is a 1:1 mapping * author: * paul vixie, 29may94 */ int res_queriesmatch (const u_char *buf1, const u_char *eom1, const u_char *buf2, const u_char *eom2) { const u_char *cp = buf1 + HFIXEDSZ; int qdcount = ntohs (((HEADER*)buf1)->qdcount); if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) return (0); while (qdcount-- > 0) { char tname[MAXDNAME+1]; int n, ttype, tclass; n = dn_expand (buf1, eom1, cp, tname, sizeof(tname)); if (n < 0) return (-1); cp += n; ttype = _getshort (cp); cp += INT16SZ; tclass = _getshort (cp); cp += INT16SZ; if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) return (0); } return (1); }
/* * parse_question: * Extract and parse a question record * * returns a pointer to the question (or NULL on failure). */ s_question * parse_question( char **cpp, char *msg) { s_question *ptr; if ((ptr = (s_question *)malloc(sizeof(s_question))) == NULL ) return(NULL); if ((ptr->qname = expand_cdname(cpp,msg)) == NULL ) { free( ptr ); return(NULL); } ptr->qtype = _getshort(*cpp); *cpp += sizeof(u_short); ptr->qclass = _getshort(*cpp); *cpp += sizeof(u_short); return(ptr); }
/* * int res_nameinquery(name, type, class, buf, eom) * look for (name,type,class) in the query section of packet (buf,eom) * returns: * -1 : format error * 0 : not found * >0 : found * author: * paul vixie, 29may94 */ int res_nameinquery (const char *name, int type, int Class, const u_char *buf, const u_char *eom) { const u_char *cp = buf + HFIXEDSZ; int qdcount = ntohs (((HEADER*)buf)->qdcount); while (qdcount-- > 0) { char tname[MAXDNAME+1]; int n, ttype, tclass; n = dn_expand (buf, eom, cp, tname, sizeof(tname)); if (n < 0) return (-1); cp += n; ttype = _getshort (cp); cp += INT16SZ; tclass = _getshort (cp); cp += INT16SZ; if (ttype == type && tclass == Class && !stricmp(tname,name)) return (1); } return (0); }
/* * Print resource record fields in human readable form. */ static char * p_rr(char *cp, char *msg, FILE *file) { int type, class, dlen, n, c; struct in_addr inaddr; char *cp1, *cp2; if ((cp = p_cdname(cp, msg, file)) == NULL) return (NULL); /* compression error */ fprintf(file,"\n\ttype = %s", __p_type(type = _getshort(cp))); cp += sizeof(u_short); fprintf(file,", class = %s", __p_class(class = _getshort(cp))); cp += sizeof(u_short); fprintf(file,", ttl = %s", __p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,", dlen = %d\n", dlen = _getshort(cp)); cp += sizeof(u_short); cp1 = cp; /* * Print type specific data, if appropriate */ switch (type) { case T_A: switch (class) { case C_IN: case C_HS: bcopy(cp, (char *)&inaddr, sizeof(inaddr)); if (dlen == 4) { fprintf(file,"\tinternet address = %s\n", inet_ntoa(inaddr)); cp += dlen; } else if (dlen == 7) { fprintf(file,"\tinternet address = %s", inet_ntoa(inaddr)); fprintf(file,", protocol = %d", cp[4]); fprintf(file,", port = %d\n", (cp[5] << 8) + cp[6]); cp += dlen; } break; default: cp += dlen; } break; case T_CNAME: case T_MB: case T_MG: case T_MR: case T_NS: case T_PTR: fprintf(file,"\tdomain name = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n"); break; case T_HINFO: if (n = *cp++) { fprintf(file,"\tCPU=%.*s\n", n, cp); cp += n; } if (n = *cp++) { fprintf(file,"\tOS=%.*s\n", n, cp); cp += n; } break; case T_SOA: fprintf(file,"\torigin = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n\tmail addr = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n\tserial = %ld", _getlong(cp)); cp += sizeof(u_long); fprintf(file,"\n\trefresh = %s", __p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,"\n\tretry = %s", __p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,"\n\texpire = %s", __p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,"\n\tmin = %s\n", __p_time(_getlong(cp))); cp += sizeof(u_long); break; case T_MX: fprintf(file,"\tpreference = %ld,",_getshort(cp)); cp += sizeof(u_short); fprintf(file," name = "); cp = p_cdname(cp, msg, file); break; case T_TXT: (void) fputs("\t\"", file); cp2 = cp1 + dlen; while (cp < cp2) { if (n = (unsigned char) *cp++) { for (c = n; c > 0 && cp < cp2; c--) if (*cp == '\n') { (void) putc('\\', file); (void) putc(*cp++, file); } else (void) putc(*cp++, file); } } (void) fputs("\"\n", file); break; case T_MINFO: fprintf(file,"\trequests = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n\terrors = "); cp = p_cdname(cp, msg, file); break; case T_UINFO: fprintf(file,"\t%s\n", cp); cp += dlen; break; case T_UID: case T_GID: if (dlen == 4) { fprintf(file,"\t%ld\n", _getlong(cp)); cp += sizeof(int); } break; case T_WKS: if (dlen < sizeof(u_long) + 1) break; bcopy(cp, (char *)&inaddr, sizeof(inaddr)); cp += sizeof(u_long); fprintf(file,"\tinternet address = %s, protocol = %d\n\t", inet_ntoa(inaddr), *cp++); n = 0; while (cp < cp1 + dlen) { c = *cp++; do { if (c & 0200) fprintf(file," %d", n); c <<= 1; } while (++n & 07); } putc('\n',file); break; #ifdef ALLOW_T_UNSPEC case T_UNSPEC: { int NumBytes = 8; char *DataPtr; int i; if (dlen < NumBytes) NumBytes = dlen; fprintf(file, "\tFirst %d bytes of hex data:", NumBytes); for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++) fprintf(file, " %x", *DataPtr); fputs("\n", file); cp += dlen; } break; #endif /* ALLOW_T_UNSPEC */ default: fprintf(file,"\t???\n"); cp += dlen; } if (cp != cp1 + dlen) { fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen); cp = NULL; } fprintf(file,"\n"); return (cp); }
/* * Print the contents of a query. * This is intended to be primarily a debugging routine. */ void __fp_query(char *msg, FILE *file) { register char *cp; register HEADER *hp; register int n; /* * Print header fields. */ hp = (HEADER *)msg; cp = msg + sizeof(HEADER); fprintf(file,"HEADER:\n"); fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); fprintf(file,", id = %d", ntohs(hp->id)); fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); fprintf(file,"\theader flags: "); if (hp->qr) fprintf(file," qr"); if (hp->aa) fprintf(file," aa"); if (hp->tc) fprintf(file," tc"); if (hp->rd) fprintf(file," rd"); if (hp->ra) fprintf(file," ra"); if (hp->pr) fprintf(file," pr"); fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount)); fprintf(file,", ancount = %d", ntohs(hp->ancount)); fprintf(file,", nscount = %d", ntohs(hp->nscount)); fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount)); /* * Print question records. */ if (n = ntohs(hp->qdcount)) { fprintf(file,"QUESTIONS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_cdname(cp, msg, file); if (cp == NULL) return; fprintf(file,", type = %s", __p_type(_getshort(cp))); cp += sizeof(u_short); fprintf(file, ", class = %s\n\n", __p_class(_getshort(cp))); cp += sizeof(u_short); } } /* * Print authoritative answer records */ if (n = ntohs(hp->ancount)) { fprintf(file,"ANSWERS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_rr(cp, msg, file); if (cp == NULL) return; } } /* * print name server records */ if (n = ntohs(hp->nscount)) { fprintf(file,"NAME SERVERS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_rr(cp, msg, file); if (cp == NULL) return; } } /* * print additional records */ if (n = ntohs(hp->arcount)) { fprintf(file,"ADDITIONAL RECORDS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_rr(cp, msg, file); if (cp == NULL) return; } } }
int gethinfo(register char *hostname, register char *cpu, register int cpulen, register char *os, register int oslen) { #ifdef HAVE_DN_SKIPNAME register querybuf *qb; register u_char *cp, *eom; register char *bp; register int n; register HEADER *hp; register int type, class, buflen, ancount, qdcount; querybuf qbuf; qb = &qbuf; n = res_query(hostname, C_IN, T_HINFO, qb->buf, sizeof(qb->buf)); if (n < 0) return (0); eom = qb->buf + n; /* * find first satisfactory answer */ hp = &qb->hdr; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; buflen = sizeof(hostbuf); cp = qb->buf + sizeof(HEADER); if (qdcount) { cp += dn_skipname(cp, eom) + QFIXEDSZ; while (--qdcount > 0) cp += dn_skipname(cp, eom) + QFIXEDSZ; } while (--ancount >= 0 && cp < eom) { if ((n = dn_expand((u_char *)qb->buf, (u_char *)eom, (u_char *)cp, (u_char *)bp, buflen)) < 0) break; cp += n; type = _getshort(cp); cp += sizeof(u_short); class = _getshort(cp); cp += sizeof(u_short) + sizeof(u_int32_t); n = _getshort(cp); cp += sizeof(u_short); if (type == T_HINFO) { /* Unpack */ n = *cp++; if (n > cpulen - 1) return (0); BCOPY(cp, cpu, n); cp += n; cpu[n] = '\0'; n = *cp++; if (n > oslen - 1) return (0); BCOPY(cp, os, n); os[n] = '\0'; return (1); } /* Skip unexpected junk */ cp += n; } #endif return (0); }
static int name_server_send (int ns, struct sockaddr_in *nsap) { int resplen = 0; if (badns & (1 << ns)) /* this NameServer already marked bad */ { resolve_close(); return (NEXT_NS); } if (Qhook) { int done = 0; int loops = 0; do { res_sendhookact act = (*Qhook) (&nsap, (const u_char**)&ns_buf, &ns_buflen, ns_ans, ns_anssiz, &resplen); switch (act) { case res_goahead: done = 1; break; case res_nextns: resolve_close(); return (NEXT_NS); case res_done: return (resplen); case res_modified: /* give the hook another try */ if (++loops < 42) break; /* fallthrough */ case res_error: /* fallthrough */ default: return (-1); } } while (!done); } Dprint (_res.options & RES_DEBUG, (";; Querying server (# %d) address = %s\n", ns + 1, inet_ntoa(nsap->sin_addr))); if (v_circuit) /* i.e. TCP */ { int truncated; u_short len; u_char *cp; /* Use virtual circuit; at most one attempt per server. */ Try = _res.retry; truncated = 0; if (!sock || !vc) { DWORD his_ip = ntohl (nsap->sin_addr.s_addr); WORD his_port = ntohs (nsap->sin_port); if (sock) resolve_close(); sock = (sock_type*) calloc (sizeof(_tcp_Socket), 1); if (!sock) { Perror ("calloc(vc)", "no memory"); return (-1); } if (!tcp_open(&sock->tcp,0,his_ip,his_port,NULL) || !tcp_conn(&sock->tcp,&errno,dns_timeout)) { Aerror ("tcp_open/vc", "failed/timeout", *nsap); badns |= (1 << ns); resolve_close(); return (NEXT_NS); } vc = 1; } /* Send length & message */ { int send_len = INT16SZ + ns_buflen; BYTE *send_buf = (BYTE*) alloca (send_len); PUTSHORT (ns_buflen, send_buf); memcpy (send_buf + INT16SZ, ns_buf, ns_buflen); if (sock_write(sock,send_buf,send_len) != send_len) { Perror ("sock_write() failed", sockerr(sock)); badns |= (1 << ns); resolve_close(); return (NEXT_NS); } } /* Receive length & response */ cp = ns_ans; len = INT16SZ; while ((n = tcp_read(&sock->tcp,cp,len,&errno,dns_timeout)) > 0) { cp += n; len -= n; if ((signed)len <= 0) break; } if (n <= 0) { Perror ("tcp_read() failed", sockerr(sock)); resolve_close(); return (NEXT_NS); } resplen = _getshort (ns_ans); if (resplen > ns_anssiz) { Dprint (_res.options & RES_DEBUG,(";; response truncated\n")); truncated = 1; len = ns_anssiz; } else len = resplen; cp = ns_ans; while (len && (n = tcp_read(&sock->tcp,cp,len,&errno,dns_timeout)) > 0) { cp += n; len -= n; } if (n <= 0) { Perror ("tcp_read(vc)",sockerr(sock)); resolve_close(); return (NEXT_NS); } if (truncated) { /* Flush rest of answer so connection stays in synch. */ anhp->tc = 1; len = resplen - ns_anssiz; while (len) { u_char junk[PACKETSZ]; n = (len > sizeof(junk) ? sizeof(junk) : len); n = tcp_read (&sock->tcp,junk,n,&errno,dns_timeout); if (n > 0) len -= n; else break; } } } else /* !v_circuit, i.e. UDP */ { DWORD timeout; if (!sock || vc) { if (vc) resolve_close(); sock = (sock_type*) calloc (sizeof(_udp_Socket), 1); if (!sock) { Perror ("calloc(dg)", "no memory"); return (-1); } connected = 0; } /* Connect only if we are sure we won't * receive a response from another server. */ if (!connected) { DWORD his_ip = ntohl (nsap->sin_addr.s_addr); WORD his_port = ntohs (nsap->sin_port); if (!udp_open(&sock->udp,0,his_ip,his_port,NULL)) { Aerror ("connect/dg", "ARP failed", *nsap); badns |= (1 << ns); resolve_close(); return (NEXT_NS); } connected = 1; } if (sock_write(sock,(const BYTE*)ns_buf,ns_buflen) != ns_buflen) { Perror ("sock_write() failed", ""); badns |= (1 << ns); resolve_close(); return (NEXT_NS); } /* Wait for reply */ timeout = (unsigned)_res.retrans << Try; if (Try > 0) timeout /= _res.nscount; if ((long)timeout <= 0) timeout = 1; wait: n = udp_read (&sock->udp, ns_ans, ns_anssiz, &errno, timeout); if (n == 0) { Dprint (_res.options & RES_DEBUG, (";; timeout\n")); gotsomewhere = 1; resolve_close(); return (NEXT_NS); } gotsomewhere = 1; if (hp->id != anhp->id) { /* response from old query, ignore it. * XXX - potential security hazard could be detected here. */ DprintQ ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (";; old answer:\n"), ns_ans, resplen); goto wait; } if (!(_res.options & RES_INSECURE2) && !res_queriesmatch(ns_buf, ns_buf+ns_buflen, ns_ans, ns_ans+ns_anssiz)) { /* response contains wrong query? ignore it. * XXX - potential security hazard could be detected here. */ DprintQ ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (";; wrong query name:\n"), ns_ans, resplen); goto wait; } if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || anhp->rcode == REFUSED) { DprintQ (_res.options & RES_DEBUG,("server rejected query:\n"), ns_ans,resplen); badns |= (1 << ns); resolve_close(); /* don't retry if called from dig */ if (!_res.pfcode) return (NEXT_NS); } if (!(_res.options & RES_IGNTC) && anhp->tc) { /* get rest of answer; use TCP with same server. */ Dprint (_res.options & RES_DEBUG, (";; truncated answer\n")); v_circuit = 1; resolve_close(); return (SAME_NS); } } /* if vcicuit / dg */ Dprint ((_res.options & RES_DEBUG) || ((_res.pfcode & RES_PRF_REPLY) && (_res.pfcode & RES_PRF_HEAD1)), (";; got answer:\n")); DprintQ ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (" \b"), ns_ans, resplen); /* * If using virtual circuits (TCP), we assume that the first server * is preferred over the rest (i.e. it is on the local machine) and * only keep that one open. If we have temporarily opened a virtual * circuit, or if we haven't been asked to keep a socket open, * close the socket. */ if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || !(_res.options & RES_STAYOPEN)) resolve_close(); if (Rhook) { int done = 0, loops = 0; do { res_sendhookact act = (*Rhook) (nsap, ns_buf, ns_buflen, ns_ans, ns_anssiz, &resplen); switch (act) { case res_goahead: case res_done: done = 1; break; case res_nextns: resolve_close(); return (NEXT_NS); case res_modified: /* give the hook another try */ if (++loops < 42) break; /* fallthrough */ case res_error: /* fallthrough */ default: return (-1); } } while (!done); } return (resplen); }
BOOL GetMX ( char *pszQuery, char *pszServer, OUT t_Ary_MXHostInfos &Ary_MXHostInfos ) { SOCKET hSocket; SOCKADDR_IN stSockAddr; // socket address structures int nAddrLen = sizeof( SOCKADDR_IN ); HOSTENT *pHostEnt; char achBufOut[ BUFSIZE ] = { 0 }; char achBufIn[ BUFSIZE ] = { 0 }; int nQueryLen = 0; int nRC; char *p, *np, name[128], *eom; int count, j, i, n; memset( &stSockAddr, ASCII_NULL, sizeof( stSockAddr ) ); stSockAddr.sin_family = AF_INET; stSockAddr.sin_port = htons( 53); stSockAddr.sin_addr.s_addr = inet_addr( pszServer ); if ( stSockAddr.sin_addr.s_addr == INADDR_NONE ) { pHostEnt = gethostbyname( pszServer ); if ( pHostEnt ) { stSockAddr.sin_addr.s_addr = *((ULONG *)pHostEnt->h_addr_list[0]); } else { return FALSE; } // end if } // end if /*------------------------------------------------------------ * Get a DGRAM socket */ hSocket = socket( AF_INET, SOCK_DGRAM, 0 ); if ( hSocket == INVALID_SOCKET ) { return FALSE; } // end if /*----------------------------------------------------------- * Format DNS Query */ pDNShdr = (PDNS_HDR)&( achBufOut[ 0 ] ); pDNShdr->dns_id = htons( 0xDEAD ); pDNShdr->dns_flags = htons( DNS_FLAG_RD ); // do recurse pDNShdr->dns_q_count = htons( 1 ); // one query pDNShdr->dns_rr_count = 0; // none in query pDNShdr->dns_auth_count = 0; // none in query pDNShdr->dns_add_count = 0; // none in query nQueryLen = PutQName( pszQuery, &(achBufOut[ DNS_HDR_LEN ] ) ); nQueryLen += DNS_HDR_LEN; achBufOut[ nQueryLen++ ] = 0; achBufOut[ nQueryLen++ ] = 0; achBufOut[ nQueryLen ] = DNS_RRTYPE_MX; achBufOut[ nQueryLen + 1 ] = 0; achBufOut[ nQueryLen + 2 ] = DNS_RRCLASS_IN; achBufOut[ nQueryLen + 3 ] = 0; nQueryLen += 4; /*----------------------------------------------------------- * Send DNS Query to server */ nRC = sendto( hSocket, achBufOut, nQueryLen, 0, (LPSOCKADDR)&stSockAddr, sizeof( SOCKADDR_IN ) ); if ( nRC == SOCKET_ERROR ) { closesocket( hSocket ); return FALSE; } else { } // VERIFY ( SetBlockingMode ( hSocket, TRUE ) ); // 用 select 模型实现连接超时 struct timeval timeout; fd_set r; FD_ZERO(&r); FD_SET(hSocket, &r); timeout.tv_sec = 5; //连接超时秒 timeout.tv_usec =0; int ret = select(0, &r, 0, 0, &timeout); if ( ret == SOCKET_ERROR ) { ::closesocket(hSocket); hSocket = SOCKET_ERROR; return FALSE; } // 得到可读的数据长度 long cmd = FIONREAD; u_long argp = 0; BOOL err = ioctlsocket ( hSocket, cmd, (u_long*)&argp ); if ( err || argp < 1 ) { ::closesocket(hSocket); hSocket = SOCKET_ERROR; return FALSE; } nRC = recvfrom( hSocket, achBufIn, BUFSIZE, 0, (LPSOCKADDR)&stSockAddr, &nAddrLen ); if ( nRC == SOCKET_ERROR ) { int nWSAErr = WSAGetLastError(); if ( nWSAErr != WSAETIMEDOUT ) { closesocket( hSocket ); return FALSE; } else { closesocket( hSocket ); return FALSE; } } else { pDNShdr = (PDNS_HDR)&( achBufIn[ 0 ] ); p = (char *)&pDNShdr[0]; p+=12; count = (int)*p; // Parse the Question... for (i = 0; i< ntohs(pDNShdr->dns_q_count); i++) { np = name; eom = (char *)pDNShdr+nRC; if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 ) { return FALSE; } p += n + QFIXEDSZ; } for (i = 0; i< ntohs(pDNShdr->dns_rr_count); i++) { // The Question Name appears Again... if ((n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0) { return FALSE; } p+=n; j = _getshort(p);; //TYPE p+=2; //printf("%s\tType:%d", name, j); j = _getshort(p); //CLASS p+=2; // printf("\tClass:%d", j); j = _getlong(p); //TTL p+=4; // printf("\tTTL:%d", j); j = _getshort(p); //RDLENGTH p+=2; // printf("\tRDLENGTH:%d", j); j = _getshort(p); //N?? p+=2; // This should be an MX Name... if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 ) { return FALSE; } t_MXHostInfo tMXHostInfo = {0}; strncpy ( (char*)tMXHostInfo.szMXHost, name, _countof(tMXHostInfo.szMXHost)); tMXHostInfo.N = j; Ary_MXHostInfos.Add ( tMXHostInfo ); TRACE ( _T("%s\t%d\r\n"), name, j ); p += n; } return TRUE; } closesocket( hSocket ); return FALSE; }
/* * parse_rr: * Extract and parse a resource record * * returns a pointer to the RR (or NULL on failure). */ s_rr * parse_rr( char **cpp, char *msg) { s_rr *ptr; int dlen; union u_rdata *rd; /* * Set up the RR-independent information */ if ((ptr = (s_rr *)malloc(sizeof(s_rr))) == NULL ) return(NULL); if ((ptr->name = expand_cdname(cpp,msg)) == NULL ) { free(ptr); return(NULL); } ptr->type = _getshort(*cpp); *cpp += sizeof(u_short); ptr->rclass = _getshort(*cpp); *cpp += sizeof(u_short); ptr->ttl = _getlong(*cpp); /* Size on the network is 4 bytes so use u_int not u_long as * u_long is architecture dependent (e.g. 8 bytes on 64 bit). */ *cpp += sizeof(u_int); dlen = _getshort(*cpp); ptr->dlen = dlen; *cpp += sizeof(u_short); rd = &ptr->rdata; /* * Handle RR-specifics * * (No indication of failures here is * passed back to the calling procedure) */ switch(ptr->type) { case T_A: /* Address */ switch (ptr->rclass) { case C_IN: memcpy((void *)&rd->address, (void *)*cpp, sizeof(struct in_addr)); *cpp += dlen; break; default: /* Can't really handle this - just skip it */ *cpp += dlen; } break; case T_NS: /* Name Server */ case T_MD: /* Mail Destination (OBS) */ case T_MF: /* Mail Forwarder (OBS) */ case T_CNAME: /* Canonical Name */ rd->string = expand_cdname(cpp, msg); break; case T_SOA: /* Start of Authority */ rd->soa.mname = expand_cdname(cpp, msg); rd->soa.rname = expand_cdname(cpp, msg); rd->soa.serial = _getlong(*cpp); *cpp += sizeof(u_long); rd->soa.refresh = _getlong(*cpp); *cpp += sizeof(u_long); rd->soa.retry = _getlong(*cpp); *cpp += sizeof(u_long); rd->soa.expire = _getlong(*cpp); *cpp += sizeof(u_long); rd->soa.minimum = _getlong(*cpp); *cpp += sizeof(u_long); break; case T_MB: /* Mail Box */ case T_MG: /* Mail Group */ case T_MR: /* Mail Rename */ rd->string = expand_cdname(cpp, msg); break; /* Following modification taken from VxWorks --GAT */ /* 01b,29apr97,jag Changed T_NULL to T_NULL_RR to fix conflict with loadCoffLib.h */ case T_NULL_RR: /* Null RR */ if ((rd->null.anything = (char *)malloc(dlen)) != NULL ) memcpy((void *)rd->null.anything, (void *)*cpp, dlen); rd->null.length = dlen; *cpp += dlen; break; case T_WKS: /* Well Known Services */ memcpy((void *)&rd->wks.address, (void *)*cpp, sizeof(struct in_addr)); *cpp += sizeof(struct in_addr); rd->wks.protocol = **cpp; (*cpp)++; rd->wks.maplength = dlen-(sizeof(struct in_addr) +1); if ((rd->wks.bitmap = (char *)malloc(rd->wks.maplength)) != NULL ) memcpy((void *)rd->wks.bitmap, (void *)*cpp, rd->wks.maplength); *cpp += rd->wks.maplength; break; case T_PTR: /* Domain Name Pointer */ rd->string = expand_cdname(cpp, msg); break; case T_HINFO: /* Host Info */ if (( rd->hinfo.cpu = expand_charstring(cpp, msg)) == NULL ) { cpp += dlen; break; } if (( rd->hinfo.os = expand_charstring(cpp, msg)) == NULL ) { cpp -= (strlen(rd->hinfo.cpu) +1); cpp += dlen; break; } break; case T_MINFO: /* Mailbox Info */ rd->minfo.rmailbx = expand_cdname(cpp, msg); rd->minfo.emailbx = expand_cdname(cpp, msg); break; case T_MX: /* Mail Exchanger */ rd->mx.preference = _getshort(*cpp); *cpp += sizeof(u_short); rd->mx.exchange = expand_cdname(cpp, msg); break; case T_SRV: /* Service location */ rd->srv.priority = _getshort(*cpp); *cpp += sizeof(u_short); rd->srv.weight = _getshort(*cpp); *cpp += sizeof(u_short); rd->srv.port = _getshort(*cpp); *cpp += sizeof(u_short); rd->srv.target = expand_cdname(cpp, msg); break; case T_NAPTR: /* Naming authority pointer */ { // This is copied from the other cases, but I think that // all cases should be setting *cpp += dlen, not // cpp += dlen. char **cpp_end = cpp + dlen; rd->naptr.order = _getshort(*cpp); *cpp += sizeof(u_short); rd->naptr.preference = _getshort(*cpp); *cpp += sizeof(u_short); if (( rd->naptr.flags = expand_charstring(cpp, msg)) == NULL ) { cpp = cpp_end; break; } if (( rd->naptr.services = expand_charstring(cpp, msg)) == NULL ) { cpp = cpp_end; break; } if (( rd->naptr.regexp = expand_charstring(cpp, msg)) == NULL ) { cpp = cpp_end; break; } rd->naptr.replacement = expand_cdname(cpp, msg); } break; case T_TXT: /* Text string */ rd->txt.len = **cpp; rd->txt.next = NULL; if ((rd->txt.text = expand_charstring(cpp, msg)) == NULL ) { cpp += dlen; break; } /* * Multiple strings * add onto a linked list */ if ( rd->txt.len+1 < dlen ) { struct s_TXT *txtp; char **cpp2; int n; n = rd->txt.len+1; txtp = &(rd->txt); cpp2 = cpp; while ( n < dlen ) { if ((txtp->next = (struct s_TXT *)malloc(sizeof(struct s_TXT))) == NULL ) { cpp += (dlen - rd->txt.len); break; } txtp = txtp->next; txtp->len = **cpp2; n += txtp->len+1; txtp->next = NULL; if ((txtp->text = expand_charstring(cpp2, msg)) == NULL ) { cpp += (dlen - rd->txt.len); break; } } } break; /* * RFC 1183 Additional types */ case T_AFSDB: /* AFS Server */ rd->afsdb.subtype = _getshort(*cpp); *cpp += sizeof(u_short); rd->afsdb.hostname = expand_cdname(cpp, msg); break; case T_RP: /* Responsible Person */ rd->rp.mbox_dname = expand_cdname(cpp, msg); rd->rp.txt_dname = expand_cdname(cpp, msg); break; case T_X25: /* X25 Address */ rd->string = expand_charstring(cpp, msg); break; case T_ISDN: /* ISDN Address */ if ( **cpp == dlen ) { rd->isdn.address = expand_charstring(cpp, msg); rd->isdn.sa = NULL; } else { rd->isdn.address = expand_charstring(cpp, msg); rd->isdn.sa = expand_charstring(cpp, msg); } break; case T_RT: /* Route Through */ rd->rt.preference = _getshort(*cpp); *cpp += sizeof(u_short); rd->rt.int_host = expand_cdname(cpp, msg); break; /* * Additional Non-standard types */ case T_UINFO: /* User (finger) info */ if ((rd->string = (char *)malloc(dlen+1)) != NULL ) { memcpy((void *)rd->string, (void *)*cpp, dlen); rd->string[dlen] = '\0'; } *cpp += dlen; break; case T_UID: /* User ID */ case T_GID: /* Group ID */ rd->number = _getlong(*cpp); *cpp += sizeof(u_long); break; case T_UNSPEC: /* Unspecified info */ default: /* Unrecognised */ if ((rd->string = (char *)malloc(dlen+1)) != NULL ) memcpy((void *)rd->string, (void *)*cpp, dlen); *cpp += dlen; break; } return(ptr); }