⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32_resolv.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 1983, 1989, 1993
 *    The Regents of the University of California.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Copyright (c) 1996,1999 by Internet Software Consortium.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */



#include <w32api/windows.h>
#include <w32api/iphlpapi.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <stdlib.h>
#include <sys/unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "win32_resolv.h"


// misc definitions
#define BUF_SIZE 8096
#define DNS_PORT 53
#define UDP_PROTO 17
#define TCP_PROTO 6

// internal error codes
#define RESP_TRYTCP -1
#define RESP_TRYNEXTSERVER -2
#define RESP_UNKNOWNHOST -3


// Possible opcodes for query
#define OPCODE_QUERY 0
#define OPCODE_IQUERY 1
#define OPCODE_STATUS 2



/**
 * Perform a DNS lookup using UDP
 *
 * @param dnsServer DNS Server to look up
 * @param sendPktBuf Buffer containing the packet to send
 * @param sendPktSize Size of the packet to send
 * @param recvPktBuf Buffer to put received packet in
 * @param recvPktSize Size of the recvPktBuf buffer
 * @param expectedId Id counter to identify response packets
 * @return Received buffer size, or <0 on failure
 */
int dnsUdp(struct in_addr dnsServer, 
           char* sendPktBuf, int sendPktSize,
           char* recvPktBuf, int recvPktSize,
           int* expectedId);

/**
 * Perform a DNS lookup using TCP
 *
 * @param dnsServer DNS Server to look up
 * @param sendPktBuf Buffer containing the packet to send
 * @param sendPktSize Size of the packet to send
 * @param recvPktBuf Buffer to put received packet in
 * @param recvPktSize Size of the recvPktBuf buffer
 * @param expectedId Id counter to identify response packets
 * @return Received buffer size, or <0 on failure
 */
int dnsTcp(struct in_addr dnsServer, 
           char* sendPktBuf, int sendPktSize,
           char* recvPktBuf, int recvPktSize,
           int* expectedId);


/**
 * Format a DNS query packet. Id will be set to 0
 *
 * @param dstBuf Where to put the packet
 * @param bufSize Size of the above
 * @param name Name of service to look up
 * @param domain Domain To look it up in
 * @param qClass Class of query
 * @param qType Type of query
 * @return Packet size on success, <0 on failure
 */
int formatPacket(char* dstBuf, int bufSize,
                 const char* name, const char* domain,
                 u_int16_t qClass, u_int16_t qType);


/**
 * Retrieve list of DNS servers known to the machine
 *
 * @param list Updated to point to a buffer of ULONGs. This will be malloced, 
 * so it is up to you to free it when finished. They are already in network 
 * order. Will be NULL terminated.
 * @return 0 on success, nonzero error code on failure
 */
int getDnsServers(struct in_addr** list);

/*
 * ns_name_unpack(msg, eom, src, dst, dstsiz)
 *      Unpack a domain name from a message, source may be compressed.
 * return:
 *      -1 if it fails, or consumed octets if it succeeds.
 */
int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
                   u_char *dst, size_t dstsiz);

/*
 * ns_name_uncompress(msg, eom, src, dst, dstsiz)
 *      Expand compressed domain name to presentation format.
 * return:
 *      Number of bytes read out of `src', or -1 (with errno set).
 * note:
 *      Root domain returns as "." not "".
 */
int ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
                       char *dst, size_t dstsiz);

/*
 * ns_name_ntop(src, dst, dstsiz)
 *      Convert an encoded domain name to printable ascii as per RFC1035.
 * return:
 *      Number of bytes written to buffer, or -1 (with errno set)
 * notes:
 *      The root is returned as "."
 *      All other domains are returned in non absolute form
 */
int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz);


/*
 * Expand compressed domain name 'comp_dn' to full domain name.
 * 'msg' is a pointer to the begining of the message,
 * 'eomorig' points to the first location after the message,
 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
 * Return size of compressed name or -1 if there was an error.
 */
int dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
              char *dst, int dstsiz);

/*
 * special(ch)
 *      Thinking in noninternationalized USASCII (per the DNS spec),
 *      is this characted special ("in need of quoting") ?
 * return:
 *      boolean.
 */
static int special(int ch);

/*
 * printable(ch)
 *      Thinking in noninternationalized USASCII (per the DNS spec),
 *      is this character visible and not a space when printed ?
 * return:
 *      boolean.
 */
