PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

servers/pfs/uds.c

http://www.minix3.org/
C | 1623 lines | 1060 code | 347 blank | 216 comment | 258 complexity | f9703d73c60816e202ab78bf70a82777 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. PUBLIC 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. PRIVATE 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. PRIVATE 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. PRIVATE 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. PRIVATE 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. PRIVATE 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. PRIVATE 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. PUBLIC 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. PUBLIC 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. D);
  251. if (rc != OK) {
  252. return EIO;
  253. }
  254. /* locate server socket */
  255. rc = -1; /* to trap error */
  256. for (i = 0; i < NR_FDS; i++) {
  257. if (uds_fd_table[i].addr.sun_family == AF_UNIX &&
  258. !strncmp(addr.sun_path,
  259. uds_fd_table[i].addr.sun_path,
  260. UNIX_PATH_MAX) &&
  261. uds_fd_table[i].listening == 1) {
  262. rc = 0;
  263. break;
  264. }
  265. }
  266. if (rc == -1) {
  267. /* there is no server listening on addr. Maybe someone
  268. * screwed up the ioctl()?
  269. */
  270. return EINVAL;
  271. }
  272. minorparent = i; /* parent */
  273. /* we are the parent's child */
  274. uds_fd_table[minorparent].child = minor;
  275. /* the peer has the same type as the parent. we need to be that
  276. * type too.
  277. */
  278. uds_fd_table[minor].type = uds_fd_table[minorparent].type;
  279. /* locate peer to accept in the parent's backlog */
  280. minorpeer = -1; /* to trap error */
  281. for (i = 0; i < uds_fd_table[minorparent].backlog_size; i++) {
  282. if (uds_fd_table[minorparent].backlog[i] != -1) {
  283. minorpeer = uds_fd_table[minorparent].backlog[i];
  284. uds_fd_table[minorparent].backlog[i] = -1;
  285. rc = 0;
  286. break;
  287. }
  288. }
  289. if (minorpeer == -1) {
  290. #if DEBUG == 1
  291. printf("(uds) [%d] {do_accept} suspend\n", minor);
  292. #endif
  293. /* there are no peers in the backlog, suspend and wait
  294. * for some to show up
  295. */
  296. uds_fd_table[minor].suspended = UDS_SUSPENDED_ACCEPT;
  297. return SUSPEND;
  298. }
  299. #if DEBUG == 1
  300. printf("(uds) [%d] connecting to %d -- parent is %d\n", minor,
  301. minorpeer, minorparent);
  302. #endif
  303. rc = perform_connection(dev_m_in, dev_m_out, &addr, minor, minorpeer);
  304. if (rc != OK) {
  305. #if DEBUG == 1
  306. printf("(uds) [%d] {do_accept} connection not performed\n",
  307. minor);
  308. #endif
  309. return rc;
  310. }
  311. uds_fd_table[minorparent].child = -1;
  312. /* if peer is blocked on connect() revive peer */
  313. if (uds_fd_table[minorpeer].suspended) {
  314. #if DEBUG == 1
  315. printf("(uds) [%d] {do_accept} revive %d\n", minor,
  316. minorpeer);
  317. #endif
  318. uds_fd_table[minorpeer].ready_to_revive = 1;
  319. uds_unsuspend(dev_m_in->m_source, minorpeer);
  320. }
  321. return OK;
  322. }
  323. PUBLIC int do_connect(message *dev_m_in, message *dev_m_out)
  324. {
  325. int minor;
  326. struct sockaddr_un addr;
  327. int rc, i, j;
  328. #if DEBUG == 1
  329. static int call_count = 0;
  330. printf("(uds) [%d] do_connect() call_count=%d\n", uds_minor(dev_m_in),
  331. ++call_count);
  332. #endif
  333. minor = uds_minor(dev_m_in);
  334. /* only connection oriented sockets can connect */
  335. if (uds_fd_table[minor].type != SOCK_STREAM &&
  336. uds_fd_table[minor].type != SOCK_SEQPACKET) {
  337. return EINVAL;
  338. }
  339. if (uds_fd_table[minor].peer != -1) {
  340. /* socket is already connected */
  341. return EISCONN;
  342. }
  343. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  344. (vir_bytes) 0, (vir_bytes) &addr,
  345. sizeof(struct sockaddr_un), D);
  346. if (rc != OK) {
  347. return EIO;
  348. }
  349. rc = check_perms(minor, &addr);
  350. if (rc != OK) {
  351. /* permission denied, socket file doesn't exist, etc. */
  352. return rc;
  353. }
  354. /* look for a socket of the same type that is listening on the
  355. * address we want to connect to
  356. */
  357. for (i = 0; i < NR_FDS; i++) {
  358. if (uds_fd_table[minor].type == uds_fd_table[i].type &&
  359. uds_fd_table[i].listening &&
  360. uds_fd_table[i].addr.sun_family == AF_UNIX &&
  361. !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
  362. UNIX_PATH_MAX)) {
  363. if (uds_fd_table[i].child != -1) {
  364. /* the server is blocked on accept(2) --
  365. * perform connection to the child
  366. */
  367. rc = perform_connection(dev_m_in, dev_m_out,
  368. &addr, minor, uds_fd_table[i].child);
  369. if (rc == OK) {
  370. uds_fd_table[i].child = -1;
  371. #if DEBUG == 1
  372. printf("(uds) [%d] {do_connect} revive %d\n", minor, i);
  373. #endif
  374. /* wake the parent (server) */
  375. uds_fd_table[i].ready_to_revive = 1;
  376. uds_unsuspend(dev_m_in->m_source, i);
  377. }
  378. return rc;
  379. } else {
  380. #if DEBUG == 1
  381. printf("(uds) [%d] adding to %d's backlog\n",
  382. minor, i);
  383. #endif
  384. /* tell the server were waiting to be served */
  385. /* look for a free slot in the backlog */
  386. rc = -1; /* to trap error */
  387. for (j = 0; j < uds_fd_table[i].backlog_size;
  388. j++) {
  389. if (uds_fd_table[i].backlog[j] == -1) {
  390. uds_fd_table[i].backlog[j] =
  391. minor;
  392. rc = 0;
  393. break;
  394. }
  395. }
  396. if (rc == -1) {
  397. /* backlog is full */
  398. break;
  399. }
  400. /* see if the server is blocked on select() */
  401. if (uds_fd_table[i].selecting == 1) {
  402. /* if the server wants to know
  403. * about data ready to read and
  404. * it doesn't know about it
  405. * already, then let the server
  406. * know we have data for it.
  407. */
  408. if ((uds_fd_table[i].sel_ops_in &
  409. SEL_RD) &&
  410. !(uds_fd_table[i].sel_ops_out &
  411. SEL_RD)) {
  412. uds_fd_table[i].sel_ops_out |=
  413. SEL_RD;
  414. uds_fd_table[i].status_updated
  415. = 1;
  416. uds_unsuspend(
  417. dev_m_in->m_source, i);
  418. }
  419. }
  420. /* we found our server */
  421. uds_fd_table[minor].peer = i;
  422. /* set the address */
  423. memcpy(&(uds_fd_table[minor].addr), &addr,
  424. sizeof(struct sockaddr_un));
  425. break;
  426. }
  427. }
  428. }
  429. if (uds_fd_table[minor].peer == -1) {
  430. /* could not find another open socket listening on the
  431. * specified address with room in the backlog
  432. */
  433. return ECONNREFUSED;
  434. }
  435. #if DEBUG == 1
  436. printf("(uds) [%d] {do_connect} suspend\n", minor);
  437. #endif
  438. /* suspend until the server side completes the connection with accept()
  439. */
  440. uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT;
  441. return SUSPEND;
  442. }
  443. PUBLIC int do_listen(message *dev_m_in, message *dev_m_out)
  444. {
  445. int minor;
  446. int rc;
  447. int backlog_size;
  448. #if DEBUG == 1
  449. static int call_count = 0;
  450. printf("(uds) [%d] do_listen() call_count=%d\n", uds_minor(dev_m_in),
  451. ++call_count);
  452. #endif
  453. minor = uds_minor(dev_m_in);
  454. /* ensure the socket has a type and is bound */
  455. if (uds_fd_table[minor].type == -1 ||
  456. uds_fd_table[minor].addr.sun_family != AF_UNIX) {
  457. /* probably trying to call listen() before bind() */
  458. return EINVAL;
  459. }
  460. /* the two supported types for listen(2) are SOCK_STREAM and
  461. * SOCK_SEQPACKET
  462. */
  463. if (uds_fd_table[minor].type != SOCK_STREAM &&
  464. uds_fd_table[minor].type != SOCK_SEQPACKET) {
  465. /* probably trying to call listen() with a SOCK_DGRAM */
  466. return EOPNOTSUPP;
  467. }
  468. /* The POSIX standard doesn't say what to do if listen() has
  469. * already been called. Well, there isn't an errno. we silently
  470. * let it happen, but if listen() has already been called, we
  471. * don't allow the backlog to shrink
  472. */
  473. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  474. (vir_bytes) 0, (vir_bytes) &backlog_size, sizeof(int), D);
  475. if (rc != OK) {
  476. return EIO;
  477. }
  478. if (uds_fd_table[minor].listening == 0) {
  479. /* See if backlog_size is between 0 and UDS_SOMAXCONN */
  480. if (backlog_size >= 0 && backlog_size < UDS_SOMAXCONN) {
  481. /* use the user provided backlog_size */
  482. uds_fd_table[minor].backlog_size = backlog_size;
  483. } else {
  484. /* the user gave an invalid size, use
  485. * UDS_SOMAXCONN instead
  486. */
  487. uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
  488. }
  489. } else {
  490. /* See if the user is trying to expand the backlog_size */
  491. if (backlog_size > uds_fd_table[minor].backlog_size &&
  492. backlog_size < UDS_SOMAXCONN) {
  493. /* expand backlog_size */
  494. uds_fd_table[minor].backlog_size = backlog_size;
  495. }
  496. /* Don't let the user shrink the backlog_size (we might
  497. * have clients waiting in those slots
  498. */
  499. }
  500. /* perform listen(2) */
  501. uds_fd_table[minor].listening = 1;
  502. return OK;
  503. }
  504. PUBLIC int do_socket(message *dev_m_in, message *dev_m_out)
  505. {
  506. int rc;
  507. int minor;
  508. #if DEBUG == 1
  509. static int call_count = 0;
  510. printf("(uds) [%d] do_socket() call_count=%d\n", uds_minor(dev_m_in),
  511. ++call_count);
  512. #endif
  513. minor = uds_minor(dev_m_in);
  514. /* see if this socket already has a type */
  515. if (uds_fd_table[minor].type != -1) {
  516. /* socket type can only be set once */
  517. return EINVAL;
  518. }
  519. /* get the requested type */
  520. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  521. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
  522. sizeof(int), D);
  523. if (rc != OK) {
  524. /* something went wrong and we couldn't get the type */
  525. return EIO;
  526. }
  527. /* validate the type */
  528. switch (uds_fd_table[minor].type) {
  529. case SOCK_STREAM:
  530. case SOCK_DGRAM:
  531. case SOCK_SEQPACKET:
  532. /* the type is one of the 3 valid socket types */
  533. return OK;
  534. default:
  535. /* if the type isn't one of the 3 valid socket
  536. * types, then it must be invalid.
  537. */
  538. /* set the type back to '-1' (no type set) */
  539. uds_fd_table[minor].type = -1;
  540. return EINVAL;
  541. }
  542. }
  543. PUBLIC int do_bind(message *dev_m_in, message *dev_m_out)
  544. {
  545. int minor;
  546. struct sockaddr_un addr;
  547. int rc, i;
  548. #if DEBUG == 1
  549. static int call_count = 0;
  550. printf("(uds) [%d] do_bind() call_count=%d\n", uds_minor(dev_m_in),
  551. ++call_count);
  552. #endif
  553. minor = uds_minor(dev_m_in);
  554. if ((uds_fd_table[minor].type == -1) ||
  555. (uds_fd_table[minor].addr.sun_family == AF_UNIX &&
  556. uds_fd_table[minor].type != SOCK_DGRAM)) {
  557. /* the type hasn't been set by do_socket() yet OR attempting
  558. * to re-bind() a non-SOCK_DGRAM socket
  559. */
  560. return EINVAL;
  561. }
  562. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  563. (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un),
  564. D);
  565. if (rc != OK) {
  566. return EIO;
  567. }
  568. /* do some basic sanity checks on the address */
  569. if (addr.sun_family != AF_UNIX) {
  570. /* bad family */
  571. return EAFNOSUPPORT;
  572. }
  573. if (addr.sun_path[0] == '\0') {
  574. /* bad address */
  575. return ENOENT;
  576. }
  577. rc = check_perms(minor, &addr);
  578. if (rc != OK) {
  579. /* permission denied, socket file doesn't exist, etc. */
  580. return rc;
  581. }
  582. /* make sure the address isn't already in use by another socket. */
  583. for (i = 0; i < NR_FDS; i++) {
  584. if ((uds_fd_table[i].addr.sun_family == AF_UNIX) &&
  585. !strncmp(addr.sun_path,
  586. uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {
  587. /* another socket is bound to this sun_path */
  588. return EADDRINUSE;
  589. }
  590. }
  591. /* looks good, perform the bind() */
  592. memcpy(&(uds_fd_table[minor].addr), &addr, sizeof(struct sockaddr_un));
  593. return OK;
  594. }
  595. PUBLIC int do_getsockname(message *dev_m_in, message *dev_m_out)
  596. {
  597. int minor;
  598. int rc;
  599. #if DEBUG == 1
  600. static int call_count = 0;
  601. printf("(uds) [%d] do_getsockname() call_count=%d\n",
  602. uds_minor(dev_m_in), ++call_count);
  603. #endif
  604. minor = uds_minor(dev_m_in);
  605. /* Unconditionally send the address we have assigned to this socket.
  606. * The POSIX standard doesn't say what to do if the address
  607. * hasn't been set. If the address isn't currently set, then
  608. * the user will get NULL bytes. Note: libc depends on this
  609. * behavior.
  610. */
  611. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  612. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].addr),
  613. sizeof(struct sockaddr_un), D);
  614. return rc ? EIO : OK;
  615. }
  616. PUBLIC int do_getpeername(message *dev_m_in, message *dev_m_out)
  617. {
  618. int minor;
  619. int rc;
  620. #if DEBUG == 1
  621. static int call_count = 0;
  622. printf("(uds) [%d] do_getpeername() call_count=%d\n",
  623. uds_minor(dev_m_in), ++call_count);
  624. #endif
  625. minor = uds_minor(dev_m_in);
  626. /* check that the socket is connected with a valid peer */
  627. if (uds_fd_table[minor].peer != -1) {
  628. int peer_minor;
  629. peer_minor = uds_fd_table[minor].peer;
  630. /* copy the address from the peer */
  631. rc = sys_safecopyto(VFS_PROC_NR,
  632. (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0,
  633. (vir_bytes) &(uds_fd_table[peer_minor].addr),
  634. sizeof(struct sockaddr_un), D);
  635. return rc ? EIO : OK;
  636. } else {
  637. if (uds_fd_table[minor].err == ECONNRESET) {
  638. uds_fd_table[minor].err = 0;
  639. return ECONNRESET;
  640. } else {
  641. return ENOTCONN;
  642. }
  643. }
  644. }
  645. PUBLIC int do_shutdown(message *dev_m_in, message *dev_m_out)
  646. {
  647. int minor;
  648. int rc, how;
  649. #if DEBUG == 1
  650. static int call_count = 0;
  651. printf("(uds) [%d] do_shutdown() call_count=%d\n",
  652. uds_minor(dev_m_in), ++call_count);
  653. #endif
  654. minor = uds_minor(dev_m_in);
  655. if (uds_fd_table[minor].type != SOCK_STREAM &&
  656. uds_fd_table[minor].type != SOCK_SEQPACKET) {
  657. /* socket must be a connection oriented socket */
  658. return EINVAL;
  659. }
  660. if (uds_fd_table[minor].peer == -1) {
  661. /* shutdown(2) is only valid for connected sockets */
  662. if (uds_fd_table[minor].err == ECONNRESET) {
  663. return ECONNRESET;
  664. } else {
  665. return ENOTCONN;
  666. }
  667. }
  668. /* get the 'how' parameter from the process */
  669. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  670. (vir_bytes) 0, (vir_bytes) &how, sizeof(int), D);
  671. if (rc != OK) {
  672. return EIO;
  673. }
  674. switch (how) {
  675. case SHUT_RD:
  676. /* take away read permission */
  677. uds_fd_table[minor].mode =
  678. uds_fd_table[minor].mode ^ S_IRUSR;
  679. break;
  680. case SHUT_WR:
  681. /* take away write permission */
  682. uds_fd_table[minor].mode =
  683. uds_fd_table[minor].mode ^ S_IWUSR;
  684. break;
  685. case SHUT_RDWR:
  686. /* completely shutdown */
  687. uds_fd_table[minor].mode = 0;
  688. break;
  689. default:
  690. /* the 'how' parameter is invalid */
  691. return EINVAL;
  692. }
  693. return OK;
  694. }
  695. PUBLIC int do_socketpair_old(message *dev_m_in, message *dev_m_out)
  696. {
  697. int rc;
  698. short minorin;
  699. int minorx, minory;
  700. struct sockaddr_un addr;
  701. #if DEBUG == 1
  702. static int call_count = 0;
  703. printf("(uds) [%d] do_socketpair() call_count=%d\n",
  704. uds_minor(dev_m_in), ++call_count);
  705. #endif
  706. /* first ioctl param is the first socket */
  707. minorx = uds_minor_old(dev_m_in);
  708. /* third ioctl param is the minor number of the second socket */
  709. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  710. (vir_bytes) 0, (vir_bytes) &minorin, sizeof(short), D);
  711. if (rc != OK) {
  712. return EIO;
  713. }
  714. minory = minor(minorin);
  715. #if DEBUG == 1
  716. printf("socketpair() %d - %d\n", minorx, minory);
  717. #endif
  718. /* security check - both sockets must have the same endpoint (owner) */
  719. if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner) {
  720. /* we won't allow you to magically connect your socket to
  721. * someone elses socket
  722. */
  723. return EPERM;
  724. }
  725. addr.sun_family = AF_UNIX;
  726. addr.sun_path[0] = 'X';
  727. addr.sun_path[1] = '\0';
  728. uds_fd_table[minorx].syscall_done = 1;
  729. return perform_connection(dev_m_in, dev_m_out, &addr, minorx, minory);
  730. }
  731. PUBLIC int do_socketpair(message *dev_m_in, message *dev_m_out)
  732. {
  733. int rc;
  734. dev_t minorin;
  735. int minorx, minory;
  736. struct sockaddr_un addr;
  737. #if DEBUG == 1
  738. static int call_count = 0;
  739. printf("(uds) [%d] do_socketpair() call_count=%d\n",
  740. uds_minor(dev_m_in), ++call_count);
  741. #endif
  742. /* first ioctl param is the first socket */
  743. minorx = uds_minor(dev_m_in);
  744. /* third ioctl param is the minor number of the second socket */
  745. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  746. (vir_bytes) 0, (vir_bytes) &minorin, sizeof(dev_t), D);
  747. if (rc != OK) {
  748. return EIO;
  749. }
  750. minory = minor(minorin);
  751. #if DEBUG == 1
  752. printf("socketpair() %d - %d\n", minorx, minory);
  753. #endif
  754. /* security check - both sockets must have the same endpoint (owner) */
  755. if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner) {
  756. /* we won't allow you to magically connect your socket to
  757. * someone elses socket
  758. */
  759. return EPERM;
  760. }
  761. addr.sun_family = AF_UNIX;
  762. addr.sun_path[0] = 'X';
  763. addr.sun_path[1] = '\0';
  764. uds_fd_table[minorx].syscall_done = 1;
  765. return perform_connection(dev_m_in, dev_m_out, &addr, minorx, minory);
  766. }
  767. PUBLIC int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out)
  768. {
  769. int minor;
  770. int rc;
  771. #if DEBUG == 1
  772. static int call_count = 0;
  773. printf("(uds) [%d] do_getsockopt_sotype() call_count=%d\n",
  774. uds_minor(dev_m_in), ++call_count);
  775. #endif
  776. minor = uds_minor(dev_m_in);
  777. if (uds_fd_table[minor].type == -1) {
  778. /* the type hasn't been set yet. instead of returning an
  779. * invalid type, we fail with EINVAL
  780. */
  781. return EINVAL;
  782. }
  783. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  784. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
  785. sizeof(int), D);
  786. return rc ? EIO : OK;
  787. }
  788. PUBLIC int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out)
  789. {
  790. int minor;
  791. int peer_minor;
  792. int rc;
  793. struct ucred cred;
  794. #if DEBUG == 1
  795. static int call_count = 0;
  796. printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n",
  797. uds_minor(dev_m_in), ++call_count);
  798. #endif
  799. minor = uds_minor(dev_m_in);
  800. if (uds_fd_table[minor].peer == -1) {
  801. if (uds_fd_table[minor].err == ECONNRESET) {
  802. uds_fd_table[minor].err = 0;
  803. return ECONNRESET;
  804. } else {
  805. return ENOTCONN;
  806. }
  807. }
  808. peer_minor = uds_fd_table[minor].peer;
  809. /* obtain the peer's credentials */
  810. rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
  811. if (rc == -1) {
  812. /* likely error: invalid endpoint / proc doesn't exist */
  813. return errno;
  814. }
  815. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  816. (vir_bytes) 0, (vir_bytes) &cred, sizeof(struct ucred), D);
  817. return rc ? EIO : OK;
  818. }
  819. PUBLIC int do_getsockopt_peercred_old(message *dev_m_in, message *dev_m_out)
  820. {
  821. int minor;
  822. int peer_minor;
  823. int rc;
  824. struct ucred cred;
  825. struct ucred_old cred_old;
  826. #if DEBUG == 1
  827. static int call_count = 0;
  828. printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n",
  829. uds_minor(dev_m_in), ++call_count);
  830. #endif
  831. minor = uds_minor(dev_m_in);
  832. if (uds_fd_table[minor].peer == -1) {
  833. if (uds_fd_table[minor].err == ECONNRESET) {
  834. uds_fd_table[minor].err = 0;
  835. return ECONNRESET;
  836. } else {
  837. return ENOTCONN;
  838. }
  839. }
  840. peer_minor = uds_fd_table[minor].peer;
  841. /* obtain the peer's credentials */
  842. rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
  843. if (rc == -1) {
  844. /* likely error: invalid endpoint / proc doesn't exist */
  845. return errno;
  846. }
  847. /* copy to old structure */
  848. cred_old.pid = cred.pid;
  849. cred_old.uid = (short) cred.uid;
  850. cred_old.gid = (char) cred.gid;
  851. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  852. (vir_bytes) 0, (vir_bytes) &cred_old, sizeof(struct ucred_old),
  853. D);
  854. return rc ? EIO : OK;
  855. }
  856. int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
  857. {
  858. int minor;
  859. int rc;
  860. size_t sndbuf = PIPE_BUF;
  861. #if DEBUG == 1
  862. static int call_count = 0;
  863. printf("(uds) [%d] do_getsockopt_sndbuf() call_count=%d\n",
  864. uds_minor(dev_m_in), ++call_count);
  865. #endif
  866. minor = uds_minor(dev_m_in);
  867. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  868. (vir_bytes) 0, (vir_bytes) &(sndbuf),
  869. sizeof(size_t), D);
  870. return rc ? EIO : OK;
  871. }
  872. int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
  873. {
  874. int minor;
  875. int rc;
  876. size_t sndbuf;
  877. #if DEBUG == 1
  878. static int call_count = 0;
  879. printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
  880. uds_minor(dev_m_in), ++call_count);
  881. #endif
  882. minor = uds_minor(dev_m_in);
  883. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  884. (vir_bytes) 0, (vir_bytes) &sndbuf,
  885. sizeof(size_t), D);
  886. if (rc != OK) {
  887. return EIO;
  888. }
  889. if (sndbuf > PIPE_BUF) {
  890. /* The send buffer is limited to 32K at the moment. */
  891. return ENOSYS;
  892. }
  893. /* There is no way to reduce the send buffer, do we have to
  894. * let this call fail for smaller buffers?
  895. */
  896. return OK;
  897. }
  898. int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
  899. {
  900. int minor;
  901. int rc;
  902. size_t rcvbuf = PIPE_BUF;
  903. #if DEBUG == 1
  904. static int call_count = 0;
  905. printf("(uds) [%d] do_getsockopt_rcvbuf() call_count=%d\n",
  906. uds_minor(dev_m_in), ++call_count);
  907. #endif
  908. minor = uds_minor(dev_m_in);
  909. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  910. (vir_bytes) 0, (vir_bytes) &(rcvbuf),
  911. sizeof(size_t), D);
  912. return rc ? EIO : OK;
  913. }
  914. int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
  915. {
  916. int minor;
  917. int rc;
  918. size_t rcvbuf;
  919. #if DEBUG == 1
  920. static int call_count = 0;
  921. printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
  922. uds_minor(dev_m_in), ++call_count);
  923. #endif
  924. minor = uds_minor(dev_m_in);
  925. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  926. (vir_bytes) 0, (vir_bytes) &rcvbuf,
  927. sizeof(size_t), D);
  928. if (rc != OK) {
  929. return EIO;
  930. }
  931. if (rcvbuf > PIPE_BUF) {
  932. /* The send buffer is limited to 32K at the moment. */
  933. return ENOSYS;
  934. }
  935. /* There is no way to reduce the send buffer, do we have to
  936. * let this call fail for smaller buffers?
  937. */
  938. return OK;
  939. }
  940. PUBLIC int do_sendto(message *dev_m_in, message *dev_m_out)
  941. {
  942. int minor;
  943. int rc;
  944. struct sockaddr_un addr;
  945. #if DEBUG == 1
  946. static int call_count = 0;
  947. printf("(uds) [%d] do_sendto() call_count=%d\n", uds_minor(dev_m_in),
  948. ++call_count);
  949. #endif
  950. minor = uds_minor(dev_m_in);
  951. if (uds_fd_table[minor].type != SOCK_DGRAM) {
  952. /* This IOCTL is only for SOCK_DGRAM sockets */
  953. return EINVAL;
  954. }
  955. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  956. (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un),
  957. D);
  958. if (rc != OK) {
  959. return EIO;
  960. }
  961. /* do some basic sanity checks on the address */
  962. if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0') {
  963. /* bad address */
  964. return EINVAL;
  965. }
  966. rc = check_perms(minor, &addr);
  967. if (rc != OK) {
  968. return rc;
  969. }
  970. memcpy(&(uds_fd_table[minor].target), &addr,
  971. sizeof(struct sockaddr_un));
  972. return OK;
  973. }
  974. PUBLIC int do_recvfrom(message *dev_m_in, message *dev_m_out)
  975. {
  976. int minor;
  977. int rc;
  978. #if DEBUG == 1
  979. static int call_count = 0;
  980. printf("(uds) [%d] do_recvfrom() call_count=%d\n",
  981. uds_minor(dev_m_in), ++call_count);
  982. #endif
  983. minor = uds_minor(dev_m_in);
  984. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  985. (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].source),
  986. sizeof(struct sockaddr_un), D);
  987. return rc ? EIO : OK;
  988. }
  989. int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
  990. int minor)
  991. {
  992. int rc;
  993. struct msghdr msghdr;
  994. struct cmsghdr *cmsg = NULL;
  995. #if DEBUG == 1
  996. static int call_count = 0;
  997. printf("(uds) [%d] msg_control_read() call_count=%d\n", minor,
  998. ++call_count);
  999. #endif
  1000. data->nfiledes = 0;
  1001. memset(&msghdr, '\0', sizeof(struct msghdr));
  1002. msghdr.msg_control = msg_ctrl->msg_control;
  1003. msghdr.msg_controllen = msg_ctrl->msg_controllen;
  1004. for(cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL;
  1005. cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
  1006. if (cmsg->cmsg_level == SOL_SOCKET &&
  1007. cmsg->cmsg_type == SCM_RIGHTS) {
  1008. int i;
  1009. int nfds =
  1010. MIN((cmsg->cmsg_len-CMSG_LEN(0))/sizeof(int),
  1011. OPEN_MAX);
  1012. for (i = 0; i < nfds; i++) {
  1013. if (data->nfiledes == OPEN_MAX) {
  1014. return EOVERFLOW;
  1015. }
  1016. data->fds[data->nfiledes] =
  1017. ((int *) CMSG_DATA(cmsg))[i];
  1018. #if DEBUG == 1
  1019. printf("(uds) [%d] fd[%d]=%d\n", minor,
  1020. data->nfiledes, data->fds[data->nfiledes]);
  1021. #endif
  1022. data->nfiledes++;
  1023. }
  1024. }
  1025. }
  1026. /* obtain this socket's credentials */
  1027. rc = getnucred(uds_fd_table[minor].owner, &(data->cred));
  1028. if (rc == -1) {
  1029. return errno;
  1030. }
  1031. #if DEBUG == 1
  1032. printf("(uds) [%d] cred={%d,%d,%d}\n", minor,
  1033. data->cred.pid, data->cred.uid,
  1034. data->cred.gid);
  1035. #endif
  1036. return OK;
  1037. }
  1038. PRIVATE int send_fds(int minor, struct ancillary *data)
  1039. {
  1040. int rc, i, j;
  1041. #if DEBUG == 1
  1042. static int call_count = 0;
  1043. printf("(uds) [%d] send_fds() call_count=%d\n", minor, ++call_count);
  1044. #endif
  1045. /* verify the file descriptors and get their filps. */
  1046. for (i = 0; i < data->nfiledes; i++) {
  1047. data->filps[i] = verify_fd(uds_fd_table[minor].owner,
  1048. data->fds[i]);
  1049. if (data->filps[i] == NULL) {
  1050. return EINVAL;
  1051. }
  1052. }
  1053. /* set them as in-flight */
  1054. for (i = 0; i < data->nfiledes; i++) {
  1055. rc = set_filp(data->filps[i]);
  1056. if (rc != OK) {
  1057. /* revert set_filp() calls */
  1058. for (j = i; j >= 0; j--) {
  1059. put_filp(data->filps[j]);
  1060. }
  1061. return rc;
  1062. }
  1063. }
  1064. return OK;
  1065. }
  1066. PUBLIC int clear_fds(int minor, struct ancillary *data)
  1067. {
  1068. /* This function calls put_filp() for all of the FDs in data.
  1069. * This is used when a Unix Domain Socket is closed and there
  1070. * exists references to file descriptors that haven't been received
  1071. * with recvmsg().
  1072. */
  1073. int i;
  1074. #if DEBUG == 1
  1075. static int call_count = 0;
  1076. printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
  1077. ++call_count);
  1078. #endif
  1079. for (i = 0; i < data->nfiledes; i++) {
  1080. put_filp(data->filps[i]);
  1081. #if DEBUG == 1
  1082. printf("(uds) clear_fds() => %d\n", data->fds[i]);
  1083. #endif
  1084. data->fds[i] = -1;
  1085. data->filps[i] = NULL;
  1086. }
  1087. data->nfiledes = 0;
  1088. return OK;
  1089. }
  1090. PRIVATE int recv_fds(int minor, struct ancillary *data,
  1091. struct msg_control *msg_ctrl)
  1092. {
  1093. int rc, i, j;
  1094. struct msghdr msghdr;
  1095. struct cmsghdr *cmsg;
  1096. endpoint_t to_ep;
  1097. #if DEBUG == 1
  1098. static int call_count = 0;
  1099. printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
  1100. ++call_count);
  1101. #endif
  1102. msghdr.msg_control = msg_ctrl->msg_control;
  1103. msghdr.msg_controllen = msg_ctrl->msg_controllen;
  1104. cmsg = CMSG_FIRSTHDR(&msghdr);
  1105. cmsg->cmsg_len = CMSG_LEN(sizeof(int) * data->nfiledes);
  1106. cmsg->cmsg_level = SOL_SOCKET;
  1107. cmsg->cmsg_type = SCM_RIGHTS;
  1108. to_ep = uds_fd_table[minor].owner;
  1109. /* copy to the target endpoint */
  1110. for (i = 0; i < data->nfiledes; i++) {
  1111. rc = copy_filp(to_ep, data->filps[i]);
  1112. if (rc < 0) {
  1113. /* revert set_filp() calls */
  1114. for (j = 0; j < data->nfiledes; j++) {
  1115. put_filp(data->filps[j]);
  1116. }
  1117. /* revert copy_filp() calls */
  1118. for (j = i; j >= 0; j--) {
  1119. cancel_fd(to_ep, data->fds[j]);
  1120. }
  1121. return rc;
  1122. }
  1123. data->fds[i] = rc; /* data->fds[i] now has the new FD */
  1124. }
  1125. for (i = 0; i < data->nfiledes; i++) {
  1126. put_filp(data->filps[i]);
  1127. #if DEBUG == 1
  1128. printf("(uds) recv_fds() => %d\n", data->fds[i]);
  1129. #endif
  1130. ((int *)CMSG_DATA(cmsg))[i] = data->fds[i];
  1131. data->fds[i] = -1;
  1132. data->filps[i] = NULL;
  1133. }
  1134. data->nfiledes = 0;
  1135. return OK;
  1136. }
  1137. PRIVATE int recv_cred(int minor, struct ancillary *data,
  1138. struct msg_control *msg_ctrl)
  1139. {
  1140. struct msghdr msghdr;
  1141. struct cmsghdr *cmsg;
  1142. #if DEBUG == 1
  1143. static int call_count = 0;
  1144. printf("(uds) [%d] recv_cred() call_count=%d\n", minor,
  1145. ++call_count);
  1146. #endif
  1147. msghdr.msg_control = msg_ctrl->msg_control;
  1148. msghdr.msg_controllen = msg_ctrl->msg_controllen;
  1149. cmsg = CMSG_FIRSTHDR(&msghdr);
  1150. if (cmsg->cmsg_len > 0) {
  1151. cmsg = CMSG_NXTHDR(&msghdr, cmsg);
  1152. }
  1153. cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
  1154. cmsg->cmsg_level = SOL_SOCKET;
  1155. cmsg->cmsg_type = SCM_CREDENTIALS;
  1156. memcpy(CMSG_DATA(cmsg), &(data->cred), sizeof(struct ucred));
  1157. return OK;
  1158. }
  1159. PUBLIC int do_sendmsg(message *dev_m_in, message *dev_m_out)
  1160. {
  1161. int minor, peer, rc, i;
  1162. struct msg_control msg_ctrl;
  1163. #if DEBUG == 1
  1164. static int call_count = 0;
  1165. printf("(uds) [%d] do_sendmsg() call_count=%d\n",
  1166. uds_minor(dev_m_in), ++call_count);
  1167. #endif
  1168. minor = uds_minor(dev_m_in);
  1169. memset(&msg_ctrl, '\0', sizeof(struct msg_control));
  1170. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  1171. (vir_bytes) 0, (vir_bytes) &msg_ctrl,
  1172. sizeof(struct msg_control), D);
  1173. if (rc != OK) {
  1174. return EIO;
  1175. }
  1176. /* locate peer */
  1177. peer = -1;
  1178. if (uds_fd_table[minor].type == SOCK_DGRAM) {
  1179. if (uds_fd_table[minor].target.sun_path[0] == '\0' ||
  1180. uds_fd_table[minor].target.sun_family != AF_UNIX) {
  1181. return EDESTADDRREQ;
  1182. }
  1183. for (i = 0; i < NR_FDS; i++) {
  1184. /* look for a SOCK_DGRAM socket that is bound on
  1185. * the target address
  1186. */
  1187. if (uds_fd_table[i].type == SOCK_DGRAM &&
  1188. uds_fd_table[i].addr.sun_family == AF_UNIX &&
  1189. !strncmp(uds_fd_table[minor].target.sun_path,
  1190. uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)){
  1191. peer = i;
  1192. break;
  1193. }
  1194. }
  1195. if (peer == -1) {
  1196. return ENOENT;
  1197. }
  1198. } else {
  1199. peer = uds_fd_table[minor].peer;
  1200. if (peer == -1) {
  1201. return ENOTCONN;
  1202. }
  1203. }
  1204. #if DEBUG == 1
  1205. printf("(uds) [%d] sendmsg() -- peer=%d\n", minor, peer);
  1206. #endif
  1207. /* note: it's possible that there is already some file
  1208. * descriptors in ancillary_data if the peer didn't call
  1209. * recvmsg() yet. That's okay. The receiver will
  1210. * get the current file descriptors plus the new ones.
  1211. */
  1212. rc = msg_control_read(&msg_ctrl, &uds_fd_table[peer].ancillary_data,
  1213. minor);
  1214. if (rc != OK) {
  1215. return rc;
  1216. }
  1217. return send_fds(minor, &uds_fd_table[peer].ancillary_data);
  1218. }
  1219. PUBLIC int do_recvmsg(message *dev_m_in, message *dev_m_out)
  1220. {
  1221. int minor;
  1222. int rc;
  1223. struct msg_control msg_ctrl;
  1224. socklen_t controllen_avail = 0;
  1225. socklen_t controllen_needed = 0;
  1226. socklen_t controllen_desired = 0;
  1227. #if DEBUG == 1
  1228. static int call_count = 0;
  1229. printf("(uds) [%d] do_sendmsg() call_count=%d\n",
  1230. uds_minor(dev_m_in), ++call_count);
  1231. #endif
  1232. minor = uds_minor(dev_m_in);
  1233. #if DEBUG == 1
  1234. printf("(uds) [%d] CREDENTIALS {pid:%d,uid:%d,gid:%d}\n", minor,
  1235. uds_fd_table[minor].ancillary_data.cred.pid,
  1236. uds_fd_table[minor].ancillary_data.cred.uid,
  1237. uds_fd_table[minor].ancillary_data.cred.gid);
  1238. #endif
  1239. memset(&msg_ctrl, '\0', sizeof(struct msg_control));
  1240. /* get the msg_control from the user, it will include the
  1241. * amount of space the user has allocated for control data.
  1242. */
  1243. rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  1244. (vir_bytes) 0, (vir_bytes) &msg_ctrl,
  1245. sizeof(struct msg_control), D);
  1246. if (rc != OK) {
  1247. return EIO;
  1248. }
  1249. controllen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX);
  1250. if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
  1251. controllen_needed = CMSG_LEN(sizeof(int) *
  1252. (uds_fd_table[minor].ancillary_data.nfiledes));
  1253. }
  1254. /* if there is room we also include credentials */
  1255. controllen_desired = controllen_needed +
  1256. CMSG_LEN(sizeof(struct ucred));
  1257. if (controllen_needed > controllen_avail) {
  1258. return EOVERFLOW;
  1259. }
  1260. rc = recv_fds(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl);
  1261. if (rc != OK) {
  1262. return rc;
  1263. }
  1264. if (controllen_desired <= controllen_avail) {
  1265. rc = recv_cred(minor, &uds_fd_table[minor].ancillary_data,
  1266. &msg_ctrl);
  1267. if (rc != OK) {
  1268. return rc;
  1269. }
  1270. }
  1271. /* send the user the control data */
  1272. rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
  1273. (vir_bytes) 0, (vir_bytes) &msg_ctrl,
  1274. sizeof(struct msg_control), D);
  1275. return rc ? EIO : OK;
  1276. }