libaddns/dnsmarshall.c

説明を見る。
00001 /*
00002   Linux DNS client library implementation
00003   Copyright (C) 2006 Gerald Carter <jerry@samba.org>
00004 
00005      ** NOTE! The following LGPL license applies to the libaddns
00006      ** library. This does NOT imply that all of Samba is released
00007      ** under the LGPL
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Lesser General Public
00011   License as published by the Free Software Foundation; either
00012   version 2.1 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Lesser General Public License for more details.
00018 
00019   You should have received a copy of the GNU Lesser General Public
00020   License along with this library; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
00022   02110-1301  USA
00023 */
00024 
00025 #include "dns.h"
00026 #include "assert.h"
00027 
00028 struct dns_buffer *dns_create_buffer(TALLOC_CTX *mem_ctx)
00029 {
00030         struct dns_buffer *result;
00031 
00032         if (!(result = talloc(mem_ctx, struct dns_buffer))) {
00033                 return NULL;
00034         }
00035 
00036         result->offset = 0;
00037         result->error = ERROR_DNS_SUCCESS;
00038         
00039         /*
00040          * Small inital size to excercise the realloc code
00041          */
00042         result->size = 2;
00043 
00044         if (!(result->data = TALLOC_ARRAY(result, uint8, result->size))) {
00045                 TALLOC_FREE(result);
00046                 return NULL;
00047         }
00048 
00049         return result;
00050 }
00051 
00052 void dns_marshall_buffer(struct dns_buffer *buf, const uint8 *data,
00053                          size_t len)
00054 {
00055         if (!ERR_DNS_IS_OK(buf->error)) return;
00056 
00057         if (buf->offset + len < buf->offset) {
00058                 /*
00059                  * Wraparound!
00060                  */
00061                 buf->error = ERROR_DNS_INVALID_PARAMETER;
00062                 return;
00063         }
00064 
00065         if ((buf->offset + len) > 0xffff) {
00066                 /*
00067                  * Only 64k possible
00068                  */
00069                 buf->error = ERROR_DNS_INVALID_PARAMETER;
00070                 return;
00071         }
00072                 
00073         if (buf->offset + len > buf->size) {
00074                 size_t new_size = buf->offset + len;
00075                 uint8 *new_data;
00076 
00077                 /*
00078                  * Don't do too many reallocs, round up to some multiple
00079                  */
00080 
00081                 new_size += (64 - (new_size % 64));
00082 
00083                 if (!(new_data = TALLOC_REALLOC_ARRAY(buf, buf->data, uint8,
00084                                                       new_size))) {
00085                         buf->error = ERROR_DNS_NO_MEMORY;
00086                         return;
00087                 }
00088 
00089                 buf->size = new_size;
00090                 buf->data = new_data;
00091         }
00092 
00093         memcpy(buf->data + buf->offset, data, len);
00094         buf->offset += len;
00095         return;
00096 }
00097 
00098 void dns_marshall_uint16(struct dns_buffer *buf, uint16 val)
00099 {
00100         uint16 n_val = htons(val);
00101         dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
00102 }
00103 
00104 void dns_marshall_uint32(struct dns_buffer *buf, uint32 val)
00105 {
00106         uint32 n_val = htonl(val);
00107         dns_marshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
00108 }
00109 
00110 void dns_unmarshall_buffer(struct dns_buffer *buf, uint8 *data,
00111                            size_t len)
00112 {
00113         if (!(ERR_DNS_IS_OK(buf->error))) return;
00114 
00115         if ((len > buf->size) || (buf->offset + len > buf->size)) {
00116                 buf->error = ERROR_DNS_INVALID_MESSAGE;
00117                 return;
00118         }
00119 
00120         memcpy((void *)data, (const void *)(buf->data + buf->offset), len);
00121         buf->offset += len;
00122 
00123         return;
00124 }
00125 
00126 void dns_unmarshall_uint16(struct dns_buffer *buf, uint16 *val)
00127 {
00128         uint16 n_val;
00129 
00130         dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
00131         if (!(ERR_DNS_IS_OK(buf->error))) return;
00132 
00133         *val = ntohs(n_val);
00134 }
00135 
00136 void dns_unmarshall_uint32(struct dns_buffer *buf, uint32 *val)
00137 {
00138         uint32 n_val;
00139 
00140         dns_unmarshall_buffer(buf, (uint8 *)&n_val, sizeof(n_val));
00141         if (!(ERR_DNS_IS_OK(buf->error))) return;
00142 
00143         *val = ntohl(n_val);
00144 }
00145 
00146 void dns_marshall_domain_name(struct dns_buffer *buf,
00147                               const struct dns_domain_name *name)
00148 {
00149         struct dns_domain_label *label;
00150         char end_char = '\0';
00151 
00152         /*
00153          * TODO: Implement DNS compression
00154          */
00155 
00156         for (label = name->pLabelList; label != NULL; label = label->next) {
00157                 uint8 len = label->len;
00158 
00159                 dns_marshall_buffer(buf, (uint8 *)&len, sizeof(len));
00160                 if (!ERR_DNS_IS_OK(buf->error)) return;
00161 
00162                 dns_marshall_buffer(buf, (uint8 *)label->label, len);
00163                 if (!ERR_DNS_IS_OK(buf->error)) return;
00164         }
00165 
00166         dns_marshall_buffer(buf, (uint8 *)&end_char, 1);
00167 }
00168 
00169 static void dns_unmarshall_label(TALLOC_CTX *mem_ctx,
00170                                  int level,
00171                                  struct dns_buffer *buf,
00172                                  struct dns_domain_label **plabel)
00173 {
00174         struct dns_domain_label *label;
00175         uint8 len;
00176 
00177         if (!ERR_DNS_IS_OK(buf->error)) return;
00178 
00179         if (level > 128) {
00180                 /*
00181                  * Protect against recursion
00182                  */
00183                 buf->error = ERROR_DNS_INVALID_MESSAGE;
00184                 return;
00185         }
00186 
00187         dns_unmarshall_buffer(buf, &len, sizeof(len));
00188         if (!ERR_DNS_IS_OK(buf->error)) return;
00189 
00190         if (len == 0) {
00191                 *plabel = NULL;
00192                 return;
00193         }
00194 
00195         if ((len & 0xc0) == 0xc0) {
00196                 /*
00197                  * We've got a compressed name. Build up a new "fake" buffer
00198                  * and using the calculated offset.
00199                  */
00200                 struct dns_buffer new_buf;
00201                 uint8 low;
00202 
00203                 dns_unmarshall_buffer(buf, &low, sizeof(low));
00204                 if (!ERR_DNS_IS_OK(buf->error)) return;
00205 
00206                 new_buf = *buf;
00207                 new_buf.offset = len & 0x3f;
00208                 new_buf.offset <<= 8;
00209                 new_buf.offset |= low;
00210 
00211                 dns_unmarshall_label(mem_ctx, level+1, &new_buf, plabel);
00212                 buf->error = new_buf.error;
00213                 return;
00214         }
00215 
00216         if ((len & 0xc0) != 0) {
00217                 buf->error = ERROR_DNS_INVALID_NAME;
00218                 return;
00219         }
00220 
00221         if (!(label = talloc(mem_ctx, struct dns_domain_label))) {
00222                 buf->error = ERROR_DNS_NO_MEMORY;
00223                 return;
00224         }
00225 
00226         label->len = len;
00227 
00228         if (!(label->label = TALLOC_ARRAY(label, char, len+1))) {
00229                 buf->error = ERROR_DNS_NO_MEMORY;
00230                 goto error;
00231         }
00232 
00233         dns_unmarshall_buffer(buf, (uint8 *)label->label, len);
00234         if (!ERR_DNS_IS_OK(buf->error)) goto error;
00235 
00236         dns_unmarshall_label(label, level+1, buf, &label->next);
00237         if (!ERR_DNS_IS_OK(buf->error)) goto error;
00238 
00239         *plabel = label;
00240         return;
00241 
00242  error:
00243         TALLOC_FREE(label);
00244         return;
00245 }
00246 
00247 void dns_unmarshall_domain_name(TALLOC_CTX *mem_ctx,
00248                                 struct dns_buffer *buf,
00249                                 struct dns_domain_name **pname)
00250 {
00251         struct dns_domain_name *name;
00252 
00253         if (!ERR_DNS_IS_OK(buf->error)) return;
00254 
00255         if (!(name = talloc(mem_ctx, struct dns_domain_name))) {
00256                 buf->error = ERROR_DNS_NO_MEMORY;
00257         }
00258 
00259         dns_unmarshall_label(name, 0, buf, &name->pLabelList);
00260 
00261         if (!ERR_DNS_IS_OK(buf->error)) {
00262                 return;
00263         }
00264 
00265         *pname = name;
00266         return;
00267 }
00268 
00269 static void dns_marshall_question(struct dns_buffer *buf,
00270                                   const struct dns_question *q)
00271 {
00272         dns_marshall_domain_name(buf, q->name);
00273         dns_marshall_uint16(buf, q->q_type);
00274         dns_marshall_uint16(buf, q->q_class);
00275 }
00276 
00277 static void dns_unmarshall_question(TALLOC_CTX *mem_ctx,
00278                                     struct dns_buffer *buf,
00279                                     struct dns_question **pq)
00280 {
00281         struct dns_question *q;
00282 
00283         if (!(ERR_DNS_IS_OK(buf->error))) return;
00284 
00285         if (!(q = talloc(mem_ctx, struct dns_question))) {
00286                 buf->error = ERROR_DNS_NO_MEMORY;
00287                 return;
00288         }
00289 
00290         dns_unmarshall_domain_name(q, buf, &q->name);
00291         dns_unmarshall_uint16(buf, &q->q_type);
00292         dns_unmarshall_uint16(buf, &q->q_class);
00293 
00294         if (!(ERR_DNS_IS_OK(buf->error))) return;
00295 
00296         *pq = q;
00297 }
00298 
00299 static void dns_marshall_rr(struct dns_buffer *buf,
00300                             const struct dns_rrec *r)
00301 {
00302         dns_marshall_domain_name(buf, r->name);
00303         dns_marshall_uint16(buf, r->type);
00304         dns_marshall_uint16(buf, r->r_class);
00305         dns_marshall_uint32(buf, r->ttl);
00306         dns_marshall_uint16(buf, r->data_length);
00307         dns_marshall_buffer(buf, r->data, r->data_length);
00308 }
00309 
00310 static void dns_unmarshall_rr(TALLOC_CTX *mem_ctx,
00311                               struct dns_buffer *buf,
00312                               struct dns_rrec **pr)
00313 {
00314         struct dns_rrec *r;
00315 
00316         if (!(ERR_DNS_IS_OK(buf->error))) return;
00317 
00318         if (!(r = talloc(mem_ctx, struct dns_rrec))) {
00319                 buf->error = ERROR_DNS_NO_MEMORY;
00320                 return;
00321         }
00322 
00323         dns_unmarshall_domain_name(r, buf, &r->name);
00324         dns_unmarshall_uint16(buf, &r->type);
00325         dns_unmarshall_uint16(buf, &r->r_class);
00326         dns_unmarshall_uint32(buf, &r->ttl);
00327         dns_unmarshall_uint16(buf, &r->data_length);
00328         r->data = NULL;
00329 
00330         if (!(ERR_DNS_IS_OK(buf->error))) return;
00331 
00332         if (r->data_length != 0) {
00333                 if (!(r->data = TALLOC_ARRAY(r, uint8, r->data_length))) {
00334                         buf->error = ERROR_DNS_NO_MEMORY;
00335                         return;
00336                 }
00337                 dns_unmarshall_buffer(buf, r->data, r->data_length);
00338         }
00339 
00340         if (!(ERR_DNS_IS_OK(buf->error))) return;
00341 
00342         *pr = r;
00343 }
00344 
00345 DNS_ERROR dns_marshall_request(TALLOC_CTX *mem_ctx,
00346                                const struct dns_request *req,
00347                                struct dns_buffer **pbuf)
00348 {
00349         struct dns_buffer *buf;
00350         uint16 i;
00351 
00352         if (!(buf = dns_create_buffer(mem_ctx))) {
00353                 return ERROR_DNS_NO_MEMORY;
00354         }
00355 
00356         dns_marshall_uint16(buf, req->id);
00357         dns_marshall_uint16(buf, req->flags);
00358         dns_marshall_uint16(buf, req->num_questions);
00359         dns_marshall_uint16(buf, req->num_answers);
00360         dns_marshall_uint16(buf, req->num_auths);
00361         dns_marshall_uint16(buf, req->num_additionals);
00362 
00363         for (i=0; i<req->num_questions; i++) {
00364                 dns_marshall_question(buf, req->questions[i]);
00365         }
00366         for (i=0; i<req->num_answers; i++) {
00367                 dns_marshall_rr(buf, req->answers[i]);
00368         }
00369         for (i=0; i<req->num_auths; i++) {
00370                 dns_marshall_rr(buf, req->auths[i]);
00371         }
00372         for (i=0; i<req->num_additionals; i++) {
00373                 dns_marshall_rr(buf, req->additionals[i]);
00374         }
00375 
00376         if (!ERR_DNS_IS_OK(buf->error)) {
00377                 DNS_ERROR err = buf->error;
00378                 TALLOC_FREE(buf);
00379                 return err;
00380         }
00381 
00382         *pbuf = buf;
00383         return ERROR_DNS_SUCCESS;
00384 }
00385 
00386 DNS_ERROR dns_unmarshall_request(TALLOC_CTX *mem_ctx,
00387                                  struct dns_buffer *buf,
00388                                  struct dns_request **preq)
00389 {
00390         struct dns_request *req;
00391         uint16 i;
00392         DNS_ERROR err;
00393 
00394         if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request))) {
00395                 return ERROR_DNS_NO_MEMORY;
00396         }
00397 
00398         dns_unmarshall_uint16(buf, &req->id);
00399         dns_unmarshall_uint16(buf, &req->flags);
00400         dns_unmarshall_uint16(buf, &req->num_questions);
00401         dns_unmarshall_uint16(buf, &req->num_answers);
00402         dns_unmarshall_uint16(buf, &req->num_auths);
00403         dns_unmarshall_uint16(buf, &req->num_additionals);
00404 
00405         if (!ERR_DNS_IS_OK(buf->error)) goto error;
00406 
00407         err = ERROR_DNS_NO_MEMORY;
00408 
00409         if ((req->num_questions != 0) &&
00410             !(req->questions = TALLOC_ARRAY(req, struct dns_question *,
00411                                             req->num_questions))) {
00412                 goto error;
00413         }
00414         if ((req->num_answers != 0) &&
00415             !(req->answers = TALLOC_ARRAY(req, struct dns_rrec *,
00416                                           req->num_answers))) {
00417                 goto error;
00418         }
00419         if ((req->num_auths != 0) &&
00420             !(req->auths = TALLOC_ARRAY(req, struct dns_rrec *,
00421                                         req->num_auths))) {
00422                 goto error;
00423         }
00424         if ((req->num_additionals != 0) &&
00425             !(req->additionals = TALLOC_ARRAY(req, struct dns_rrec *,
00426                                               req->num_additionals))) {
00427                 goto error;
00428         }
00429 
00430         for (i=0; i<req->num_questions; i++) {
00431                 dns_unmarshall_question(req->questions, buf,
00432                                         &req->questions[i]);
00433         }
00434         for (i=0; i<req->num_answers; i++) {
00435                 dns_unmarshall_rr(req->answers, buf,
00436                                   &req->answers[i]);
00437         }
00438         for (i=0; i<req->num_auths; i++) {
00439                 dns_unmarshall_rr(req->auths, buf,
00440                                   &req->auths[i]);
00441         }
00442         for (i=0; i<req->num_additionals; i++) {
00443                 dns_unmarshall_rr(req->additionals, buf,
00444                                   &req->additionals[i]);
00445         }
00446 
00447         if (!ERR_DNS_IS_OK(buf->error)) {
00448                 err = buf->error;
00449                 goto error;
00450         }
00451 
00452         *preq = req;
00453         return ERROR_DNS_SUCCESS;
00454 
00455  error:
00456         err = buf->error;
00457         TALLOC_FREE(req);
00458         return err;
00459 }
00460 
00461 struct dns_request *dns_update2request(struct dns_update_request *update)
00462 {
00463         struct dns_request *req;
00464 
00465         /*
00466          * This is a non-specified construct that happens to work on Linux/gcc
00467          * and I would expect it to work everywhere else. dns_request and
00468          * dns_update_request are essentially the same structures with
00469          * different names, so any difference would mean that the compiler
00470          * applied two different variations of padding given the same types in
00471          * the structures.
00472          */
00473 
00474         req = (struct dns_request *)(void *)update;
00475 
00476         /*
00477          * The assert statement here looks like we could do the equivalent
00478          * assignments to get portable, but it would mean that we have to
00479          * allocate the dns_question record for the dns_zone records. We
00480          * assume that if this assert works then the same holds true for
00481          * dns_zone<>dns_question as well.
00482          */
00483 
00484 #ifdef DEVELOPER
00485         assert((req->id == update->id) && (req->flags == update->flags) &&
00486                (req->num_questions == update->num_zones) &&
00487                (req->num_answers == update->num_preqs) &&
00488                (req->num_auths == update->num_updates) &&
00489                (req->num_additionals == update->num_additionals) &&
00490                (req->questions ==
00491                 (struct dns_question **)(void *)update->zones) &&
00492                (req->answers == update->preqs) &&
00493                (req->auths == update->updates) &&
00494                (req->additionals == update->additionals));
00495 #endif
00496 
00497         return req;
00498 }
00499 
00500 struct dns_update_request *dns_request2update(struct dns_request *request)
00501 {
00502         /*
00503          * For portability concerns see dns_update2request;
00504          */
00505         return (struct dns_update_request *)(void *)request;
00506 }
00507 
00508 DNS_ERROR dns_marshall_update_request(TALLOC_CTX *mem_ctx,
00509                                       struct dns_update_request *update,
00510                                       struct dns_buffer **pbuf)
00511 {
00512         return dns_marshall_request(mem_ctx, dns_update2request(update), pbuf);
00513 }
00514 
00515 DNS_ERROR dns_unmarshall_update_request(TALLOC_CTX *mem_ctx,
00516                                         struct dns_buffer *buf,
00517                                         struct dns_update_request **pupreq)
00518 {
00519         /*
00520          * See comments above about portability. If the above works, this will
00521          * as well.
00522          */
00523 
00524         return dns_unmarshall_request(mem_ctx, buf,
00525                                       (struct dns_request **)(void *)pupreq);
00526 }
00527 
00528 uint16 dns_response_code(uint16 flags)
00529 {
00530         return flags & 0xF;
00531 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7