static int printable(int ch);


// list of digits
static const char       digits[] = "0123456789";






/**
 * Retrieve list of DNS servers known to the machine
 *
 * @param list Updated to point to a buffer of ULONGs. This will be malloced, 
 * so it is up to you to free it when finished. They are already in network 
 * order. Will be NULL terminated.
 * @return 0 on success, nonzero error code on failure
 */
int getDnsServers(struct in_addr** list) {
  int err;
  int count;
  ULONG fixedInfoSize;
  PFIXED_INFO fixedInfo;
  PIP_ADDR_STRING addrStr;
  
  // get size of FIXED_INFO structure
  if (!(err = GetNetworkParams(NULL, &fixedInfoSize))) {
    if (err != ERROR_BUFFER_OVERFLOW) {
      return err;
    }
  }
  
  // alloc memory
  if (!(fixedInfo = malloc(fixedInfoSize))) {
    return -ENOMEM;
  }
  
  // Get the network params
  if (!(err = GetNetworkParams(fixedInfo, &fixedInfoSize))) {
    // First of all, count the number of servers
    count = 1;
    addrStr = fixedInfo->DnsServerList.Next;
    while(addrStr) {
      count++;
      addrStr = addrStr->Next;
    }

    // I know this cannot happen, but just in case someone changes the above
    if (count == 0) {
      *list = NULL;
      return 0;
    }

    // Allocate memory to store 'em in
    if (!(*list = (struct in_addr*) malloc(sizeof(struct in_addr) * count+1))) {
      return -ENOMEM;
    }
    
    // Now, copy 'em into the list
    count = 0;
    (*list)[count++].s_addr = 
      inet_addr(fixedInfo->DnsServerList.IpAddress.String);
    addrStr = fixedInfo->DnsServerList.Next;
    while(addrStr) {
      (*list)[count++].s_addr = inet_addr(addrStr->IpAddress.String);
      addrStr = addrStr->Next;
    }
    (*list)[count].s_addr = 0;
  } else {
    free(fixedInfo);
    return err;
  }
  
  // OK!
  free(fixedInfo);
  return 0;
}

/**
 * Format a DNS query packet. Id will be set to 0
 *
 * @param dstBuf Where to put the packet
 * @param bufSize Size of the above
 * @param name Name of service to look up
 * @param domain Domain To look it up in
 * @param qClass Class of query
 * @param qType Type of query
 * @return Packet size on success, <0 on failure
 */
int formatPacket(char* dstBuf, int bufSize,
                 const char* name, const char* domain,
                 u_int16_t qClass, u_int16_t qType) {
  int offset;
  int lastCountOffset;
  HEADER* headerSection;
  char tmpName[NS_MAXDNAME+10];



  // slap the two names together correctly
  if ((name == NULL) && (domain == NULL)) {
    return -1;
  }
  if ((name != NULL) && (domain == NULL)) {
    return -1;
  }
  if (name != NULL) {
    strcpy(tmpName, name);
  }
  if (tmpName[strlen(tmpName)-1] != '.') {
    strcat(tmpName, ".");
  }
  strcat(tmpName, domain);

  // check if buffer is big enough
  if ((sizeof(HEADER) + strlen(tmpName) + 4) > bufSize) {
    return -ENOMEM;
  }

  // zero the buffer
  memset(dstBuf, 0, bufSize);

  // make up DNS header section
  headerSection = (HEADER*) dstBuf;
  headerSection->id = htons(0);
  headerSection->rd = 1;
  headerSection->qdcount = htons(1); // One single query present

  // Fill out the question section
  offset = sizeof(HEADER);

  // We're now doing the name to look up, separated by NULLs
  lastCountOffset = offset;
  offset++; // Keep one byte free for count of first component of name
  strcpy(dstBuf + offset, tmpName);

  // Now, loop through the string we've just copied converting '.' to NULL
  while(dstBuf[offset]) {
    // If we've hit a '.', update the PREVIOUS 
    // counter to the size of the bit BEFORE the '.'
    if (dstBuf[offset] == '.') {
      dstBuf[lastCountOffset] = offset - lastCountOffset -1;
      lastCountOffset = offset;
      dstBuf[offset] = 0;
    }
    
    // next char
    offset++;
  }

  // Finally, need to update the count for the bit betweent the last 
  // dot and the end of string. Note: If the last character is a '.', it will 
  // already have been turned into a NULL

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -