Back to index

courier  0.68.2
rfc1035dumprrdata.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2004 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "rfc1035.h"
00007 #include      "rfc822/encode.h"
00008 #include      <string.h>
00009 #include      <stdlib.h>
00010 #include      <sys/types.h>
00011 #include      <arpa/inet.h>
00012 #if TIME_WITH_SYS_TIME
00013 #include      <sys/time.h>
00014 #include      <time.h>
00015 #else
00016 #if HAVE_SYS_TIME_H
00017 #include      <sys/time.h>
00018 #else
00019 #include      <time.h>
00020 #endif
00021 #endif
00022 
00023 
00024 static char *dumpsoa(struct rfc1035_reply *r, struct rfc1035_rr *rr)
00025 {
00026 char   name1[RFC1035_MAXNAMESIZE+1], name2[RFC1035_MAXNAMESIZE+1];
00027 char   *p;
00028 char   timebuf[RFC1035_MAXTIMEBUFSIZE+1];
00029 
00030        rfc1035_replyhostname(r, rr->rr.soa.rname_label, name1);
00031        rfc1035_replyhostname(r, rr->rr.soa.mname_label, name2);
00032 
00033        p=(char *)malloc(strlen(name1)+strlen(name2)+500);
00034        if (!p)       return (0);
00035 
00036        strcat(strcat(strcat(strcpy(p, name2), ". "), name1), ". (\n\t\t\t\t");
00037        sprintf(p+strlen(p), "%lu ; serial\n", 
00038                      (unsigned long)rr->rr.soa.serial);
00039        sprintf(p+strlen(p), "\t\t\t\t%s  ; refresh\n", 
00040                      rfc1035_fmttime( rr->rr.soa.refresh, timebuf));
00041        sprintf(p+strlen(p), "\t\t\t\t%s  ; retry\n", 
00042                      rfc1035_fmttime( rr->rr.soa.retry, timebuf));
00043        sprintf(p+strlen(p), "\t\t\t\t%s  ; expire\n", 
00044                      rfc1035_fmttime( rr->rr.soa.expire, timebuf));
00045        sprintf(p+strlen(p), "\t\t\t\t%s) ; minimum", 
00046                      rfc1035_fmttime( rr->rr.soa.minimum, timebuf));
00047        return (p);
00048 }
00049 
00050 static void str_cat(char *p, const char **q)
00051 {
00052 int    l=(int)(unsigned char)*(*q)++;
00053 
00054        while (*p)    p++;
00055        memcpy(p, *q, l);
00056        p[l]=0;
00057        *q += l;
00058 }
00059 
00060 static char *dumptxt(struct rfc1035_reply *r, struct rfc1035_rr *rr)
00061 {
00062 int    len=1;
00063 char   *p=0;
00064 int    pass;
00065 const char *cp;
00066 
00067        for (pass=0; pass<2; pass++)
00068        {
00069               if (pass && (p=(char *)malloc(len)) == 0) return (0);
00070               if (pass)     *p=0;
00071 
00072               cp=rr->rdata;
00073               while (cp < rr->rdata+rr->rdlength)
00074               {
00075               int l=(int)(unsigned char)*cp;
00076 
00077                      if (l >= rr->rdata+rr->rdlength-cp)       return (0);
00078                      if (pass == 0)
00079                             cp += l+1;
00080                      len += l+4;
00081                      if (pass && *p)
00082                             strcat(p, "\n\t\t\t");
00083                      if (pass)
00084                             str_cat(p, &cp);
00085               }
00086        }
00087        return (p);
00088 }
00089 
00090 struct fmt_rrsig_info {
00091 
00092        char *buf;
00093        size_t n;
00094 };
00095 
00096 
00097 static void append_str(struct fmt_rrsig_info *info, const char *str, size_t l)
00098 {
00099        if (info->buf)
00100        {
00101               memcpy(info->buf, str, l);
00102 
00103               info->buf += l;
00104        }
00105 
00106        info->n += l;
00107 }
00108 
00109 static void tostr_callback(const char *str, void *vp)
00110 {
00111        append_str( (struct fmt_rrsig_info *)vp, str, strlen(str));
00112 }
00113 
00114 static void append_int32(struct fmt_rrsig_info *info, RFC1035_UINT32 val)
00115 {
00116        char bufp[30];
00117        char *q=bufp+sizeof(bufp);
00118 
00119        do
00120        {
00121               *--q = '0' + (val % 10);
00122 
00123               val /= 10;
00124        } while (val);
00125 
00126        append_str(info, q, bufp+sizeof(bufp)-q);
00127 }
00128 
00129 static void append_time_t(struct fmt_rrsig_info *info, time_t timeval)
00130 {
00131        char bufp[30];
00132        struct tm result;
00133 
00134        gmtime_r(&timeval, &result);
00135 
00136        strftime(bufp, sizeof(bufp), "%Y%m%d%H%M%S", &result);
00137 
00138        append_str(info, bufp, strlen(bufp));
00139 }
00140 
00141 static int encode_callback_func(const char *p, size_t n,
00142                             void *vp)
00143 {
00144        struct fmt_rrsig_info *info=(struct fmt_rrsig_info *)vp;
00145 
00146        while (n)
00147        {
00148               size_t i;
00149 
00150               if (*p == '\n')
00151               {
00152                      append_str(info, " ", 1);
00153                      ++p;
00154                      --n;
00155                      continue;
00156               }
00157 
00158               for (i=0; i<n; ++i)
00159                      if (p[i] == '\n')
00160                             break;
00161 
00162               append_str(info, p, i);
00163 
00164               p += i;
00165               n -= i;
00166        }
00167        return 0;
00168 
00169 }
00170 
00171 static size_t fmt_rrsig(struct rfc1035_reply *r,
00172                      struct rfc1035_rr *rr, time_t now, char *buf)
00173 {
00174        char   p[RFC1035_MAXNAMESIZE+1];
00175 
00176        char   timebuf[RFC1035_MAXTIMEBUFSIZE+1];
00177 
00178        time_t signature_inception, signature_expiration;
00179 
00180        struct libmail_encode_info lei;
00181 
00182        struct fmt_rrsig_info fri;
00183 
00184        fri.buf=buf;
00185        fri.n=0;
00186 
00187        rfc1035_type_itostr(rr->rr.rrsig.type_covered, tostr_callback, &fri);
00188 
00189        append_str(&fri, " ", 1);
00190 
00191        append_int32(&fri, rr->rr.rrsig.algorithm);
00192 
00193        append_str(&fri, " ", 1);
00194 
00195        append_int32(&fri, rr->rr.rrsig.labels);
00196 
00197        append_str(&fri, " ", 1);
00198 
00199        rfc1035_fmttime(rr->rr.rrsig.original_ttl, timebuf);
00200 
00201        append_str(&fri, timebuf, strlen(timebuf));
00202 
00203        append_str(&fri, " ", 1);
00204 
00205        if (sizeof(time_t) == 4)
00206        {
00207               signature_inception=rr->rr.rrsig.signature_inception;
00208               signature_expiration=rr->rr.rrsig.signature_expiration;
00209        }
00210        else
00211        {
00212               time_t now_epoch=(now & ~0xFFFFFFFFLL);
00213 
00214               time_t cur_epoch=now_epoch | rr->rr.rrsig.signature_inception;
00215 
00216               time_t prev_epoch=cur_epoch - 0xFFFFFFFF-1;
00217               time_t next_epoch=cur_epoch + 0xFFFFFFFF+1;
00218 
00219 
00220 #define time2diff(a,b) ((a) < (b) ? (b)-(a):(a)-(b))
00221 
00222 #define closest2now(now,time1,time2)                                  \
00223               (time2diff((now), (time1)) < time2diff((now), (time2))  \
00224                ? (time1):(time2))
00225 
00226               signature_inception =
00227                      closest2now(now, closest2now(now,
00228                                                prev_epoch,
00229                                                cur_epoch),
00230                                 next_epoch);
00231 
00232               signature_expiration =
00233                      signature_inception +
00234                      ((rr->rr.rrsig.signature_expiration -
00235                        rr->rr.rrsig.signature_inception)
00236                       & 0x7FFFFFFF);
00237        }
00238 
00239        append_time_t(&fri, signature_inception);
00240 
00241        append_str(&fri, " ", 1);
00242 
00243        append_time_t(&fri, signature_expiration);
00244 
00245        append_str(&fri, " ", 1);
00246 
00247        append_int32(&fri, rr->rr.rrsig.key_tag);
00248 
00249        append_str(&fri, " ", 1);
00250 
00251        rfc1035_replyhostname(r, rr->rr.rrsig.signer_name, p);
00252 
00253        append_str(&fri, p, strlen(p));
00254 
00255        append_str(&fri, ". ", 2);
00256 
00257        libmail_encode_start(&lei, "base64", encode_callback_func, &fri);
00258 
00259        libmail_encode(&lei, rr->rr.rrsig.signature,
00260                      rr->rr.rrsig.signature_len);
00261        libmail_encode_end(&lei);
00262 
00263        return fri.n;
00264 }
00265 
00266 char *rfc1035_dumprrdata(struct rfc1035_reply *r, struct rfc1035_rr *rr)
00267 {
00268        if (rr->rrclass != RFC1035_CLASS_IN)      return (0);
00269        switch (rr->rrtype)  {
00270        case RFC1035_TYPE_A:
00271               {
00272               char   ipbuf[RFC1035_NTOABUFSIZE];
00273 
00274                      rfc1035_ntoa_ipv4(&rr->rr.inaddr, ipbuf);
00275                      return (strdup(ipbuf));
00276               }
00277 #if    RFC1035_IPV6
00278        case RFC1035_TYPE_AAAA:
00279               {
00280               char   ipbuf[INET6_ADDRSTRLEN];
00281 
00282                      if (inet_ntop(AF_INET6, &rr->rr.in6addr,
00283                             ipbuf, sizeof(ipbuf)) == 0)
00284                             ipbuf[0]=0;
00285                      return (strdup(ipbuf));
00286               }
00287 #endif
00288        case RFC1035_TYPE_TXT:
00289               return (dumptxt(r, rr));
00290        case RFC1035_TYPE_CNAME:
00291        case RFC1035_TYPE_MB:
00292        case RFC1035_TYPE_MG:
00293        case RFC1035_TYPE_MR:
00294        case RFC1035_TYPE_MD:
00295        case RFC1035_TYPE_MF:
00296        case RFC1035_TYPE_NS:
00297        case RFC1035_TYPE_PTR:
00298               {
00299               char   p[RFC1035_MAXNAMESIZE+1], *q;
00300 
00301                      rfc1035_replyhostname(r, rr->rr.domainname, p);
00302 
00303                      if ((q=(char *)malloc(strlen(p)+2)) != 0)
00304                             strcat(strcpy(q, p), ".");
00305                      return (q);
00306               }
00307 
00308        case RFC1035_TYPE_SOA:
00309               return (dumpsoa(r, rr));
00310               break;
00311        case RFC1035_TYPE_MX:
00312 
00313               {
00314               char   p[RFC1035_MAXNAMESIZE+1], *q;
00315 
00316                      rfc1035_replyhostname(r, rr->rr.mx.mx_label, p);
00317 
00318                      if ((q=(char *)malloc(strlen(p)+40)) != 0)
00319                      {
00320                             sprintf(q, "%d %s.",
00321                                    (int)rr->rr.mx.preference, p);
00322                      }
00323                      return (q);
00324               }
00325 
00326        case RFC1035_TYPE_HINFO:
00327               {
00328               char *p=malloc( (int)(unsigned char)*rr->rr.hinfo.hinfo_str+
00329                             (int)(unsigned char)*rr->rr.hinfo.os_str+10);
00330 
00331                      if (p)
00332                      {
00333                      const char *q=rr->rr.hinfo.hinfo_str;
00334 
00335                             *p=0;
00336                             str_cat(p, &q);
00337                             strcat(p, ", ");
00338                             q=rr->rr.hinfo.os_str;
00339                             str_cat(p, &q);
00340                      }
00341                      return (p);
00342               }
00343        case RFC1035_TYPE_MINFO:
00344               {
00345               char   p[RFC1035_MAXNAMESIZE+1], t[RFC1035_MAXNAMESIZE+1], *q;
00346 
00347                      rfc1035_replyhostname(r, rr->rr.minfo.rmailbx_label, p);
00348                      rfc1035_replyhostname(r, rr->rr.minfo.emailbx_label, t);
00349 
00350                      if ((q=(char *)malloc(strlen(p)+strlen(t)+4)) == 0)
00351                             return (0);
00352                      strcat(strcat(strcat(strcpy(q, p), ". "), t), ".");
00353                      return (q);
00354               }
00355 
00356        case RFC1035_TYPE_RRSIG:
00357               {
00358                      time_t now=time(NULL);
00359 
00360                      size_t n=fmt_rrsig(r, rr, now, NULL);
00361                      char *p;
00362 
00363                      if ((p=malloc(n+1)) == 0)
00364                             return (0);
00365 
00366                      fmt_rrsig(r, rr, now, p);
00367 
00368                      p[n]=0;
00369                      return p;
00370               }
00371        }
00372        return (0);
00373 }