]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/res_mkupdate.c
2 * Copyright (c) 1996 by Internet Software Consortium.
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
19 * Portions copyright (c) 1999, 2000
21 * All rights reserved.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
37 * This product includes software developed by Intel Corporation and
40 * 4. Neither the name of Intel Corporation or its contributors may be
41 * used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
45 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
48 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
54 * THE POSSIBILITY OF SUCH DAMAGE.
59 * Based on the Dynamic DNS reference implementation by Viraj Bais
60 * <viraj_bais@ccm.fm.intel.com>
63 #include <sys/types.h>
64 #include <sys/param.h>
66 #include <netinet/in.h>
67 #include <arpa/nameser.h>
68 #include <arpa/inet.h>
80 #include "res_config.h"
82 static int getnum_str(u_char
**, u_char
*);
83 static int getword_str(char *, int, u_char
**, u_char
*);
85 #define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
88 * Form update packets.
89 * Returns the size of the resulting packet if no error
91 * returns -1 if error in reading a word/number in rdata
92 * portion for update packets
93 * -2 if length of buffer passed is insufficient
94 * -3 if zone section is not the first section in
95 * the linked list, or section order has a problem
96 * -4 on a number overflow
97 * -5 unknown operation or no records
100 res_mkupdate(ns_updrec
*rrecp_in
, u_char
*buf
, int buflen
) {
101 ns_updrec
*rrecp_start
= rrecp_in
;
103 u_char
*cp
, *sp1
, *sp2
, *startp
, *endp
;
104 int n
, i
, soanum
, multiline
;
108 int section
, numrrs
= 0, counts
[ns_s_max
];
109 u_int16_t rtype
, rclass
;
111 u_char
*dnptrs
[20], **dpp
, **lastdnptr
;
113 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
114 h_errno
= NETDB_INTERNAL
;
119 * Initialize header fields.
121 if ((buf
== NULL
) || (buflen
< HFIXEDSZ
))
123 memset(buf
, 0, HFIXEDSZ
);
125 hp
->id
= htons(++_res
.id
);
126 hp
->opcode
= ns_o_update
;
128 sp1
= buf
+ 2*INT16SZ
; /* save pointer to zocount */
134 lastdnptr
= dnptrs
+ sizeof dnptrs
/ sizeof dnptrs
[0];
136 if (rrecp_start
== NULL
)
138 else if (rrecp_start
->r_section
!= S_ZONE
)
141 memset(counts
, 0, sizeof counts
);
142 for (rrecp
= rrecp_start
; rrecp
; rrecp
= rrecp
->r_grpnext
) {
144 section
= rrecp
->r_section
;
145 if (section
< 0 || section
>= ns_s_max
)
148 for (i
= section
+ 1; i
< ns_s_max
; i
++)
151 rtype
= rrecp
->r_type
;
152 rclass
= rrecp
->r_class
;
154 /* overload class and type */
155 if (section
== S_PREREQ
) {
157 switch (rrecp
->r_opcode
) {
173 if (rrecp
->r_size
== 0)
178 "res_mkupdate: incorrect opcode: %d\n",
183 } else if (section
== S_UPDATE
) {
184 switch (rrecp
->r_opcode
) {
186 rclass
= rrecp
->r_size
== 0 ? C_ANY
: C_NONE
;
192 "res_mkupdate: incorrect opcode: %d\n",
200 * XXX appending default domain to owner name is omitted,
201 * fqdn must be provided
203 if ((n
= dn_comp(rrecp
->r_dname
, cp
, buflen
, dnptrs
,
207 ShrinkBuffer(n
+ 2*INT16SZ
);
209 PUTSHORT(rclass
, cp
);
210 if (section
== S_ZONE
) {
211 if (numrrs
!= 1 || rrecp
->r_type
!= T_SOA
)
215 ShrinkBuffer(INT32SZ
+ INT16SZ
);
217 sp2
= cp
; /* save pointer to length byte */
219 if (rrecp
->r_size
== 0) {
220 if (section
== S_UPDATE
&& rclass
!= C_ANY
)
227 startp
= rrecp
->r_data
;
228 endp
= startp
+ rrecp
->r_size
- 1;
229 /* XXX this should be done centrally. */
230 switch (rrecp
->r_type
) {
232 if (!getword_str(buf2
, sizeof buf2
, &startp
, endp
))
234 if (!inet_aton(buf2
, &ina
))
236 n1
= ntohl(ina
.s_addr
);
237 ShrinkBuffer(INT32SZ
);
246 if (!getword_str(buf2
, sizeof buf2
, &startp
, endp
))
248 n
= dn_comp(buf2
, cp
, buflen
, dnptrs
, lastdnptr
);
257 for (i
= 0; i
< 2; i
++) {
258 if (!getword_str(buf2
, sizeof buf2
, &startp
,
261 n
= dn_comp(buf2
, cp
, buflen
,
268 if (rrecp
->r_type
== T_SOA
) {
269 ShrinkBuffer(5 * INT32SZ
);
270 while (isspace(*startp
) || !*startp
)
272 if (*startp
== '(') {
277 /* serial, refresh, retry, expire, minimum */
278 for (i
= 0; i
< 5; i
++) {
279 soanum
= getnum_str(&startp
, endp
);
285 while (isspace(*startp
) || !*startp
)
295 n
= getnum_str(&startp
, endp
);
299 ShrinkBuffer(INT16SZ
);
300 if (!getword_str(buf2
, sizeof buf2
, &startp
, endp
))
302 n
= dn_comp(buf2
, cp
, buflen
, dnptrs
, lastdnptr
);
309 n
= getnum_str(&startp
, endp
);
313 ShrinkBuffer(INT16SZ
);
314 for (i
= 0; i
< 2; i
++) {
315 if (!getword_str(buf2
, sizeof buf2
, &startp
,
318 n
= dn_comp(buf2
, cp
, buflen
, dnptrs
,
333 /* XXX - more fine tuning needed here */
334 ShrinkBuffer(rrecp
->r_size
);
335 memcpy(cp
, rrecp
->r_data
, rrecp
->r_size
);
341 n
= (u_int16_t
)((cp
- sp2
) - INT16SZ
);
345 hp
->qdcount
= htons(counts
[0]);
346 hp
->ancount
= htons(counts
[1]);
347 hp
->nscount
= htons(counts
[2]);
348 hp
->arcount
= htons(counts
[3]);
349 return ((int)(cp
- buf
));
353 * Get a whitespace delimited word from a string (not file)
354 * into buf. modify the start pointer to point after the
355 * word in the string.
358 getword_str(char *buf
, int size
, u_char
**startpp
, u_char
*endp
) {
362 for (cp
= buf
; *startpp
<= endp
; ) {
364 if (isspace(c
) || c
== '\0') {
365 if (cp
!= buf
) /* trailing whitespace */
367 else { /* leading whitespace */
373 if (cp
>= buf
+size
-1)
382 * Get a whitespace delimited number from a string (not file) into buf
383 * update the start pointer to point after the number in the string.
386 getnum_str(u_char
**startpp
, u_char
*endp
) {
392 for (n
= 0; *startpp
<= endp
; ) {
394 if (isspace(c
) || c
== '\0') {
395 if (seendigit
) /* trailing whitespace */
397 else { /* leading whitespace */
403 while ((*startpp
<= endp
) &&
404 ((c
= **startpp
) != '\n'))
411 if (c
== ')' && seendigit
) {
418 n
= n
* 10 + (c
- '0');
425 * Allocate a resource record buffer & save rr info.
428 res_mkupdrec(int section
, const char *dname
,
429 u_int
class, u_int type
, u_long ttl
) {
430 ns_updrec
*rrecp
= (ns_updrec
*)calloc(1, sizeof(ns_updrec
));
432 if (!rrecp
|| !(rrecp
->r_dname
= strdup(dname
)))
434 rrecp
->r_class
= (u_int16_t
)class;
435 rrecp
->r_type
= (u_int16_t
)type
;
436 rrecp
->r_ttl
= (u_int32_t
)ttl
;
437 rrecp
->r_section
= (u_int8_t
)section
;
442 * Free a resource record buffer created by res_mkupdrec.
445 res_freeupdrec(ns_updrec
*rrecp
) {
446 /* Note: freeing r_dp is the caller's responsibility. */
447 if (rrecp
->r_dname
!= NULL
)
448 free(rrecp
->r_dname
);