conversions.c 43 KB

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