handle multiple uba's
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
4a2ddbf1 1/* uipc_syscalls.c 4.20 82/06/20 */
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;
cc15ab5d 37
2b4b57cd
BJ
38 u.u_error = socreate(&rso, SOCK_STREAM,
39 &localproto, (struct sockaddr *)0, 0);
cc15ab5d 40 if (u.u_error)
c8c7dd0e 41 return;
2b4b57cd
BJ
42 u.u_error = socreate(&wso, SOCK_STREAM,
43 &localproto, (struct sockaddr *)0, 0);
c8c7dd0e 44 if (u.u_error)
cc15ab5d
BJ
45 goto free;
46 rf = falloc();
47 if (rf == NULL)
48 goto free2;
49 r = u.u_r.r_val1;
50 rf->f_flag = FREAD|FSOCKET;
51 rf->f_socket = rso;
52 wf = falloc();
53 if (wf == NULL)
54 goto free3;
55 wf->f_flag = FWRITE|FSOCKET;
56 wf->f_socket = wso;
57 u.u_r.r_val2 = u.u_r.r_val1;
58 u.u_r.r_val1 = r;
225bec1b 59 if (piconnect(wso, rso) == 0)
cc15ab5d 60 goto free4;
c8c7dd0e 61 return;
cc15ab5d
BJ
62free4:
63 wf->f_count = 0;
1d356e13 64 u.u_ofile[u.u_r.r_val2] = 0;
cc15ab5d
BJ
65free3:
66 rf->f_count = 0;
67 u.u_ofile[r] = 0;
68free2:
4ad99bae 69 wso->so_state |= SS_USERGONE;
cc15ab5d
BJ
70 sofree(wso);
71free:
4ad99bae 72 rso->so_state |= SS_USERGONE;
cc15ab5d 73 sofree(rso);
c8c7dd0e
BJ
74}
75
c8c7dd0e 76/*
2b4b57cd 77 * Socket system call interface. Copy sa arguments
cc15ab5d
BJ
78 * set up file descriptor and call internal socket
79 * creation routine.
c8c7dd0e 80 */
cc15ab5d 81ssocket()
c8c7dd0e 82{
cc15ab5d
BJ
83 register struct a {
84 int type;
2b4b57cd
BJ
85 struct sockproto *asp;
86 struct sockaddr *asa;
cc15ab5d
BJ
87 int options;
88 } *uap = (struct a *)u.u_ap;
2b4b57cd
BJ
89 struct sockproto sp;
90 struct sockaddr sa;
91 struct socket *so;
cc15ab5d 92 register struct file *fp;
c8c7dd0e 93
cc15ab5d
BJ
94 if ((fp = falloc()) == NULL)
95 return;
96 fp->f_flag = FSOCKET|FREAD|FWRITE;
2b4b57cd
BJ
97 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
98 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
99 u.u_error = EFAULT;
100 return;
c8c7dd0e 101 }
2b4b57cd
BJ
102 u.u_error = socreate(&so, uap->type,
103 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
cc15ab5d
BJ
104 if (u.u_error)
105 goto bad;
2b4b57cd 106 fp->f_socket = so;
cc15ab5d
BJ
107 return;
108bad:
109 u.u_ofile[u.u_r.r_val1] = 0;
110 fp->f_count = 0;
c8c7dd0e 111}
ae921915 112
2b4b57cd
BJ
113/*
114 * Accept system call interface.
115 */
ae921915
BJ
116saccept()
117{
2b4b57cd
BJ
118 register struct a {
119 int fdes;
120 struct sockaddr *asa;
121 } *uap = (struct a *)u.u_ap;
122 struct sockaddr sa;
123 register struct file *fp;
124 struct socket *so;
125 int s;
ae921915 126
2b4b57cd
BJ
127 if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
128 u.u_error = EFAULT;
129 return;
130 }
131 fp = getf(uap->fdes);
132 if (fp == 0)
133 return;
134 if ((fp->f_flag & FSOCKET) == 0) {
135 u.u_error = ENOTSOCK;
136 return;
137 }
138 s = splnet();
139 so = fp->f_socket;
62364f0e 140 if ((so->so_state & SS_NBIO) &&
2b4b57cd
BJ
141 (so->so_state & SS_CONNAWAITING) == 0) {
142 u.u_error = EWOULDBLOCK;
143 splx(s);
144 return;
145 }
62229532
BJ
146 while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) {
147 if (so->so_state & SS_CANTRCVMORE) {
148 so->so_error = ECONNABORTED;
149 break;
150 }
d08c5322 151 sleep((caddr_t)&so->so_timeo, PZERO+1);
62229532 152 }
f269ef23
BJ
153 if (so->so_error) {
154 u.u_error = so->so_error;
155 splx(s);
156 return;
157 }
2b4b57cd
BJ
158 u.u_error = soaccept(so, &sa);
159 if (u.u_error) {
160 splx(s);
161 return;
162 }
d08c5322
BJ
163 if (uap->asa)
164 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
2b4b57cd
BJ
165 /* deal with new file descriptor case */
166 /* u.u_r.r_val1 = ... */
167 splx(s);
ae921915
BJ
168}
169
c8c7dd0e
BJ
170/*
171 * Connect socket to foreign peer; system call
2b4b57cd 172 * interface. Copy sa arguments and call internal routine.
c8c7dd0e
BJ
173 */
174sconnect()
175{
176 register struct a {
2b4b57cd
BJ
177 int fdes;
178 struct sockaddr *a;
c8c7dd0e 179 } *uap = (struct a *)u.u_ap;
2b4b57cd 180 struct sockaddr sa;
c8c7dd0e
BJ
181 register struct file *fp;
182 register struct socket *so;
183 int s;
184
2b4b57cd 185 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
186 u.u_error = EFAULT;
187 return;
188 }
189 fp = getf(uap->fdes);
190 if (fp == 0)
191 return;
192 if ((fp->f_flag & FSOCKET) == 0) {
193 u.u_error = ENOTSOCK;
194 return;
195 }
196 so = fp->f_socket;
2b4b57cd 197 u.u_error = soconnect(so, &sa);
c8c7dd0e
BJ
198 if (u.u_error)
199 return;
200 s = splnet();
62364f0e 201 if ((so->so_state & SS_NBIO) &&
cc15ab5d 202 (so->so_state & SS_ISCONNECTING)) {
c8c7dd0e 203 u.u_error = EINPROGRESS;
cc15ab5d 204 splx(s);
c8c7dd0e
BJ
205 return;
206 }
cc15ab5d 207 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
208 sleep((caddr_t)&so->so_timeo, PZERO+1);
209 u.u_error = so->so_error;
cc15ab5d
BJ
210 so->so_error = 0;
211 splx(s);
c8c7dd0e
BJ
212}
213
c8c7dd0e
BJ
214/*
215 * Send data on socket.
216 */
217ssend()
218{
219 register struct a {
220 int fdes;
2b4b57cd 221 struct sockaddr *asa;
c8c7dd0e 222 caddr_t cbuf;
2b4b57cd 223 unsigned count;
c8c7dd0e
BJ
224 } *uap = (struct a *)u.u_ap;
225 register struct file *fp;
2b4b57cd 226 struct sockaddr sa;
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 259 struct sockaddr sa;
cc15ab5d
BJ
260
261 fp = getf(uap->fdes);
262 if (fp == 0)
263 return;
264 if ((fp->f_flag & FSOCKET) == 0) {
265 u.u_error = ENOTSOCK;
266 return;
267 }
d6e7dc87 268 u.u_base = uap->cbuf;
cc15ab5d
BJ
269 u.u_count = uap->count;
270 u.u_segflg = 0;
271 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
2b4b57cd 272 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
273 u.u_error = EFAULT;
274 return;
275 }
2b4b57cd
BJ
276 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
277 if (u.u_error)
278 return;
279 if (uap->asa)
280 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
d6e7dc87 281 u.u_r.r_val1 = uap->count - u.u_count;
cc15ab5d 282}
a3076b07
BJ
283
284/*
285 * Get socket address.
286 */
287ssocketaddr()
288{
289 register struct a {
290 int fdes;
291 struct sockaddr *asa;
292 } *uap = (struct a *)u.u_ap;
293 register struct file *fp;
05d69517
SL
294 register struct socket *so;
295 struct sockaddr addr;
a3076b07
BJ
296
297 fp = getf(uap->fdes);
298 if (fp == 0)
299 return;
300 if ((fp->f_flag & FSOCKET) == 0) {
301 u.u_error = ENOTSOCK;
302 return;
303 }
05d69517
SL
304 so = fp->f_socket;
305 u.u_error =
306 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr);
307 if (u.u_error)
2752c877 308 return;
05d69517
SL
309 if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr)))
310 u.u_error = EFAULT;
2752c877 311}