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 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 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 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 * 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 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 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 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 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 * 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 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