sys_socket.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* $OpenBSD: sys_socket.c,v 1.20 2015/05/13 10:42:46 jsg Exp $ */
  2. /* $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $ */
  3. /*
  4. * Copyright (c) 1982, 1986, 1990, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the University nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * @(#)sys_socket.c 8.1 (Berkeley) 6/10/93
  32. */
  33. #include <sys/param.h>
  34. #include <sys/systm.h>
  35. #include <sys/file.h>
  36. #include <sys/proc.h>
  37. #include <sys/mbuf.h>
  38. #include <sys/protosw.h>
  39. #include <sys/socket.h>
  40. #include <sys/socketvar.h>
  41. #include <sys/ioctl.h>
  42. #include <sys/poll.h>
  43. #include <sys/stat.h>
  44. #include <net/if.h>
  45. #include <net/route.h>
  46. struct fileops socketops = {
  47. soo_read, soo_write, soo_ioctl, soo_poll, soo_kqfilter,
  48. soo_stat, soo_close
  49. };
  50. /* ARGSUSED */
  51. int
  52. soo_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
  53. {
  54. return (soreceive((struct socket *)fp->f_data, (struct mbuf **)NULL,
  55. uio, (struct mbuf **)NULL, (struct mbuf **)NULL, (int *)NULL,
  56. (socklen_t)0));
  57. }
  58. /* ARGSUSED */
  59. int
  60. soo_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
  61. {
  62. return (sosend((struct socket *)fp->f_data, (struct mbuf *)NULL,
  63. uio, (struct mbuf *)NULL, (struct mbuf *)NULL, 0));
  64. }
  65. int
  66. soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
  67. {
  68. struct socket *so = (struct socket *)fp->f_data;
  69. switch (cmd) {
  70. case FIONBIO:
  71. if (*(int *)data)
  72. so->so_state |= SS_NBIO;
  73. else
  74. so->so_state &= ~SS_NBIO;
  75. return (0);
  76. case FIOASYNC:
  77. if (*(int *)data) {
  78. so->so_state |= SS_ASYNC;
  79. so->so_rcv.sb_flags |= SB_ASYNC;
  80. so->so_snd.sb_flags |= SB_ASYNC;
  81. } else {
  82. so->so_state &= ~SS_ASYNC;
  83. so->so_rcv.sb_flags &= ~SB_ASYNC;
  84. so->so_snd.sb_flags &= ~SB_ASYNC;
  85. }
  86. return (0);
  87. case FIONREAD:
  88. *(int *)data = so->so_rcv.sb_datacc;
  89. return (0);
  90. case SIOCSPGRP:
  91. so->so_pgid = *(int *)data;
  92. so->so_siguid = p->p_ucred->cr_ruid;
  93. so->so_sigeuid = p->p_ucred->cr_uid;
  94. return (0);
  95. case SIOCGPGRP:
  96. *(int *)data = so->so_pgid;
  97. return (0);
  98. case SIOCATMARK:
  99. *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
  100. return (0);
  101. }
  102. /*
  103. * Interface/routing/protocol specific ioctls:
  104. * interface and routing ioctls should have a
  105. * different entry since a socket's unnecessary
  106. */
  107. if (IOCGROUP(cmd) == 'i')
  108. return (ifioctl(so, cmd, data, p));
  109. if (IOCGROUP(cmd) == 'r')
  110. return (rtioctl(cmd, data, p));
  111. return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
  112. (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)NULL, p));
  113. }
  114. int
  115. soo_poll(struct file *fp, int events, struct proc *p)
  116. {
  117. struct socket *so = fp->f_data;
  118. int revents = 0;
  119. int s = splsoftnet();
  120. if (events & (POLLIN | POLLRDNORM)) {
  121. if (soreadable(so))
  122. revents |= events & (POLLIN | POLLRDNORM);
  123. }
  124. /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */
  125. if (so->so_state & SS_ISDISCONNECTED) {
  126. revents |= POLLHUP;
  127. } else if (events & (POLLOUT | POLLWRNORM)) {
  128. if (sowriteable(so))
  129. revents |= events & (POLLOUT | POLLWRNORM);
  130. }
  131. if (events & (POLLPRI | POLLRDBAND)) {
  132. if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
  133. revents |= events & (POLLPRI | POLLRDBAND);
  134. }
  135. if (revents == 0) {
  136. if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
  137. selrecord(p, &so->so_rcv.sb_sel);
  138. so->so_rcv.sb_flagsintr |= SB_SEL;
  139. }
  140. if (events & (POLLOUT | POLLWRNORM)) {
  141. selrecord(p, &so->so_snd.sb_sel);
  142. so->so_snd.sb_flagsintr |= SB_SEL;
  143. }
  144. }
  145. splx(s);
  146. return (revents);
  147. }
  148. int
  149. soo_stat(struct file *fp, struct stat *ub, struct proc *p)
  150. {
  151. struct socket *so = fp->f_data;
  152. memset(ub, 0, sizeof (*ub));
  153. ub->st_mode = S_IFSOCK;
  154. if ((so->so_state & SS_CANTRCVMORE) == 0 ||
  155. so->so_rcv.sb_cc != 0)
  156. ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
  157. if ((so->so_state & SS_CANTSENDMORE) == 0)
  158. ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
  159. ub->st_uid = so->so_euid;
  160. ub->st_gid = so->so_egid;
  161. (void) ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
  162. (struct mbuf *)ub, NULL, NULL, p));
  163. return (0);
  164. }
  165. /* ARGSUSED */
  166. int
  167. soo_close(struct file *fp, struct proc *p)
  168. {
  169. int error = 0;
  170. if (fp->f_data)
  171. error = soclose(fp->f_data);
  172. fp->f_data = 0;
  173. return (error);
  174. }