]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/res_mkupdate.c
2 Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
3 This program and the accompanying materials are licensed and made available
4 under the terms and conditions of the BSD License which accompanies this
5 distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php.
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 * Copyright (c) 1996 by Internet Software Consortium.
14 * Permission to use, copy, modify, and distribute this software for any
15 * purpose with or without fee is hereby granted, provided that the above
16 * copyright notice and this permission notice appear in all copies.
18 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
19 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
21 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
22 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
23 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
24 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29 * Portions copyright (c) 1999, 2000
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
47 * This product includes software developed by Intel Corporation and
50 * 4. Neither the name of Intel Corporation or its contributors may be
51 * used to endorse or promote products derived from this software
52 * without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
55 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
58 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
64 * THE POSSIBILITY OF SUCH DAMAGE.
69 * Based on the Dynamic DNS reference implementation by Viraj Bais
70 * <viraj_bais@ccm.fm.intel.com>
73 #include <sys/types.h>
74 #include <sys/param.h>
76 #include <netinet/in.h>
77 #include <arpa/nameser.h>
78 #include <arpa/inet.h>
90 #include "res_config.h"
92 static int getnum_str(u_char
**, u_char
*);
93 static int getword_str(char *, int, u_char
**, u_char
*);
95 #define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
98 * Form update packets.
99 * Returns the size of the resulting packet if no error
101 * returns -1 if error in reading a word/number in rdata
102 * portion for update packets
103 * -2 if length of buffer passed is insufficient
104 * -3 if zone section is not the first section in
105 * the linked list, or section order has a problem
106 * -4 on a number overflow
107 * -5 unknown operation or no records
110 res_mkupdate(ns_updrec
*rrecp_in
, u_char
*buf
, int buflen
) {
111 ns_updrec
*rrecp_start
= rrecp_in
;
113 u_char
*cp
, *sp2
, *startp
, *endp
;
114 int n
, i
, soanum
, multiline
;
118 int section
, numrrs
= 0, counts
[ns_s_max
];
119 u_int16_t rtype
, rclass
;
121 u_char
*dnptrs
[20], **dpp
, **lastdnptr
;
123 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
124 h_errno
= NETDB_INTERNAL
;
129 * Initialize header fields.
131 if ((buf
== NULL
) || (buflen
< HFIXEDSZ
))
133 memset(buf
, 0, HFIXEDSZ
);
135 hp
->id
= htons(++_res
.id
);
136 hp
->opcode
= ns_o_update
;
143 lastdnptr
= dnptrs
+ sizeof dnptrs
/ sizeof dnptrs
[0];
145 if (rrecp_start
== NULL
)
147 else if (rrecp_start
->r_section
!= S_ZONE
)
150 memset(counts
, 0, sizeof counts
);
151 for (rrecp
= rrecp_start
; rrecp
; rrecp
= rrecp
->r_grpnext
) {
153 section
= rrecp
->r_section
;
154 if (section
< 0 || section
>= ns_s_max
)
157 for (i
= section
+ 1; i
< ns_s_max
; i
++)
160 rtype
= rrecp
->r_type
;
161 rclass
= rrecp
->r_class
;
163 /* overload class and type */
164 if (section
== S_PREREQ
) {
166 switch (rrecp
->r_opcode
) {
182 if (rrecp
->r_size
== 0)
187 "res_mkupdate: incorrect opcode: %d\n",
192 } else if (section
== S_UPDATE
) {
193 switch (rrecp
->r_opcode
) {
195 rclass
= rrecp
->r_size
== 0 ? C_ANY
: C_NONE
;
201 "res_mkupdate: incorrect opcode: %d\n",
209 * XXX appending default domain to owner name is omitted,
210 * fqdn must be provided
212 if ((n
= dn_comp(rrecp
->r_dname
, cp
, buflen
, dnptrs
,
216 ShrinkBuffer(n
+ 2*INT16SZ
);
218 PUTSHORT(rclass
, cp
);
219 if (section
== S_ZONE
) {
220 if (numrrs
!= 1 || rrecp
->r_type
!= T_SOA
)
224 ShrinkBuffer(INT32SZ
+ INT16SZ
);
226 sp2
= cp
; /* save pointer to length byte */
228 if (rrecp
->r_size
== 0) {
229 if (section
== S_UPDATE
&& rclass
!= C_ANY
)
236 startp
= rrecp
->r_data
;
237 endp
= startp
+ rrecp
->r_size
- 1;
238 /* XXX this should be done centrally. */
239 switch (rrecp
->r_type
) {
241 if (!getword_str(buf2
, sizeof buf2
, &startp
, endp
))
243 if (!inet_aton(buf2
, &ina
))
245 n1
= ntohl(ina
.s_addr
);
246 ShrinkBuffer(INT32SZ
);
255 if (!getword_str(buf2
, sizeof buf2
, &startp
, endp
))
257 n
= dn_comp(buf2
, cp
, buflen
, dnptrs
, lastdnptr
);
266 for (i
= 0; i
< 2; i
++) {
267 if (!getword_str(buf2
, sizeof buf2
, &startp
,
270 n
= dn_comp(buf2
, cp
, buflen
,
277 if (rrecp
->r_type
== T_SOA
) {
278 ShrinkBuffer(5 * INT32SZ
);
279 while (isspace(*startp
) || !*startp
)
281 if (*startp
== '(') {
286 /* serial, refresh, retry, expire, minimum */
287 for (i
= 0; i
< 5; i
++) {
288 soanum
= getnum_str(&startp
, endp
);
294 while (isspace(*startp
) || !*startp
)
304 n
= getnum_str(&startp
, endp
);
308 ShrinkBuffer(INT16SZ
);
309 if (!getword_str(buf2
, sizeof buf2
, &startp
, endp
))
311 n
= dn_comp(buf2
, cp
, buflen
, dnptrs
, lastdnptr
);
318 n
= getnum_str(&startp
, endp
);
322 ShrinkBuffer(INT16SZ
);
323 for (i
= 0; i
< 2; i
++) {
324 if (!getword_str(buf2
, sizeof buf2
, &startp
,
327 n
= dn_comp(buf2
, cp
, buflen
, dnptrs
,
342 /* XXX - more fine tuning needed here */
343 ShrinkBuffer(rrecp
->r_size
);
344 memcpy(cp
, rrecp
->r_data
, rrecp
->r_size
);
350 n
= (u_int16_t
)((cp
- sp2
) - INT16SZ
);
354 hp
->qdcount
= htons(counts
[0]);
355 hp
->ancount
= htons(counts
[1]);
356 hp
->nscount
= htons(counts
[2]);
357 hp
->arcount
= htons(counts
[3]);
358 return ((int)(cp
- buf
));
362 * Get a whitespace delimited word from a string (not file)
363 * into buf. modify the start pointer to point after the
364 * word in the string.
367 getword_str(char *buf
, int size
, u_char
**startpp
, u_char
*endp
) {
371 for (cp
= buf
; *startpp
<= endp
; ) {
373 if (isspace(c
) || c
== '\0') {
374 if (cp
!= buf
) /* trailing whitespace */
376 else { /* leading whitespace */
382 if (cp
>= buf
+size
-1)
391 * Get a whitespace delimited number from a string (not file) into buf
392 * update the start pointer to point after the number in the string.
395 getnum_str(u_char
**startpp
, u_char
*endp
) {
401 for (n
= 0; *startpp
<= endp
; ) {
403 if (isspace(c
) || c
== '\0') {
404 if (seendigit
) /* trailing whitespace */
406 else { /* leading whitespace */
412 while ((*startpp
<= endp
) &&
413 ((c
= **startpp
) != '\n'))
420 if (c
== ')' && seendigit
) {
427 n
= n
* 10 + (c
- '0');
434 * Allocate a resource record buffer & save rr info.
437 res_mkupdrec(int section
, const char *dname
,
438 u_int
class, u_int type
, u_long ttl
) {
439 ns_updrec
*rrecp
= (ns_updrec
*)calloc(1, sizeof(ns_updrec
));
441 if (!rrecp
|| !(rrecp
->r_dname
= strdup(dname
))) {
445 rrecp
->r_class
= (u_int16_t
)class;
446 rrecp
->r_type
= (u_int16_t
)type
;
447 rrecp
->r_ttl
= (u_int32_t
)ttl
;
448 rrecp
->r_section
= (u_int8_t
)section
;
453 * Free a resource record buffer created by res_mkupdrec.
456 res_freeupdrec(ns_updrec
*rrecp
) {
457 /* Note: freeing r_dp is the caller's responsibility. */
458 if (rrecp
->r_dname
!= NULL
)
459 free(rrecp
->r_dname
);