Back to index

courier  0.68.2
rfc1035qptr.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2011 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "rfc1035.h"
00007 #include      <string.h>
00008 #include      <errno.h>
00009 
00010 
00011 static int ptr(struct rfc1035_res *, const void *, int,
00012               void (*)(const char *, void *),
00013               void *);
00014 
00015 static void save_name(const char *name, void *void_arg)
00016 {
00017        strcpy((char *)void_arg, name);
00018 }
00019 
00020 int rfc1035_ptr(struct rfc1035_res *res, const RFC1035_ADDR *addr,
00021                 char *name)
00022 {
00023        return rfc1035_ptr_x(res, addr, save_name, name);
00024 }
00025 
00026 /* Convenient function to do reverse IP lookup */
00027 #if    RFC1035_IPV6
00028 
00029 int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *addr,
00030                 void (*cb_func)(const char *, void *),
00031                 void *cb_arg)
00032 {
00033 struct in_addr       in4;
00034 
00035        if (IN6_IS_ADDR_V4MAPPED(addr))
00036        {
00037               rfc1035_ipv6to4(&in4, addr);
00038               if (ptr(res, &in4, AF_INET, cb_func, cb_arg) == 0) return (0);
00039               return (-1);
00040        }
00041        return (ptr(res, addr, AF_INET6, cb_func,cb_arg));
00042 }
00043 
00044 #else
00045 int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *a,
00046                 void (*cb_func)(const char *, void *),
00047                 void *cb_arg)
00048 {
00049        return (ptr(res, a, AF_INET, cb_func, cb_arg));
00050 }
00051 #endif
00052 
00053 static int ptr(struct rfc1035_res *res, const void *addr, int af,
00054               void (*cb_func)(const char *, void *),
00055               void *cb_arg)
00056 {
00057 struct rfc1035_reply *reply;
00058 int    n;
00059 char   name[256], ptrbuf[256];
00060 
00061 #if    RFC1035_IPV6
00062 
00063        if (af == AF_INET6)
00064        {
00065        const char *sin6=(const char *)addr;
00066        unsigned i;
00067 
00068               *name=0;
00069               for (i=sizeof(struct in6_addr); i; )
00070               {
00071               char   buf[10];
00072 
00073                      --i;
00074                      sprintf(buf, "%x.%x.",
00075                             (int)(unsigned char)(sin6[i] & 0x0F),
00076                             (int)(unsigned char)((sin6[i] >> 4) & 0x0F));
00077                      strcat(name, buf);
00078               }
00079               strcat(name, "ip6.arpa");
00080        }
00081        else
00082 #endif
00083        if (af != AF_INET)
00084        {
00085               errno=ENOENT;
00086               return (-1); /* hard error */
00087        }
00088        else
00089        {
00090        const char *p;
00091        unsigned char a=0,b=0,c=0,d=0;
00092        struct in_addr       ia;
00093 
00094               memcpy(&ia, addr, sizeof(ia));
00095               rfc1035_ntoa_ipv4(&ia, name);
00096               p=name;
00097 
00098               while (*p >= '0' && *p <= '9')
00099                      a= (int)a * 10 + (*p++ - '0');
00100               if (*p)       p++;
00101               while (*p >= '0' && *p <= '9')
00102                      b= (int)b * 10 + (*p++ - '0');
00103               if (*p)       p++;
00104               while (*p >= '0' && *p <= '9')
00105                      c= (int)c * 10 + (*p++ - '0');
00106               if (*p)       p++;
00107               while (*p >= '0' && *p <= '9')
00108                      d= (int)d * 10 + (*p++ - '0');
00109 
00110               sprintf(name, "%d.%d.%d.%d.in-addr.arpa",
00111                      (int)d, (int)c, (int)b, (int)a);
00112        }
00113 
00114        if (rfc1035_resolve_cname(res, name,
00115               RFC1035_TYPE_PTR, RFC1035_CLASS_IN, &reply, 0) < 0 ||
00116               reply == 0 ||
00117               (n=rfc1035_replysearch_an( res, reply, name, RFC1035_TYPE_PTR,
00118                      RFC1035_CLASS_IN, 0)) < 0 ||
00119               rfc1035_replyhostname(reply, reply->allrrs[n]->rr.domainname,
00120                      ptrbuf) == 0)
00121        {
00122               if (reply && reply->rcode != RFC1035_RCODE_NXDOMAIN &&
00123                      reply->rcode != RFC1035_RCODE_NOERROR)
00124               {
00125                      rfc1035_replyfree(reply);
00126                      errno=EAGAIN;
00127                      return (-1);
00128               }
00129 
00130               if (reply) rfc1035_replyfree(reply);
00131               errno=ENOENT;
00132               return (-1); /* hard error */
00133        }
00134 
00135        (*cb_func)(ptrbuf, cb_arg);
00136 
00137        while ((n=rfc1035_replysearch_an(res, reply, name,
00138                                     RFC1035_TYPE_PTR,
00139                                     RFC1035_CLASS_IN, n+1)) >= 0)
00140        {
00141               if (rfc1035_replyhostname(reply,
00142                                      reply->allrrs[n]->rr.domainname,
00143                                      ptrbuf))
00144                      (*cb_func)(ptrbuf, cb_arg);
00145        }
00146 
00147        rfc1035_replyfree(reply);
00148        return (0);
00149 }