PageRenderTime 30ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/uts/common/io/ksocket/ksocket.c

https://github.com/richlowe/illumos-gate
C | 933 lines | 675 code | 158 blank | 100 comment | 219 complexity | 2659cb9b6377f42f0eed60f32609186a MD5 | raw file
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
  23. * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24. */
  25. #include <sys/file.h>
  26. #include <sys/stropts.h>
  27. #include <sys/socket.h>
  28. #include <sys/socketvar.h>
  29. #include <sys/sysmacros.h>
  30. #include <sys/filio.h> /* FIO* ioctls */
  31. #include <sys/sockio.h> /* SIOC* ioctls */
  32. #include <sys/poll_impl.h>
  33. #include <sys/cmn_err.h>
  34. #include <sys/ksocket.h>
  35. #include <io/ksocket/ksocket_impl.h>
  36. #include <fs/sockfs/sockcommon.h>
  37. #define SOCKETMOD_TCP "tcp"
  38. #define SOCKETMOD_UDP "udp"
  39. /*
  40. * Kernel Sockets
  41. *
  42. * Mostly a wrapper around the private socket_* functions.
  43. */
  44. int
  45. ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags,
  46. struct cred *cr)
  47. {
  48. static const int version = SOV_DEFAULT;
  49. int error = 0;
  50. struct sonode *so;
  51. *ksp = NULL;
  52. /* All Solaris components should pass a cred for this operation. */
  53. ASSERT(cr != NULL);
  54. if (domain == AF_NCA)
  55. return (EAFNOSUPPORT);
  56. ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP);
  57. so = socket_create(domain, type, protocol, NULL, NULL, version, flags,
  58. cr, &error);
  59. if (so == NULL) {
  60. if (error == EAFNOSUPPORT) {
  61. char *mod = NULL;
  62. /*
  63. * Could be that root file sytem is not loaded or
  64. * soconfig has not run yet.
  65. */
  66. if (type == SOCK_STREAM && (domain == AF_INET ||
  67. domain == AF_INET6) && (protocol == 0 ||
  68. protocol == IPPROTO_TCP)) {
  69. mod = SOCKETMOD_TCP;
  70. } else if (type == SOCK_DGRAM && (domain == AF_INET ||
  71. domain == AF_INET6) && (protocol == 0 ||
  72. protocol == IPPROTO_UDP)) {
  73. mod = SOCKETMOD_UDP;
  74. } else {
  75. return (EAFNOSUPPORT);
  76. }
  77. so = socket_create(domain, type, protocol, NULL,
  78. mod, version, flags, cr, &error);
  79. if (so == NULL)
  80. return (error);
  81. } else {
  82. return (error);
  83. }
  84. }
  85. so->so_mode |= SM_KERNEL;
  86. *ksp = SOTOKS(so);
  87. return (0);
  88. }
  89. int
  90. ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
  91. struct cred *cr)
  92. {
  93. int error;
  94. /* All Solaris components should pass a cred for this operation. */
  95. ASSERT(cr != NULL);
  96. if (!KSOCKET_VALID(ks))
  97. return (ENOTSOCK);
  98. error = socket_bind(KSTOSO(ks), addr, addrlen, _SOBIND_SOCKBSD, cr);
  99. return (error);
  100. }
  101. int
  102. ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
  103. {
  104. /* All Solaris components should pass a cred for this operation. */
  105. ASSERT(cr != NULL);
  106. if (!KSOCKET_VALID(ks))
  107. return (ENOTSOCK);
  108. return (socket_listen(KSTOSO(ks), backlog, cr));
  109. }
  110. int
  111. ksocket_accept(ksocket_t ks, struct sockaddr *addr,
  112. socklen_t *addrlenp, ksocket_t *nks, struct cred *cr)
  113. {
  114. int error;
  115. struct sonode *nso = NULL;
  116. /* All Solaris components should pass a cred for this operation. */
  117. ASSERT(cr != NULL);
  118. *nks = NULL;
  119. if (!KSOCKET_VALID(ks))
  120. return (ENOTSOCK);
  121. if (addr != NULL && addrlenp == NULL)
  122. return (EFAULT);
  123. error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso);
  124. if (error != 0)
  125. return (error);
  126. ASSERT(nso != NULL);
  127. nso->so_mode |= SM_KERNEL;
  128. if (addr != NULL && addrlenp != NULL) {
  129. error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr);
  130. if (error != 0) {
  131. (void) socket_close(nso, 0, cr);
  132. socket_destroy(nso);
  133. return ((error == ENOTCONN) ? ECONNABORTED : error);
  134. }
  135. }
  136. *nks = SOTOKS(nso);
  137. return (error);
  138. }
  139. int
  140. ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
  141. struct cred *cr)
  142. {
  143. /* All Solaris components should pass a cred for this operation. */
  144. ASSERT(cr != NULL);
  145. if (!KSOCKET_VALID(ks))
  146. return (ENOTSOCK);
  147. return (socket_connect(KSTOSO(ks), addr, addrlen,
  148. KSOCKET_FMODE(ks), 0, cr));
  149. }
  150. int
  151. ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags,
  152. size_t *sent, struct cred *cr)
  153. {
  154. int error;
  155. struct nmsghdr msghdr;
  156. struct uio auio;
  157. struct iovec iov;
  158. /* All Solaris components should pass a cred for this operation. */
  159. ASSERT(cr != NULL);
  160. if (!KSOCKET_VALID(ks)) {
  161. if (sent != NULL)
  162. *sent = 0;
  163. return (ENOTSOCK);
  164. }
  165. iov.iov_base = msg;
  166. iov.iov_len = msglen;
  167. bzero(&auio, sizeof (struct uio));
  168. auio.uio_loffset = 0;
  169. auio.uio_iov = &iov;
  170. auio.uio_iovcnt = 1;
  171. auio.uio_resid = msglen;
  172. if (flags & MSG_USERSPACE)
  173. auio.uio_segflg = UIO_USERSPACE;
  174. else
  175. auio.uio_segflg = UIO_SYSSPACE;
  176. auio.uio_extflg = UIO_COPY_DEFAULT;
  177. auio.uio_limit = 0;
  178. auio.uio_fmode = KSOCKET_FMODE(ks);
  179. msghdr.msg_name = NULL;
  180. msghdr.msg_namelen = 0;
  181. msghdr.msg_control = NULL;
  182. msghdr.msg_controllen = 0;
  183. msghdr.msg_flags = flags | MSG_EOR;
  184. error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
  185. if (error != 0) {
  186. if (sent != NULL)
  187. *sent = 0;
  188. return (error);
  189. }
  190. if (sent != NULL)
  191. *sent = msglen - auio.uio_resid;
  192. return (0);
  193. }
  194. int
  195. ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags,
  196. struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr)
  197. {
  198. int error;
  199. struct nmsghdr msghdr;
  200. struct uio auio;
  201. struct iovec iov;
  202. /* All Solaris components should pass a cred for this operation. */
  203. ASSERT(cr != NULL);
  204. if (!KSOCKET_VALID(ks)) {
  205. if (sent != NULL)
  206. *sent = 0;
  207. return (ENOTSOCK);
  208. }
  209. iov.iov_base = msg;
  210. iov.iov_len = msglen;
  211. bzero(&auio, sizeof (struct uio));
  212. auio.uio_loffset = 0;
  213. auio.uio_iov = &iov;
  214. auio.uio_iovcnt = 1;
  215. auio.uio_resid = msglen;
  216. if (flags & MSG_USERSPACE)
  217. auio.uio_segflg = UIO_USERSPACE;
  218. else
  219. auio.uio_segflg = UIO_SYSSPACE;
  220. auio.uio_extflg = UIO_COPY_DEFAULT;
  221. auio.uio_limit = 0;
  222. auio.uio_fmode = KSOCKET_FMODE(ks);
  223. msghdr.msg_iov = &iov;
  224. msghdr.msg_iovlen = 1;
  225. msghdr.msg_name = (char *)name;
  226. msghdr.msg_namelen = namelen;
  227. msghdr.msg_control = NULL;
  228. msghdr.msg_controllen = 0;
  229. msghdr.msg_flags = flags | MSG_EOR;
  230. error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr);
  231. if (error != 0) {
  232. if (sent != NULL)
  233. *sent = 0;
  234. return (error);
  235. }
  236. if (sent != NULL)
  237. *sent = msglen - auio.uio_resid;
  238. return (0);
  239. }
  240. int
  241. ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags,
  242. size_t *sent, struct cred *cr)
  243. {
  244. int error;
  245. ssize_t len;
  246. int i;
  247. struct uio auio;
  248. /* All Solaris components should pass a cred for this operation. */
  249. ASSERT(cr != NULL);
  250. if (!KSOCKET_VALID(ks)) {
  251. if (sent != NULL)
  252. *sent = 0;
  253. return (ENOTSOCK);
  254. }
  255. bzero(&auio, sizeof (struct uio));
  256. auio.uio_loffset = 0;
  257. auio.uio_iov = msg->msg_iov;
  258. auio.uio_iovcnt = msg->msg_iovlen;
  259. if (flags & MSG_USERSPACE)
  260. auio.uio_segflg = UIO_USERSPACE;
  261. else
  262. auio.uio_segflg = UIO_SYSSPACE;
  263. auio.uio_extflg = UIO_COPY_DEFAULT;
  264. auio.uio_limit = 0;
  265. auio.uio_fmode = KSOCKET_FMODE(ks);
  266. len = 0;
  267. for (i = 0; i < msg->msg_iovlen; i++) {
  268. ssize_t iovlen;
  269. iovlen = (msg->msg_iov)[i].iov_len;
  270. len += iovlen;
  271. if (len < 0 || iovlen < 0)
  272. return (EINVAL);
  273. }
  274. auio.uio_resid = len;
  275. msg->msg_flags = flags | MSG_EOR;
  276. error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr);
  277. if (error != 0) {
  278. if (sent != NULL)
  279. *sent = 0;
  280. return (error);
  281. }
  282. if (sent != NULL)
  283. *sent = len - auio.uio_resid;
  284. return (0);
  285. }
  286. int
  287. ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags,
  288. size_t *recv, struct cred *cr)
  289. {
  290. int error;
  291. struct nmsghdr msghdr;
  292. struct uio auio;
  293. struct iovec iov;
  294. /* All Solaris components should pass a cred for this operation. */
  295. ASSERT(cr != NULL);
  296. if (!KSOCKET_VALID(ks)) {
  297. if (recv != NULL)
  298. *recv = 0;
  299. return (ENOTSOCK);
  300. }
  301. iov.iov_base = msg;
  302. iov.iov_len = msglen;
  303. bzero(&auio, sizeof (struct uio));
  304. auio.uio_loffset = 0;
  305. auio.uio_iov = &iov;
  306. auio.uio_iovcnt = 1;
  307. auio.uio_resid = msglen;
  308. if (flags & MSG_USERSPACE)
  309. auio.uio_segflg = UIO_USERSPACE;
  310. else
  311. auio.uio_segflg = UIO_SYSSPACE;
  312. auio.uio_extflg = UIO_COPY_DEFAULT;
  313. auio.uio_limit = 0;
  314. auio.uio_fmode = KSOCKET_FMODE(ks);
  315. msghdr.msg_name = NULL;
  316. msghdr.msg_namelen = 0;
  317. msghdr.msg_control = NULL;
  318. msghdr.msg_controllen = 0;
  319. msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
  320. MSG_DONTWAIT | MSG_USERSPACE);
  321. error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
  322. if (error != 0) {
  323. if (recv != NULL)
  324. *recv = 0;
  325. return (error);
  326. }
  327. if (recv != NULL)
  328. *recv = msglen - auio.uio_resid;
  329. return (0);
  330. }
  331. int
  332. ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags,
  333. struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr)
  334. {
  335. int error;
  336. struct nmsghdr msghdr;
  337. struct uio auio;
  338. struct iovec iov;
  339. /* All Solaris components should pass a cred for this operation. */
  340. ASSERT(cr != NULL);
  341. if (!KSOCKET_VALID(ks)) {
  342. if (recv != NULL)
  343. *recv = 0;
  344. return (ENOTSOCK);
  345. }
  346. iov.iov_base = msg;
  347. iov.iov_len = msglen;
  348. bzero(&auio, sizeof (struct uio));
  349. auio.uio_loffset = 0;
  350. auio.uio_iov = &iov;
  351. auio.uio_iovcnt = 1;
  352. auio.uio_resid = msglen;
  353. if (flags & MSG_USERSPACE)
  354. auio.uio_segflg = UIO_USERSPACE;
  355. else
  356. auio.uio_segflg = UIO_SYSSPACE;
  357. auio.uio_extflg = UIO_COPY_DEFAULT;
  358. auio.uio_limit = 0;
  359. auio.uio_fmode = KSOCKET_FMODE(ks);
  360. msghdr.msg_name = (char *)name;
  361. msghdr.msg_namelen = *namelen;
  362. msghdr.msg_control = NULL;
  363. msghdr.msg_controllen = 0;
  364. msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
  365. MSG_DONTWAIT | MSG_USERSPACE);
  366. error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr);
  367. if (error != 0) {
  368. if (recv != NULL)
  369. *recv = 0;
  370. return (error);
  371. }
  372. if (recv != NULL)
  373. *recv = msglen - auio.uio_resid;
  374. bcopy(msghdr.msg_name, name, msghdr.msg_namelen);
  375. bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen));
  376. return (0);
  377. }
  378. int
  379. ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recv,
  380. struct cred *cr)
  381. {
  382. int error;
  383. ssize_t len;
  384. int i;
  385. struct uio auio;
  386. /* All Solaris components should pass a cred for this operation. */
  387. ASSERT(cr != NULL);
  388. if (!KSOCKET_VALID(ks)) {
  389. if (recv != NULL)
  390. *recv = 0;
  391. return (ENOTSOCK);
  392. }
  393. bzero(&auio, sizeof (struct uio));
  394. auio.uio_loffset = 0;
  395. auio.uio_iov = msg->msg_iov;
  396. auio.uio_iovcnt = msg->msg_iovlen;
  397. if (msg->msg_flags & MSG_USERSPACE)
  398. auio.uio_segflg = UIO_USERSPACE;
  399. else
  400. auio.uio_segflg = UIO_SYSSPACE;
  401. auio.uio_extflg = UIO_COPY_DEFAULT;
  402. auio.uio_limit = 0;
  403. auio.uio_fmode = KSOCKET_FMODE(ks);
  404. len = 0;
  405. for (i = 0; i < msg->msg_iovlen; i++) {
  406. ssize_t iovlen;
  407. iovlen = (msg->msg_iov)[i].iov_len;
  408. len += iovlen;
  409. if (len < 0 || iovlen < 0)
  410. return (EINVAL);
  411. }
  412. auio.uio_resid = len;
  413. msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL |
  414. MSG_DONTWAIT | MSG_USERSPACE);
  415. error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr);
  416. if (error != 0) {
  417. if (recv != NULL)
  418. *recv = 0;
  419. return (error);
  420. }
  421. if (recv != NULL)
  422. *recv = len - auio.uio_resid;
  423. return (0);
  424. }
  425. int
  426. ksocket_shutdown(ksocket_t ks, int how, struct cred *cr)
  427. {
  428. struct sonode *so;
  429. /* All Solaris components should pass a cred for this operation. */
  430. ASSERT(cr != NULL);
  431. if (!KSOCKET_VALID(ks))
  432. return (ENOTSOCK);
  433. so = KSTOSO(ks);
  434. return (socket_shutdown(so, how, cr));
  435. }
  436. int
  437. ksocket_close(ksocket_t ks, struct cred *cr)
  438. {
  439. struct sonode *so;
  440. so = KSTOSO(ks);
  441. /* All Solaris components should pass a cred for this operation. */
  442. ASSERT(cr != NULL);
  443. mutex_enter(&so->so_lock);
  444. if (!KSOCKET_VALID(ks)) {
  445. mutex_exit(&so->so_lock);
  446. return (ENOTSOCK);
  447. }
  448. so->so_state |= SS_CLOSING;
  449. if (so->so_count > 1) {
  450. mutex_enter(&so->so_acceptq_lock);
  451. cv_broadcast(&so->so_acceptq_cv);
  452. mutex_exit(&so->so_acceptq_lock);
  453. cv_broadcast(&so->so_rcv_cv);
  454. cv_broadcast(&so->so_state_cv);
  455. cv_broadcast(&so->so_single_cv);
  456. cv_broadcast(&so->so_read_cv);
  457. cv_broadcast(&so->so_snd_cv);
  458. cv_broadcast(&so->so_copy_cv);
  459. }
  460. while (so->so_count > 1)
  461. cv_wait(&so->so_closing_cv, &so->so_lock);
  462. mutex_exit(&so->so_lock);
  463. /* Remove callbacks, if any */
  464. (void) ksocket_setcallbacks(ks, NULL, NULL, cr);
  465. (void) socket_close(so, 0, cr);
  466. socket_destroy(so);
  467. return (0);
  468. }
  469. int
  470. ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
  471. struct cred *cr)
  472. {
  473. struct sonode *so;
  474. /* All Solaris components should pass a cred for this operation. */
  475. ASSERT(cr != NULL);
  476. if (!KSOCKET_VALID(ks))
  477. return (ENOTSOCK);
  478. so = KSTOSO(ks);
  479. if (addrlen == NULL || (addr == NULL && *addrlen != 0))
  480. return (EFAULT);
  481. return (socket_getsockname(so, addr, addrlen, cr));
  482. }
  483. int
  484. ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
  485. struct cred *cr)
  486. {
  487. struct sonode *so;
  488. /* All Solaris components should pass a cred for this operation. */
  489. ASSERT(cr != NULL);
  490. if (!KSOCKET_VALID(ks))
  491. return (ENOTSOCK);
  492. so = KSTOSO(ks);
  493. if (addrlen == NULL || (addr == NULL && *addrlen != 0))
  494. return (EFAULT);
  495. return (socket_getpeername(so, addr, addrlen, B_FALSE, cr));
  496. }
  497. int
  498. ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval,
  499. int *optlen, struct cred *cr)
  500. {
  501. struct sonode *so;
  502. /* All Solaris components should pass a cred for this operation. */
  503. ASSERT(cr != NULL);
  504. if (!KSOCKET_VALID(ks))
  505. return (ENOTSOCK);
  506. so = KSTOSO(ks);
  507. if (optlen == NULL)
  508. return (EFAULT);
  509. if (*optlen > SO_MAXARGSIZE)
  510. return (EINVAL);
  511. return (socket_getsockopt(so, level, optname, optval,
  512. (socklen_t *)optlen, 0, cr));
  513. }
  514. int
  515. ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval,
  516. int optlen, struct cred *cr)
  517. {
  518. struct sonode *so;
  519. /* All Solaris components should pass a cred for this operation. */
  520. ASSERT(cr != NULL);
  521. if (!KSOCKET_VALID(ks))
  522. return (ENOTSOCK);
  523. so = KSTOSO(ks);
  524. if (optval == NULL)
  525. optlen = 0;
  526. return (socket_setsockopt(so, level, optname, optval,
  527. (t_uscalar_t)optlen, cr));
  528. }
  529. /* ARGSUSED */
  530. int
  531. ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg,
  532. struct cred *cr)
  533. {
  534. struct sonode *so;
  535. /* All Solaris components should pass a cred for this operation. */
  536. ASSERT(cr != NULL);
  537. if (!KSOCKET_VALID(ks))
  538. return (ENOTSOCK);
  539. so = KSTOSO(ks);
  540. if (cb == NULL && arg != NULL)
  541. return (EFAULT);
  542. if (cb == NULL) {
  543. mutex_enter(&so->so_lock);
  544. bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t));
  545. so->so_ksock_cb_arg = NULL;
  546. mutex_exit(&so->so_lock);
  547. } else {
  548. mutex_enter(&so->so_lock);
  549. SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED)
  550. SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED)
  551. SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED)
  552. SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA)
  553. SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN)
  554. SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND)
  555. SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA)
  556. SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE)
  557. SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE)
  558. so->so_ksock_cb_arg = arg;
  559. mutex_exit(&so->so_lock);
  560. }
  561. return (0);
  562. }
  563. int
  564. ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr)
  565. {
  566. struct sonode *so;
  567. int rval;
  568. /* All Solaris components should pass a cred for this operation. */
  569. ASSERT(cr != NULL);
  570. if (!KSOCKET_VALID(ks))
  571. return (ENOTSOCK);
  572. so = KSTOSO(ks);
  573. switch (cmd) {
  574. default:
  575. /* STREAM iotcls are not supported */
  576. if ((cmd & 0xffffff00U) == STR) {
  577. rval = EOPNOTSUPP;
  578. } else {
  579. rval = socket_ioctl(so, cmd, arg,
  580. KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp);
  581. }
  582. break;
  583. case FIOASYNC:
  584. case SIOCSPGRP:
  585. case FIOSETOWN:
  586. case SIOCGPGRP:
  587. case FIOGETOWN:
  588. rval = EOPNOTSUPP;
  589. break;
  590. }
  591. return (rval);
  592. }
  593. /*
  594. * Wait for an input event, similar to t_kspoll().
  595. * Ideas and code borrowed from ../devpoll.c
  596. * Basically, setup just enough poll data structures so
  597. * we can block on a CV until timeout or pollwakeup().
  598. */
  599. int
  600. ksocket_spoll(ksocket_t ks, int timo, short events, short *revents,
  601. struct cred *cr)
  602. {
  603. struct sonode *so;
  604. pollhead_t *php, *php2;
  605. polldat_t *pdp;
  606. pollcache_t *pcp;
  607. int error;
  608. clock_t expires = 0;
  609. clock_t rval;
  610. /* All Solaris components should pass a cred for this operation. */
  611. ASSERT(cr != NULL);
  612. ASSERT(curthread->t_pollcache == NULL);
  613. if (revents == NULL)
  614. return (EINVAL);
  615. if (!KSOCKET_VALID(ks))
  616. return (ENOTSOCK);
  617. so = KSTOSO(ks);
  618. /*
  619. * Check if there are any events already pending.
  620. * If we're not willing to block, (timo == 0) then
  621. * pass "anyyet">0 to socket_poll so it can skip
  622. * some work. Othewise pass "anyyet"=0 and if
  623. * there are no events pending, it will fill in
  624. * the pollhead pointer we need for pollwakeup().
  625. *
  626. * XXX - pollrelock() logic needs to know which
  627. * which pollcache lock to grab. It'd be a
  628. * cleaner solution if we could pass pcp as
  629. * an arguement in VOP_POLL interface instead
  630. * of implicitly passing it using thread_t
  631. * struct. On the other hand, changing VOP_POLL
  632. * interface will require all driver/file system
  633. * poll routine to change. May want to revisit
  634. * the tradeoff later.
  635. */
  636. php = NULL;
  637. *revents = 0;
  638. pcp = pcache_alloc();
  639. pcache_create(pcp, 1);
  640. mutex_enter(&pcp->pc_lock);
  641. curthread->t_pollcache = pcp;
  642. error = socket_poll(so, (short)events, (timo == 0),
  643. revents, &php);
  644. curthread->t_pollcache = NULL;
  645. mutex_exit(&pcp->pc_lock);
  646. if (error != 0 || *revents != 0 || timo == 0)
  647. goto out;
  648. /*
  649. * Need to block. Did not get *revents, so the
  650. * php should be non-NULL, but let's verify.
  651. * Also compute when our sleep expires.
  652. */
  653. if (php == NULL) {
  654. error = EIO;
  655. goto out;
  656. }
  657. if (timo > 0)
  658. expires = ddi_get_lbolt() +
  659. MSEC_TO_TICK_ROUNDUP(timo);
  660. /*
  661. * Setup: pollhead -> polldat -> pollcache
  662. * needed for pollwakeup()
  663. * pdp should be freed by pcache_destroy
  664. */
  665. pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP);
  666. pdp->pd_fd = 0;
  667. pdp->pd_events = events;
  668. pdp->pd_pcache = pcp;
  669. pcache_insert_fd(pcp, pdp, 1);
  670. pollhead_insert(php, pdp);
  671. pdp->pd_php = php;
  672. mutex_enter(&pcp->pc_lock);
  673. while (!(so->so_state & SS_CLOSING)) {
  674. pcp->pc_flag = 0;
  675. /* Ditto pcp comment above. */
  676. curthread->t_pollcache = pcp;
  677. error = socket_poll(so, (short)events, 0,
  678. revents, &php2);
  679. curthread->t_pollcache = NULL;
  680. ASSERT(php2 == php);
  681. if (error != 0 || *revents != 0)
  682. break;
  683. if (pcp->pc_flag & T_POLLWAKE)
  684. continue;
  685. if (timo == -1) {
  686. rval = cv_wait_sig(&pcp->pc_cv, &pcp->pc_lock);
  687. } else {
  688. rval = cv_timedwait_sig(&pcp->pc_cv, &pcp->pc_lock,
  689. expires);
  690. }
  691. if (rval <= 0) {
  692. if (rval == 0)
  693. error = EINTR;
  694. break;
  695. }
  696. }
  697. mutex_exit(&pcp->pc_lock);
  698. if (pdp->pd_php != NULL) {
  699. pollhead_delete(pdp->pd_php, pdp);
  700. pdp->pd_php = NULL;
  701. pdp->pd_fd = NULL;
  702. }
  703. /*
  704. * pollwakeup() may still interact with this pollcache. Wait until
  705. * it is done.
  706. */
  707. mutex_enter(&pcp->pc_no_exit);
  708. ASSERT(pcp->pc_busy >= 0);
  709. while (pcp->pc_busy > 0)
  710. cv_wait(&pcp->pc_busy_cv, &pcp->pc_no_exit);
  711. mutex_exit(&pcp->pc_no_exit);
  712. out:
  713. pcache_destroy(pcp);
  714. return (error);
  715. }
  716. int
  717. ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags,
  718. mblk_t **mpp, cred_t *cr)
  719. {
  720. struct sonode *so;
  721. int i_val;
  722. socklen_t val_len;
  723. mblk_t *mp = *mpp;
  724. int error;
  725. /* All Solaris components should pass a cred for this operation. */
  726. ASSERT(cr != NULL);
  727. if (!KSOCKET_VALID(ks))
  728. return (ENOTSOCK);
  729. so = KSTOSO(ks);
  730. if (flags & MSG_MBLK_QUICKRELE) {
  731. error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID,
  732. &i_val, &val_len, 0, cr);
  733. if (error != 0)
  734. return (error);
  735. /* Zero copy is not enable */
  736. if (i_val == 0)
  737. return (ECANCELED);
  738. for (; mp != NULL; mp = mp->b_cont)
  739. mp->b_datap->db_struioflag |= STRUIO_ZC;
  740. }
  741. error = socket_sendmblk(so, msg, flags, cr, mpp);
  742. return (error);
  743. }
  744. void
  745. ksocket_hold(ksocket_t ks)
  746. {
  747. struct sonode *so;
  748. so = KSTOSO(ks);
  749. if (!mutex_owned(&so->so_lock)) {
  750. mutex_enter(&so->so_lock);
  751. so->so_count++;
  752. mutex_exit(&so->so_lock);
  753. } else
  754. so->so_count++;
  755. }
  756. void
  757. ksocket_rele(ksocket_t ks)
  758. {
  759. struct sonode *so;
  760. so = KSTOSO(ks);
  761. /*
  762. * When so_count equals 1 means no thread working on this ksocket
  763. */
  764. if (so->so_count < 2)
  765. cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1");
  766. if (!mutex_owned(&so->so_lock)) {
  767. mutex_enter(&so->so_lock);
  768. if (--so->so_count == 1)
  769. cv_signal(&so->so_closing_cv);
  770. mutex_exit(&so->so_lock);
  771. } else {
  772. if (--so->so_count == 1)
  773. cv_signal(&so->so_closing_cv);
  774. }
  775. }