/* Copyright 1999-2007 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Original Copyright (c) Netmask.IT!® 2006-2007 * * DNS Protocol module for Apache 2.x */ #include "../rr.h" static DNS_RDATA_UNSERIALIZE(mx) { const char *ptr = data; char label[63] = ""; /** RFC 1035 says label can only be 63 octets long */ apr_byte_t len; dns_rdata_t *rrdata; dns_rdata_mx_t *mx = apr_pcalloc(pool, sizeof(*mx)); *rdata = rrdata = apr_pcalloc(pool, sizeof(*rrdata)); dns_init_rdata_const(mx, rrdata); rrdata->rdata = mx; /** Grab preference */ memcpy(&(mx->preference), data, sizeof(apr_uint16_t)); data+=sizeof(apr_uint16_t); /** initialize exchange */ mx->exchange = apr_pstrdup(pool, ""); memcpy(&len, ptr, 1); while (len > 0) { ptr++; apr_cpystrn(label, ptr, len + 1); ptr += len; mx->exchange = apr_pstrcat(pool, mx->exchange, label, ".", NULL); memcpy(&len, ptr, 1); } return APR_SUCCESS; } static DNS_RDATA_SERIALIZE(mx) { dns_rdata_mx_t *mx; apr_byte_t llen; char *ptr, *label, *last = NULL; mx = (dns_rdata_mx_t *)rdata; /** The length byte takes the same space as a char, so we just need * strlen(cname) of space (cname should have trailing .) and room * for the first length byte (other length bytes replace "." characters) */ *dlen = sizeof(apr_uint16_t) + strlen(mx->exchange) + 1; if (mx->exchange[*dlen-2] != '.') (*dlen)++; if (data == NULL) return APR_SUCCESS; mx = (dns_rdata_mx_t *)rdata; memcpy(data, (const void *)&(mx->preference), sizeof(apr_uint16_t)); /** Point to beginning of data */ ptr = data; label = apr_strtok(mx->exchange, ".", &last); while (label != NULL) { llen = strlen(label); if (llen == 0) { /** Trailing . - Set NULL and break */ *ptr = 0; ptr++; break; } /** Write length token */ *ptr = llen; ptr++; /** Write label */ memcpy(ptr, label, llen); /** Move pointer */ ptr+=llen; /** Advance to next token */ label = apr_strtok(NULL, ".", &last); } *ptr = 0; ptr++; return APR_SUCCESS; } static DNS_RDATA_PSERIALIZE(mx) DNS_RDATA_IMPLEMENT(mx);