PageRenderTime 64ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/servers/pfs/uds.c

http://www.minix3.org/
C | 1603 lines | 1046 code | 341 blank | 216 comment | 258 complexity | fb93ac05c0b9c60e9cdb97b486812876 MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /*
  2. * Unix Domain Sockets Implementation (PF_UNIX, PF_LOCAL)
  3. * This code handles ioctl(2) commands to implement the socket API.
  4. * Some helper functions are also present.
  5. *
  6. * The entry points into this file are...
  7. *
  8. * uds_init: initialize the descriptor table.
  9. * do_accept: handles the accept(2) syscall.
  10. * do_connect: handles the connect(2) syscall.
  11. * do_listen: handles the listen(2) syscall.
  12. * do_socket: handles the socket(2) syscall.
  13. * do_bind: handles the bind(2) syscall.
  14. * do_getsockname: handles the getsockname(2) syscall.
  15. * do_getpeername: handles the getpeername(2) syscall.
  16. * do_shutdown: handles the shutdown(2) syscall.
  17. * do_socketpair: handles the socketpair(2) syscall.
  18. * do_getsockopt_sotype: handles the getsockopt(2) syscall.
  19. * do_getsockopt_peercred: handles the getsockopt(2) syscall.
  20. * do_getsockopt_sndbuf: handles the getsockopt(2) syscall.
  21. * do_setsockopt_sndbuf: handles the setsockopt(2) syscall.
  22. * do_getsockopt_rcvbuf: handles the getsockopt(2) syscall.
  23. * do_setsockopt_rcvbuf: handles the setsockopt(2) syscall.
  24. * do_sendto: handles the sendto(2) syscall.
  25. * do_recvfrom: handles the recvfrom(2) syscall.
  26. * do_sendmsg: handles the sendmsg(2) syscall.
  27. * do_recvmsg: handles the recvmsg(2) syscall.
  28. * perform_connection: performs the connection of two descriptors.
  29. * clear_fds: calls put_filp for undelivered FDs.
  30. *
  31. * Also see...
  32. *
  33. * table.c, dev_uds.c, uds.h
  34. */
  35. #define DEBUG 0
  36. #include "inc.h"
  37. #include "const.h"
  38. #include "glo.h"
  39. #include "uds.h"
  40. /* File Descriptor Table */
  41. uds_fd_t uds_fd_table[NR_FDS];
  42. /* initialize the descriptor table */
  43. void uds_init(void)
  44. {
  45. /*
  46. * Setting everything to NULL implicitly sets the
  47. * state to UDS_FREE.
  48. */
  49. memset(uds_fd_table, '\0', sizeof(uds_fd_t) * NR_FDS);
  50. }
  51. /* check the permissions of a socket file */
  52. static int check_perms(int minor, struct sockaddr_un *addr)
  53. {
  54. int rc;
  55. message vfs_m;
  56. cp_grant_id_t grant_id;
  57. grant_id = cpf_grant_direct(VFS_PROC_NR, (vir_bytes) addr->sun_path,
  58. UNIX_PATH_MAX, CPF_READ | CPF_WRITE);
  59. /* ask the VFS to verify the permissions */
  60. memset(&vfs_m, '\0', sizeof(message));
  61. vfs_m.m_type = PFS_REQ_CHECK_PERMS;
  62. vfs_m.USER_ENDPT = uds_fd_table[minor].owner;
  63. vfs_m.IO_GRANT = (char *) grant_id;
  64. vfs_m.COUNT = UNIX_PATH_MAX;
  65. rc = sendrec(VFS_PROC_NR, &vfs_m);
  66. cpf_revoke(grant_id);
  67. if (OK != rc) {
  68. printf("(uds) sendrec error... req_nr: %d err: %d\n",
  69. vfs_m.m_type, rc);
  70. return EIO;
  71. }
  72. #if DEBUG == 1
  73. printf("(uds) VFS reply => %d\n", vfs_m.m_type);
  74. printf("(uds) Canonical Path => %s\n", addr->sun_path);
  75. #endif
  76. return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
  77. }
  78. static filp_id_t verify_fd(endpoint_t ep, int fd)
  79. {
  80. int rc;
  81. message vfs_m;
  82. #if DEBUG == 1
  83. static int call_count = 0;
  84. printf("(uds) verify_fd(%d,%d) call_count=%d\n", ep, fd,
  85. ++call_count);
  86. #endif
  87. memset(&vfs_m, '\0', sizeof(message));
  88. vfs_m.m_type = PFS_REQ_VERIFY_FD;
  89. vfs_m.USER_ENDPT = ep;
  90. vfs_m.COUNT = fd;
  91. rc = sendrec(VFS_PROC_NR, &vfs_m);
  92. if (OK != rc) {
  93. printf("(uds) sendrec error... req_nr: %d err: %d\n",
  94. vfs_m.m_type, rc);
  95. return NULL;
  96. }
  97. #if DEBUG == 1
  98. printf("(uds) VFS reply => %d\n", vfs_m.m_type);
  99. #endif
  100. return vfs_m.ADDRESS;
  101. }
  102. static int set_filp(filp_id_t sfilp)
  103. {
  104. int rc;
  105. message vfs_m;
  106. #if DEBUG == 1
  107. static int call_count = 0;
  108. printf("(uds) set_filp(0x%x) call_count=%d\n", sfilp, ++call_count);
  109. #endif
  110. memset(&vfs_m, '\0', sizeof(message));
  111. vfs_m.m_type = PFS_REQ_SET_FILP;
  112. vfs_m.ADDRESS = sfilp;
  113. rc = sendrec(VFS_PROC_NR, &vfs_m);
  114. if (OK != rc) {
  115. printf("(uds) sendrec error... req_nr: %d err: %d\n",
  116. vfs_m.m_type, rc);
  117. return EIO;
  118. }
  119. #if DEBUG == 1
  120. printf("(uds) VFS reply => %d\n", vfs_m.m_type);
  121. #endif
  122. return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
  123. }
  124. static int copy_filp(endpoint_t to_ep, filp_id_t cfilp)
  125. {
  126. int rc;
  127. message vfs_m;
  128. #if DEBUG == 1
  129. static int call_count = 0;
  130. printf("(uds) copy_filp(%d, 0x%x) call_count=%d\n",to_ep, cfilp,
  131. ++call_count);
  132. #endif
  133. memset(&vfs_m, '\0', sizeof(message));
  134. vfs_m.m_type = PFS_REQ_COPY_FILP;
  135. vfs_m.USER_ENDPT = to_ep;
  136. vfs_m.ADDRESS = cfilp;
  137. rc = sendrec(VFS_PROC_NR, &vfs_m);
  138. if (OK != rc) {
  139. printf("(uds) sendrec error... req_nr: %d err: %d\n",
  140. vfs_m.m_type, rc);
  141. return EIO;
  142. }
  143. #if DEBUG == 1
  144. printf("(uds) VFS reply => %d\n", vfs_m.m_type);
  145. #endif
  146. return vfs_m.m_type;
  147. }
  148. static int put_filp(filp_id_t pfilp)
  149. {
  150. int rc;
  151. message vfs_m;
  152. #if DEBUG == 1
  153. static int call_count = 0;
  154. printf("(uds) put_filp(0x%x) call_count=%d\n", pfilp, ++call_count);
  155. #endif
  156. memset(&vfs_m, '\0', sizeof(message));
  157. vfs_m.m_type = PFS_REQ_PUT_FILP;
  158. vfs_m.ADDRESS = pfilp;
  159. rc = sendrec(VFS_PROC_NR, &vfs_m);
  160. if (OK != rc) {
  161. printf("(uds) sendrec error... req_nr: %d err: %d\n",
  162. vfs_m.m_type, rc);
  163. return EIO;
  164. }
  165. #if DEBUG == 1
  166. printf("(uds) VFS reply => %d\n", vfs_m.m_type);
  167. #endif
  168. return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
  169. }
  170. static int cancel_fd(endpoint_t ep, int fd)
  171. {
  172. int rc;
  173. message vfs_m;
  174. #if DEBUG == 1
  175. static int call_count = 0;
  176. printf("(uds) cancel_fd(%d,%d) call_count=%d\n", ep, fd, ++call_count);
  177. #endif
  178. memset(&vfs_m, '\0', sizeof(message));
  179. vfs_m.m_type = PFS_REQ_CANCEL_FD;
  180. vfs_m.USER_ENDPT = ep;
  181. vfs_m.COUNT = fd;
  182. rc = sendrec(VFS_PROC_NR, &vfs_m);
  183. if (OK != rc) {
  184. printf("(uds) sendrec error... req_nr: %d err: %d\n",
  185. vfs_m.m_type, rc);
  186. return EIO;
  187. }
  188. #if DEBUG == 1
  189. printf("(uds) VFS reply => %d\n", vfs_m.m_type);
  190. #endif
  191. return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
  192. }
  193. int perform_connection(message *dev_m_in, message *dev_m_out,
  194. struct sockaddr_un *addr, int minorx, int minory)
  195. {
  196. /* there are several places were a connection is established. */
  197. /* accept(2), connect(2), uds_status(2), socketpair(2) */
  198. /* This is a helper function to make sure it is done in the */
  199. /* same way in each place with the same validation checks. */
  200. #if DEBUG == 1
  201. static int call_count = 0;
  202. printf("(uds) [%d] perform_connection() call_count=%d\n",
  203. uds_minor(dev_m_in), ++call_count);
  204. #endif
  205. /* only connection oriented types are acceptable and only like
  206. * types can connect to each other
  207. */
  208. if ((uds_fd_table[minorx].type != SOCK_SEQPACKET &&
  209. uds_fd_table[minorx].type != SOCK_STREAM) ||
  210. uds_fd_table[minorx].type != uds_fd_table[minory].type) {
  211. /* sockets are not in a valid state */
  212. return EINVAL;
  213. }
  214. /* connect the pair of sockets */
  215. uds_fd_table[minorx].peer = minory;
  216. uds_fd_table[minory].peer = minorx;
  217. /* Set the address of both sockets */
  218. memcpy(&(uds_fd_table[minorx].addr), addr, sizeof(struct sockaddr_un));
  219. memcpy(&(uds_fd_table[minory].addr), addr, sizeof(struct sockaddr_un));
  220. return OK;
  221. }
  222. int do_accept(message *dev_m_in, message *dev_m_out)
  223. {
  224. int minor;
  225. int minorparent; /* minor number of parent (server) */
  226. int minorpeer;
  227. int rc, i;
  228. struct sockaddr_un addr;
  229. #if DEBUG == 1
  230. static int call_count = 0;
  231. printf("(uds) [%d] do_accept() call_count=%d\n",
  232. uds_minor(dev_m_in), ++call_count);
  233. #endif
  234. /* Somewhat weird logic is used in this function, so here's an
  235. * overview... The minor number is the server's client socket
  236. * (the socket to be returned by accept()). The data waiting
  237. * for us in the IO Grant is the address that the server is
  238. * listening on. This function uses the address to find the
  239. * server's descriptor. From there we can perform the
  240. * connection or suspend and wait for a connect().
  241. */
  242. minor = uds_minor(dev_m_in);
  243. if (uds_fd_table[minor].type != -1) {
  244. /* this IOCTL must be called on a 'fresh' socket */
  245. return EINVAL;
  246. }
  247. /* Get the server's address */
  248. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  249. (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
  250. if (rc != OK) {
  251. return EIO;
  252. }
  253. /* locate server socket */
  254. rc = -1; /* to trap error */
  255. for (i = 0; i < NR_FDS; i++) {
  256. if (uds_fd_table[i].addr.sun_family == AF_UNIX &&
  257. !strncmp(addr.sun_path,
  258. uds_fd_table[i].addr.sun_path,
  259. UNIX_PATH_MAX) &&
  260. uds_fd_table[i].listening == 1) {
  261. rc = 0;
  262. break;
  263. }
  264. }
  265. if (rc == -1) {
  266. /* there is no server listening on addr. Maybe someone
  267. * screwed up the ioctl()?
  268. */
  269. return EINVAL;
  270. }
  271. minorparent = i; /* parent */
  272. /* we are the parent's child */
  273. uds_fd_table[minorparent].child = minor;
  274. /* the peer has the same type as the parent. we need to be that
  275. * type too.
  276. */
  277. uds_fd_table[minor].type = uds_fd_table[minorparent].type;
  278. /* locate peer to accept in the parent's backlog */
  279. minorpeer = -1; /* to trap error */
  280. for (i = 0; i < uds_fd_table[minorparent].backlog_size; i++) {
  281. if (uds_fd_table[minorparent].backlog[i] != -1) {
  282. minorpeer = uds_fd_table[minorparent].backlog[i];
  283. uds_fd_table[minorparent].backlog[i] = -1;
  284. rc = 0;
  285. break;
  286. }
  287. }
  288. if (minorpeer == -1) {
  289. #if DEBUG == 1
  290. printf("(uds) [%d] {do_accept} suspend\n", minor);
  291. #endif
  292. /* there are no peers in the backlog, suspend and wait
  293. * for some to show up
  294. */
  295. uds_fd_table[minor].suspended = UDS_SUSPENDED_ACCEPT;
  296. return SUSPEND;
  297. }
  298. #if DEBUG == 1
  299. printf("(uds) [%d] connecting to %d -- parent is %d\n", minor,
  300. minorpeer, minorparent);
  301. #endif
  302. rc = perform_connection(dev_m_in, dev_m_out, &addr, minor, minorpeer);
  303. if (rc != OK) {
  304. #if DEBUG == 1
  305. printf("(uds) [%d] {do_accept} connection not performed\n",
  306. minor);
  307. #endif
  308. return rc;
  309. }
  310. uds_fd_table[minorparent].child = -1;
  311. /* if peer is blocked on connect() revive peer */
  312. if (uds_fd_table[minorpeer].suspended) {
  313. #if DEBUG == 1
  314. printf("(uds) [%d] {do_accept} revive %d\n", minor,
  315. minorpeer);
  316. #endif
  317. uds_fd_table[minorpeer].ready_to_revive = 1;
  318. uds_unsuspend(dev_m_in->m_source, minorpeer);
  319. }
  320. return OK;
  321. }
  322. int do_connect(message *dev_m_in, message *dev_m_out)
  323. {
  324. int minor;
  325. struct sockaddr_un addr;
  326. int rc, i, j;
  327. #if DEBUG == 1
  328. static int call_count = 0;
  329. printf("(uds) [%d] do_connect() call_count=%d\n", uds_minor(dev_m_in),
  330. ++call_count);
  331. #endif
  332. minor = uds_minor(dev_m_in);
  333. /* only connection oriented sockets can connect */
  334. if (uds_fd_table[minor].type != SOCK_STREAM &&
  335. uds_fd_table[minor].type != SOCK_SEQPACKET) {
  336. return EINVAL;
  337. }
  338. if (uds_fd_table[minor].peer != -1) {
  339. /* socket is already connected */
  340. return EISCONN;
  341. }
  342. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  343. (vir_bytes) 0, (vir_bytes) &addr,
  344. sizeof(struct sockaddr_un));
  345. if (rc != OK) {
  346. return EIO;
  347. }
  348. rc = check_perms(minor, &addr);
  349. if (rc != OK) {
  350. /* permission denied, socket file doesn't exist, etc. */
  351. return rc;
  352. }
  353. /* look for a socket of the same type that is listening on the
  354. * address we want to connect to
  355. */
  356. for (i = 0; i < NR_FDS; i++) {
  357. if (uds_fd_table[minor].type == uds_fd_table[i].type &&
  358. uds_fd_table[i].listening &&
  359. uds_fd_table[i].addr.sun_family == AF_UNIX &&
  360. !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
  361. UNIX_PATH_MAX)) {
  362. if (uds_fd_table[i].child != -1) {
  363. /* the server is blocked on accept(2) --
  364. * perform connection to the child
  365. */
  366. rc = perform_connection(dev_m_in, dev_m_out,
  367. &addr, minor, uds_fd_table[i].child);
  368. if (rc == OK) {
  369. uds_fd_table[i].child = -1;
  370. #if DEBUG == 1
  371. printf("(uds) [%d] {do_connect} revive %d\n", minor, i);
  372. #endif
  373. /* wake the parent (server) */
  374. uds_fd_table[i].ready_to_revive = 1;
  375. uds_unsuspend(dev_m_in->m_source, i);
  376. }
  377. return rc;
  378. } else {
  379. #if DEBUG == 1
  380. printf("(uds) [%d] adding to %d's backlog\n",
  381. minor, i);
  382. #endif
  383. /* tell the server were waiting to be served */
  384. /* look for a free slot in the backlog */
  385. rc = -1; /* to trap error */
  386. for (j = 0; j < uds_fd_table[i].backlog_size;
  387. j++) {
  388. if (uds_fd_table[i].backlog[j] == -1) {
  389. uds_fd_table[i].backlog[j] =
  390. minor;
  391. rc = 0;
  392. break;
  393. }
  394. }
  395. if (rc == -1) {
  396. /* backlog is full */
  397. break;
  398. }
  399. /* see if the server is blocked on select() */
  400. if (uds_fd_table[i].selecting == 1) {
  401. /* if the server wants to know
  402. * about data ready to read and
  403. * it doesn't know about it
  404. * already, then let the server
  405. * know we have data for it.
  406. */
  407. if ((uds_fd_table[i].sel_ops_in &
  408. SEL_RD) &&
  409. !(uds_fd_table[i].sel_ops_out &
  410. SEL_RD)) {
  411. uds_fd_table[i].sel_ops_out |=
  412. SEL_RD;
  413. uds_fd_table[i].status_updated
  414. = 1;
  415. uds_unsuspend(
  416. dev_m_in->m_source, i);
  417. }
  418. }
  419. /* we found our server */
  420. uds_fd_table[minor].peer = i;
  421. /* set the address */
  422. memcpy(&(uds_fd_table[minor].addr), &addr,
  423. sizeof(struct sockaddr_un));
  424. break;
  425. }
  426. }
  427. }
  428. if (uds_fd_table[minor].peer == -1) {
  429. /* could not find another open socket listening on the
  430. * specified address with room in the backlog
  431. */
  432. return ECONNREFUSED;
  433. }
  434. #if DEBUG == 1
  435. printf("(uds) [%d] {do_connect} suspend\n", minor);
  436. #endif
  437. /* suspend until the server side completes the connection with accept()
  438. */
  439. uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT;
  440. return SUSPEND;
  441. }
  442. int do_listen(message *dev_m_in, message *dev_m_out)
  443. {
  444. int minor;
  445. int rc;
  446. int backlog_size;
  447. #if DEBUG == 1
  448. static int call_count = 0;
  449. printf("(uds) [%d] do_listen() call_count=%d\n", uds_minor(dev_m_in),
  450. ++call_count);
  451. #endif
  452. minor = uds_minor(dev_m_in);
  453. /* ensure the socket has a type and is bound */
  454. if (uds_fd_table[minor].type == -1 ||
  455. uds_fd_table[minor].addr.sun_family != AF_UNIX) {
  456. /* probably trying to call listen() before bind() */
  457. return EINVAL;
  458. }
  459. /* the two supported types for listen(2) are SOCK_STREAM and
  460. * SOCK_SEQPACKET
  461. */
  462. if (uds_fd_table[minor].type != SOCK_STREAM &&
  463. uds_fd_table[minor].type != SOCK_SEQPACKET) {
  464. /* probably trying to call listen() with a SOCK_DGRAM */
  465. return EOPNOTSUPP;
  466. }
  467. /* The POSIX standard doesn't say what to do if listen() has
  468. * already been called. Well, there isn't an errno. we silently
  469. * let it happen, but if listen() has already been called, we
  470. * don't allow the backlog to shrink
  471. */
  472. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  473. (vir_bytes) 0, (vir_bytes) &backlog_size, sizeof(int));
  474. if (rc != OK) {
  475. return EIO;
  476. }
  477. if (uds_fd_table[minor].listening == 0) {
  478. /* See if backlog_size is between 0 and UDS_SOMAXCONN */
  479. if (backlog_size >= 0 && backlog_size < UDS_SOMAXCONN) {
  480. /* use the user provided backlog_size */
  481. uds_fd_table[minor].backlog_size = backlog_size;
  482. } else {
  483. /* the user gave an invalid size, use
  484. * UDS_SOMAXCONN instead
  485. */
  486. uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
  487. }
  488. } else {
  489. /* See if the user is trying to expand the backlog_size */
  490. if (backlog_size > uds_fd_table[minor].backlog_size &&
  491. backlog_size < UDS_SOMAXCONN) {
  492. /* expand backlog_size */
  493. uds_fd_table[minor].backlog_size = backlog_size;
  494. }
  495. /* Don't let the user shrink the backlog_size (we might
  496. * have clients waiting in those slots
  497. */
  498. }
  499. /* perform listen(2) */
  500. uds_fd_table[minor].listening = 1;
  501. return OK;
  502. }
  503. int do_socket(message *dev_m_in, message *dev_m_out)
  504. {
  505. int rc;
  506. int minor;
  507. #if DEBUG == 1
  508. static int call_count = 0;
  509. printf("(uds) [%d] do_socket() call_count=%d\n", uds_minor(dev_m_in),
  510. ++call_count);
  511. #endif
  512. minor = uds_minor(dev_m_in);
  513. /* see if this socket already has a type */
  514. if (uds_fd_table[minor].type != -1) {
  515. /* socket type can only be set once */
  516. return EINVAL;
  517. }
  518. /* get the requested type */
  519. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  520. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
  521. sizeof(int));
  522. if (rc != OK) {
  523. /* something went wrong and we couldn't get the type */
  524. return EIO;
  525. }
  526. /* validate the type */
  527. switch (uds_fd_table[minor].type) {
  528. case SOCK_STREAM:
  529. case SOCK_DGRAM:
  530. case SOCK_SEQPACKET:
  531. /* the type is one of the 3 valid socket types */
  532. return OK;
  533. default:
  534. /* if the type isn't one of the 3 valid socket
  535. * types, then it must be invalid.
  536. */
  537. /* set the type back to '-1' (no type set) */
  538. uds_fd_table[minor].type = -1;
  539. return EINVAL;
  540. }
  541. }
  542. int do_bind(message *dev_m_in, message *dev_m_out)
  543. {
  544. int minor;
  545. struct sockaddr_un addr;
  546. int rc, i;
  547. #if DEBUG == 1
  548. static int call_count = 0;
  549. printf("(uds) [%d] do_bind() call_count=%d\n", uds_minor(dev_m_in),
  550. ++call_count);
  551. #endif
  552. minor = uds_minor(dev_m_in);
  553. if ((uds_fd_table[minor].type == -1) ||
  554. (uds_fd_table[minor].addr.sun_family == AF_UNIX &&
  555. uds_fd_table[minor].type != SOCK_DGRAM)) {
  556. /* the type hasn't been set by do_socket() yet OR attempting
  557. * to re-bind() a non-SOCK_DGRAM socket
  558. */
  559. return EINVAL;
  560. }
  561. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  562. (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
  563. if (rc != OK) {
  564. return EIO;
  565. }
  566. /* do some basic sanity checks on the address */
  567. if (addr.sun_family != AF_UNIX) {
  568. /* bad family */
  569. return EAFNOSUPPORT;
  570. }
  571. if (addr.sun_path[0] == '\0') {
  572. /* bad address */
  573. return ENOENT;
  574. }
  575. rc = check_perms(minor, &addr);
  576. if (rc != OK) {
  577. /* permission denied, socket file doesn't exist, etc. */
  578. return rc;
  579. }
  580. /* make sure the address isn't already in use by another socket. */
  581. for (i = 0; i < NR_FDS; i++) {
  582. if ((uds_fd_table[i].addr.sun_family == AF_UNIX) &&
  583. !strncmp(addr.sun_path,
  584. uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {
  585. /* another socket is bound to this sun_path */
  586. return EADDRINUSE;
  587. }
  588. }
  589. /* looks good, perform the bind() */
  590. memcpy(&(uds_fd_table[minor].addr), &addr, sizeof(struct sockaddr_un));
  591. return OK;
  592. }
  593. int do_getsockname(message *dev_m_in, message *dev_m_out)
  594. {
  595. int minor;
  596. int rc;
  597. #if DEBUG == 1
  598. static int call_count = 0;
  599. printf("(uds) [%d] do_getsockname() call_count=%d\n",
  600. uds_minor(dev_m_in), ++call_count);
  601. #endif
  602. minor = uds_minor(dev_m_in);
  603. /* Unconditionally send the address we have assigned to this socket.
  604. * The POSIX standard doesn't say what to do if the address
  605. * hasn't been set. If the address isn't currently set, then
  606. * the user will get NULL bytes. Note: libc depends on this
  607. * behavior.
  608. */
  609. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  610. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].addr),
  611. sizeof(struct sockaddr_un));
  612. return rc ? EIO : OK;
  613. }
  614. int do_getpeername(message *dev_m_in, message *dev_m_out)
  615. {
  616. int minor;
  617. int rc;
  618. #if DEBUG == 1
  619. static int call_count = 0;
  620. printf("(uds) [%d] do_getpeername() call_count=%d\n",
  621. uds_minor(dev_m_in), ++call_count);
  622. #endif
  623. minor = uds_minor(dev_m_in);
  624. /* check that the socket is connected with a valid peer */
  625. if (uds_fd_table[minor].peer != -1) {
  626. int peer_minor;
  627. peer_minor = uds_fd_table[minor].peer;
  628. /* copy the address from the peer */
  629. rc = sys_safecopyto(VFS_PROC_NR,
  630. (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0,
  631. (vir_bytes) &(uds_fd_table[peer_minor].addr),
  632. sizeof(struct sockaddr_un));
  633. return rc ? EIO : OK;
  634. } else {
  635. if (uds_fd_table[minor].err == ECONNRESET) {
  636. uds_fd_table[minor].err = 0;
  637. return ECONNRESET;
  638. } else {
  639. return ENOTCONN;
  640. }
  641. }
  642. }
  643. int do_shutdown(message *dev_m_in, message *dev_m_out)
  644. {
  645. int minor;
  646. int rc, how;
  647. #if DEBUG == 1
  648. static int call_count = 0;
  649. printf("(uds) [%d] do_shutdown() call_count=%d\n",
  650. uds_minor(dev_m_in), ++call_count);
  651. #endif
  652. minor = uds_minor(dev_m_in);
  653. if (uds_fd_table[minor].type != SOCK_STREAM &&
  654. uds_fd_table[minor].type != SOCK_SEQPACKET) {
  655. /* socket must be a connection oriented socket */
  656. return EINVAL;
  657. }
  658. if (uds_fd_table[minor].peer == -1) {
  659. /* shutdown(2) is only valid for connected sockets */
  660. if (uds_fd_table[minor].err == ECONNRESET) {
  661. return ECONNRESET;
  662. } else {
  663. return ENOTCONN;
  664. }
  665. }
  666. /* get the 'how' parameter from the process */
  667. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  668. (vir_bytes) 0, (vir_bytes) &how, sizeof(int));
  669. if (rc != OK) {
  670. return EIO;
  671. }
  672. switch (how) {
  673. case SHUT_RD:
  674. /* take away read permission */
  675. uds_fd_table[minor].mode =
  676. uds_fd_table[minor].mode ^ S_IRUSR;
  677. break;
  678. case SHUT_WR:
  679. /* take away write permission */
  680. uds_fd_table[minor].mode =
  681. uds_fd_table[minor].mode ^ S_IWUSR;
  682. break;
  683. case SHUT_RDWR:
  684. /* completely shutdown */
  685. uds_fd_table[minor].mode = 0;
  686. break;
  687. default:
  688. /* the 'how' parameter is invalid */
  689. return EINVAL;
  690. }
  691. return OK;
  692. }
  693. int do_socketpair_old(message *dev_m_in, message *dev_m_out)
  694. {
  695. int rc;
  696. short minorin;
  697. int minorx, minory;
  698. struct sockaddr_un addr;
  699. #if DEBUG == 1
  700. static int call_count = 0;
  701. printf("(uds) [%d] do_socketpair() call_count=%d\n",
  702. uds_minor(dev_m_in), ++call_count);
  703. #endif
  704. /* first ioctl param is the first socket */
  705. minorx = uds_minor_old(dev_m_in);
  706. /* third ioctl param is the minor number of the second socket */
  707. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  708. (vir_bytes) 0, (vir_bytes) &minorin, sizeof(short));
  709. if (rc != OK) {
  710. return EIO;
  711. }
  712. minory = minor(minorin);
  713. #if DEBUG == 1
  714. printf("socketpair() %d - %d\n", minorx, minory);
  715. #endif
  716. /* security check - both sockets must have the same endpoint (owner) */
  717. if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner) {
  718. /* we won't allow you to magically connect your socket to
  719. * someone elses socket
  720. */
  721. return EPERM;
  722. }
  723. addr.sun_family = AF_UNIX;
  724. addr.sun_path[0] = 'X';
  725. addr.sun_path[1] = '\0';
  726. uds_fd_table[minorx].syscall_done = 1;
  727. return perform_connection(dev_m_in, dev_m_out, &addr, minorx, minory);
  728. }
  729. int do_socketpair(message *dev_m_in, message *dev_m_out)
  730. {
  731. int rc;
  732. dev_t minorin;
  733. int minorx, minory;
  734. struct sockaddr_un addr;
  735. #if DEBUG == 1
  736. static int call_count = 0;
  737. printf("(uds) [%d] do_socketpair() call_count=%d\n",
  738. uds_minor(dev_m_in), ++call_count);
  739. #endif
  740. /* first ioctl param is the first socket */
  741. minorx = uds_minor(dev_m_in);
  742. /* third ioctl param is the minor number of the second socket */
  743. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  744. (vir_bytes) 0, (vir_bytes) &minorin, sizeof(dev_t));
  745. if (rc != OK) {
  746. return EIO;
  747. }
  748. minory = minor(minorin);
  749. #if DEBUG == 1
  750. printf("socketpair() %d - %d\n", minorx, minory);
  751. #endif
  752. /* security check - both sockets must have the same endpoint (owner) */
  753. if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner) {
  754. /* we won't allow you to magically connect your socket to
  755. * someone elses socket
  756. */
  757. return EPERM;
  758. }
  759. addr.sun_family = AF_UNIX;
  760. addr.sun_path[0] = 'X';
  761. addr.sun_path[1] = '\0';
  762. uds_fd_table[minorx].syscall_done = 1;
  763. return perform_connection(dev_m_in, dev_m_out, &addr, minorx, minory);
  764. }
  765. int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out)
  766. {
  767. int minor;
  768. int rc;
  769. #if DEBUG == 1
  770. static int call_count = 0;
  771. printf("(uds) [%d] do_getsockopt_sotype() call_count=%d\n",
  772. uds_minor(dev_m_in), ++call_count);
  773. #endif
  774. minor = uds_minor(dev_m_in);
  775. if (uds_fd_table[minor].type == -1) {
  776. /* the type hasn't been set yet. instead of returning an
  777. * invalid type, we fail with EINVAL
  778. */
  779. return EINVAL;
  780. }
  781. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  782. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
  783. sizeof(int));
  784. return rc ? EIO : OK;
  785. }
  786. int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out)
  787. {
  788. int minor;
  789. int peer_minor;
  790. int rc;
  791. struct ucred cred;
  792. #if DEBUG == 1
  793. static int call_count = 0;
  794. printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n",
  795. uds_minor(dev_m_in), ++call_count);
  796. #endif
  797. minor = uds_minor(dev_m_in);
  798. if (uds_fd_table[minor].peer == -1) {
  799. if (uds_fd_table[minor].err == ECONNRESET) {
  800. uds_fd_table[minor].err = 0;
  801. return ECONNRESET;
  802. } else {
  803. return ENOTCONN;
  804. }
  805. }
  806. peer_minor = uds_fd_table[minor].peer;
  807. /* obtain the peer's credentials */
  808. rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
  809. if (rc == -1) {
  810. /* likely error: invalid endpoint / proc doesn't exist */
  811. return errno;
  812. }
  813. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  814. (vir_bytes) 0, (vir_bytes) &cred, sizeof(struct ucred));
  815. return rc ? EIO : OK;
  816. }
  817. int do_getsockopt_peercred_old(message *dev_m_in, message *dev_m_out)
  818. {
  819. int minor;
  820. int peer_minor;
  821. int rc;
  822. struct ucred cred;
  823. struct ucred_old cred_old;
  824. #if DEBUG == 1
  825. static int call_count = 0;
  826. printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n",
  827. uds_minor(dev_m_in), ++call_count);
  828. #endif
  829. minor = uds_minor(dev_m_in);
  830. if (uds_fd_table[minor].peer == -1) {
  831. if (uds_fd_table[minor].err == ECONNRESET) {
  832. uds_fd_table[minor].err = 0;
  833. return ECONNRESET;
  834. } else {
  835. return ENOTCONN;
  836. }
  837. }
  838. peer_minor = uds_fd_table[minor].peer;
  839. /* obtain the peer's credentials */
  840. rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
  841. if (rc == -1) {
  842. /* likely error: invalid endpoint / proc doesn't exist */
  843. return errno;
  844. }
  845. /* copy to old structure */
  846. cred_old.pid = cred.pid;
  847. cred_old.uid = (short) cred.uid;
  848. cred_old.gid = (char) cred.gid;
  849. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  850. (vir_bytes) 0, (vir_bytes) &cred_old, sizeof(struct ucred_old));
  851. return rc ? EIO : OK;
  852. }
  853. int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
  854. {
  855. int rc;
  856. size_t sndbuf = PIPE_BUF;
  857. #if DEBUG == 1
  858. static int call_count = 0;
  859. printf("(uds) [%d] do_getsockopt_sndbuf() call_count=%d\n",
  860. uds_minor(dev_m_in), ++call_count);
  861. #endif
  862. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  863. (vir_bytes) 0, (vir_bytes) &(sndbuf), sizeof(size_t));
  864. return rc ? EIO : OK;
  865. }
  866. int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
  867. {
  868. int rc;
  869. size_t sndbuf;
  870. #if DEBUG == 1
  871. static int call_count = 0;
  872. printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
  873. uds_minor(dev_m_in), ++call_count);
  874. #endif
  875. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  876. (vir_bytes) 0, (vir_bytes) &sndbuf,
  877. sizeof(size_t));
  878. if (rc != OK) {
  879. return EIO;
  880. }
  881. if (sndbuf > PIPE_BUF) {
  882. /* The send buffer is limited to 32K at the moment. */
  883. return ENOSYS;
  884. }
  885. /* There is no way to reduce the send buffer, do we have to
  886. * let this call fail for smaller buffers?
  887. */
  888. return OK;
  889. }
  890. int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
  891. {
  892. int rc;
  893. size_t rcvbuf = PIPE_BUF;
  894. #if DEBUG == 1
  895. static int call_count = 0;
  896. printf("(uds) [%d] do_getsockopt_rcvbuf() call_count=%d\n",
  897. uds_minor(dev_m_in), ++call_count);
  898. #endif
  899. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  900. (vir_bytes) 0, (vir_bytes) &(rcvbuf), sizeof(size_t));
  901. return rc ? EIO : OK;
  902. }
  903. int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
  904. {
  905. int rc;
  906. size_t rcvbuf;
  907. #if DEBUG == 1
  908. static int call_count = 0;
  909. printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
  910. uds_minor(dev_m_in), ++call_count);
  911. #endif
  912. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  913. (vir_bytes) 0, (vir_bytes) &rcvbuf,
  914. sizeof(size_t));
  915. if (rc != OK) {
  916. return EIO;
  917. }
  918. if (rcvbuf > PIPE_BUF) {
  919. /* The send buffer is limited to 32K at the moment. */
  920. return ENOSYS;
  921. }
  922. /* There is no way to reduce the send buffer, do we have to
  923. * let this call fail for smaller buffers?
  924. */
  925. return OK;
  926. }
  927. int do_sendto(message *dev_m_in, message *dev_m_out)
  928. {
  929. int minor;
  930. int rc;
  931. struct sockaddr_un addr;
  932. #if DEBUG == 1
  933. static int call_count = 0;
  934. printf("(uds) [%d] do_sendto() call_count=%d\n", uds_minor(dev_m_in),
  935. ++call_count);
  936. #endif
  937. minor = uds_minor(dev_m_in);
  938. if (uds_fd_table[minor].type != SOCK_DGRAM) {
  939. /* This IOCTL is only for SOCK_DGRAM sockets */
  940. return EINVAL;
  941. }
  942. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  943. (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
  944. if (rc != OK) {
  945. return EIO;
  946. }
  947. /* do some basic sanity checks on the address */
  948. if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0') {
  949. /* bad address */
  950. return EINVAL;
  951. }
  952. rc = check_perms(minor, &addr);
  953. if (rc != OK) {
  954. return rc;
  955. }
  956. memcpy(&(uds_fd_table[minor].target), &addr,
  957. sizeof(struct sockaddr_un));
  958. return OK;
  959. }
  960. int do_recvfrom(message *dev_m_in, message *dev_m_out)
  961. {
  962. int minor;
  963. int rc;
  964. #if DEBUG == 1
  965. static int call_count = 0;
  966. printf("(uds) [%d] do_recvfrom() call_count=%d\n",
  967. uds_minor(dev_m_in), ++call_count);
  968. #endif
  969. minor = uds_minor(dev_m_in);
  970. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  971. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].source),
  972. sizeof(struct sockaddr_un));
  973. return rc ? EIO : OK;
  974. }
  975. int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
  976. int minor)
  977. {
  978. int rc;
  979. struct msghdr msghdr;
  980. struct cmsghdr *cmsg = NULL;
  981. #if DEBUG == 1
  982. static int call_count = 0;
  983. printf("(uds) [%d] msg_control_read() call_count=%d\n", minor,
  984. ++call_count);
  985. #endif
  986. data->nfiledes = 0;
  987. memset(&msghdr, '\0', sizeof(struct msghdr));
  988. msghdr.msg_control = msg_ctrl->msg_control;
  989. msghdr.msg_controllen = msg_ctrl->msg_controllen;
  990. for(cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL;
  991. cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
  992. if (cmsg->cmsg_level == SOL_SOCKET &&
  993. cmsg->cmsg_type == SCM_RIGHTS) {
  994. int i;
  995. int nfds =
  996. MIN((cmsg->cmsg_len-CMSG_LEN(0))/sizeof(int),
  997. OPEN_MAX);
  998. for (i = 0; i < nfds; i++) {
  999. if (data->nfiledes == OPEN_MAX) {
  1000. return EOVERFLOW;
  1001. }
  1002. data->fds[data->nfiledes] =
  1003. ((int *) CMSG_DATA(cmsg))[i];
  1004. #if DEBUG == 1
  1005. printf("(uds) [%d] fd[%d]=%d\n", minor,
  1006. data->nfiledes, data->fds[data->nfiledes]);
  1007. #endif
  1008. data->nfiledes++;
  1009. }
  1010. }
  1011. }
  1012. /* obtain this socket's credentials */
  1013. rc = getnucred(uds_fd_table[minor].owner, &(data->cred));
  1014. if (rc == -1) {
  1015. return errno;
  1016. }
  1017. #if DEBUG == 1
  1018. printf("(uds) [%d] cred={%d,%d,%d}\n", minor,
  1019. data->cred.pid, data->cred.uid,
  1020. data->cred.gid);
  1021. #endif
  1022. return OK;
  1023. }
  1024. static int send_fds(int minor, struct ancillary *data)
  1025. {
  1026. int rc, i, j;
  1027. #if DEBUG == 1
  1028. static int call_count = 0;
  1029. printf("(uds) [%d] send_fds() call_count=%d\n", minor, ++call_count);
  1030. #endif
  1031. /* verify the file descriptors and get their filps. */
  1032. for (i = 0; i < data->nfiledes; i++) {
  1033. data->filps[i] = verify_fd(uds_fd_table[minor].owner,
  1034. data->fds[i]);
  1035. if (data->filps[i] == NULL) {
  1036. return EINVAL;
  1037. }
  1038. }
  1039. /* set them as in-flight */
  1040. for (i = 0; i < data->nfiledes; i++) {
  1041. rc = set_filp(data->filps[i]);
  1042. if (rc != OK) {
  1043. /* revert set_filp() calls */
  1044. for (j = i; j >= 0; j--) {
  1045. put_filp(data->filps[j]);
  1046. }
  1047. return rc;
  1048. }
  1049. }
  1050. return OK;
  1051. }
  1052. int clear_fds(int minor, struct ancillary *data)
  1053. {
  1054. /* This function calls put_filp() for all of the FDs in data.
  1055. * This is used when a Unix Domain Socket is closed and there
  1056. * exists references to file descriptors that haven't been received
  1057. * with recvmsg().
  1058. */
  1059. int i;
  1060. #if DEBUG == 1
  1061. static int call_count = 0;
  1062. printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
  1063. ++call_count);
  1064. #endif
  1065. for (i = 0; i < data->nfiledes; i++) {
  1066. put_filp(data->filps[i]);
  1067. #if DEBUG == 1
  1068. printf("(uds) clear_fds() => %d\n", data->fds[i]);
  1069. #endif
  1070. data->fds[i] = -1;
  1071. data->filps[i] = NULL;
  1072. }
  1073. data->nfiledes = 0;
  1074. return OK;
  1075. }
  1076. static int recv_fds(int minor, struct ancillary *data,
  1077. struct msg_control *msg_ctrl)
  1078. {
  1079. int rc, i, j;
  1080. struct msghdr msghdr;
  1081. struct cmsghdr *cmsg;
  1082. endpoint_t to_ep;
  1083. #if DEBUG == 1
  1084. static int call_count = 0;
  1085. printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
  1086. ++call_count);
  1087. #endif
  1088. msghdr.msg_control = msg_ctrl->msg_control;
  1089. msghdr.msg_controllen = msg_ctrl->msg_controllen;
  1090. cmsg = CMSG_FIRSTHDR(&msghdr);
  1091. cmsg->cmsg_len = CMSG_LEN(sizeof(int) * data->nfiledes);
  1092. cmsg->cmsg_level = SOL_SOCKET;
  1093. cmsg->cmsg_type = SCM_RIGHTS;
  1094. to_ep = uds_fd_table[minor].owner;
  1095. /* copy to the target endpoint */
  1096. for (i = 0; i < data->nfiledes; i++) {
  1097. rc = copy_filp(to_ep, data->filps[i]);
  1098. if (rc < 0) {
  1099. /* revert set_filp() calls */
  1100. for (j = 0; j < data->nfiledes; j++) {
  1101. put_filp(data->filps[j]);
  1102. }
  1103. /* revert copy_filp() calls */
  1104. for (j = i; j >= 0; j--) {
  1105. cancel_fd(to_ep, data->fds[j]);
  1106. }
  1107. return rc;
  1108. }
  1109. data->fds[i] = rc; /* data->fds[i] now has the new FD */
  1110. }
  1111. for (i = 0; i < data->nfiledes; i++) {
  1112. put_filp(data->filps[i]);
  1113. #if DEBUG == 1
  1114. printf("(uds) recv_fds() => %d\n", data->fds[i]);
  1115. #endif
  1116. ((int *)CMSG_DATA(cmsg))[i] = data->fds[i];
  1117. data->fds[i] = -1;
  1118. data->filps[i] = NULL;
  1119. }
  1120. data->nfiledes = 0;
  1121. return OK;
  1122. }
  1123. static int recv_cred(int minor, struct ancillary *data,
  1124. struct msg_control *msg_ctrl)
  1125. {
  1126. struct msghdr msghdr;
  1127. struct cmsghdr *cmsg;
  1128. #if DEBUG == 1
  1129. static int call_count = 0;
  1130. printf("(uds) [%d] recv_cred() call_count=%d\n", minor,
  1131. ++call_count);
  1132. #endif
  1133. msghdr.msg_control = msg_ctrl->msg_control;
  1134. msghdr.msg_controllen = msg_ctrl->msg_controllen;
  1135. cmsg = CMSG_FIRSTHDR(&msghdr);
  1136. if (cmsg->cmsg_len > 0) {
  1137. cmsg = CMSG_NXTHDR(&msghdr, cmsg);
  1138. }
  1139. cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
  1140. cmsg->cmsg_level = SOL_SOCKET;
  1141. cmsg->cmsg_type = SCM_CREDENTIALS;
  1142. memcpy(CMSG_DATA(cmsg), &(data->cred), sizeof(struct ucred));
  1143. return OK;
  1144. }
  1145. int do_sendmsg(message *dev_m_in, message *dev_m_out)
  1146. {
  1147. int minor, peer, rc, i;
  1148. struct msg_control msg_ctrl;
  1149. #if DEBUG == 1
  1150. static int call_count = 0;
  1151. printf("(uds) [%d] do_sendmsg() call_count=%d\n",
  1152. uds_minor(dev_m_in), ++call_count);
  1153. #endif
  1154. minor = uds_minor(dev_m_in);
  1155. memset(&msg_ctrl, '\0', sizeof(struct msg_control));
  1156. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  1157. (vir_bytes) 0, (vir_bytes) &msg_ctrl,
  1158. sizeof(struct msg_control));
  1159. if (rc != OK) {
  1160. return EIO;
  1161. }
  1162. /* locate peer */
  1163. peer = -1;
  1164. if (uds_fd_table[minor].type == SOCK_DGRAM) {
  1165. if (uds_fd_table[minor].target.sun_path[0] == '\0' ||
  1166. uds_fd_table[minor].target.sun_family != AF_UNIX) {
  1167. return EDESTADDRREQ;
  1168. }
  1169. for (i = 0; i < NR_FDS; i++) {
  1170. /* look for a SOCK_DGRAM socket that is bound on
  1171. * the target address
  1172. */
  1173. if (uds_fd_table[i].type == SOCK_DGRAM &&
  1174. uds_fd_table[i].addr.sun_family == AF_UNIX &&
  1175. !strncmp(uds_fd_table[minor].target.sun_path,
  1176. uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)){
  1177. peer = i;
  1178. break;
  1179. }
  1180. }
  1181. if (peer == -1) {
  1182. return ENOENT;
  1183. }
  1184. } else {
  1185. peer = uds_fd_table[minor].peer;
  1186. if (peer == -1) {
  1187. return ENOTCONN;
  1188. }
  1189. }
  1190. #if DEBUG == 1
  1191. printf("(uds) [%d] sendmsg() -- peer=%d\n", minor, peer);
  1192. #endif
  1193. /* note: it's possible that there is already some file
  1194. * descriptors in ancillary_data if the peer didn't call
  1195. * recvmsg() yet. That's okay. The receiver will
  1196. * get the current file descriptors plus the new ones.
  1197. */
  1198. rc = msg_control_read(&msg_ctrl, &uds_fd_table[peer].ancillary_data,
  1199. minor);
  1200. if (rc != OK) {
  1201. return rc;
  1202. }
  1203. return send_fds(minor, &uds_fd_table[peer].ancillary_data);
  1204. }
  1205. int do_recvmsg(message *dev_m_in, message *dev_m_out)
  1206. {
  1207. int minor;
  1208. int rc;
  1209. struct msg_control msg_ctrl;
  1210. socklen_t controllen_avail = 0;
  1211. socklen_t controllen_needed = 0;
  1212. socklen_t controllen_desired = 0;
  1213. #if DEBUG == 1
  1214. static int call_count = 0;
  1215. printf("(uds) [%d] do_sendmsg() call_count=%d\n",
  1216. uds_minor(dev_m_in), ++call_count);
  1217. #endif
  1218. minor = uds_minor(dev_m_in);
  1219. #if DEBUG == 1
  1220. printf("(uds) [%d] CREDENTIALS {pid:%d,uid:%d,gid:%d}\n", minor,
  1221. uds_fd_table[minor].ancillary_data.cred.pid,
  1222. uds_fd_table[minor].ancillary_data.cred.uid,
  1223. uds_fd_table[minor].ancillary_data.cred.gid);
  1224. #endif
  1225. memset(&msg_ctrl, '\0', sizeof(struct msg_control));
  1226. /* get the msg_control from the user, it will include the
  1227. * amount of space the user has allocated for control data.
  1228. */
  1229. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  1230. (vir_bytes) 0, (vir_bytes) &msg_ctrl,
  1231. sizeof(struct msg_control));
  1232. if (rc != OK) {
  1233. return EIO;
  1234. }
  1235. controllen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX);
  1236. if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
  1237. controllen_needed = CMSG_LEN(sizeof(int) *
  1238. (uds_fd_table[minor].ancillary_data.nfiledes));
  1239. }
  1240. /* if there is room we also include credentials */
  1241. controllen_desired = controllen_needed +
  1242. CMSG_LEN(sizeof(struct ucred));
  1243. if (controllen_needed > controllen_avail) {
  1244. return EOVERFLOW;
  1245. }
  1246. rc = recv_fds(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl);
  1247. if (rc != OK) {
  1248. return rc;
  1249. }
  1250. if (controllen_desired <= controllen_avail) {
  1251. rc = recv_cred(minor, &uds_fd_table[minor].ancillary_data,
  1252. &msg_ctrl);
  1253. if (rc != OK) {
  1254. return rc;
  1255. }
  1256. }
  1257. /* send the user the control data */
  1258. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  1259. (vir_bytes) 0, (vir_bytes) &msg_ctrl,
  1260. sizeof(struct msg_control));
  1261. return rc ? EIO : OK;
  1262. }