2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
10 * Permission to use, copy, modify, and/or distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
17 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #include <port_before.h>
25 #include <arpa/nameser.h>
31 #include <port_after.h>
33 static int rdcpy(ns_newmsg
*, ns_type
, const u_char
*, size_t);
35 /* Initialize a "newmsg" object to empty.
38 ns_newmsg_init(u_char
*buffer
, size_t bufsiz
, ns_newmsg
*handle
) {
39 ns_msg
*msg
= &handle
->msg
;
41 memset(handle
, 0, sizeof *handle
);
43 msg
->_eom
= buffer
+ bufsiz
;
46 msg
->_msg_ptr
= buffer
+ NS_HFIXEDSZ
;
47 handle
->dnptrs
[0] = msg
->_msg
;
48 handle
->dnptrs
[1] = NULL
;
49 handle
->lastdnptr
= &handle
->dnptrs
[sizeof handle
->dnptrs
/
50 sizeof handle
->dnptrs
[0] - 1];
54 /* Initialize a "newmsg" object by copying an existing parsed message.
57 ns_newmsg_copy(ns_newmsg
*handle
, ns_msg
*msg
) {
61 ns_newmsg_id(handle
, ns_msg_id(*msg
));
62 for (flag
= ns_f_qr
; flag
< ns_f_max
; flag
++)
63 ns_newmsg_flag(handle
, flag
, ns_msg_getflag(*msg
, flag
));
64 for (sect
= ns_s_qd
; sect
< ns_s_max
; sect
++) {
67 count
= ns_msg_count(*msg
, sect
);
68 for (i
= 0; i
< count
; i
++) {
72 if (ns_parserr2(msg
, sect
, i
, &rr
) < 0)
75 x
= ns_newmsg_q(handle
,
80 x
= ns_newmsg_rr(handle
, sect
,
94 /* Set the message-ID in a "newmsg" object.
97 ns_newmsg_id(ns_newmsg
*handle
, u_int16_t id
) {
98 ns_msg
*msg
= &handle
->msg
;
103 /* Set a flag (including rcode or opcode) in a "newmsg" object.
106 ns_newmsg_flag(ns_newmsg
*handle
, ns_flag flag
, u_int value
) {
107 extern struct _ns_flagdata _ns_flagdata
[16];
108 struct _ns_flagdata
*fd
= &_ns_flagdata
[flag
];
109 ns_msg
*msg
= &handle
->msg
;
111 assert(flag
< ns_f_max
);
112 msg
->_flags
&= (~fd
->mask
);
113 msg
->_flags
|= (value
<< fd
->shift
);
116 /* Add a question (or zone, if it's an update) to a "newmsg" object.
119 ns_newmsg_q(ns_newmsg
*handle
, ns_nname_ct qname
,
120 ns_type qtype
, ns_class qclass
)
122 ns_msg
*msg
= &handle
->msg
;
126 if (msg
->_sect
!= ns_s_qd
) {
130 t
= (u_char
*) (unsigned long) msg
->_msg_ptr
;
131 if (msg
->_rrnum
== 0)
132 msg
->_sections
[ns_s_qd
] = t
;
133 n
= ns_name_pack(qname
, t
, msg
->_eom
- t
,
134 handle
->dnptrs
, handle
->lastdnptr
);
138 if (t
+ QFIXEDSZ
>= msg
->_eom
) {
145 msg
->_counts
[ns_s_qd
] = ++msg
->_rrnum
;
149 /* Add an RR to a "newmsg" object.
152 ns_newmsg_rr(ns_newmsg
*handle
, ns_sect sect
,
153 ns_nname_ct name
, ns_type type
,
154 ns_class rr_class
, u_int32_t ttl
,
155 u_int16_t rdlen
, const u_char
*rdata
)
157 ns_msg
*msg
= &handle
->msg
;
161 if (sect
< msg
->_sect
) {
165 t
= (u_char
*) (unsigned long) msg
->_msg_ptr
;
166 if (sect
> msg
->_sect
) {
168 msg
->_sections
[sect
] = t
;
171 n
= ns_name_pack(name
, t
, msg
->_eom
- t
,
172 handle
->dnptrs
, handle
->lastdnptr
);
176 if (t
+ RRFIXEDSZ
+ rdlen
>= msg
->_eom
) {
181 NS_PUT16(rr_class
, t
);
184 if (rdcpy(handle
, type
, rdata
, rdlen
) < 0)
186 msg
->_counts
[sect
] = ++msg
->_rrnum
;
190 /* Complete a "newmsg" object and return its size for use in write().
191 * (Note: the "newmsg" object is also made ready for ns_parserr() etc.)
194 ns_newmsg_done(ns_newmsg
*handle
) {
195 ns_msg
*msg
= &handle
->msg
;
199 t
= (u_char
*) (unsigned long) msg
->_msg
;
200 NS_PUT16(msg
->_id
, t
);
201 NS_PUT16(msg
->_flags
, t
);
202 for (sect
= 0; sect
< ns_s_max
; sect
++)
203 NS_PUT16(msg
->_counts
[sect
], t
);
204 msg
->_eom
= msg
->_msg_ptr
;
205 msg
->_sect
= ns_s_max
;
207 msg
->_msg_ptr
= NULL
;
208 return (msg
->_eom
- msg
->_msg
);
213 /* Copy an RDATA, using compression pointers where RFC1035 permits.
216 rdcpy(ns_newmsg
*handle
, ns_type type
, const u_char
*rdata
, size_t rdlen
) {
217 ns_msg
*msg
= &handle
->msg
;
218 u_char
*p
= (u_char
*) (unsigned long) msg
->_msg_ptr
;
219 u_char
*t
= p
+ NS_INT16SZ
;
226 n
= ns_name_pack(rdata
, t
, msg
->_eom
- t
,
227 handle
->dnptrs
, handle
->lastdnptr
);
231 if (ns_name_skip(&rdata
, msg
->_eom
) < 0)
235 n
= ns_name_pack(rdata
, t
, msg
->_eom
- t
,
236 handle
->dnptrs
, handle
->lastdnptr
);
240 if (ns_name_skip(&rdata
, msg
->_eom
) < 0)
243 /* Serial, Refresh, Retry, Expiry, and Minimum. */
244 if ((msg
->_eom
- t
) < (NS_INT32SZ
* 5)) {
248 memcpy(t
, rdata
, NS_INT32SZ
* 5);
249 t
+= (NS_INT32SZ
* 5);
254 /* PTRDNAME, CNAME, or NSDNAME. */
255 n
= ns_name_pack(rdata
, t
, msg
->_eom
- t
,
256 handle
->dnptrs
, handle
->lastdnptr
);
262 memcpy(t
, rdata
, rdlen
);