add BLKDEV_IOSIZE for use by character devices
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
05d69517 1/* uipc_syscalls.c 4.17 82/04/10 */
c8c7dd0e
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/proc.h"
8#include "../h/file.h"
9#include "../h/inode.h"
10#include "../h/buf.h"
11#include "../h/mbuf.h"
c8c7dd0e
BJ
12#include "../h/protosw.h"
13#include "../h/socket.h"
14#include "../h/socketvar.h"
3b3ee18d
BJ
15#include "../net/in.h"
16#include "../net/in_systm.h"
c8c7dd0e
BJ
17
18/*
19 * Socket system call interface.
20 *
21 * These routines interface the socket routines to UNIX,
22 * isolating the system interface from the socket-protocol interface.
23 *
cc15ab5d 24 * TODO:
cc15ab5d 25 * SO_INTNOTIFY
c8c7dd0e
BJ
26 */
27
4c078bb2 28static struct sockproto localproto = { PF_UNIX, 0 };
c8c7dd0e 29/*
cc15ab5d 30 * Pipe system call interface.
c8c7dd0e 31 */
cc15ab5d 32spipe()
c8c7dd0e 33{
cc15ab5d
BJ
34 register struct file *rf, *wf;
35 struct socket *rso, *wso;
36 int r;
2b4b57cd 37COUNT(SPIPE);
cc15ab5d 38
2b4b57cd
BJ
39 u.u_error = socreate(&rso, SOCK_STREAM,
40 &localproto, (struct sockaddr *)0, 0);
cc15ab5d 41 if (u.u_error)
c8c7dd0e 42 return;
2b4b57cd
BJ
43 u.u_error = socreate(&wso, SOCK_STREAM,
44 &localproto, (struct sockaddr *)0, 0);
c8c7dd0e 45 if (u.u_error)
cc15ab5d
BJ
46 goto free;
47 rf = falloc();
48 if (rf == NULL)
49 goto free2;
50 r = u.u_r.r_val1;
51 rf->f_flag = FREAD|FSOCKET;
52 rf->f_socket = rso;
53 wf = falloc();
54 if (wf == NULL)
55 goto free3;
56 wf->f_flag = FWRITE|FSOCKET;
57 wf->f_socket = wso;
58 u.u_r.r_val2 = u.u_r.r_val1;
59 u.u_r.r_val1 = r;
225bec1b 60 if (piconnect(wso, rso) == 0)
cc15ab5d 61 goto free4;
c8c7dd0e 62 return;
cc15ab5d
BJ
63free4:
64 wf->f_count = 0;
c8c7dd0e 65 u.u_ofile[u.u_r.r_val1] = 0;
cc15ab5d
BJ
66free3:
67 rf->f_count = 0;
68 u.u_ofile[r] = 0;
69free2:
4ad99bae 70 wso->so_state |= SS_USERGONE;
cc15ab5d
BJ
71 sofree(wso);
72free:
4ad99bae 73 rso->so_state |= SS_USERGONE;
cc15ab5d 74 sofree(rso);
c8c7dd0e
BJ
75}
76
c8c7dd0e 77/*
2b4b57cd 78 * Socket system call interface. Copy sa arguments
cc15ab5d
BJ
79 * set up file descriptor and call internal socket
80 * creation routine.
c8c7dd0e 81 */
cc15ab5d 82ssocket()
c8c7dd0e 83{
cc15ab5d
BJ
84 register struct a {
85 int type;
2b4b57cd
BJ
86 struct sockproto *asp;
87 struct sockaddr *asa;
cc15ab5d
BJ
88 int options;
89 } *uap = (struct a *)u.u_ap;
2b4b57cd
BJ
90 struct sockproto sp;
91 struct sockaddr sa;
92 struct socket *so;
cc15ab5d 93 register struct file *fp;
2b4b57cd 94COUNT(SSOCKET);
c8c7dd0e 95
cc15ab5d
BJ
96 if ((fp = falloc()) == NULL)
97 return;
98 fp->f_flag = FSOCKET|FREAD|FWRITE;
2b4b57cd
BJ
99 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
100 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
101 u.u_error = EFAULT;
102 return;
c8c7dd0e 103 }
2b4b57cd
BJ
104 u.u_error = socreate(&so, uap->type,
105 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
cc15ab5d
BJ
106 if (u.u_error)
107 goto bad;
2b4b57cd 108 fp->f_socket = so;
cc15ab5d
BJ
109 return;
110bad:
111 u.u_ofile[u.u_r.r_val1] = 0;
112 fp->f_count = 0;
c8c7dd0e 113}
ae921915 114
2b4b57cd
BJ
115/*
116 * Accept system call interface.
117 */
ae921915
BJ
118saccept()
119{
2b4b57cd
BJ
120 register struct a {
121 int fdes;
122 struct sockaddr *asa;
123 } *uap = (struct a *)u.u_ap;
124 struct sockaddr sa;
125 register struct file *fp;
126 struct socket *so;
127 int s;
128COUNT(SACCEPT);
ae921915 129
2b4b57cd
BJ
130 if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
131 u.u_error = EFAULT;
132 return;
133 }
134 fp = getf(uap->fdes);
135 if (fp == 0)
136 return;
137 if ((fp->f_flag & FSOCKET) == 0) {
138 u.u_error = ENOTSOCK;
139 return;
140 }
141 s = splnet();
142 so = fp->f_socket;
62364f0e 143 if ((so->so_state & SS_NBIO) &&
2b4b57cd
BJ
144 (so->so_state & SS_CONNAWAITING) == 0) {
145 u.u_error = EWOULDBLOCK;
146 splx(s);
147 return;
148 }
f269ef23 149 while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0)
d08c5322 150 sleep((caddr_t)&so->so_timeo, PZERO+1);
f269ef23
BJ
151 if (so->so_error) {
152 u.u_error = so->so_error;
153 splx(s);
154 return;
155 }
2b4b57cd
BJ
156 u.u_error = soaccept(so, &sa);
157 if (u.u_error) {
158 splx(s);
159 return;
160 }
d08c5322
BJ
161 if (uap->asa)
162 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
2b4b57cd
BJ
163 /* deal with new file descriptor case */
164 /* u.u_r.r_val1 = ... */
165 splx(s);
ae921915
BJ
166}
167
c8c7dd0e
BJ
168/*
169 * Connect socket to foreign peer; system call
2b4b57cd 170 * interface. Copy sa arguments and call internal routine.
c8c7dd0e
BJ
171 */
172sconnect()
173{
174 register struct a {
2b4b57cd
BJ
175 int fdes;
176 struct sockaddr *a;
c8c7dd0e 177 } *uap = (struct a *)u.u_ap;
2b4b57cd 178 struct sockaddr sa;
c8c7dd0e
BJ
179 register struct file *fp;
180 register struct socket *so;
181 int s;
2b4b57cd 182COUNT(SCONNECT);
c8c7dd0e 183
2b4b57cd 184 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
185 u.u_error = EFAULT;
186 return;
187 }
188 fp = getf(uap->fdes);
189 if (fp == 0)
190 return;
191 if ((fp->f_flag & FSOCKET) == 0) {
192 u.u_error = ENOTSOCK;
193 return;
194 }
195 so = fp->f_socket;
2b4b57cd 196 u.u_error = soconnect(so, &sa);
c8c7dd0e
BJ
197 if (u.u_error)
198 return;
199 s = splnet();
62364f0e 200 if ((so->so_state & SS_NBIO) &&
cc15ab5d 201 (so->so_state & SS_ISCONNECTING)) {
c8c7dd0e 202 u.u_error = EINPROGRESS;
cc15ab5d 203 splx(s);
c8c7dd0e
BJ
204 return;
205 }
cc15ab5d 206 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
207 sleep((caddr_t)&so->so_timeo, PZERO+1);
208 u.u_error = so->so_error;
cc15ab5d
BJ
209 so->so_error = 0;
210 splx(s);
c8c7dd0e
BJ
211}
212
c8c7dd0e
BJ
213/*
214 * Send data on socket.
215 */
216ssend()
217{
218 register struct a {
219 int fdes;
2b4b57cd 220 struct sockaddr *asa;
c8c7dd0e 221 caddr_t cbuf;
2b4b57cd 222 unsigned count;
c8c7dd0e
BJ
223 } *uap = (struct a *)u.u_ap;
224 register struct file *fp;
2b4b57cd
BJ
225 struct sockaddr sa;
226COUNT(SSEND);
c8c7dd0e
BJ
227
228 fp = getf(uap->fdes);
229 if (fp == 0)
230 return;
231 if ((fp->f_flag & FSOCKET) == 0) {
232 u.u_error = ENOTSOCK;
233 return;
234 }
d6e7dc87 235 u.u_base = uap->cbuf;
c8c7dd0e
BJ
236 u.u_count = uap->count;
237 u.u_segflg = 0;
cc15ab5d 238 if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
2b4b57cd 239 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
240 u.u_error = EFAULT;
241 return;
242 }
2b4b57cd 243 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
d6e7dc87 244 u.u_r.r_val1 = uap->count - u.u_count;
c8c7dd0e
BJ
245}
246
cc15ab5d
BJ
247/*
248 * Receive data on socket.
249 */
250sreceive()
251{
252 register struct a {
253 int fdes;
2b4b57cd 254 struct sockaddr *asa;
cc15ab5d 255 caddr_t cbuf;
ae921915 256 u_int count;
cc15ab5d
BJ
257 } *uap = (struct a *)u.u_ap;
258 register struct file *fp;
2b4b57cd
BJ
259 struct sockaddr sa;
260COUNT(SRECEIVE);
cc15ab5d
BJ
261
262 fp = getf(uap->fdes);
263 if (fp == 0)
264 return;
265 if ((fp->f_flag & FSOCKET) == 0) {
266 u.u_error = ENOTSOCK;
267 return;
268 }
d6e7dc87 269 u.u_base = uap->cbuf;
cc15ab5d
BJ
270 u.u_count = uap->count;
271 u.u_segflg = 0;
272 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
2b4b57cd 273 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
274 u.u_error = EFAULT;
275 return;
276 }
2b4b57cd
BJ
277 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
278 if (u.u_error)
279 return;
280 if (uap->asa)
281 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
d6e7dc87 282 u.u_r.r_val1 = uap->count - u.u_count;
cc15ab5d 283}
a3076b07
BJ
284
285/*
286 * Get socket address.
287 */
288ssocketaddr()
289{
290 register struct a {
291 int fdes;
292 struct sockaddr *asa;
293 } *uap = (struct a *)u.u_ap;
294 register struct file *fp;
05d69517
SL
295 register struct socket *so;
296 struct sockaddr addr;
a3076b07
BJ
297COUNT(SSOCKETADDR);
298
299 fp = getf(uap->fdes);
300 if (fp == 0)
301 return;
302 if ((fp->f_flag & FSOCKET) == 0) {
303 u.u_error = ENOTSOCK;
304 return;
305 }
05d69517
SL
306 so = fp->f_socket;
307 u.u_error =
308 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr);
309 if (u.u_error)
2752c877 310 return;
05d69517
SL
311 if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr)))
312 u.u_error = EFAULT;
2752c877 313}