]> git.ipfire.org Git - thirdparty/dhcp.git/blame - dhcpctl/dhcpctl.c
Added option definition
[thirdparty/dhcp.git] / dhcpctl / dhcpctl.c
CommitLineData
1d6fed18
TL
1/* dhcpctl.c
2
3 Subroutines providing general support for objects. */
4
5/*
7512d88b 6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1999-2003 by Internet Software Consortium
1d6fed18 8 *
7512d88b
TM
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
1d6fed18 12 *
98311e4b
DH
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1d6fed18 20 *
98311e4b
DH
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
2c85ac9b 25 * https://www.isc.org/
49733f31 26 *
1d6fed18
TL
27 */
28
fe5b0fdd 29#include "dhcpd.h"
6a4c4be8 30#include <omapip/omapip_p.h>
1d6fed18
TL
31#include "dhcpctl.h"
32
33omapi_object_type_t *dhcpctl_callback_type;
b94dc677 34omapi_object_type_t *dhcpctl_remote_type;
1d6fed18
TL
35
36/* dhcpctl_initialize ()
37
38 Must be called before any other dhcpctl function. */
39
40dhcpctl_status dhcpctl_initialize ()
41{
e02a24b9
TL
42 isc_result_t status;
43
98bf1607 44 /* Set up the isc and dns library managers */
61ef216b
SR
45 status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
46 NULL, NULL);
98bf1607
SR
47 if (status != ISC_R_SUCCESS)
48 return status;
49
e02a24b9
TL
50 status = omapi_init();
51 if (status != ISC_R_SUCCESS)
52 return status;
53
54 status = omapi_object_type_register (&dhcpctl_callback_type,
55 "dhcpctl-callback",
56 dhcpctl_callback_set_value,
57 dhcpctl_callback_get_value,
58 dhcpctl_callback_destroy,
59 dhcpctl_callback_signal_handler,
60 dhcpctl_callback_stuff_values,
61 0, 0, 0, 0, 0, 0,
62 sizeof
98311e4b
DH
63 (dhcpctl_callback_object_t), 0,
64 RC_MISC);
e02a24b9
TL
65 if (status != ISC_R_SUCCESS)
66 return status;
67
68 status = omapi_object_type_register (&dhcpctl_remote_type,
69 "dhcpctl-remote",
70 dhcpctl_remote_set_value,
71 dhcpctl_remote_get_value,
72 dhcpctl_remote_destroy,
73 dhcpctl_remote_signal_handler,
74 dhcpctl_remote_stuff_values,
75 0, 0, 0, 0, 0, 0,
84864dd8 76 sizeof (dhcpctl_remote_object_t),
98311e4b 77 0, RC_MISC);
e02a24b9
TL
78 if (status != ISC_R_SUCCESS)
79 return status;
80
1d6fed18
TL
81 return ISC_R_SUCCESS;
82}
83
84/* dhcpctl_connect
85
86 synchronous
87 returns nonzero status code if it didn't connect, zero otherwise
88 stores connection handle through connection, which can be used
89 for subsequent access to the specified server.
90 server_name is the name of the server, and port is the TCP
91 port on which it is listening.
92 authinfo is the handle to an object containing authentication
93 information. */
94
95dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
b1b7b521 96 const char *server_name, int port,
1d6fed18
TL
97 dhcpctl_handle authinfo)
98{
99 isc_result_t status;
100
4bd8800e 101 status = omapi_generic_new (connection, MDL);
1d6fed18
TL
102 if (status != ISC_R_SUCCESS) {
103 return status;
104 }
105
106 status = omapi_protocol_connect (*connection, server_name,
871f37bf 107 (unsigned)port, authinfo);
275082dd
TL
108 if (status == ISC_R_SUCCESS)
109 return status;
98bf1607 110 if (status != DHCP_R_INCOMPLETE) {
4bd8800e 111 omapi_object_dereference (connection, MDL);
1d6fed18
TL
112 return status;
113 }
114
115 status = omapi_wait_for_completion (*connection, 0);
116 if (status != ISC_R_SUCCESS) {
4bd8800e 117 omapi_object_dereference (connection, MDL);
1d6fed18
TL
118 return status;
119 }
120
121 return status;
122}
123
1d6fed18
TL
124/* dhcpctl_wait_for_completion
125
126 synchronous
127 returns zero if the callback completes, a nonzero status if
128 there was some problem relating to the wait operation. The
129 status of the queued request will be stored through s, and
130 will also be either zero for success or nonzero for some kind
131 of failure. Never returns until completion or until the
132 connection to the server is lost. This performs the same
133 function as dhcpctl_set_callback and the subsequent callback,
134 for programs that want to do inline execution instead of using
135 callbacks. */
136
137dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
138 dhcpctl_status *s)
139{
b94dc677
TL
140 isc_result_t status;
141 status = omapi_wait_for_completion (h, 0);
142 if (status != ISC_R_SUCCESS)
143 return status;
144 if (h -> type == dhcpctl_remote_type)
145 *s = ((dhcpctl_remote_object_t *)h) -> waitstatus;
146 return ISC_R_SUCCESS;
1d6fed18
TL
147}
148
149/* dhcpctl_get_value
150
151 synchronous
152 returns zero if the call succeeded, a nonzero status code if
153 it didn't.
154 result is the address of an empty data string (initialized
155 with bzero or cleared with data_string_forget). On
156 successful completion, the addressed data string will contain
157 the value that was fetched.
158 dhcpctl_handle refers to some dhcpctl item
159 value_name refers to some value related to that item - e.g.,
160 for a handle associated with a completed host lookup, value
161 could be one of "hardware-address", "dhcp-client-identifier",
162 "known" or "client-hostname". */
163
164dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result,
b1b7b521 165 dhcpctl_handle h, const char *value_name)
1d6fed18
TL
166{
167 isc_result_t status;
168 omapi_value_t *tv = (omapi_value_t *)0;
b1b7b521 169 unsigned len;
1d6fed18
TL
170 int ip;
171
d2513ce0 172 status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv);
1d6fed18
TL
173 if (status != ISC_R_SUCCESS)
174 return status;
1d6fed18
TL
175
176 switch (tv -> value -> type) {
177 case omapi_datatype_int:
178 len = sizeof (int);
179 break;
180
181 case omapi_datatype_string:
182 case omapi_datatype_data:
183 len = tv -> value -> u.buffer.len;
184 break;
185
186 case omapi_datatype_object:
187 len = sizeof (omapi_handle_t);
188 break;
189
190 default:
4bd8800e 191 omapi_typed_data_dereference (&tv -> value, MDL);
1d6fed18
TL
192 return ISC_R_UNEXPECTED;
193 }
194
4bd8800e 195 status = omapi_data_string_new (result, len, MDL);
1d6fed18 196 if (status != ISC_R_SUCCESS) {
4bd8800e 197 omapi_typed_data_dereference (&tv -> value, MDL);
1d6fed18
TL
198 return status;
199 }
200
201 switch (tv -> value -> type) {
202 case omapi_datatype_int:
203 ip = htonl (tv -> value -> u.integer);
204 memcpy ((*result) -> value, &ip, sizeof ip);
205 break;
206
207 case omapi_datatype_string:
208 case omapi_datatype_data:
209 memcpy ((*result) -> value,
210 tv -> value -> u.buffer.value,
211 tv -> value -> u.buffer.len);
212 break;
213
214 case omapi_datatype_object:
215 ip = htonl (tv -> value -> u.object -> handle);
216 memcpy ((*result) -> value, &ip, sizeof ip);
217 break;
218 }
219
4bd8800e 220 omapi_value_dereference (&tv, MDL);
1d6fed18
TL
221 return ISC_R_SUCCESS;
222}
223
224/* dhcpctl_get_boolean
225
226 like dhcpctl_get_value, but more convenient for boolean
227 values, since no data_string needs to be dealt with. */
228
229dhcpctl_status dhcpctl_get_boolean (int *result,
b1b7b521 230 dhcpctl_handle h, const char *value_name)
1d6fed18
TL
231{
232 isc_result_t status;
233 dhcpctl_data_string data = (dhcpctl_data_string)0;
234 int rv;
235
236 status = dhcpctl_get_value (&data, h, value_name);
237 if (status != ISC_R_SUCCESS)
238 return status;
239 if (data -> len != sizeof rv) {
4bd8800e 240 omapi_data_string_dereference (&data, MDL);
1d6fed18
TL
241 return ISC_R_UNEXPECTED;
242 }
243 memcpy (&rv, data -> value, sizeof rv);
244 *result = ntohl (rv);
36e2c224 245 omapi_data_string_dereference (&data, MDL);
1d6fed18
TL
246 return ISC_R_SUCCESS;
247}
248
249/* dhcpctl_set_value
250
251 Sets a value on an object referred to by a dhcpctl_handle.
252 The opposite of dhcpctl_get_value. Does not update the
253 server - just sets the value on the handle. */
254
255dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value,
b1b7b521 256 const char *value_name)
1d6fed18
TL
257{
258 isc_result_t status;
259 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
260 omapi_data_string_t *name = (omapi_data_string_t *)0;
1d6fed18 261
4bd8800e 262 status = omapi_data_string_new (&name, strlen (value_name), MDL);
1d6fed18
TL
263 if (status != ISC_R_SUCCESS)
264 return status;
d2513ce0 265 memcpy (name -> value, value_name, strlen (value_name));
1d6fed18 266
4bd8800e 267 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data,
1d6fed18
TL
268 value -> len);
269 if (status != ISC_R_SUCCESS) {
4bd8800e 270 omapi_data_string_dereference (&name, MDL);
1d6fed18
TL
271 return status;
272 }
273 memcpy (tv -> u.buffer.value, value -> value, value -> len);
274
275 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
4bd8800e
TL
276 omapi_data_string_dereference (&name, MDL);
277 omapi_typed_data_dereference (&tv, MDL);
1d6fed18
TL
278 return status;
279}
280
281/* dhcpctl_set_string_value
282
283 Sets a NUL-terminated ASCII value on an object referred to by
284 a dhcpctl_handle. like dhcpctl_set_value, but saves the
285 trouble of creating a data_string for a NUL-terminated string.
286 Does not update the server - just sets the value on the handle. */
287
7528da64
TL
288dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value,
289 const char *value_name)
1d6fed18
TL
290{
291 isc_result_t status;
292 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
293 omapi_data_string_t *name = (omapi_data_string_t *)0;
1d6fed18 294
4bd8800e 295 status = omapi_data_string_new (&name, strlen (value_name), MDL);
1d6fed18
TL
296 if (status != ISC_R_SUCCESS)
297 return status;
d2513ce0 298 memcpy (name -> value, value_name, strlen (value_name));
1d6fed18 299
4bd8800e 300 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value);
1d6fed18 301 if (status != ISC_R_SUCCESS) {
4bd8800e 302 omapi_data_string_dereference (&name, MDL);
1d6fed18
TL
303 return status;
304 }
305
306 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
4bd8800e
TL
307 omapi_data_string_dereference (&name, MDL);
308 omapi_typed_data_dereference (&tv, MDL);
1d6fed18
TL
309 return status;
310}
311
31bbee78
TL
312/* dhcpctl_set_buffer_value
313
d758ad8c
TL
314 Sets a value on an object referred to by a dhcpctl_handle. like
315 dhcpctl_set_value, but saves the trouble of creating a data_string
316 for string for which we have a buffer and length. Does not update
317 the server - just sets the value on the handle. */
31bbee78
TL
318
319dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h,
320 const char *value, unsigned len,
321 const char *value_name)
322{
323 isc_result_t status;
324 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
325 omapi_data_string_t *name = (omapi_data_string_t *)0;
31bbee78
TL
326 unsigned ll;
327
328 ll = strlen (value_name);
329 status = omapi_data_string_new (&name, ll, MDL);
330 if (status != ISC_R_SUCCESS)
331 return status;
332 memcpy (name -> value, value_name, ll);
333
334 status = omapi_typed_data_new (MDL, &tv,
335 omapi_datatype_data, len, value);
336 if (status != ISC_R_SUCCESS) {
337 omapi_data_string_dereference (&name, MDL);
338 return status;
339 }
340 memcpy (tv -> u.buffer.value, value, len);
341
342 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
343 omapi_data_string_dereference (&name, MDL);
344 omapi_typed_data_dereference (&tv, MDL);
345 return status;
346}
347
d758ad8c
TL
348/* dhcpctl_set_null_value
349
350 Sets a null value on an object referred to by a dhcpctl_handle. */
351
352dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h,
353 const char *value_name)
354{
355 isc_result_t status;
356 omapi_data_string_t *name = (omapi_data_string_t *)0;
357 unsigned ll;
358
359 ll = strlen (value_name);
360 status = omapi_data_string_new (&name, ll, MDL);
361 if (status != ISC_R_SUCCESS)
362 return status;
363 memcpy (name -> value, value_name, ll);
364
365 status = omapi_set_value (h, (omapi_object_t *)0, name,
366 (omapi_typed_data_t *)0);
367 omapi_data_string_dereference (&name, MDL);
368 return status;
369}
370
d2513ce0
TL
371/* dhcpctl_set_boolean_value
372
373 Sets a boolean value on an object - like dhcpctl_set_value,
374 only more convenient for booleans. */
375
376dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value,
b1b7b521 377 const char *value_name)
d2513ce0
TL
378{
379 isc_result_t status;
380 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
381 omapi_data_string_t *name = (omapi_data_string_t *)0;
d2513ce0 382
4bd8800e 383 status = omapi_data_string_new (&name, strlen (value_name), MDL);
d2513ce0
TL
384 if (status != ISC_R_SUCCESS)
385 return status;
386 memcpy (name -> value, value_name, strlen (value_name));
387
4bd8800e 388 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
d2513ce0 389 if (status != ISC_R_SUCCESS) {
4bd8800e 390 omapi_data_string_dereference (&name, MDL);
d2513ce0
TL
391 return status;
392 }
393
394 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
4bd8800e
TL
395 omapi_data_string_dereference (&name, MDL);
396 omapi_typed_data_dereference (&tv, MDL);
d2513ce0
TL
397 return status;
398}
399
400/* dhcpctl_set_int_value
1d6fed18
TL
401
402 Sets a boolean value on an object - like dhcpctl_set_value,
403 only more convenient for booleans. */
404
d2513ce0 405dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value,
b1b7b521 406 const char *value_name)
1d6fed18
TL
407{
408 isc_result_t status;
409 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
410 omapi_data_string_t *name = (omapi_data_string_t *)0;
1d6fed18 411
4bd8800e 412 status = omapi_data_string_new (&name, strlen (value_name), MDL);
1d6fed18
TL
413 if (status != ISC_R_SUCCESS)
414 return status;
d2513ce0 415 memcpy (name -> value, value_name, strlen (value_name));
1d6fed18 416
4bd8800e 417 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
1d6fed18 418 if (status != ISC_R_SUCCESS) {
4bd8800e 419 omapi_data_string_dereference (&name, MDL);
1d6fed18
TL
420 return status;
421 }
422
423 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
4bd8800e
TL
424 omapi_data_string_dereference (&name, MDL);
425 omapi_typed_data_dereference (&tv, MDL);
1d6fed18
TL
426 return status;
427}
428
429/* dhcpctl_object_update
430
431 Queues an update on the object referenced by the handle (there
432 can't be any other work in progress on the handle). An
433 update means local parameters will be sent to the server. */
434
435dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection,
436 dhcpctl_handle h)
437{
438 isc_result_t status;
439 omapi_object_t *message = (omapi_object_t *)0;
3f75c8fa
TL
440 dhcpctl_remote_object_t *ro;
441
442 if (h -> type != dhcpctl_remote_type)
98bf1607 443 return DHCP_R_INVALIDARG;
3f75c8fa 444 ro = (dhcpctl_remote_object_t *)h;
1d6fed18 445
4bd8800e 446 status = omapi_message_new (&message, MDL);
1d6fed18 447 if (status != ISC_R_SUCCESS) {
4bd8800e 448 omapi_object_dereference (&message, MDL);
1d6fed18
TL
449 return status;
450 }
d2513ce0
TL
451 status = omapi_set_int_value (message, (omapi_object_t *)0,
452 "op", OMAPI_OP_UPDATE);
1d6fed18 453 if (status != ISC_R_SUCCESS) {
4bd8800e 454 omapi_object_dereference (&message, MDL);
1d6fed18
TL
455 return status;
456 }
3f75c8fa 457
d2513ce0
TL
458 status = omapi_set_object_value (message, (omapi_object_t *)0,
459 "object", h);
1d6fed18 460 if (status != ISC_R_SUCCESS) {
4bd8800e 461 omapi_object_dereference (&message, MDL);
1d6fed18
TL
462 return status;
463 }
464
3f75c8fa
TL
465 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
466 (int)(ro -> remote_handle));
467 if (status != ISC_R_SUCCESS) {
468 omapi_object_dereference (&message, MDL);
469 return status;
470 }
471
1d6fed18
TL
472 omapi_message_register (message);
473 status = omapi_protocol_send_message (connection -> outer,
474 (omapi_object_t *)0,
475 message, (omapi_object_t *)0);
4bd8800e 476 omapi_object_dereference (&message, MDL);
1d6fed18
TL
477 return status;
478}
479
480/* Requests a refresh on the object referenced by the handle (there
481 can't be any other work in progress on the handle). A
482 refresh means local parameters are updated from the server. */
483
484dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection,
485 dhcpctl_handle h)
486{
487 isc_result_t status;
488 omapi_object_t *message = (omapi_object_t *)0;
3f75c8fa
TL
489 dhcpctl_remote_object_t *ro;
490
491 if (h -> type != dhcpctl_remote_type)
98bf1607 492 return DHCP_R_INVALIDARG;
3f75c8fa 493 ro = (dhcpctl_remote_object_t *)h;
1d6fed18 494
4bd8800e 495 status = omapi_message_new (&message, MDL);
1d6fed18 496 if (status != ISC_R_SUCCESS) {
4bd8800e 497 omapi_object_dereference (&message, MDL);
1d6fed18
TL
498 return status;
499 }
d2513ce0
TL
500 status = omapi_set_int_value (message, (omapi_object_t *)0,
501 "op", OMAPI_OP_REFRESH);
1d6fed18 502 if (status != ISC_R_SUCCESS) {
4bd8800e 503 omapi_object_dereference (&message, MDL);
1d6fed18
TL
504 return status;
505 }
d2513ce0 506 status = omapi_set_int_value (message, (omapi_object_t *)0,
3f75c8fa 507 "handle", (int)(ro -> remote_handle));
1d6fed18 508 if (status != ISC_R_SUCCESS) {
4bd8800e 509 omapi_object_dereference (&message, MDL);
52f59a91
TL
510 return status;
511 }
512
513 omapi_message_register (message);
514 status = omapi_protocol_send_message (connection -> outer,
515 (omapi_object_t *)0,
516 message, (omapi_object_t *)0);
d758ad8c
TL
517
518 /* We don't want to send the contents of the object down the
519 wire, but we do need to reference it so that we know what
520 to do with the update. */
521 status = omapi_set_object_value (message, (omapi_object_t *)0,
522 "object", h);
523 if (status != ISC_R_SUCCESS) {
524 omapi_object_dereference (&message, MDL);
525 return status;
526 }
527
4bd8800e 528 omapi_object_dereference (&message, MDL);
52f59a91
TL
529 return status;
530}
531
83b89e97 532/* Requests the removal of the object referenced by the handle (there
52f59a91 533 can't be any other work in progress on the handle). A
83b89e97
TL
534 removal means that all searchable references to the object on the
535 server are deleted. */
52f59a91 536
83b89e97 537dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection,
52f59a91
TL
538 dhcpctl_handle h)
539{
540 isc_result_t status;
541 omapi_object_t *message = (omapi_object_t *)0;
542 dhcpctl_remote_object_t *ro;
543
544 if (h -> type != dhcpctl_remote_type)
98bf1607 545 return DHCP_R_INVALIDARG;
52f59a91
TL
546 ro = (dhcpctl_remote_object_t *)h;
547
4bd8800e 548 status = omapi_message_new (&message, MDL);
52f59a91 549 if (status != ISC_R_SUCCESS) {
4bd8800e 550 omapi_object_dereference (&message, MDL);
52f59a91
TL
551 return status;
552 }
553 status = omapi_set_int_value (message, (omapi_object_t *)0,
554 "op", OMAPI_OP_DELETE);
555 if (status != ISC_R_SUCCESS) {
4bd8800e 556 omapi_object_dereference (&message, MDL);
52f59a91
TL
557 return status;
558 }
559
560 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
b1b7b521 561 (int)(ro -> remote_handle));
52f59a91 562 if (status != ISC_R_SUCCESS) {
4bd8800e 563 omapi_object_dereference (&message, MDL);
52f59a91
TL
564 return status;
565 }
566
567 status = omapi_set_object_value (message, (omapi_object_t *)0,
568 "notify-object", h);
569 if (status != ISC_R_SUCCESS) {
4bd8800e 570 omapi_object_dereference (&message, MDL);
1d6fed18
TL
571 return status;
572 }
573
574 omapi_message_register (message);
575 status = omapi_protocol_send_message (connection -> outer,
576 (omapi_object_t *)0,
577 message, (omapi_object_t *)0);
4bd8800e 578 omapi_object_dereference (&message, MDL);
1d6fed18
TL
579 return status;
580}
581
29dd6d57 582isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp,
4bd8800e 583 const char *file, int line)
29dd6d57 584{
4bd8800e 585 return omapi_data_string_dereference (vp, file, line);
29dd6d57 586}