No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / libbind / dist / nameser / ns_newmsg.c
blob842f5fdcab336a7c4a44ee994c069235152537ad
1 /* $NetBSD$ */
3 /*
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.
19 #ifndef lint
20 static const char rcsid[] = "Id: ns_newmsg.c,v 1.3 2009/02/26 10:48:57 marka Exp";
21 #endif
23 #include <arpa/nameser.h>
25 #include <assert.h>
26 #include <errno.h>
27 #include <string.h>
29 static int rdcpy(ns_newmsg *, ns_type, const u_char *, size_t);
31 /* Initialize a "newmsg" object to empty.
33 int
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);
38 msg->_msg = buffer;
39 msg->_eom = buffer + bufsiz;
40 msg->_sect = ns_s_qd;
41 msg->_rrnum = 0;
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];
47 return (0);
50 /* Initialize a "newmsg" object by copying an existing parsed message.
52 int
53 ns_newmsg_copy(ns_newmsg *handle, ns_msg *msg) {
54 ns_flag flag;
55 ns_sect sect;
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++) {
61 int i, count;
63 count = ns_msg_count(*msg, sect);
64 for (i = 0; i < count; i++) {
65 ns_rr2 rr;
66 int x;
68 if (ns_parserr2(msg, sect, i, &rr) < 0)
69 return (-1);
70 if (sect == ns_s_qd)
71 x = ns_newmsg_q(handle,
72 ns_rr_nname(rr),
73 ns_rr_type(rr),
74 ns_rr_class(rr));
75 else
76 x = ns_newmsg_rr(handle, sect,
77 ns_rr_nname(rr),
78 ns_rr_type(rr),
79 ns_rr_class(rr),
80 ns_rr_ttl(rr),
81 ns_rr_rdlen(rr),
82 ns_rr_rdata(rr));
83 if (x < 0)
84 return (-1);
87 return (0);
90 /* Set the message-ID in a "newmsg" object.
92 void
93 ns_newmsg_id(ns_newmsg *handle, u_int16_t id) {
94 ns_msg *msg = &handle->msg;
96 msg->_id = id;
99 /* Set a flag (including rcode or opcode) in a "newmsg" object.
101 void
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;
119 u_char *t;
120 int n;
122 if (msg->_sect != ns_s_qd) {
123 errno = ENODEV;
124 return (-1);
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);
131 if (n < 0)
132 return (-1);
133 t += n;
134 if (t + QFIXEDSZ >= msg->_eom) {
135 errno = EMSGSIZE;
136 return (-1);
138 NS_PUT16(qtype, t);
139 NS_PUT16(qclass, t);
140 msg->_msg_ptr = t;
141 msg->_counts[ns_s_qd] = ++msg->_rrnum;
142 return (0);
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;
154 u_char *t;
155 int n;
157 if (sect < msg->_sect) {
158 errno = ENODEV;
159 return (-1);
161 t = (u_char *) (unsigned long) msg->_msg_ptr;
162 if (sect > msg->_sect) {
163 msg->_sect = sect;
164 msg->_sections[sect] = t;
165 msg->_rrnum = 0;
167 n = ns_name_pack(name, t, msg->_eom - t,
168 handle->dnptrs, handle->lastdnptr);
169 if (n < 0)
170 return (-1);
171 t += n;
172 if (t + RRFIXEDSZ + rdlen >= msg->_eom) {
173 errno = EMSGSIZE;
174 return (-1);
176 NS_PUT16(type, t);
177 NS_PUT16(rr_class, t);
178 NS_PUT32(ttl, t);
179 msg->_msg_ptr = t;
180 if (rdcpy(handle, type, rdata, rdlen) < 0)
181 return (-1);
182 msg->_counts[sect] = ++msg->_rrnum;
183 return (0);
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.)
189 size_t
190 ns_newmsg_done(ns_newmsg *handle) {
191 ns_msg *msg = &handle->msg;
192 ns_sect sect;
193 u_char *t;
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;
202 msg->_rrnum = -1;
203 msg->_msg_ptr = NULL;
204 return (msg->_eom - msg->_msg);
207 /* Private. */
209 /* Copy an RDATA, using compression pointers where RFC1035 permits.
211 static int
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;
216 u_char *s = t;
217 int n;
219 switch (type) {
220 case ns_t_soa:
221 /* MNAME. */
222 n = ns_name_pack(rdata, t, msg->_eom - t,
223 handle->dnptrs, handle->lastdnptr);
224 if (n < 0)
225 return (-1);
226 t += n;
227 if (ns_name_skip(&rdata, msg->_eom) < 0)
228 return (-1);
230 /* ANAME. */
231 n = ns_name_pack(rdata, t, msg->_eom - t,
232 handle->dnptrs, handle->lastdnptr);
233 if (n < 0)
234 return (-1);
235 t += n;
236 if (ns_name_skip(&rdata, msg->_eom) < 0)
237 return (-1);
239 /* Serial, Refresh, Retry, Expiry, and Minimum. */
240 if ((msg->_eom - t) < (NS_INT32SZ * 5)) {
241 errno = EMSGSIZE;
242 return (-1);
244 memcpy(t, rdata, NS_INT32SZ * 5);
245 t += (NS_INT32SZ * 5);
246 break;
247 case ns_t_ptr:
248 case ns_t_cname:
249 case ns_t_ns:
250 /* PTRDNAME, CNAME, or NSDNAME. */
251 n = ns_name_pack(rdata, t, msg->_eom - t,
252 handle->dnptrs, handle->lastdnptr);
253 if (n < 0)
254 return (-1);
255 t += n;
256 break;
257 default:
258 memcpy(t, rdata, rdlen);
259 t += rdlen;
261 NS_PUT16(t - s, p);
262 msg->_msg_ptr = t;
263 return (0);