1 /*
2  * Copyright (c) 1999 by Sun Microsystems, Inc.
3  * All rights reserved.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * As of BIND 8.2.2, ISC (a) removed res_mkupdate(), res_update(), and
10  * res_mkupdrec() from what they consider the supported interface. The
11  * functions still exist, but their calling interface has changed, since
12  * the ns_updrec structure has changed.
13  *
14  * It seems probable that res_mkupdate()  etc. will return, though possibly
15  * with other changes, in some future BIND release. In order to avoid
16  * going to PSARC twice (once to remove the functions, and then again to
17  * add them back), we retain the old interface as a wrapper around the
18  * new one.
19  */
20 
21 #include <port_before.h>
22 
23 #include <malloc.h>
24 #include <strings.h>
25 #include <sys/types.h>
26 #include <netinet/in.h>
27 
28 #include <res_update.h>
29 #undef	ns_updrec
30 #undef	res_mkupdate
31 #undef	res_update
32 #undef	res_mkupdrec
33 #undef	res_freeupdrec
34 #include <arpa/nameser.h>
35 
36 #include <port_after.h>
37 
38 void	res_freeupdrec(ns_updrec *);
39 
40 
41 static int
42 old2new(ns_updrec *old, __ISC_ns_updrec *new) {
43 
44 	if (old->r_dname != 0) {
45 		if ((new->r_dname = strdup(old->r_dname)) == 0)
46 			return (-1);
47 	} else {
48 		new->r_dname = 0;
49 	}
50 
51 	new->r_glink.prev =
52 	new->r_glink.next =
53 	new->r_link.prev  =
54 	new->r_link.next  = 0;
55 
56 	new->r_section	= old->r_section;
57 	new->r_class	= old->r_class;
58 	new->r_type	= old->r_type;
59 	new->r_ttl	= old->r_ttl;
60 	new->r_data	= old->r_data;
61 	new->r_size	= old->r_size;
62 	new->r_opcode	= old->r_opcode;
63 	new->r_dp	= old->r_dp;
64 	new->r_deldp	= old->r_deldp;
65 	new->r_zone	= old->r_zone;
66 
67 	return (0);
68 }
69 
70 
71 static int
72 new2old(__ISC_ns_updrec *new, ns_updrec *old) {
73 	/* XXX r_prev and r_next unchanged */
74 	if (new->r_dname != 0) {
75 		if ((old->r_dname = strdup(new->r_dname)) == 0)
76 			return (-1);
77 	} else {
78 		old->r_dname = 0;
79 	}
80 	old->r_section	= new->r_section;
81 	old->r_class	= new->r_class;
82 	old->r_type	= new->r_type;
83 	old->r_ttl	= new->r_ttl;
84 	old->r_data	= new->r_data;
85 	old->r_size	= new->r_size;
86 	old->r_opcode	= new->r_opcode;
87 	old->r_grpnext	= 0;			/* XXX */
88 	old->r_dp	= new->r_dp;
89 	old->r_deldp	= new->r_deldp;
90 	old->r_zone	= new->r_zone;
91 
92 	return (0);
93 }
94 
95 
96 static void
97 delete_list(__ISC_ns_updrec *list) {
98 
99 	__ISC_ns_updrec	*next;
100 
101 	for (; list != 0; list = next) {
102 		next = list->r_link.next;
103 		__ISC_res_freeupdrec(list);
104 	}
105 }
106 
107 
108 static __ISC_ns_updrec *
109 copy_list(ns_updrec *old) {
110 
111 	__ISC_ns_updrec *list = 0, *r, *p;
112 
113 	if (old == 0)
114 		return (0);
115 
116 	for (p = 0; old != 0; old = old->r_next, p = r) {
117 		if ((r = calloc(1, sizeof (*r))) == 0 ||
118 			old2new(old, r) != 0) {
119 			free(r);
120 			delete_list(list);
121 			return (0);
122 		}
123 		r->r_link.prev = p;
124 		r->r_link.next = 0;
125 		if (p != 0)
126 			p->r_link.next = r;
127 		else
128 			list = r;
129 	}
130 
131 	return (list);
132 }
133 
134 
135 int
136 res_mkupdate(ns_updrec  *rrecp_in, u_char *buf, int length) {
137 
138 	__ISC_ns_updrec	*r;
139 	int		ret;
140 
141 	if ((r = copy_list(rrecp_in)) == 0)
142 		return (-1);
143 
144 	ret = __ISC_res_mkupdate(r, buf, length);
145 
146 	delete_list(r);
147 
148 	return (ret);
149 }
150 
151 
152 int
153 res_update(ns_updrec *rrecp_in) {
154 
155 	__ISC_ns_updrec	*r;
156 	int		ret;
157 
158 	if ((r = copy_list(rrecp_in)) == 0)
159 		return (-1);
160 
161 	ret = __ISC_res_update(r);
162 
163 	delete_list(r);
164 
165 	return (ret);
166 }
167 
168 
169 
170 ns_updrec *
171 res_mkupdrec(int section, const char *dname, uint_t class, uint_t type,
172 		uint_t ttl) {
173 
174 	__ISC_ns_updrec	*n;
175 	ns_updrec	*o;
176 
177 	n = __ISC_res_mkupdrec(section, dname, class, type, ttl);
178 	if (n == 0)
179 		return (0);
180 
181 	if ((o = calloc(1, sizeof (*o))) != 0) {
182 		if (new2old(n, o) != 0) {
183 			res_freeupdrec(o);
184 			o = 0;
185 		}
186 	}
187 
188 	__ISC_res_freeupdrec(n);
189 
190 	return (o);
191 }
192 
193 
194 void
195 res_freeupdrec(ns_updrec *rrecp) {
196 	if (rrecp == 0)
197 		return;
198 	/* Note: freeing r_dp is the caller's responsibility. */
199 	if (rrecp->r_dname != NULL)
200 		free(rrecp->r_dname);
201 	free(rrecp);
202 }
203