xdr.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
  2. /*
  3. * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  4. * unrestricted use provided that this legend is included on all tape
  5. * media and as a part of the software program in whole or part. Users
  6. * may copy or modify Sun RPC without charge, but are not authorized
  7. * to license or distribute it to anyone else except as part of a product or
  8. * program developed by the user.
  9. *
  10. * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  11. * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  12. * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  13. *
  14. * Sun RPC is provided with no support and without any obligation on the
  15. * part of Sun Microsystems, Inc. to assist in its use, correction,
  16. * modification or enhancement.
  17. *
  18. * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  19. * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  20. * OR ANY PART THEREOF.
  21. *
  22. * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  23. * or profits or other special, indirect and consequential damages, even if
  24. * Sun has been advised of the possibility of such damages.
  25. *
  26. * Sun Microsystems, Inc.
  27. * 2550 Garcia Avenue
  28. * Mountain View, California 94043
  29. */
  30. #if 0
  31. static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
  32. #endif
  33. /*
  34. * xdr.c, Generic XDR routines implementation.
  35. *
  36. * Copyright (C) 1986, Sun Microsystems, Inc.
  37. *
  38. * These are the "generic" xdr routines used to serialize and de-serialize
  39. * most common data items. See xdr.h for more info on the interface to
  40. * xdr.
  41. */
  42. #include <stdio.h>
  43. #include <limits.h>
  44. #include <string.h>
  45. #include <rpc/types.h>
  46. #include <rpc/xdr.h>
  47. /*
  48. * constants specific to the xdr "protocol"
  49. */
  50. #define XDR_FALSE ((long) 0)
  51. #define XDR_TRUE ((long) 1)
  52. #define LASTUNSIGNED ((u_int) 0-1)
  53. /*
  54. * for unit alignment
  55. */
  56. static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
  57. /*
  58. * Free a data structure using XDR
  59. * Not a filter, but a convenient utility nonetheless
  60. */
  61. void
  62. xdr_free (xdrproc_t proc, char *objp)
  63. {
  64. XDR x;
  65. x.x_op = XDR_FREE;
  66. (*proc) (&x, objp);
  67. }
  68. /*
  69. * XDR nothing
  70. */
  71. bool_t
  72. xdr_void (void)
  73. {
  74. return TRUE;
  75. }
  76. libc_hidden_def(xdr_void)
  77. /*
  78. * XDR long integers
  79. * The definition of xdr_long() is kept for backward
  80. * compatibility. Instead xdr_int() should be used.
  81. */
  82. bool_t
  83. xdr_long (XDR *xdrs, long *lp)
  84. {
  85. if (xdrs->x_op == XDR_ENCODE
  86. && (sizeof (int32_t) == sizeof (long)
  87. || (int32_t) *lp == *lp))
  88. return XDR_PUTLONG (xdrs, lp);
  89. if (xdrs->x_op == XDR_DECODE)
  90. return XDR_GETLONG (xdrs, lp);
  91. if (xdrs->x_op == XDR_FREE)
  92. return TRUE;
  93. return FALSE;
  94. }
  95. libc_hidden_def(xdr_long)
  96. /*
  97. * XDR short integers
  98. */
  99. bool_t
  100. xdr_short (XDR *xdrs, short *sp)
  101. {
  102. long l;
  103. switch (xdrs->x_op)
  104. {
  105. case XDR_ENCODE:
  106. l = (long) *sp;
  107. return XDR_PUTLONG (xdrs, &l);
  108. case XDR_DECODE:
  109. if (!XDR_GETLONG (xdrs, &l))
  110. {
  111. return FALSE;
  112. }
  113. *sp = (short) l;
  114. return TRUE;
  115. case XDR_FREE:
  116. return TRUE;
  117. }
  118. return FALSE;
  119. }
  120. libc_hidden_def(xdr_short)
  121. /*
  122. * XDR integers
  123. */
  124. bool_t
  125. xdr_int (XDR *xdrs, int *ip)
  126. {
  127. #if INT_MAX < LONG_MAX
  128. long l;
  129. switch (xdrs->x_op)
  130. {
  131. case XDR_ENCODE:
  132. l = (long) *ip;
  133. return XDR_PUTLONG (xdrs, &l);
  134. case XDR_DECODE:
  135. if (!XDR_GETLONG (xdrs, &l))
  136. {
  137. return FALSE;
  138. }
  139. *ip = (int) l;
  140. case XDR_FREE:
  141. return TRUE;
  142. }
  143. return FALSE;
  144. #elif INT_MAX == LONG_MAX
  145. return xdr_long (xdrs, (long *) ip);
  146. #elif INT_MAX == SHRT_MAX
  147. return xdr_short (xdrs, (short *) ip);
  148. #else
  149. #error unexpected integer sizes in xdr_int()
  150. #endif
  151. }
  152. libc_hidden_def(xdr_int)
  153. /*
  154. * XDR unsigned long integers
  155. * The definition of xdr_u_long() is kept for backward
  156. * compatibility. Instead xdr_u_int() should be used.
  157. */
  158. bool_t
  159. xdr_u_long (XDR *xdrs, u_long *ulp)
  160. {
  161. switch (xdrs->x_op)
  162. {
  163. case XDR_DECODE:
  164. {
  165. long int tmp;
  166. if (XDR_GETLONG (xdrs, &tmp) == FALSE)
  167. return FALSE;
  168. *ulp = (uint32_t) tmp;
  169. return TRUE;
  170. }
  171. case XDR_ENCODE:
  172. if (sizeof (uint32_t) != sizeof (u_long)
  173. && (uint32_t) *ulp != *ulp)
  174. return FALSE;
  175. return XDR_PUTLONG (xdrs, (long *) ulp);
  176. case XDR_FREE:
  177. return TRUE;
  178. }
  179. return FALSE;
  180. }
  181. libc_hidden_def(xdr_u_long)
  182. /*
  183. * XDR unsigned integers
  184. */
  185. bool_t
  186. xdr_u_int (XDR *xdrs, u_int *up)
  187. {
  188. #if UINT_MAX < ULONG_MAX
  189. u_long l;
  190. switch (xdrs->x_op)
  191. {
  192. case XDR_ENCODE:
  193. l = (u_long) * up;
  194. return XDR_PUTLONG (xdrs, (long *) &l);
  195. case XDR_DECODE:
  196. if (!XDR_GETLONG (xdrs, (long *) &l))
  197. {
  198. return FALSE;
  199. }
  200. *up = (u_int) l;
  201. case XDR_FREE:
  202. return TRUE;
  203. }
  204. return FALSE;
  205. #elif UINT_MAX == ULONG_MAX
  206. return xdr_u_long (xdrs, (u_long *) up);
  207. #elif UINT_MAX == USHRT_MAX
  208. return xdr_short (xdrs, (short *) up);
  209. #else
  210. #error unexpected integer sizes in xdr_u_int()
  211. #endif
  212. }
  213. libc_hidden_def(xdr_u_int)
  214. /*
  215. * XDR hyper integers
  216. * same as xdr_u_hyper - open coded to save a proc call!
  217. */
  218. bool_t
  219. xdr_hyper (XDR *xdrs, quad_t *llp)
  220. {
  221. long t1;
  222. unsigned long t2;
  223. if (xdrs->x_op == XDR_ENCODE)
  224. {
  225. t1 = (long) ((*llp) >> 32);
  226. t2 = (long) (*llp);
  227. return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, (long *) &t2));
  228. }
  229. if (xdrs->x_op == XDR_DECODE)
  230. {
  231. if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, (long *) &t2))
  232. return FALSE;
  233. /* t2 must be unsigned for this to work */
  234. *llp = ((quad_t) t1) << 32;
  235. *llp |= t2;
  236. return TRUE;
  237. }
  238. if (xdrs->x_op == XDR_FREE)
  239. return TRUE;
  240. return FALSE;
  241. }
  242. libc_hidden_def(xdr_hyper)
  243. /*
  244. * XDR hyper integers
  245. * same as xdr_hyper - open coded to save a proc call!
  246. */
  247. bool_t
  248. xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
  249. {
  250. unsigned long t1;
  251. unsigned long t2;
  252. if (xdrs->x_op == XDR_ENCODE)
  253. {
  254. t1 = (unsigned long) ((*ullp) >> 32);
  255. t2 = (unsigned long) (*ullp);
  256. return (XDR_PUTLONG(xdrs, (long *) &t1) && XDR_PUTLONG(xdrs, (long *) &t2));
  257. }
  258. if (xdrs->x_op == XDR_DECODE)
  259. {
  260. if (!XDR_GETLONG(xdrs, (long *) &t1) || !XDR_GETLONG(xdrs, (long *) &t2))
  261. return FALSE;
  262. *ullp = ((u_quad_t) t1) << 32;
  263. *ullp |= t2;
  264. return TRUE;
  265. }
  266. if (xdrs->x_op == XDR_FREE)
  267. return TRUE;
  268. return FALSE;
  269. }
  270. libc_hidden_def(xdr_u_hyper)
  271. bool_t
  272. xdr_longlong_t (XDR *xdrs, quad_t *llp)
  273. {
  274. return xdr_hyper (xdrs, llp);
  275. }
  276. bool_t
  277. xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
  278. {
  279. return xdr_u_hyper (xdrs, ullp);
  280. }
  281. /*
  282. * XDR unsigned short integers
  283. */
  284. bool_t
  285. xdr_u_short (XDR *xdrs, u_short *usp)
  286. {
  287. u_long l;
  288. switch (xdrs->x_op)
  289. {
  290. case XDR_ENCODE:
  291. l = (u_long) * usp;
  292. return XDR_PUTLONG (xdrs, (long *) &l);
  293. case XDR_DECODE:
  294. if (!XDR_GETLONG (xdrs, (long *) &l))
  295. {
  296. return FALSE;
  297. }
  298. *usp = (u_short) l;
  299. return TRUE;
  300. case XDR_FREE:
  301. return TRUE;
  302. }
  303. return FALSE;
  304. }
  305. libc_hidden_def(xdr_u_short)
  306. /*
  307. * XDR a char
  308. */
  309. bool_t
  310. xdr_char (XDR *xdrs, char *cp)
  311. {
  312. int i;
  313. i = (*cp);
  314. if (!xdr_int (xdrs, &i))
  315. {
  316. return FALSE;
  317. }
  318. *cp = i;
  319. return TRUE;
  320. }
  321. /*
  322. * XDR an unsigned char
  323. */
  324. bool_t
  325. xdr_u_char (XDR *xdrs, u_char *cp)
  326. {
  327. u_int u;
  328. u = (*cp);
  329. if (!xdr_u_int (xdrs, &u))
  330. {
  331. return FALSE;
  332. }
  333. *cp = u;
  334. return TRUE;
  335. }
  336. /*
  337. * XDR booleans
  338. */
  339. bool_t
  340. xdr_bool (XDR *xdrs, bool_t *bp)
  341. {
  342. long lb;
  343. switch (xdrs->x_op)
  344. {
  345. case XDR_ENCODE:
  346. lb = *bp ? XDR_TRUE : XDR_FALSE;
  347. return XDR_PUTLONG (xdrs, &lb);
  348. case XDR_DECODE:
  349. if (!XDR_GETLONG (xdrs, &lb))
  350. {
  351. return FALSE;
  352. }
  353. *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  354. return TRUE;
  355. case XDR_FREE:
  356. return TRUE;
  357. }
  358. return FALSE;
  359. }
  360. libc_hidden_def(xdr_bool)
  361. /*
  362. * XDR enumerations
  363. */
  364. bool_t
  365. xdr_enum (XDR *xdrs, enum_t *ep)
  366. {
  367. enum sizecheck
  368. {
  369. SIZEVAL
  370. }; /* used to find the size of an enum */
  371. /*
  372. * enums are treated as ints
  373. */
  374. if (sizeof (enum sizecheck) == 4)
  375. {
  376. #if INT_MAX < LONG_MAX
  377. long l;
  378. switch (xdrs->x_op)
  379. {
  380. case XDR_ENCODE:
  381. l = *ep;
  382. return XDR_PUTLONG (xdrs, &l);
  383. case XDR_DECODE:
  384. if (!XDR_GETLONG (xdrs, &l))
  385. {
  386. return FALSE;
  387. }
  388. *ep = l;
  389. case XDR_FREE:
  390. return TRUE;
  391. }
  392. return FALSE;
  393. #else
  394. return xdr_long (xdrs, (long *) ep);
  395. #endif
  396. }
  397. else if (sizeof (enum sizecheck) == sizeof (short))
  398. {
  399. return xdr_short (xdrs, (short *) ep);
  400. }
  401. else
  402. {
  403. return FALSE;
  404. }
  405. }
  406. libc_hidden_def(xdr_enum)
  407. /*
  408. * XDR opaque data
  409. * Allows the specification of a fixed size sequence of opaque bytes.
  410. * cp points to the opaque object and cnt gives the byte length.
  411. */
  412. bool_t
  413. xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
  414. {
  415. u_int rndup;
  416. static char crud[BYTES_PER_XDR_UNIT];
  417. /*
  418. * if no data we are done
  419. */
  420. if (cnt == 0)
  421. return TRUE;
  422. /*
  423. * round byte count to full xdr units
  424. */
  425. rndup = cnt % BYTES_PER_XDR_UNIT;
  426. if (rndup > 0)
  427. rndup = BYTES_PER_XDR_UNIT - rndup;
  428. switch (xdrs->x_op)
  429. {
  430. case XDR_DECODE:
  431. if (!XDR_GETBYTES (xdrs, cp, cnt))
  432. {
  433. return FALSE;
  434. }
  435. if (rndup == 0)
  436. return TRUE;
  437. return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
  438. case XDR_ENCODE:
  439. if (!XDR_PUTBYTES (xdrs, cp, cnt))
  440. {
  441. return FALSE;
  442. }
  443. if (rndup == 0)
  444. return TRUE;
  445. return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
  446. case XDR_FREE:
  447. return TRUE;
  448. }
  449. return FALSE;
  450. }
  451. libc_hidden_def(xdr_opaque)
  452. /*
  453. * XDR counted bytes
  454. * *cpp is a pointer to the bytes, *sizep is the count.
  455. * If *cpp is NULL maxsize bytes are allocated
  456. */
  457. bool_t
  458. xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
  459. {
  460. char *sp = *cpp; /* sp is the actual string pointer */
  461. u_int nodesize;
  462. /*
  463. * first deal with the length since xdr bytes are counted
  464. */
  465. if (!xdr_u_int (xdrs, sizep))
  466. {
  467. return FALSE;
  468. }
  469. nodesize = *sizep;
  470. if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
  471. {
  472. return FALSE;
  473. }
  474. /*
  475. * now deal with the actual bytes
  476. */
  477. switch (xdrs->x_op)
  478. {
  479. case XDR_DECODE:
  480. if (nodesize == 0)
  481. {
  482. return TRUE;
  483. }
  484. if (sp == NULL)
  485. {
  486. *cpp = sp = (char *) mem_alloc (nodesize);
  487. }
  488. if (sp == NULL)
  489. {
  490. (void) fputs ("xdr_bytes: out of memory\n", stderr);
  491. return FALSE;
  492. }
  493. /* fall into ... */
  494. case XDR_ENCODE:
  495. return xdr_opaque (xdrs, sp, nodesize);
  496. case XDR_FREE:
  497. if (sp != NULL)
  498. {
  499. mem_free (sp, nodesize);
  500. *cpp = NULL;
  501. }
  502. return TRUE;
  503. }
  504. return FALSE;
  505. }
  506. libc_hidden_def(xdr_bytes)
  507. /*
  508. * Implemented here due to commonality of the object.
  509. */
  510. bool_t
  511. xdr_netobj (XDR *xdrs, struct netobj *np)
  512. {
  513. return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
  514. }
  515. /*
  516. * XDR a discriminated union
  517. * Support routine for discriminated unions.
  518. * You create an array of xdrdiscrim structures, terminated with
  519. * an entry with a null procedure pointer. The routine gets
  520. * the discriminant value and then searches the array of xdrdiscrims
  521. * looking for that value. It calls the procedure given in the xdrdiscrim
  522. * to handle the discriminant. If there is no specific routine a default
  523. * routine may be called.
  524. * If there is no specific or default routine an error is returned.
  525. */
  526. bool_t
  527. xdr_union (XDR *xdrs, enum_t *dscmp, char *unp, const struct xdr_discrim *choices, xdrproc_t dfault)
  528. {
  529. enum_t dscm;
  530. /*
  531. * we deal with the discriminator; it's an enum
  532. */
  533. if (!xdr_enum (xdrs, dscmp))
  534. {
  535. return FALSE;
  536. }
  537. dscm = *dscmp;
  538. /*
  539. * search choices for a value that matches the discriminator.
  540. * if we find one, execute the xdr routine for that value.
  541. */
  542. for (; choices->proc != NULL_xdrproc_t; choices++)
  543. {
  544. if (choices->value == dscm)
  545. return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
  546. }
  547. /*
  548. * no match - execute the default xdr routine if there is one
  549. */
  550. return ((dfault == NULL_xdrproc_t) ? FALSE :
  551. (*dfault) (xdrs, unp, LASTUNSIGNED));
  552. }
  553. libc_hidden_def(xdr_union)
  554. /*
  555. * Non-portable xdr primitives.
  556. * Care should be taken when moving these routines to new architectures.
  557. */
  558. /*
  559. * XDR null terminated ASCII strings
  560. * xdr_string deals with "C strings" - arrays of bytes that are
  561. * terminated by a NULL character. The parameter cpp references a
  562. * pointer to storage; If the pointer is null, then the necessary
  563. * storage is allocated. The last parameter is the max allowed length
  564. * of the string as specified by a protocol.
  565. */
  566. bool_t
  567. xdr_string (XDR *xdrs, char **cpp, u_int maxsize)
  568. {
  569. char *sp = *cpp; /* sp is the actual string pointer */
  570. u_int size;
  571. u_int nodesize;
  572. /*
  573. * first deal with the length since xdr strings are counted-strings
  574. */
  575. switch (xdrs->x_op)
  576. {
  577. case XDR_FREE:
  578. if (sp == NULL)
  579. {
  580. return TRUE; /* already free */
  581. }
  582. /* fall through... */
  583. case XDR_ENCODE:
  584. if (sp == NULL)
  585. return FALSE;
  586. size = strlen (sp);
  587. break;
  588. case XDR_DECODE:
  589. break;
  590. }
  591. if (!xdr_u_int (xdrs, &size))
  592. {
  593. return FALSE;
  594. }
  595. if (size > maxsize)
  596. {
  597. return FALSE;
  598. }
  599. nodesize = size + 1;
  600. /*
  601. * now deal with the actual bytes
  602. */
  603. switch (xdrs->x_op)
  604. {
  605. case XDR_DECODE:
  606. if (nodesize == 0)
  607. {
  608. return TRUE;
  609. }
  610. if (sp == NULL)
  611. *cpp = sp = (char *) mem_alloc (nodesize);
  612. if (sp == NULL)
  613. {
  614. (void) fputs ("xdr_string: out of memory\n", stderr);
  615. return FALSE;
  616. }
  617. sp[size] = 0;
  618. /* fall into ... */
  619. case XDR_ENCODE:
  620. return xdr_opaque (xdrs, sp, size);
  621. case XDR_FREE:
  622. mem_free (sp, nodesize);
  623. *cpp = NULL;
  624. return TRUE;
  625. }
  626. return FALSE;
  627. }
  628. libc_hidden_def(xdr_string)
  629. /*
  630. * Wrapper for xdr_string that can be called directly from
  631. * routines like clnt_call
  632. */
  633. bool_t
  634. xdr_wrapstring (XDR *xdrs, char **cpp)
  635. {
  636. if (xdr_string (xdrs, cpp, LASTUNSIGNED))
  637. {
  638. return TRUE;
  639. }
  640. return FALSE;
  641. }