4 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
20 static const char rcsid
[] = "Id: ns_newmsg.c,v 1.3 2009/02/26 10:48:57 marka Exp";
23 #include <arpa/nameser.h>
29 static int rdcpy(ns_newmsg
*, ns_type
, const u_char
*, size_t);
31 /* Initialize a "newmsg" object to empty.
34 ns_newmsg_init(u_char
*buffer
, size_t bufsiz
, ns_newmsg
*handle
) {
35 ns_msg
*msg
= &handle
->msg
;
37 memset(handle
, 0, sizeof *handle
);
39 msg
->_eom
= buffer
+ bufsiz
;
42 msg
->_msg_ptr
= buffer
+ NS_HFIXEDSZ
;
43 handle
->dnptrs
[0] = msg
->_msg
;
44 handle
->dnptrs
[1] = NULL
;
45 handle
->lastdnptr
= &handle
->dnptrs
[sizeof handle
->dnptrs
/
46 sizeof handle
->dnptrs
[0] - 1];
50 /* Initialize a "newmsg" object by copying an existing parsed message.
53 ns_newmsg_copy(ns_newmsg
*handle
, ns_msg
*msg
) {
57 ns_newmsg_id(handle
, ns_msg_id(*msg
));
58 for (flag
= ns_f_qr
; flag
< ns_f_max
; flag
++)
59 ns_newmsg_flag(handle
, flag
, ns_msg_getflag(*msg
, flag
));
60 for (sect
= ns_s_qd
; sect
< ns_s_max
; sect
++) {
63 count
= ns_msg_count(*msg
, sect
);
64 for (i
= 0; i
< count
; i
++) {
68 if (ns_parserr2(msg
, sect
, i
, &rr
) < 0)
71 x
= ns_newmsg_q(handle
,
76 x
= ns_newmsg_rr(handle
, sect
,
90 /* Set the message-ID in a "newmsg" object.
93 ns_newmsg_id(ns_newmsg
*handle
, u_int16_t id
) {
94 ns_msg
*msg
= &handle
->msg
;
99 /* Set a flag (including rcode or opcode) in a "newmsg" object.
102 ns_newmsg_flag(ns_newmsg
*handle
, ns_flag flag
, u_int value
) {
103 extern struct _ns_flagdata _ns_flagdata
[16];
104 struct _ns_flagdata
*fd
= &_ns_flagdata
[flag
];
105 ns_msg
*msg
= &handle
->msg
;
107 assert(flag
< ns_f_max
);
108 msg
->_flags
&= (~fd
->mask
);
109 msg
->_flags
|= (value
<< fd
->shift
);
112 /* Add a question (or zone, if it's an update) to a "newmsg" object.
115 ns_newmsg_q(ns_newmsg
*handle
, ns_nname_ct qname
,
116 ns_type qtype
, ns_class qclass
)
118 ns_msg
*msg
= &handle
->msg
;
122 if (msg
->_sect
!= ns_s_qd
) {
126 t
= (u_char
*) (unsigned long) msg
->_msg_ptr
;
127 if (msg
->_rrnum
== 0)
128 msg
->_sections
[ns_s_qd
] = t
;
129 n
= ns_name_pack(qname
, t
, msg
->_eom
- t
,
130 handle
->dnptrs
, handle
->lastdnptr
);
134 if (t
+ QFIXEDSZ
>= msg
->_eom
) {
141 msg
->_counts
[ns_s_qd
] = ++msg
->_rrnum
;
145 /* Add an RR to a "newmsg" object.
148 ns_newmsg_rr(ns_newmsg
*handle
, ns_sect sect
,
149 ns_nname_ct name
, ns_type type
,
150 ns_class rr_class
, u_int32_t ttl
,
151 u_int16_t rdlen
, const u_char
*rdata
)
153 ns_msg
*msg
= &handle
->msg
;
157 if (sect
< msg
->_sect
) {
161 t
= (u_char
*) (unsigned long) msg
->_msg_ptr
;
162 if (sect
> msg
->_sect
) {
164 msg
->_sections
[sect
] = t
;
167 n
= ns_name_pack(name
, t
, msg
->_eom
- t
,
168 handle
->dnptrs
, handle
->lastdnptr
);
172 if (t
+ RRFIXEDSZ
+ rdlen
>= msg
->_eom
) {
177 NS_PUT16(rr_class
, t
);
180 if (rdcpy(handle
, type
, rdata
, rdlen
) < 0)
182 msg
->_counts
[sect
] = ++msg
->_rrnum
;
186 /* Complete a "newmsg" object and return its size for use in write().
187 * (Note: the "newmsg" object is also made ready for ns_parserr() etc.)
190 ns_newmsg_done(ns_newmsg
*handle
) {
191 ns_msg
*msg
= &handle
->msg
;
195 t
= (u_char
*) (unsigned long) msg
->_msg
;
196 NS_PUT16(msg
->_id
, t
);
197 NS_PUT16(msg
->_flags
, t
);
198 for (sect
= 0; sect
< ns_s_max
; sect
++)
199 NS_PUT16(msg
->_counts
[sect
], t
);
200 msg
->_eom
= msg
->_msg_ptr
;
201 msg
->_sect
= ns_s_max
;
203 msg
->_msg_ptr
= NULL
;
204 return (msg
->_eom
- msg
->_msg
);
209 /* Copy an RDATA, using compression pointers where RFC1035 permits.
212 rdcpy(ns_newmsg
*handle
, ns_type type
, const u_char
*rdata
, size_t rdlen
) {
213 ns_msg
*msg
= &handle
->msg
;
214 u_char
*p
= (u_char
*) (unsigned long) msg
->_msg_ptr
;
215 u_char
*t
= p
+ NS_INT16SZ
;
222 n
= ns_name_pack(rdata
, t
, msg
->_eom
- t
,
223 handle
->dnptrs
, handle
->lastdnptr
);
227 if (ns_name_skip(&rdata
, msg
->_eom
) < 0)
231 n
= ns_name_pack(rdata
, t
, msg
->_eom
- t
,
232 handle
->dnptrs
, handle
->lastdnptr
);
236 if (ns_name_skip(&rdata
, msg
->_eom
) < 0)
239 /* Serial, Refresh, Retry, Expiry, and Minimum. */
240 if ((msg
->_eom
- t
) < (NS_INT32SZ
* 5)) {
244 memcpy(t
, rdata
, NS_INT32SZ
* 5);
245 t
+= (NS_INT32SZ
* 5);
250 /* PTRDNAME, CNAME, or NSDNAME. */
251 n
= ns_name_pack(rdata
, t
, msg
->_eom
- t
,
252 handle
->dnptrs
, handle
->lastdnptr
);
258 memcpy(t
, rdata
, rdlen
);