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

📄 loc.c

📁 bind 源码 最新实现 linux/unix/windows平台
💻 C
字号:
#include "loc.h"/* $Id: loc.c,v 1.1.2.1 2005/04/01 06:13:59 marka Exp $ *//* Global variables */short rr_errno;/*   Prints the actual usage */voidusage (){  (void) fprintf (stderr,		  "Usage: %s: [-v] [-d nnn] hostname\n", progname);  exit (2);}/*   Panics */voidpanic (message)     char *message;{  (void) fprintf (stderr,		  "%s: %s\n", progname, message);  exit (2);}/*   ** IN_ADDR_ARPA -- Convert dotted quad string to reverse in-addr.arpa   ** ------------------------------------------------------------------   **   **   Returns:   **           Pointer to appropriate reverse in-addr.arpa name   **           with trailing dot to force absolute domain name.   **           NULL in case of invalid dotted quad input string. */#ifndef ARPA_ROOT#define ARPA_ROOT "in-addr.arpa"#endifchar *in_addr_arpa (dottedquad)     char *dottedquad;		/* input string with dotted quad */{  static char addrbuf[4 * 4 + sizeof (ARPA_ROOT) + 2];  unsigned int a[4];  register int n;  n = sscanf (dottedquad, "%u.%u.%u.%u", &a[0], &a[1], &a[2], &a[3]);  switch (n)    {    case 4:      (void) sprintf (addrbuf, "%u.%u.%u.%u.%s.",	     a[3] & 0xff, a[2] & 0xff, a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);      break;    case 3:      (void) sprintf (addrbuf, "%u.%u.%u.%s.",		      a[2] & 0xff, a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);      break;    case 2:      (void) sprintf (addrbuf, "%u.%u.%s.",		      a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);      break;    case 1:      (void) sprintf (addrbuf, "%u.%s.",		      a[0] & 0xff, ARPA_ROOT);      break;    default:      return (NULL);    }  while (--n >= 0)    if (a[n] > 255)      return (NULL);  return (addrbuf);}/*    Returns a human-readable version of the LOC information or   NULL if it failed. Argument is a name (of a network or a machine)   and a boolean telling is it is a network name or a machine name. */char *getlocbyname (name, is_network)     const char *name;     short is_network;{  char *result;  struct list_in_addr *list, *p;  result = findRR (name, T_LOC);  if (result != NULL)    {      if (debug >= 2)	printf ("LOC record found for the name %s\n", name);      return result;    }  else    {      if (!is_network)	{	  list = findA (name);	  if (debug >= 2)	    printf ("No LOC record found for the name %s, trying addresses\n", name);	  if (list != NULL)	    {	      for (p = list; p != NULL; p = p->next)		{		  if (debug >= 2)		    printf ("Trying address %s\n", inet_ntoa (p->addr));		  result = getlocbyaddr (p->addr, NULL);		  if (result != NULL)		    return result;		}	      return NULL;	    }	  else	    {	      if (debug >= 2)		printf ("   No A record found for %s\n", name);	      return NULL;	    }	}      else	{	  if (debug >= 2)	    printf ("No LOC record found for the network name %s\n", name);	  return NULL;	}    }}/*    Returns a human-readable version of the LOC information or   NULL if it failed. Argument is an IP address. */char *getlocbyaddr (addr, mask)     const struct in_addr addr;     const struct in_addr *mask;{  struct in_addr netaddr;  u_int32_t a;  struct in_addr themask;  char *text_addr, *text_mask;  if (mask == NULL)    {      themask.s_addr = (u_int32_t) 0;    }  else    {      themask = *mask;    }  text_addr = (char *) malloc (256);  text_mask = (char *) malloc (256);  strcpy (text_addr, inet_ntoa (addr));  strcpy (text_mask, inet_ntoa (themask));  if (debug >= 2)    printf ("Testing address %s/%s\n", text_addr, text_mask);  if (mask == NULL)    {      a = ntohl (addr.s_addr);      if (IN_CLASSA (a))	{	  netaddr.s_addr = htonl (a & IN_CLASSA_NET);	}      else if (IN_CLASSB (a))	{	  netaddr.s_addr = htonl (a & IN_CLASSB_NET);	}      else if (IN_CLASSC (a))	{	  netaddr.s_addr = htonl (a & IN_CLASSC_NET);	}      else	{	  /* Error */	}      return getlocbynet (in_addr_arpa (inet_ntoa (netaddr)), addr, mask);    }  else    {      netaddr.s_addr = addr.s_addr & themask.s_addr;      return getlocbynet (in_addr_arpa (inet_ntoa (netaddr)), addr, mask);    }}/*    Returns a human-readable LOC.   Argument is a network name in the 0.z.y.x.in-addr.arpa format   and the original address */char *getlocbynet (name, addr, mask)     char *name;     struct in_addr addr;     struct in_addr *mask;{  char *network;  char *result, *result_int;  struct list_in_addr *list;  if (debug >= 2)    printf ("Testing network %s\n", name);  network = findRR (name, T_PTR);  if (network == NULL)    {      if (debug >= 2)	printf ("No name for network %s\n", name);      return NULL;    }  else    {      result = getlocbyname (network, TRUE);      list = findA (network);      if (list == NULL)	{	  return result;	}      else if ((mask != NULL) &&	       ((mask->s_addr) == (list->addr.s_addr)))	{	  /* Already checked */	  return result;	}      else	{	  result_int = getlocbyaddr (addr, &list->addr);	  if (result_int == NULL)	    return result;	  else	    return result_int;	}    }}/*    The code for these two functions is stolen from the examples in Liu and Albitz   book "DNS and BIND" (O'Reilly). *//**************************************************************** * skipName -- This routine skips over a domain name.  If the   * *     domain name expansion fails, it crashes.                 * *     dn_skipname() is probably not on your manual             * *     page; it is similar to dn_expand() except that it just   * *     skips over the name.  dn_skipname() is in res_comp.c if  * *     you need to find it.                                     * ****************************************************************/intskipName (cp, endOfMsg)     u_char *cp;     u_char *endOfMsg;{  int n;  if ((n = dn_skipname (cp, endOfMsg)) < 0)    {      panic ("dn_skipname failed\n");    }  return (n);}/**************************************************************** * skipToData -- This routine advances the cp pointer to the    * *     start of the resource record data portion.  On the way,  * *     it fills in the type, class, ttl, and data length        * ****************************************************************/intskipToData (cp, type, class, ttl, dlen, endOfMsg)     u_char *cp;     u_short *type;     u_short *class;     u_int32_t *ttl;     u_short *dlen;     u_char *endOfMsg;{  u_char *tmp_cp = cp;		/* temporary version of cp */  /* Skip the domain name; it matches the name we looked up */  tmp_cp += skipName (tmp_cp, endOfMsg);  /*   * Grab the type, class, and ttl.  GETSHORT and GETLONG   * are macros defined in arpa/nameser.h.   */  GETSHORT (*type, tmp_cp);  GETSHORT (*class, tmp_cp);  GETLONG (*ttl, tmp_cp);  GETSHORT (*dlen, tmp_cp);  return (tmp_cp - cp);}/*    Returns a human-readable version of a DNS RR (resource record)   associated with the name 'domain'.   If it does not find, ir returns NULL and sets rr_errno to explain why.   The code for this function is stolen from the examples in Liu and Albitz   book "DNS and BIND" (O'Reilly). */char *findRR (domain, requested_type)     char *domain;     int requested_type;{  char *result, *message;  union    {      HEADER hdr;		/* defined in resolv.h */      u_char buf[PACKETSZ];	/* defined in arpa/nameser.h */    }  response;			/* response buffers */short found = 0;  int responseLen;		/* buffer length */  u_char *cp;			/* character pointer to parse DNS packet */  u_char *endOfMsg;		/* need to know the end of the message */  u_short class;		/* classes defined in arpa/nameser.h */  u_short type;			/* types defined in arpa/nameser.h */  u_int32_t ttl;		/* resource record time to live */  u_short dlen;			/* size of resource record data */  int i, count, dup;		/* misc variables */  char *ptrList[1];  int ptrNum = 0;  struct in_addr addr;  result = (char *) malloc (256);  message = (char *) malloc (256);  /*    * Look up the records for the given domain name.   * We expect the domain to be a fully qualified name, so   * we use res_query().  If we wanted the resolver search    * algorithm, we would have used res_search() instead.   */  if ((responseLen =       res_query (domain,	/* the domain we care about   */		  C_IN,		/* Internet class records     */		  requested_type,	/* Look up name server records */		  (u_char *) & response,	/*response buffer */		  sizeof (response)))	/*buffer size    */      < 0)    {				/*If negative    */      rr_errno = h_errno;      return NULL;    }  /*   * Keep track of the end of the message so we don't    * pass it while parsing the response.  responseLen is    * the value returned by res_query.   */  endOfMsg = response.buf + responseLen;  /*   * Set a pointer to the start of the question section,    * which begins immediately AFTER the header.   */  cp = response.buf + sizeof (HEADER);  /*   * Skip over the whole question section.  The question    * section is comprised of a name, a type, and a class.     * QFIXEDSZ (defined in arpa/nameser.h) is the size of    * the type and class portions, which is fixed.  Therefore,    * we can skip the question section by skipping the    * name (at the beginning) and then advancing QFIXEDSZ.   * After this calculation, cp points to the start of the    * answer section, which is a list of NS records.   */  cp += skipName (cp, endOfMsg) + QFIXEDSZ;  count = ntohs (response.hdr.ancount) +    ntohs (response.hdr.nscount);  while ((--count >= 0)		/* still more records     */	 && (cp < endOfMsg))    {				/* still inside the packet */      /* Skip to the data portion of the resource record */      cp += skipToData (cp, &type, &class, &ttl, &dlen, endOfMsg);      if (type == requested_type)	{	  switch (requested_type)	    {	    case (T_LOC):	      loc_ntoa (cp, result);	      return result;	      break;	    case (T_PTR):	      ptrList[ptrNum] = (char *) malloc (MAXDNAME);	      if (ptrList[ptrNum] == NULL)		{		  panic ("Malloc failed");		}	      if (dn_expand (response.buf,	/* Start of the packet   */			     endOfMsg,	/* End of the packet     */			     cp,	/* Position in the packet */			     (u_char *) ptrList[ptrNum],	/* Result    */			     MAXDNAME)	/* size of ptrList buffer */		  < 0)		{		/* Negative: error    */		  panic ("dn_expand failed");		}	      /*	       * Check the name we've just unpacked and add it to 	       * the list if it is not a duplicate.	       * If it is a duplicate, just ignore it.	       */	      for (i = 0, dup = 0; (i < ptrNum) && !dup; i++)		dup = !strcasecmp (ptrList[i], ptrList[ptrNum]);	      if (dup)		free (ptrList[ptrNum]);	      else		ptrNum++;	      strcpy (result, ptrList[0]);	      return result;	      break;	    case (T_A):	      bcopy ((char *) cp, (char *) &addr, INADDRSZ);	      strcat (result, " ");	      strcat (result, inet_ntoa (addr));	      found = 1;	      break;	    default:	      sprintf (message, "Unexpected type %u", requested_type);	      panic (message);	    }	}      /* Advance the pointer over the resource record data */      cp += dlen;    }				/* end of while */  if (found)   return result;elsereturn NULL;}struct list_in_addr *findA (domain)     char *domain;{  struct list_in_addr *result, *end;  union    {      HEADER hdr;		/* defined in resolv.h */      u_char buf[PACKETSZ];	/* defined in arpa/nameser.h */    }  response;			/* response buffers */  int responseLen;		/* buffer length */  u_char *cp;			/* character pointer to parse DNS packet */  u_char *endOfMsg;		/* need to know the end of the message */  u_short class;		/* classes defined in arpa/nameser.h */  u_short type;			/* types defined in arpa/nameser.h */  u_int32_t ttl;		/* resource record time to live */  u_short dlen;			/* size of resource record data */  int count;			/* misc variables */  struct in_addr addr;  end = NULL;  result = NULL;  /*    * Look up the records for the given domain name.   * We expect the domain to be a fully qualified name, so   * we use res_query().  If we wanted the resolver search    * algorithm, we would have used res_search() instead.   */  if ((responseLen =       res_query (domain,	/* the domain we care about   */		  C_IN,		/* Internet class records     */		  T_A,		  (u_char *) & response,	/*response buffer */		  sizeof (response)))	/*buffer size    */      < 0)    {				/*If negative    */      rr_errno = h_errno;      return NULL;    }  /*   * Keep track of the end of the message so we don't    * pass it while parsing the response.  responseLen is    * the value returned by res_query.   */  endOfMsg = response.buf + responseLen;  /*   * Set a pointer to the start of the question section,    * which begins immediately AFTER the header.   */  cp = response.buf + sizeof (HEADER);  /*   * Skip over the whole question section.  The question    * section is comprised of a name, a type, and a class.     * QFIXEDSZ (defined in arpa/nameser.h) is the size of    * the type and class portions, which is fixed.  Therefore,    * we can skip the question section by skipping the    * name (at the beginning) and then advancing QFIXEDSZ.   * After this calculation, cp points to the start of the    * answer section, which is a list of NS records.   */  cp += skipName (cp, endOfMsg) + QFIXEDSZ;  count = ntohs (response.hdr.ancount) +    ntohs (response.hdr.nscount);  while ((--count >= 0)		/* still more records     */	 && (cp < endOfMsg))    {				/* still inside the packet */      /* Skip to the data portion of the resource record */      cp += skipToData (cp, &type, &class, &ttl, &dlen, endOfMsg);      if (type == T_A)	{	  bcopy ((char *) cp, (char *) &addr, INADDRSZ);	  if (end == NULL)	    {	      result = (void *) malloc (sizeof (struct list_in_addr));	      result->addr = addr;	      result->next = NULL;	      end = result;	    }	  else	    {	      end->next = (void *) malloc (sizeof (struct list_in_addr));	      end = end->next;	      end->addr = addr;	      end->next = NULL;	    }	}      /* Advance the pointer over the resource record data */      cp += dlen;    }				/* end of while */  return result;}

⌨️ 快捷键说明

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