conversions.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  1. #ifdef __sun
  2. /* to enable 'new' ancillary data layout instead */
  3. # define _XPG4_2
  4. #endif
  5. #include "sockaddr_conv.h"
  6. #include "conversions.h"
  7. #include "sendrecvmsg.h" /* for ancillary registry */
  8. #ifdef PHP_WIN32
  9. # include "windows_common.h"
  10. #endif
  11. #include <Zend/zend_llist.h>
  12. #include <zend_smart_str.h>
  13. #ifndef PHP_WIN32
  14. # include <sys/types.h>
  15. # include <sys/socket.h>
  16. # include <arpa/inet.h>
  17. # include <netinet/in.h>
  18. # include <sys/un.h>
  19. # include <sys/ioctl.h>
  20. # include <net/if.h>
  21. #else
  22. # include <stdint.h>
  23. #endif
  24. #include <limits.h>
  25. #include <stdarg.h>
  26. #include <stddef.h>
  27. #ifdef PHP_WIN32
  28. typedef unsigned short sa_family_t;
  29. # define msghdr _WSAMSG
  30. /*
  31. struct _WSAMSG {
  32. LPSOCKADDR name; //void *msg_name
  33. INT namelen; //socklen_t msg_namelen
  34. LPWSABUF lpBuffers; //struct iovec *msg_iov
  35. ULONG dwBufferCount; //size_t msg_iovlen
  36. WSABUF Control; //void *msg_control, size_t msg_controllen
  37. DWORD dwFlags; //int msg_flags
  38. }
  39. */
  40. # define msg_name name
  41. # define msg_namelen namelen
  42. # define msg_iov lpBuffers
  43. # define msg_iovlen dwBufferCount
  44. # define msg_control Control.buf
  45. # define msg_controllen Control.len
  46. # define msg_flags dwFlags
  47. # define iov_base buf
  48. # define iov_len len
  49. # ifdef CMSG_DATA
  50. # undef CMSG_DATA
  51. # endif
  52. # define CMSG_DATA WSA_CMSG_DATA
  53. #endif
  54. #define MAX_USER_BUFF_SIZE ((size_t)(100*1024*1024))
  55. #define DEFAULT_BUFF_SIZE 8192
  56. struct _ser_context {
  57. HashTable params; /* stores pointers; has to be first */
  58. struct err_s err;
  59. zend_llist keys,
  60. /* common part to res_context ends here */
  61. allocations;
  62. php_socket *sock;
  63. };
  64. struct _res_context {
  65. HashTable params; /* stores pointers; has to be first */
  66. struct err_s err;
  67. zend_llist keys;
  68. };
  69. typedef struct {
  70. /* zval info */
  71. const char *name;
  72. unsigned name_size;
  73. int required;
  74. /* structure info */
  75. size_t field_offset; /* 0 to pass full structure, e.g. when more than
  76. one field is to be changed; in that case the
  77. callbacks need to know the name of the fields */
  78. /* callbacks */
  79. from_zval_write_field *from_zval;
  80. to_zval_read_field *to_zval;
  81. } field_descriptor;
  82. #define KEY_FILL_SOCKADDR "fill_sockaddr"
  83. #define KEY_RECVMSG_RET "recvmsg_ret"
  84. #define KEY_CMSG_LEN "cmsg_len"
  85. const struct key_value empty_key_value_list[] = {{0}};
  86. /* PARAMETERS */
  87. static int param_get_bool(void *ctx, const char *key, int def)
  88. {
  89. int *elem;
  90. if ((elem = zend_hash_str_find_ptr(ctx, key, strlen(key))) != NULL) {
  91. return *elem;
  92. } else {
  93. return def;
  94. }
  95. }
  96. /* MEMORY */
  97. static inline void *accounted_emalloc(size_t alloc_size, ser_context *ctx)
  98. {
  99. void *ret = emalloc(alloc_size);
  100. zend_llist_add_element(&ctx->allocations, &ret);
  101. return ret;
  102. }
  103. static inline void *accounted_ecalloc(size_t nmemb, size_t alloc_size, ser_context *ctx)
  104. {
  105. void *ret = ecalloc(nmemb, alloc_size);
  106. zend_llist_add_element(&ctx->allocations, &ret);
  107. return ret;
  108. }
  109. static inline void *accounted_safe_ecalloc(size_t nmemb, size_t alloc_size, size_t offset, ser_context *ctx)
  110. {
  111. void *ret = safe_emalloc(nmemb, alloc_size, offset);
  112. memset(ret, '\0', nmemb * alloc_size + offset);
  113. zend_llist_add_element(&ctx->allocations, &ret);
  114. return ret;
  115. }
  116. /* ERRORS */
  117. static void do_from_to_zval_err(struct err_s *err,
  118. zend_llist *keys,
  119. const char *what_conv,
  120. const char *fmt,
  121. va_list ap)
  122. {
  123. smart_str path = {0};
  124. const char **node;
  125. char *user_msg;
  126. int user_msg_size;
  127. zend_llist_position pos;
  128. if (err->has_error) {
  129. return;
  130. }
  131. for (node = zend_llist_get_first_ex(keys, &pos);
  132. node != NULL;
  133. node = zend_llist_get_next_ex(keys, &pos)) {
  134. smart_str_appends(&path, *node);
  135. smart_str_appends(&path, " > ");
  136. }
  137. if (path.s && ZSTR_LEN(path.s) > 3) {
  138. ZSTR_LEN(path.s) -= 3;
  139. }
  140. smart_str_0(&path);
  141. user_msg_size = vspprintf(&user_msg, 0, fmt, ap);
  142. err->has_error = 1;
  143. err->level = E_WARNING;
  144. spprintf(&err->msg, 0, "error converting %s data (path: %s): %.*s",
  145. what_conv,
  146. path.s && *ZSTR_VAL(path.s) != '\0' ? ZSTR_VAL(path.s) : "unavailable",
  147. user_msg_size, user_msg);
  148. err->should_free = 1;
  149. efree(user_msg);
  150. smart_str_free(&path);
  151. }
  152. ZEND_ATTRIBUTE_FORMAT(printf, 2 ,3)
  153. static void do_from_zval_err(ser_context *ctx, const char *fmt, ...)
  154. {
  155. va_list ap;
  156. va_start(ap, fmt);
  157. do_from_to_zval_err(&ctx->err, &ctx->keys, "user", fmt, ap);
  158. va_end(ap);
  159. }
  160. ZEND_ATTRIBUTE_FORMAT(printf, 2 ,3)
  161. static void do_to_zval_err(res_context *ctx, const char *fmt, ...)
  162. {
  163. va_list ap;
  164. va_start(ap, fmt);
  165. do_from_to_zval_err(&ctx->err, &ctx->keys, "native", fmt, ap);
  166. va_end(ap);
  167. }
  168. void err_msg_dispose(struct err_s *err)
  169. {
  170. if (err->msg != NULL) {
  171. php_error_docref(NULL, err->level, "%s", err->msg);
  172. if (err->should_free) {
  173. efree(err->msg);
  174. }
  175. }
  176. }
  177. void allocations_dispose(zend_llist **allocations)
  178. {
  179. zend_llist_destroy(*allocations);
  180. efree(*allocations);
  181. *allocations = NULL;
  182. }
  183. static unsigned from_array_iterate(const zval *arr,
  184. void (*func)(zval *elem, unsigned i, void **args, ser_context *ctx),
  185. void **args,
  186. ser_context *ctx)
  187. {
  188. unsigned i;
  189. zval *elem;
  190. char buf[sizeof("element #4294967295")];
  191. char *bufp = buf;
  192. /* Note i starts at 1, not 0! */
  193. i = 1;
  194. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), elem) {
  195. if ((size_t)snprintf(buf, sizeof(buf), "element #%u", i) >= sizeof(buf)) {
  196. memcpy(buf, "element", sizeof("element"));
  197. }
  198. zend_llist_add_element(&ctx->keys, &bufp);
  199. func(elem, i, args, ctx);
  200. zend_llist_remove_tail(&ctx->keys);
  201. if (ctx->err.has_error) {
  202. break;
  203. }
  204. i++;
  205. } ZEND_HASH_FOREACH_END();
  206. return i -1;
  207. }
  208. /* Generic Aggregated conversions */
  209. static void from_zval_write_aggregation(const zval *container,
  210. char *structure,
  211. const field_descriptor *descriptors,
  212. ser_context *ctx)
  213. {
  214. const field_descriptor *descr;
  215. zval *elem;
  216. if (Z_TYPE_P(container) != IS_ARRAY) {
  217. do_from_zval_err(ctx, "%s", "expected an array here");
  218. }
  219. for (descr = descriptors; descr->name != NULL && !ctx->err.has_error; descr++) {
  220. if ((elem = zend_hash_str_find(Z_ARRVAL_P(container),
  221. descr->name, descr->name_size - 1)) != NULL) {
  222. if (descr->from_zval == NULL) {
  223. do_from_zval_err(ctx, "No information on how to convert value "
  224. "of key '%s'", descr->name);
  225. break;
  226. }
  227. zend_llist_add_element(&ctx->keys, (void*)&descr->name);
  228. descr->from_zval(elem, ((char*)structure) + descr->field_offset, ctx);
  229. zend_llist_remove_tail(&ctx->keys);
  230. } else if (descr->required) {
  231. do_from_zval_err(ctx, "The key '%s' is required", descr->name);
  232. break;
  233. }
  234. }
  235. }
  236. static void to_zval_read_aggregation(const char *structure,
  237. zval *zarr, /* initialized array */
  238. const field_descriptor *descriptors,
  239. res_context *ctx)
  240. {
  241. const field_descriptor *descr;
  242. assert(Z_TYPE_P(zarr) == IS_ARRAY);
  243. assert(Z_ARRVAL_P(zarr) != NULL);
  244. for (descr = descriptors; descr->name != NULL && !ctx->err.has_error; descr++) {
  245. zval *new_zv, tmp;
  246. if (descr->to_zval == NULL) {
  247. do_to_zval_err(ctx, "No information on how to convert native "
  248. "field into value for key '%s'", descr->name);
  249. break;
  250. }
  251. ZVAL_NULL(&tmp);
  252. new_zv = zend_symtable_str_update(Z_ARRVAL_P(zarr), descr->name, descr->name_size - 1, &tmp);
  253. zend_llist_add_element(&ctx->keys, (void*)&descr->name);
  254. descr->to_zval(structure + descr->field_offset, new_zv, ctx);
  255. zend_llist_remove_tail(&ctx->keys);
  256. }
  257. }
  258. /* CONVERSIONS for integers */
  259. static zend_long from_zval_integer_common(const zval *arr_value, ser_context *ctx)
  260. {
  261. zend_long ret = 0;
  262. zval lzval;
  263. ZVAL_NULL(&lzval);
  264. if (Z_TYPE_P(arr_value) != IS_LONG) {
  265. ZVAL_COPY(&lzval, (zval *)arr_value);
  266. arr_value = &lzval;
  267. }
  268. switch (Z_TYPE_P(arr_value)) {
  269. case IS_LONG:
  270. long_case:
  271. ret = Z_LVAL_P(arr_value);
  272. break;
  273. /* if not long we're operating on lzval */
  274. case IS_DOUBLE:
  275. double_case:
  276. convert_to_long(&lzval);
  277. goto long_case;
  278. case IS_OBJECT:
  279. case IS_STRING: {
  280. zend_long lval;
  281. double dval;
  282. if (!try_convert_to_string(&lzval)) {
  283. ctx->err.has_error = 1;
  284. break;
  285. }
  286. switch (is_numeric_string(Z_STRVAL(lzval), Z_STRLEN(lzval), &lval, &dval, 0)) {
  287. case IS_DOUBLE:
  288. zval_ptr_dtor_str(&lzval);
  289. ZVAL_DOUBLE(&lzval, dval);
  290. goto double_case;
  291. case IS_LONG:
  292. zval_ptr_dtor_str(&lzval);
  293. ZVAL_LONG(&lzval, lval);
  294. goto long_case;
  295. }
  296. /* if we get here, we don't have a numeric string */
  297. do_from_zval_err(ctx, "expected an integer, but got a non numeric "
  298. "string (possibly from a converted object): '%s'", Z_STRVAL_P(arr_value));
  299. break;
  300. }
  301. default:
  302. do_from_zval_err(ctx, "%s", "expected an integer, either of a PHP "
  303. "integer type or of a convertible type");
  304. break;
  305. }
  306. zval_ptr_dtor(&lzval);
  307. return ret;
  308. }
  309. void from_zval_write_int(const zval *arr_value, char *field, ser_context *ctx)
  310. {
  311. zend_long lval;
  312. int ival;
  313. lval = from_zval_integer_common(arr_value, ctx);
  314. if (ctx->err.has_error) {
  315. return;
  316. }
  317. if (lval > INT_MAX || lval < INT_MIN) {
  318. do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
  319. "for a native int");
  320. return;
  321. }
  322. ival = (int)lval;
  323. memcpy(field, &ival, sizeof(ival));
  324. }
  325. static void from_zval_write_uint32(const zval *arr_value, char *field, ser_context *ctx)
  326. {
  327. zend_long lval;
  328. uint32_t ival;
  329. lval = from_zval_integer_common(arr_value, ctx);
  330. if (ctx->err.has_error) {
  331. return;
  332. }
  333. if (sizeof(zend_long) > sizeof(uint32_t) && (lval < 0 || lval > 0xFFFFFFFF)) {
  334. do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
  335. "for an unsigned 32-bit integer");
  336. return;
  337. }
  338. ival = (uint32_t)lval;
  339. memcpy(field, &ival, sizeof(ival));
  340. }
  341. static void from_zval_write_net_uint16(const zval *arr_value, char *field, ser_context *ctx)
  342. {
  343. zend_long lval;
  344. uint16_t ival;
  345. lval = from_zval_integer_common(arr_value, ctx);
  346. if (ctx->err.has_error) {
  347. return;
  348. }
  349. if (lval < 0 || lval > 0xFFFF) {
  350. do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
  351. "for an unsigned 16-bit integer");
  352. return;
  353. }
  354. ival = htons((uint16_t)lval);
  355. memcpy(field, &ival, sizeof(ival));
  356. }
  357. static void from_zval_write_sa_family(const zval *arr_value, char *field, ser_context *ctx)
  358. {
  359. zend_long lval;
  360. sa_family_t ival;
  361. lval = from_zval_integer_common(arr_value, ctx);
  362. if (ctx->err.has_error) {
  363. return;
  364. }
  365. if (lval < 0 || lval > (sa_family_t)-1) { /* sa_family_t is unsigned */
  366. do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
  367. "for a sa_family_t value");
  368. return;
  369. }
  370. ival = (sa_family_t)lval;
  371. memcpy(field, &ival, sizeof(ival));
  372. }
  373. #ifdef SO_PASSCRED
  374. static void from_zval_write_pid_t(const zval *arr_value, char *field, ser_context *ctx)
  375. {
  376. zend_long lval;
  377. pid_t ival;
  378. lval = from_zval_integer_common(arr_value, ctx);
  379. if (ctx->err.has_error) {
  380. return;
  381. }
  382. if (lval < 0 || (pid_t)lval != lval) { /* pid_t is signed */
  383. do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
  384. "for a pid_t value");
  385. return;
  386. }
  387. ival = (pid_t)lval;
  388. memcpy(field, &ival, sizeof(ival));
  389. }
  390. static void from_zval_write_uid_t(const zval *arr_value, char *field, ser_context *ctx)
  391. {
  392. zend_long lval;
  393. uid_t ival;
  394. lval = from_zval_integer_common(arr_value, ctx);
  395. if (ctx->err.has_error) {
  396. return;
  397. }
  398. /* uid_t can be signed or unsigned (generally unsigned) */
  399. if ((uid_t)-1 > (uid_t)0) {
  400. if (sizeof(zend_long) > sizeof(uid_t) && (lval < 0 || (uid_t)lval != lval)) {
  401. do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
  402. "for a uid_t value");
  403. return;
  404. }
  405. } else {
  406. if (sizeof(zend_long) > sizeof(uid_t) && (uid_t)lval != lval) {
  407. do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
  408. "for a uid_t value");
  409. return;
  410. }
  411. }
  412. ival = (uid_t)lval;
  413. memcpy(field, &ival, sizeof(ival));
  414. }
  415. #endif
  416. void to_zval_read_int(const char *data, zval *zv, res_context *ctx)
  417. {
  418. int ival;
  419. memcpy(&ival, data, sizeof(ival));
  420. ZVAL_LONG(zv, (zend_long)ival);
  421. }
  422. static void to_zval_read_net_uint16(const char *data, zval *zv, res_context *ctx)
  423. {
  424. uint16_t ival;
  425. memcpy(&ival, data, sizeof(ival));
  426. ZVAL_LONG(zv, (zend_long)ntohs(ival));
  427. }
  428. static void to_zval_read_sa_family(const char *data, zval *zv, res_context *ctx)
  429. {
  430. sa_family_t ival;
  431. memcpy(&ival, data, sizeof(ival));
  432. ZVAL_LONG(zv, (zend_long)ival);
  433. }
  434. #if HAVE_IPV6
  435. static void to_zval_read_unsigned(const char *data, zval *zv, res_context *ctx)
  436. {
  437. unsigned ival;
  438. memcpy(&ival, data, sizeof(ival));
  439. ZVAL_LONG(zv, (zend_long)ival);
  440. }
  441. static void to_zval_read_uint32(const char *data, zval *zv, res_context *ctx)
  442. {
  443. uint32_t ival;
  444. memcpy(&ival, data, sizeof(ival));
  445. ZVAL_LONG(zv, (zend_long)ival);
  446. }
  447. #endif
  448. #ifdef SO_PASSCRED
  449. static void to_zval_read_pid_t(const char *data, zval *zv, res_context *ctx)
  450. {
  451. pid_t ival;
  452. memcpy(&ival, data, sizeof(ival));
  453. ZVAL_LONG(zv, (zend_long)ival);
  454. }
  455. static void to_zval_read_uid_t(const char *data, zval *zv, res_context *ctx)
  456. {
  457. uid_t ival;
  458. memcpy(&ival, data, sizeof(ival));
  459. ZVAL_LONG(zv, (zend_long)ival);
  460. }
  461. #endif
  462. /* CONVERSIONS for sockaddr */
  463. static void from_zval_write_sin_addr(const zval *zaddr_str, char *inaddr, ser_context *ctx)
  464. {
  465. int res;
  466. struct sockaddr_in saddr = {0};
  467. zend_string *addr_str, *tmp_addr_str;
  468. addr_str = zval_get_tmp_string((zval *) zaddr_str, &tmp_addr_str);
  469. res = php_set_inet_addr(&saddr, ZSTR_VAL(addr_str), ctx->sock);
  470. if (res) {
  471. memcpy(inaddr, &saddr.sin_addr, sizeof saddr.sin_addr);
  472. } else {
  473. /* error already emitted, but let's emit another more relevant */
  474. do_from_zval_err(ctx, "could not resolve address '%s' to get an AF_INET "
  475. "address", ZSTR_VAL(addr_str));
  476. }
  477. zend_tmp_string_release(tmp_addr_str);
  478. }
  479. static void to_zval_read_sin_addr(const char *data, zval *zv, res_context *ctx)
  480. {
  481. const struct in_addr *addr = (const struct in_addr *)data;
  482. socklen_t size = INET_ADDRSTRLEN;
  483. zend_string *str = zend_string_alloc(size - 1, 0);
  484. memset(ZSTR_VAL(str), '\0', size);
  485. ZVAL_NEW_STR(zv, str);
  486. if (inet_ntop(AF_INET, addr, Z_STRVAL_P(zv), size) == NULL) {
  487. do_to_zval_err(ctx, "could not convert IPv4 address to string "
  488. "(errno %d)", errno);
  489. return;
  490. }
  491. Z_STRLEN_P(zv) = strlen(Z_STRVAL_P(zv));
  492. }
  493. static const field_descriptor descriptors_sockaddr_in[] = {
  494. {"family", sizeof("family"), 0, offsetof(struct sockaddr_in, sin_family), from_zval_write_sa_family, to_zval_read_sa_family},
  495. {"addr", sizeof("addr"), 0, offsetof(struct sockaddr_in, sin_addr), from_zval_write_sin_addr, to_zval_read_sin_addr},
  496. {"port", sizeof("port"), 0, offsetof(struct sockaddr_in, sin_port), from_zval_write_net_uint16, to_zval_read_net_uint16},
  497. {0}
  498. };
  499. static void from_zval_write_sockaddr_in(const zval *container, char *sockaddr, ser_context *ctx)
  500. {
  501. from_zval_write_aggregation(container, sockaddr, descriptors_sockaddr_in, ctx);
  502. }
  503. static void to_zval_read_sockaddr_in(const char *data, zval *zv, res_context *ctx)
  504. {
  505. to_zval_read_aggregation(data, zv, descriptors_sockaddr_in, ctx);
  506. }
  507. #if HAVE_IPV6
  508. static void from_zval_write_sin6_addr(const zval *zaddr_str, char *addr6, ser_context *ctx)
  509. {
  510. int res;
  511. struct sockaddr_in6 saddr6 = {0};
  512. zend_string *addr_str, *tmp_addr_str;
  513. addr_str = zval_get_tmp_string((zval *) zaddr_str, &tmp_addr_str);
  514. res = php_set_inet6_addr(&saddr6, ZSTR_VAL(addr_str), ctx->sock);
  515. if (res) {
  516. memcpy(addr6, &saddr6.sin6_addr, sizeof saddr6.sin6_addr);
  517. } else {
  518. /* error already emitted, but let's emit another more relevant */
  519. do_from_zval_err(ctx, "could not resolve address '%s' to get an AF_INET6 "
  520. "address", Z_STRVAL_P(zaddr_str));
  521. }
  522. zend_tmp_string_release(tmp_addr_str);
  523. }
  524. static void to_zval_read_sin6_addr(const char *data, zval *zv, res_context *ctx)
  525. {
  526. const struct in6_addr *addr = (const struct in6_addr *)data;
  527. socklen_t size = INET6_ADDRSTRLEN;
  528. zend_string *str = zend_string_alloc(size - 1, 0);
  529. memset(ZSTR_VAL(str), '\0', size);
  530. ZVAL_NEW_STR(zv, str);
  531. if (inet_ntop(AF_INET6, addr, Z_STRVAL_P(zv), size) == NULL) {
  532. do_to_zval_err(ctx, "could not convert IPv6 address to string "
  533. "(errno %d)", errno);
  534. return;
  535. }
  536. Z_STRLEN_P(zv) = strlen(Z_STRVAL_P(zv));
  537. }
  538. static const field_descriptor descriptors_sockaddr_in6[] = {
  539. {"family", sizeof("family"), 0, offsetof(struct sockaddr_in6, sin6_family), from_zval_write_sa_family, to_zval_read_sa_family},
  540. {"addr", sizeof("addr"), 0, offsetof(struct sockaddr_in6, sin6_addr), from_zval_write_sin6_addr, to_zval_read_sin6_addr},
  541. {"port", sizeof("port"), 0, offsetof(struct sockaddr_in6, sin6_port), from_zval_write_net_uint16, to_zval_read_net_uint16},
  542. {"flowinfo", sizeof("flowinfo"), 0, offsetof(struct sockaddr_in6, sin6_flowinfo), from_zval_write_uint32, to_zval_read_uint32},
  543. {"scope_id", sizeof("scope_id"), 0, offsetof(struct sockaddr_in6, sin6_scope_id), from_zval_write_uint32, to_zval_read_uint32},
  544. {0}
  545. };
  546. static void from_zval_write_sockaddr_in6(const zval *container, char *sockaddr6, ser_context *ctx)
  547. {
  548. from_zval_write_aggregation(container, sockaddr6, descriptors_sockaddr_in6, ctx);
  549. }
  550. static void to_zval_read_sockaddr_in6(const char *data, zval *zv, res_context *ctx)
  551. {
  552. to_zval_read_aggregation(data, zv, descriptors_sockaddr_in6, ctx);
  553. }
  554. #endif /* HAVE_IPV6 */
  555. static void from_zval_write_sun_path(const zval *path, char *sockaddr_un_c, ser_context *ctx)
  556. {
  557. zend_string *path_str, *tmp_path_str;
  558. struct sockaddr_un *saddr = (struct sockaddr_un*)sockaddr_un_c;
  559. path_str = zval_get_tmp_string((zval *) path, &tmp_path_str);
  560. /* code in this file relies on the path being nul terminated, even though
  561. * this is not required, at least on linux for abstract paths. It also
  562. * assumes that the path is not empty */
  563. if (ZSTR_LEN(path_str) == 0) {
  564. do_from_zval_err(ctx, "%s", "the path is cannot be empty");
  565. zend_tmp_string_release(tmp_path_str);
  566. return;
  567. }
  568. if (ZSTR_LEN(path_str) >= sizeof(saddr->sun_path)) {
  569. do_from_zval_err(ctx, "the path is too long, the maximum permitted "
  570. "length is %zd", sizeof(saddr->sun_path) - 1);
  571. zend_tmp_string_release(tmp_path_str);
  572. return;
  573. }
  574. memcpy(&saddr->sun_path, ZSTR_VAL(path_str), ZSTR_LEN(path_str));
  575. saddr->sun_path[ZSTR_LEN(path_str)] = '\0';
  576. zend_tmp_string_release(tmp_path_str);
  577. }
  578. static void to_zval_read_sun_path(const char *data, zval *zv, res_context *ctx) {
  579. struct sockaddr_un *saddr = (struct sockaddr_un*)data;
  580. char *nul_pos;
  581. nul_pos = memchr(&saddr->sun_path, '\0', sizeof(saddr->sun_path));
  582. if (nul_pos == NULL) {
  583. do_to_zval_err(ctx, "could not find a NUL in the path");
  584. return;
  585. }
  586. ZVAL_STRINGL(zv, saddr->sun_path, nul_pos - (char*)&saddr->sun_path);
  587. }
  588. static const field_descriptor descriptors_sockaddr_un[] = {
  589. {"family", sizeof("family"), 0, offsetof(struct sockaddr_un, sun_family), from_zval_write_sa_family, to_zval_read_sa_family},
  590. {"path", sizeof("path"), 0, 0, from_zval_write_sun_path, to_zval_read_sun_path},
  591. {0}
  592. };
  593. static void from_zval_write_sockaddr_un(const zval *container, char *sockaddr, ser_context *ctx)
  594. {
  595. from_zval_write_aggregation(container, sockaddr, descriptors_sockaddr_un, ctx);
  596. }
  597. static void to_zval_read_sockaddr_un(const char *data, zval *zv, res_context *ctx)
  598. {
  599. to_zval_read_aggregation(data, zv, descriptors_sockaddr_un, ctx);
  600. }
  601. static void from_zval_write_sockaddr_aux(const zval *container,
  602. struct sockaddr **sockaddr_ptr,
  603. socklen_t *sockaddr_len,
  604. ser_context *ctx)
  605. {
  606. int family;
  607. zval *elem;
  608. int fill_sockaddr;
  609. *sockaddr_ptr = NULL;
  610. *sockaddr_len = 0;
  611. if (Z_TYPE_P(container) != IS_ARRAY) {
  612. do_from_zval_err(ctx, "%s", "expected an array here");
  613. return;
  614. }
  615. fill_sockaddr = param_get_bool(ctx, KEY_FILL_SOCKADDR, 1);
  616. if ((elem = zend_hash_str_find(Z_ARRVAL_P(container), "family", sizeof("family") - 1)) != NULL
  617. && Z_TYPE_P(elem) != IS_NULL) {
  618. const char *node = "family";
  619. zend_llist_add_element(&ctx->keys, &node);
  620. from_zval_write_int(elem, (char*)&family, ctx);
  621. zend_llist_remove_tail(&ctx->keys);
  622. } else {
  623. family = ctx->sock->type;
  624. }
  625. switch (family) {
  626. case AF_INET:
  627. /* though not all OSes support sockaddr_in used in IPv6 sockets */
  628. if (ctx->sock->type != AF_INET && ctx->sock->type != AF_INET6) {
  629. do_from_zval_err(ctx, "the specified family (number %d) is not "
  630. "supported on this socket", family);
  631. return;
  632. }
  633. *sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_in), ctx);
  634. *sockaddr_len = sizeof(struct sockaddr_in);
  635. if (fill_sockaddr) {
  636. from_zval_write_sockaddr_in(container, (char*)*sockaddr_ptr, ctx);
  637. (*sockaddr_ptr)->sa_family = AF_INET;
  638. }
  639. break;
  640. #if HAVE_IPV6
  641. case AF_INET6:
  642. if (ctx->sock->type != AF_INET6) {
  643. do_from_zval_err(ctx, "the specified family (AF_INET6) is not "
  644. "supported on this socket");
  645. return;
  646. }
  647. *sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_in6), ctx);
  648. *sockaddr_len = sizeof(struct sockaddr_in6);
  649. if (fill_sockaddr) {
  650. from_zval_write_sockaddr_in6(container, (char*)*sockaddr_ptr, ctx);
  651. (*sockaddr_ptr)->sa_family = AF_INET6;
  652. }
  653. break;
  654. #endif /* HAVE_IPV6 */
  655. case AF_UNIX:
  656. if (ctx->sock->type != AF_UNIX) {
  657. do_from_zval_err(ctx, "the specified family (AF_UNIX) is not "
  658. "supported on this socket");
  659. return;
  660. }
  661. *sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_un), ctx);
  662. if (fill_sockaddr) {
  663. struct sockaddr_un *sock_un = (struct sockaddr_un*)*sockaddr_ptr;
  664. from_zval_write_sockaddr_un(container, (char*)*sockaddr_ptr, ctx);
  665. (*sockaddr_ptr)->sa_family = AF_UNIX;
  666. /* calculating length is more complicated here. Giving the size of
  667. * struct sockaddr_un here and relying on the nul termination of
  668. * sun_path does not work for paths in the abstract namespace. Note
  669. * that we always assume the path is not empty and nul terminated */
  670. *sockaddr_len = offsetof(struct sockaddr_un, sun_path) +
  671. (sock_un->sun_path[0] == '\0'
  672. ? (1 + strlen(&sock_un->sun_path[1]))
  673. : strlen(sock_un->sun_path));
  674. } else {
  675. *sockaddr_len = sizeof(struct sockaddr_un);
  676. }
  677. break;
  678. default:
  679. do_from_zval_err(ctx, "%s", "the only families currently supported are "
  680. "AF_INET, AF_INET6 and AF_UNIX");
  681. break;
  682. }
  683. }
  684. static void to_zval_read_sockaddr_aux(const char *sockaddr_c, zval *zv, res_context *ctx)
  685. {
  686. const struct sockaddr *saddr = (struct sockaddr *)sockaddr_c;
  687. if (saddr->sa_family == 0) {
  688. ZVAL_NULL(zv);
  689. return;
  690. }
  691. array_init(zv);
  692. switch (saddr->sa_family) {
  693. case AF_INET:
  694. to_zval_read_sockaddr_in(sockaddr_c, zv, ctx);
  695. break;
  696. #if HAVE_IPV6
  697. case AF_INET6:
  698. to_zval_read_sockaddr_in6(sockaddr_c, zv, ctx);
  699. break;
  700. #endif /* HAVE_IPV6 */
  701. case AF_UNIX:
  702. to_zval_read_sockaddr_un(sockaddr_c, zv, ctx);
  703. break;
  704. default:
  705. do_to_zval_err(ctx, "cannot read struct sockaddr with family %d; "
  706. "not supported",
  707. (int)saddr->sa_family);
  708. break;
  709. }
  710. }
  711. /* CONVERSIONS for cmsghdr */
  712. /*
  713. * [ level => , type => , data => [],]
  714. * struct cmsghdr {
  715. * socklen_t cmsg_len; // data byte count, including header
  716. * int cmsg_level; // originating protocol
  717. * int cmsg_type; // protocol-specific type
  718. * // followed by unsigned char cmsg_data[];
  719. * };
  720. */
  721. static void from_zval_write_control(const zval *arr,
  722. void **control_buf,
  723. zend_llist_element *alloc,
  724. size_t *control_len,
  725. size_t *offset,
  726. ser_context *ctx)
  727. {
  728. struct cmsghdr *cmsghdr;
  729. int level,
  730. type;
  731. size_t data_len,
  732. req_space,
  733. space_left;
  734. ancillary_reg_entry *entry;
  735. static const field_descriptor descriptor_level[] = {
  736. {"level", sizeof("level"), 0, 0, from_zval_write_int, 0},
  737. {0}
  738. };
  739. static const field_descriptor descriptor_type[] = {
  740. {"type", sizeof("type"), 0, 0, from_zval_write_int, 0},
  741. {0}
  742. };
  743. field_descriptor descriptor_data[] = {
  744. {"data", sizeof("data"), 0, 0, 0, 0},
  745. {0}
  746. };
  747. from_zval_write_aggregation(arr, (char *)&level, descriptor_level, ctx);
  748. if (ctx->err.has_error) {
  749. return;
  750. }
  751. from_zval_write_aggregation(arr, (char *)&type, descriptor_type, ctx);
  752. if (ctx->err.has_error) {
  753. return;
  754. }
  755. entry = get_ancillary_reg_entry(level, type);
  756. if (entry == NULL) {
  757. do_from_zval_err(ctx, "cmsghdr with level %d and type %d not supported",
  758. level, type);
  759. return;
  760. }
  761. if (entry->calc_space) {
  762. zval *data_elem;
  763. /* arr must be an array at this point */
  764. if ((data_elem = zend_hash_str_find(Z_ARRVAL_P(arr), "data", sizeof("data") - 1)) == NULL) {
  765. do_from_zval_err(ctx, "cmsghdr should have a 'data' element here");
  766. return;
  767. }
  768. data_len = entry->calc_space(data_elem, ctx);
  769. if (ctx->err.has_error) {
  770. return;
  771. }
  772. } else {
  773. data_len = entry->size;
  774. }
  775. req_space = CMSG_SPACE(data_len);
  776. space_left = *control_len - *offset;
  777. assert(*control_len >= *offset);
  778. if (space_left < req_space) {
  779. *control_buf = safe_erealloc(*control_buf, 2, req_space, *control_len);
  780. *control_len += 2 * req_space;
  781. memset((char *)*control_buf + *offset, '\0', *control_len - *offset);
  782. memcpy(&alloc->data, control_buf, sizeof *control_buf);
  783. }
  784. cmsghdr = (struct cmsghdr*)(((char*)*control_buf) + *offset);
  785. cmsghdr->cmsg_level = level;
  786. cmsghdr->cmsg_type = type;
  787. cmsghdr->cmsg_len = CMSG_LEN(data_len);
  788. descriptor_data[0].from_zval = entry->from_array;
  789. from_zval_write_aggregation(arr, (char*)CMSG_DATA(cmsghdr), descriptor_data, ctx);
  790. *offset += req_space;
  791. }
  792. static void from_zval_write_control_array(const zval *arr, char *msghdr_c, ser_context *ctx)
  793. {
  794. char buf[sizeof("element #4294967295")];
  795. char *bufp = buf;
  796. zval *elem;
  797. uint32_t i = 0;
  798. int num_elems;
  799. void *control_buf;
  800. zend_llist_element *alloc;
  801. size_t control_len,
  802. cur_offset;
  803. struct msghdr *msg = (struct msghdr*)msghdr_c;
  804. if (Z_TYPE_P(arr) != IS_ARRAY) {
  805. do_from_zval_err(ctx, "%s", "expected an array here");
  806. return;
  807. }
  808. num_elems = zend_hash_num_elements(Z_ARRVAL_P(arr));
  809. if (num_elems == 0) {
  810. return;
  811. }
  812. /* estimate each message at 20 bytes */
  813. control_buf = accounted_safe_ecalloc(num_elems, CMSG_SPACE(20), 0, ctx);
  814. alloc = ctx->allocations.tail;
  815. control_len = (size_t)num_elems * CMSG_SPACE(20);
  816. cur_offset = 0;
  817. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), elem) {
  818. if (ctx->err.has_error) {
  819. break;
  820. }
  821. if ((size_t)snprintf(buf, sizeof(buf), "element #%u", (unsigned)i++) >= sizeof(buf)) {
  822. memcpy(buf, "element", sizeof("element"));
  823. }
  824. zend_llist_add_element(&ctx->keys, &bufp);
  825. from_zval_write_control(elem, &control_buf, alloc, &control_len, &cur_offset, ctx);
  826. zend_llist_remove_tail(&ctx->keys);
  827. } ZEND_HASH_FOREACH_END();
  828. msg->msg_control = control_buf;
  829. msg->msg_controllen = cur_offset; /* not control_len, which may be larger */
  830. }
  831. static void to_zval_read_cmsg_data(const char *cmsghdr_c, zval *zv, res_context *ctx)
  832. {
  833. const struct cmsghdr *cmsg = (const struct cmsghdr *)cmsghdr_c;
  834. ancillary_reg_entry *entry;
  835. size_t len,
  836. *len_p = &len;
  837. entry = get_ancillary_reg_entry(cmsg->cmsg_level, cmsg->cmsg_type);
  838. if (entry == NULL) {
  839. do_to_zval_err(ctx, "cmsghdr with level %d and type %d not supported",
  840. cmsg->cmsg_level, cmsg->cmsg_type);
  841. return;
  842. }
  843. if (CMSG_LEN(entry->size) > cmsg->cmsg_len) {
  844. do_to_zval_err(ctx, "the cmsghdr structure is unexpectedly small; "
  845. "expected a length of at least " ZEND_LONG_FMT ", but got " ZEND_LONG_FMT,
  846. (zend_long)CMSG_LEN(entry->size), (zend_long)cmsg->cmsg_len);
  847. return;
  848. }
  849. len = (size_t)cmsg->cmsg_len; /* use another var because type of cmsg_len varies */
  850. if (zend_hash_str_add_ptr(&ctx->params, KEY_CMSG_LEN, sizeof(KEY_CMSG_LEN) - 1, len_p) == NULL) {
  851. do_to_zval_err(ctx, "%s", "could not set parameter " KEY_CMSG_LEN);
  852. return;
  853. }
  854. entry->to_array((const char *)CMSG_DATA(cmsg), zv, ctx);
  855. zend_hash_str_del(&ctx->params, KEY_CMSG_LEN, sizeof(KEY_CMSG_LEN) - 1);
  856. }
  857. static void to_zval_read_control(const char *cmsghdr_c, zval *zv, res_context *ctx)
  858. {
  859. /* takes a cmsghdr, not a msghdr like from_zval_write_control */
  860. static const field_descriptor descriptors[] = {
  861. {"level", sizeof("level"), 0, offsetof(struct cmsghdr, cmsg_level), 0, to_zval_read_int},
  862. {"type", sizeof("type"), 0, offsetof(struct cmsghdr, cmsg_type), 0, to_zval_read_int},
  863. {"data", sizeof("data"), 0, 0 /* cmsghdr passed */, 0, to_zval_read_cmsg_data},
  864. {0}
  865. };
  866. array_init_size(zv, 3);
  867. to_zval_read_aggregation(cmsghdr_c, zv, descriptors, ctx);
  868. }
  869. static void to_zval_read_control_array(const char *msghdr_c, zval *zv, res_context *ctx)
  870. {
  871. struct msghdr *msg = (struct msghdr *)msghdr_c;
  872. struct cmsghdr *cmsg;
  873. char buf[sizeof("element #4294967295")];
  874. char *bufp = buf;
  875. uint32_t i = 1;
  876. array_init(zv);
  877. for (cmsg = CMSG_FIRSTHDR(msg);
  878. cmsg != NULL && !ctx->err.has_error;
  879. cmsg = CMSG_NXTHDR(msg, cmsg)) {
  880. zval *elem, tmp;
  881. ZVAL_NULL(&tmp);
  882. elem = zend_hash_next_index_insert(Z_ARRVAL_P(zv), &tmp);
  883. if ((size_t)snprintf(buf, sizeof(buf), "element #%u", (unsigned)i++) >= sizeof(buf)) {
  884. memcpy(buf, "element", sizeof("element"));
  885. }
  886. zend_llist_add_element(&ctx->keys, &bufp);
  887. to_zval_read_control((const char *)cmsg, elem, ctx);
  888. zend_llist_remove_tail(&ctx->keys);
  889. }
  890. }
  891. /* CONVERSIONS for msghdr */
  892. static void from_zval_write_name(const zval *zname_arr, char *msghdr_c, ser_context *ctx)
  893. {
  894. struct sockaddr *sockaddr;
  895. socklen_t sockaddr_len;
  896. struct msghdr *msghdr = (struct msghdr *)msghdr_c;
  897. from_zval_write_sockaddr_aux(zname_arr, &sockaddr, &sockaddr_len, ctx);
  898. msghdr->msg_name = sockaddr;
  899. msghdr->msg_namelen = sockaddr_len;
  900. }
  901. static void to_zval_read_name(const char *sockaddr_p, zval *zv, res_context *ctx)
  902. {
  903. void *name = (void*)*(void**)sockaddr_p;
  904. if (name == NULL) {
  905. ZVAL_NULL(zv);
  906. } else {
  907. to_zval_read_sockaddr_aux(name, zv, ctx);
  908. }
  909. }
  910. static void from_zval_write_msghdr_buffer_size(const zval *elem, char *msghdr_c, ser_context *ctx)
  911. {
  912. zend_long lval;
  913. struct msghdr *msghdr = (struct msghdr *)msghdr_c;
  914. lval = from_zval_integer_common(elem, ctx);
  915. if (ctx->err.has_error) {
  916. return;
  917. }
  918. if (lval < 0 || (zend_ulong)lval > MAX_USER_BUFF_SIZE) {
  919. do_from_zval_err(ctx, "the buffer size must be between 1 and " ZEND_LONG_FMT "; "
  920. "given " ZEND_LONG_FMT, (zend_long)MAX_USER_BUFF_SIZE, lval);
  921. return;
  922. }
  923. msghdr->msg_iovlen = 1;
  924. msghdr->msg_iov = accounted_emalloc(sizeof(*msghdr->msg_iov) * 1, ctx);
  925. msghdr->msg_iov[0].iov_base = accounted_emalloc((size_t)lval, ctx);
  926. msghdr->msg_iov[0].iov_len = (size_t)lval;
  927. }
  928. static void from_zval_write_iov_array_aux(zval *elem, unsigned i, void **args, ser_context *ctx)
  929. {
  930. struct msghdr *msg = args[0];
  931. zend_string *str, *tmp_str;
  932. str = zval_get_tmp_string(elem, &tmp_str);
  933. msg->msg_iov[i - 1].iov_base = accounted_emalloc(ZSTR_LEN(str), ctx);
  934. msg->msg_iov[i - 1].iov_len = ZSTR_LEN(str);
  935. memcpy(msg->msg_iov[i - 1].iov_base, ZSTR_VAL(str), ZSTR_LEN(str));
  936. zend_tmp_string_release(tmp_str);
  937. }
  938. static void from_zval_write_iov_array(const zval *arr, char *msghdr_c, ser_context *ctx)
  939. {
  940. int num_elem;
  941. struct msghdr *msg = (struct msghdr*)msghdr_c;
  942. if (Z_TYPE_P(arr) != IS_ARRAY) {
  943. do_from_zval_err(ctx, "%s", "expected an array here");
  944. return;
  945. }
  946. num_elem = zend_hash_num_elements(Z_ARRVAL_P(arr));
  947. if (num_elem == 0) {
  948. return;
  949. }
  950. msg->msg_iov = accounted_safe_ecalloc(num_elem, sizeof *msg->msg_iov, 0, ctx);
  951. msg->msg_iovlen = (size_t)num_elem;
  952. from_array_iterate(arr, from_zval_write_iov_array_aux, (void**)&msg, ctx);
  953. }
  954. static void from_zval_write_controllen(const zval *elem, char *msghdr_c, ser_context *ctx)
  955. {
  956. struct msghdr *msghdr = (struct msghdr *)msghdr_c;
  957. uint32_t len;
  958. /* controllen should be an unsigned with at least 32-bit. Let's assume
  959. * this least common denominator
  960. */
  961. from_zval_write_uint32(elem, (char*)&len, ctx);
  962. if (!ctx->err.has_error && len == 0) {
  963. do_from_zval_err(ctx, "controllen cannot be 0");
  964. return;
  965. }
  966. msghdr->msg_control = accounted_emalloc(len, ctx);
  967. msghdr->msg_controllen = len;
  968. }
  969. void from_zval_write_msghdr_send(const zval *container, char *msghdr_c, ser_context *ctx)
  970. {
  971. static const field_descriptor descriptors[] = {
  972. {"name", sizeof("name"), 0, 0, from_zval_write_name, 0},
  973. {"iov", sizeof("iov"), 0, 0, from_zval_write_iov_array, 0},
  974. {"control", sizeof("control"), 0, 0, from_zval_write_control_array, 0},
  975. {0}
  976. };
  977. from_zval_write_aggregation(container, msghdr_c, descriptors, ctx);
  978. }
  979. void from_zval_write_msghdr_recv(const zval *container, char *msghdr_c, ser_context *ctx)
  980. {
  981. /* zval to struct msghdr, version for recvmsg(). It differs from the version
  982. * for sendmsg() in that it:
  983. * - has a buffer_size instead of an iov array;
  984. * - has no control element; has a controllen element instead
  985. * struct msghdr {
  986. * void *msg_name;
  987. * socklen_t msg_namelen;
  988. * struct iovec *msg_iov;
  989. * size_t msg_iovlen;
  990. * void *msg_control;
  991. * size_t msg_controllen; //can also be socklen_t
  992. * int msg_flags;
  993. * };
  994. */
  995. static const field_descriptor descriptors[] = {
  996. {"name", sizeof("name"), 0, 0, from_zval_write_name, 0},
  997. {"buffer_size", sizeof("buffer_size"), 0, 0, from_zval_write_msghdr_buffer_size, 0},
  998. {"controllen", sizeof("controllen"), 1, 0, from_zval_write_controllen, 0},
  999. {0}
  1000. };
  1001. struct msghdr *msghdr = (struct msghdr *)msghdr_c;
  1002. const int falsev = 0,
  1003. *falsevp = &falsev;
  1004. if (zend_hash_str_add_ptr(&ctx->params, KEY_FILL_SOCKADDR, sizeof(KEY_FILL_SOCKADDR) - 1, (void *)falsevp) == NULL) {
  1005. do_from_zval_err(ctx, "could not add fill_sockaddr; this is a bug");
  1006. return;
  1007. }
  1008. from_zval_write_aggregation(container, msghdr_c, descriptors, ctx);
  1009. zend_hash_str_del(&ctx->params, KEY_FILL_SOCKADDR, sizeof(KEY_FILL_SOCKADDR) - 1);
  1010. if (ctx->err.has_error) {
  1011. return;
  1012. }
  1013. if (msghdr->msg_iovlen == 0) {
  1014. msghdr->msg_iovlen = 1;
  1015. msghdr->msg_iov = accounted_emalloc(sizeof(*msghdr->msg_iov) * 1, ctx);
  1016. msghdr->msg_iov[0].iov_base = accounted_emalloc((size_t)DEFAULT_BUFF_SIZE, ctx);
  1017. msghdr->msg_iov[0].iov_len = (size_t)DEFAULT_BUFF_SIZE;
  1018. }
  1019. }
  1020. static void to_zval_read_iov(const char *msghdr_c, zval *zv, res_context *ctx)
  1021. {
  1022. const struct msghdr *msghdr = (const struct msghdr *)msghdr_c;
  1023. size_t iovlen = msghdr->msg_iovlen;
  1024. ssize_t *recvmsg_ret,
  1025. bytes_left;
  1026. uint32_t i;
  1027. if (iovlen > UINT_MAX) {
  1028. do_to_zval_err(ctx, "unexpectedly large value for iov_len: %lu",
  1029. (unsigned long)iovlen);
  1030. }
  1031. array_init_size(zv, (uint32_t)iovlen);
  1032. if ((recvmsg_ret = zend_hash_str_find_ptr(&ctx->params, KEY_RECVMSG_RET, sizeof(KEY_RECVMSG_RET) - 1)) == NULL) {
  1033. do_to_zval_err(ctx, "recvmsg_ret not found in params. This is a bug");
  1034. return;
  1035. }
  1036. bytes_left = *recvmsg_ret;
  1037. for (i = 0; bytes_left > 0 && i < (uint32_t)iovlen; i++) {
  1038. zval elem;
  1039. size_t len = MIN(msghdr->msg_iov[i].iov_len, (size_t)bytes_left);
  1040. zend_string *buf = zend_string_alloc(len, 0);
  1041. memcpy(ZSTR_VAL(buf), msghdr->msg_iov[i].iov_base, ZSTR_LEN(buf));
  1042. ZSTR_VAL(buf)[ZSTR_LEN(buf)] = '\0';
  1043. ZVAL_NEW_STR(&elem, buf);
  1044. add_next_index_zval(zv, &elem);
  1045. bytes_left -= len;
  1046. }
  1047. }
  1048. void to_zval_read_msghdr(const char *msghdr_c, zval *zv, res_context *ctx)
  1049. {
  1050. static const field_descriptor descriptors[] = {
  1051. {"name", sizeof("name"), 0, offsetof(struct msghdr, msg_name), 0, to_zval_read_name},
  1052. {"control", sizeof("control"), 0, 0, 0, to_zval_read_control_array},
  1053. {"iov", sizeof("iov"), 0, 0, 0, to_zval_read_iov},
  1054. {"flags", sizeof("flags"), 0, offsetof(struct msghdr, msg_flags), 0, to_zval_read_int},
  1055. {0}
  1056. };
  1057. array_init_size(zv, 4);
  1058. to_zval_read_aggregation(msghdr_c, zv, descriptors, ctx);
  1059. }
  1060. #if defined(IPV6_PKTINFO) && HAVE_IPV6
  1061. /* CONVERSIONS for if_index */
  1062. static void from_zval_write_ifindex(const zval *zv, char *uinteger, ser_context *ctx)
  1063. {
  1064. unsigned ret = 0;
  1065. if (Z_TYPE_P(zv) == IS_LONG) {
  1066. if (Z_LVAL_P(zv) < 0 || (zend_ulong)Z_LVAL_P(zv) > UINT_MAX) { /* allow 0 (unspecified interface) */
  1067. do_from_zval_err(ctx, "the interface index cannot be negative or "
  1068. "larger than %u; given " ZEND_LONG_FMT, UINT_MAX, Z_LVAL_P(zv));
  1069. } else {
  1070. ret = (unsigned)Z_LVAL_P(zv);
  1071. }
  1072. } else {
  1073. zend_string *str, *tmp_str;
  1074. str = zval_get_tmp_string((zval *) zv, &tmp_str);
  1075. #if HAVE_IF_NAMETOINDEX
  1076. ret = if_nametoindex(ZSTR_VAL(str));
  1077. if (ret == 0) {
  1078. do_from_zval_err(ctx, "no interface with name \"%s\" could be found", ZSTR_VAL(str));
  1079. }
  1080. #elif defined(SIOCGIFINDEX)
  1081. {
  1082. struct ifreq ifr;
  1083. if (strlcpy(ifr.ifr_name, ZSTR_VAL(str), sizeof(ifr.ifr_name))
  1084. >= sizeof(ifr.ifr_name)) {
  1085. do_from_zval_err(ctx, "the interface name \"%s\" is too large ", ZSTR_VAL(str));
  1086. } else if (ioctl(ctx->sock->bsd_socket, SIOCGIFINDEX, &ifr) < 0) {
  1087. if (errno == ENODEV) {
  1088. do_from_zval_err(ctx, "no interface with name \"%s\" could be "
  1089. "found", ZSTR_VAL(str));
  1090. } else {
  1091. do_from_zval_err(ctx, "error fetching interface index for "
  1092. "interface with name \"%s\" (errno %d)",
  1093. ZSTR_VAL(str), errno);
  1094. }
  1095. } else {
  1096. ret = (unsigned)ifr.ifr_ifindex;
  1097. }
  1098. }
  1099. #else
  1100. do_from_zval_err(ctx,
  1101. "this platform does not support looking up an interface by "
  1102. "name, an integer interface index must be supplied instead");
  1103. #endif
  1104. zend_tmp_string_release(tmp_str);
  1105. }
  1106. if (!ctx->err.has_error) {
  1107. memcpy(uinteger, &ret, sizeof(ret));
  1108. }
  1109. }
  1110. /* CONVERSIONS for struct in6_pktinfo */
  1111. static const field_descriptor descriptors_in6_pktinfo[] = {
  1112. {"addr", sizeof("addr"), 1, offsetof(struct in6_pktinfo, ipi6_addr), from_zval_write_sin6_addr, to_zval_read_sin6_addr},
  1113. {"ifindex", sizeof("ifindex"), 1, offsetof(struct in6_pktinfo, ipi6_ifindex), from_zval_write_ifindex, to_zval_read_unsigned},
  1114. {0}
  1115. };
  1116. void from_zval_write_in6_pktinfo(const zval *container, char *in6_pktinfo_c, ser_context *ctx)
  1117. {
  1118. from_zval_write_aggregation(container, in6_pktinfo_c, descriptors_in6_pktinfo, ctx);
  1119. }
  1120. void to_zval_read_in6_pktinfo(const char *data, zval *zv, res_context *ctx)
  1121. {
  1122. array_init_size(zv, 2);
  1123. to_zval_read_aggregation(data, zv, descriptors_in6_pktinfo, ctx);
  1124. }
  1125. #endif
  1126. /* CONVERSIONS for struct ucred/cmsgcred */
  1127. #ifdef SO_PASSCRED
  1128. static const field_descriptor descriptors_ucred[] = {
  1129. #if defined(ANC_CREDS_UCRED)
  1130. {"pid", sizeof("pid"), 1, offsetof(struct ucred, pid), from_zval_write_pid_t, to_zval_read_pid_t},
  1131. {"uid", sizeof("uid"), 1, offsetof(struct ucred, uid), from_zval_write_uid_t, to_zval_read_uid_t},
  1132. /* assume the type gid_t is the same as uid_t: */
  1133. {"gid", sizeof("gid"), 1, offsetof(struct ucred, gid), from_zval_write_uid_t, to_zval_read_uid_t},
  1134. #elif defined(ANC_CREDS_CMSGCRED)
  1135. {"pid", sizeof("pid"), 1, offsetof(struct cmsgcred, cmcred_pid), from_zval_write_pid_t, to_zval_read_pid_t},
  1136. {"uid", sizeof("uid"), 1, offsetof(struct cmsgcred, cmcred_uid), from_zval_write_uid_t, to_zval_read_uid_t},
  1137. /* assume the type gid_t is the same as uid_t: */
  1138. {"gid", sizeof("gid"), 1, offsetof(struct cmsgcred, cmcred_gid), from_zval_write_uid_t, to_zval_read_uid_t},
  1139. #endif
  1140. {0}
  1141. };
  1142. void from_zval_write_ucred(const zval *container, char *ucred_c, ser_context *ctx)
  1143. {
  1144. from_zval_write_aggregation(container, ucred_c, descriptors_ucred, ctx);
  1145. }
  1146. void to_zval_read_ucred(const char *data, zval *zv, res_context *ctx)
  1147. {
  1148. array_init_size(zv, 3);
  1149. to_zval_read_aggregation(data, zv, descriptors_ucred, ctx);
  1150. }
  1151. #endif
  1152. /* CONVERSIONS for SCM_RIGHTS */
  1153. #ifdef SCM_RIGHTS
  1154. size_t calculate_scm_rights_space(const zval *arr, ser_context *ctx)
  1155. {
  1156. int num_elems;
  1157. if (Z_TYPE_P(arr) != IS_ARRAY) {
  1158. do_from_zval_err(ctx, "%s", "expected an array here");
  1159. return (size_t)-1;
  1160. }
  1161. num_elems = zend_hash_num_elements(Z_ARRVAL_P(arr));
  1162. if (num_elems == 0) {
  1163. do_from_zval_err(ctx, "%s", "expected at least one element in this array");
  1164. return (size_t)-1;
  1165. }
  1166. return zend_hash_num_elements(Z_ARRVAL_P(arr)) * sizeof(int);
  1167. }
  1168. static void from_zval_write_fd_array_aux(zval *elem, unsigned i, void **args, ser_context *ctx)
  1169. {
  1170. int *iarr = args[0];
  1171. if (Z_TYPE_P(elem) == IS_OBJECT && Z_OBJCE_P(elem) == socket_ce) {
  1172. php_socket *sock = Z_SOCKET_P(elem);
  1173. if (IS_INVALID_SOCKET(sock)) {
  1174. do_from_zval_err(ctx, "socket is already closed");
  1175. return;
  1176. }
  1177. iarr[i] = sock->bsd_socket;
  1178. return;
  1179. }
  1180. if (Z_TYPE_P(elem) == IS_RESOURCE) {
  1181. php_stream *stream;
  1182. stream = (php_stream *)zend_fetch_resource2_ex(elem, NULL, php_file_le_stream(), php_file_le_pstream());
  1183. if (stream == NULL) {
  1184. do_from_zval_err(ctx, "resource is not a stream");
  1185. return;
  1186. }
  1187. if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&iarr[i - 1], REPORT_ERRORS) == FAILURE) {
  1188. do_from_zval_err(ctx, "cast stream to file descriptor failed");
  1189. return;
  1190. }
  1191. } else {
  1192. do_from_zval_err(ctx, "expected a Socket object or a stream resource");
  1193. }
  1194. }
  1195. void from_zval_write_fd_array(const zval *arr, char *int_arr, ser_context *ctx)
  1196. {
  1197. if (Z_TYPE_P(arr) != IS_ARRAY) {
  1198. do_from_zval_err(ctx, "%s", "expected an array here");
  1199. return;
  1200. }
  1201. from_array_iterate(arr, &from_zval_write_fd_array_aux, (void**)&int_arr, ctx);
  1202. }
  1203. void to_zval_read_fd_array(const char *data, zval *zv, res_context *ctx)
  1204. {
  1205. size_t *cmsg_len;
  1206. int num_elems,
  1207. i;
  1208. struct cmsghdr *dummy_cmsg = 0;
  1209. size_t data_offset;
  1210. data_offset = (unsigned char *)CMSG_DATA(dummy_cmsg)
  1211. - (unsigned char *)dummy_cmsg;
  1212. if ((cmsg_len = zend_hash_str_find_ptr(&ctx->params, KEY_CMSG_LEN, sizeof(KEY_CMSG_LEN) - 1)) == NULL) {
  1213. do_to_zval_err(ctx, "could not get value of parameter " KEY_CMSG_LEN);
  1214. return;
  1215. }
  1216. if (*cmsg_len < data_offset) {
  1217. do_to_zval_err(ctx, "length of cmsg is smaller than its data member "
  1218. "offset (" ZEND_LONG_FMT " vs " ZEND_LONG_FMT ")", (zend_long)*cmsg_len, (zend_long)data_offset);
  1219. return;
  1220. }
  1221. num_elems = (*cmsg_len - data_offset) / sizeof(int);
  1222. array_init_size(zv, num_elems);
  1223. for (i = 0; i < num_elems; i++) {
  1224. zval elem;
  1225. int fd;
  1226. struct stat statbuf;
  1227. fd = *((int *)data + i);
  1228. /* determine whether we have a socket */
  1229. if (fstat(fd, &statbuf) == -1) {
  1230. do_to_zval_err(ctx, "error creating resource for received file "
  1231. "descriptor %d: fstat() call failed with errno %d", fd, errno);
  1232. return;
  1233. }
  1234. if (S_ISSOCK(statbuf.st_mode)) {
  1235. object_init_ex(&elem, socket_ce);
  1236. php_socket *sock = Z_SOCKET_P(&elem);
  1237. socket_import_file_descriptor(fd, sock);
  1238. } else {
  1239. php_stream *stream = php_stream_fopen_from_fd(fd, "rw", NULL);
  1240. php_stream_to_zval(stream, &elem);
  1241. }
  1242. add_next_index_zval(zv, &elem);
  1243. }
  1244. }
  1245. #endif
  1246. /* ENTRY POINT for conversions */
  1247. static void free_from_zval_allocation(void *alloc_ptr_ptr)
  1248. {
  1249. efree(*(void**)alloc_ptr_ptr);
  1250. }
  1251. void *from_zval_run_conversions(const zval *container,
  1252. php_socket *sock,
  1253. from_zval_write_field *writer,
  1254. size_t struct_size,
  1255. const char *top_name,
  1256. zend_llist **allocations /* out */,
  1257. struct err_s *err /* in/out */)
  1258. {
  1259. ser_context ctx;
  1260. char *structure;
  1261. *allocations = NULL;
  1262. if (err->has_error) {
  1263. return NULL;
  1264. }
  1265. memset(&ctx, 0, sizeof(ctx));
  1266. zend_hash_init(&ctx.params, 8, NULL, NULL, 0);
  1267. zend_llist_init(&ctx.keys, sizeof(const char *), NULL, 0);
  1268. zend_llist_init(&ctx.allocations, sizeof(void *), &free_from_zval_allocation, 0);
  1269. ctx.sock = sock;
  1270. structure = ecalloc(1, struct_size);
  1271. zend_llist_add_element(&ctx.keys, &top_name);
  1272. zend_llist_add_element(&ctx.allocations, &structure);
  1273. /* main call */
  1274. writer(container, structure, &ctx);
  1275. if (ctx.err.has_error) {
  1276. zend_llist_destroy(&ctx.allocations); /* deallocates structure as well */
  1277. structure = NULL;
  1278. *err = ctx.err;
  1279. } else {
  1280. *allocations = emalloc(sizeof **allocations);
  1281. **allocations = ctx.allocations;
  1282. }
  1283. zend_llist_destroy(&ctx.keys);
  1284. zend_hash_destroy(&ctx.params);
  1285. return structure;
  1286. }
  1287. zval *to_zval_run_conversions(const char *structure,
  1288. to_zval_read_field *reader,
  1289. const char *top_name,
  1290. const struct key_value *key_value_pairs,
  1291. struct err_s *err, zval *zv)
  1292. {
  1293. res_context ctx;
  1294. const struct key_value *kv;
  1295. if (err->has_error) {
  1296. return NULL;
  1297. }
  1298. memset(&ctx, 0, sizeof(ctx));
  1299. zend_llist_init(&ctx.keys, sizeof(const char *), NULL, 0);
  1300. zend_llist_add_element(&ctx.keys, &top_name);
  1301. zend_hash_init(&ctx.params, 8, NULL, NULL, 0);
  1302. for (kv = key_value_pairs; kv->key != NULL; kv++) {
  1303. zend_hash_str_update_ptr(&ctx.params, kv->key, kv->key_size - 1, kv->value);
  1304. }
  1305. ZVAL_NULL(zv);
  1306. /* main call */
  1307. reader(structure, zv, &ctx);
  1308. if (ctx.err.has_error) {
  1309. zval_ptr_dtor(zv);
  1310. ZVAL_UNDEF(zv);
  1311. *err = ctx.err;
  1312. }
  1313. zend_llist_destroy(&ctx.keys);
  1314. zend_hash_destroy(&ctx.params);
  1315. return Z_ISUNDEF_P(zv)? NULL : zv;
  1316. }