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