Commit | Line | Data |
---|---|---|
62229532 | 1 | /* uipc_syscalls.c 4.18 82/06/12 */ |
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 | 28 | static struct sockproto localproto = { PF_UNIX, 0 }; |
c8c7dd0e | 29 | /* |
cc15ab5d | 30 | * Pipe system call interface. |
c8c7dd0e | 31 | */ |
cc15ab5d | 32 | spipe() |
c8c7dd0e | 33 | { |
cc15ab5d BJ |
34 | register struct file *rf, *wf; |
35 | struct socket *rso, *wso; | |
36 | int r; | |
2b4b57cd | 37 | COUNT(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 |
63 | free4: |
64 | wf->f_count = 0; | |
c8c7dd0e | 65 | u.u_ofile[u.u_r.r_val1] = 0; |
cc15ab5d BJ |
66 | free3: |
67 | rf->f_count = 0; | |
68 | u.u_ofile[r] = 0; | |
69 | free2: | |
4ad99bae | 70 | wso->so_state |= SS_USERGONE; |
cc15ab5d BJ |
71 | sofree(wso); |
72 | free: | |
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 | 82 | ssocket() |
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 | 94 | COUNT(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; |
110 | bad: | |
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 |
118 | saccept() |
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; | |
128 | COUNT(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 | } | |
62229532 BJ |
149 | while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) { |
150 | if (so->so_state & SS_CANTRCVMORE) { | |
151 | so->so_error = ECONNABORTED; | |
152 | break; | |
153 | } | |
d08c5322 | 154 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
62229532 | 155 | } |
f269ef23 BJ |
156 | if (so->so_error) { |
157 | u.u_error = so->so_error; | |
158 | splx(s); | |
159 | return; | |
160 | } | |
2b4b57cd BJ |
161 | u.u_error = soaccept(so, &sa); |
162 | if (u.u_error) { | |
163 | splx(s); | |
164 | return; | |
165 | } | |
d08c5322 BJ |
166 | if (uap->asa) |
167 | (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); | |
2b4b57cd BJ |
168 | /* deal with new file descriptor case */ |
169 | /* u.u_r.r_val1 = ... */ | |
170 | splx(s); | |
ae921915 BJ |
171 | } |
172 | ||
c8c7dd0e BJ |
173 | /* |
174 | * Connect socket to foreign peer; system call | |
2b4b57cd | 175 | * interface. Copy sa arguments and call internal routine. |
c8c7dd0e BJ |
176 | */ |
177 | sconnect() | |
178 | { | |
179 | register struct a { | |
2b4b57cd BJ |
180 | int fdes; |
181 | struct sockaddr *a; | |
c8c7dd0e | 182 | } *uap = (struct a *)u.u_ap; |
2b4b57cd | 183 | struct sockaddr sa; |
c8c7dd0e BJ |
184 | register struct file *fp; |
185 | register struct socket *so; | |
186 | int s; | |
2b4b57cd | 187 | COUNT(SCONNECT); |
c8c7dd0e | 188 | |
2b4b57cd | 189 | if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) { |
c8c7dd0e BJ |
190 | u.u_error = EFAULT; |
191 | return; | |
192 | } | |
193 | fp = getf(uap->fdes); | |
194 | if (fp == 0) | |
195 | return; | |
196 | if ((fp->f_flag & FSOCKET) == 0) { | |
197 | u.u_error = ENOTSOCK; | |
198 | return; | |
199 | } | |
200 | so = fp->f_socket; | |
2b4b57cd | 201 | u.u_error = soconnect(so, &sa); |
c8c7dd0e BJ |
202 | if (u.u_error) |
203 | return; | |
204 | s = splnet(); | |
62364f0e | 205 | if ((so->so_state & SS_NBIO) && |
cc15ab5d | 206 | (so->so_state & SS_ISCONNECTING)) { |
c8c7dd0e | 207 | u.u_error = EINPROGRESS; |
cc15ab5d | 208 | splx(s); |
c8c7dd0e BJ |
209 | return; |
210 | } | |
cc15ab5d | 211 | while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) |
c8c7dd0e BJ |
212 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
213 | u.u_error = so->so_error; | |
cc15ab5d BJ |
214 | so->so_error = 0; |
215 | splx(s); | |
c8c7dd0e BJ |
216 | } |
217 | ||
c8c7dd0e BJ |
218 | /* |
219 | * Send data on socket. | |
220 | */ | |
221 | ssend() | |
222 | { | |
223 | register struct a { | |
224 | int fdes; | |
2b4b57cd | 225 | struct sockaddr *asa; |
c8c7dd0e | 226 | caddr_t cbuf; |
2b4b57cd | 227 | unsigned count; |
c8c7dd0e BJ |
228 | } *uap = (struct a *)u.u_ap; |
229 | register struct file *fp; | |
2b4b57cd BJ |
230 | struct sockaddr sa; |
231 | COUNT(SSEND); | |
c8c7dd0e BJ |
232 | |
233 | fp = getf(uap->fdes); | |
234 | if (fp == 0) | |
235 | return; | |
236 | if ((fp->f_flag & FSOCKET) == 0) { | |
237 | u.u_error = ENOTSOCK; | |
238 | return; | |
239 | } | |
d6e7dc87 | 240 | u.u_base = uap->cbuf; |
c8c7dd0e BJ |
241 | u.u_count = uap->count; |
242 | u.u_segflg = 0; | |
cc15ab5d | 243 | if (useracc(uap->cbuf, uap->count, B_READ) == 0 || |
2b4b57cd | 244 | uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { |
c8c7dd0e BJ |
245 | u.u_error = EFAULT; |
246 | return; | |
247 | } | |
2b4b57cd | 248 | u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0); |
d6e7dc87 | 249 | u.u_r.r_val1 = uap->count - u.u_count; |
c8c7dd0e BJ |
250 | } |
251 | ||
cc15ab5d BJ |
252 | /* |
253 | * Receive data on socket. | |
254 | */ | |
255 | sreceive() | |
256 | { | |
257 | register struct a { | |
258 | int fdes; | |
2b4b57cd | 259 | struct sockaddr *asa; |
cc15ab5d | 260 | caddr_t cbuf; |
ae921915 | 261 | u_int count; |
cc15ab5d BJ |
262 | } *uap = (struct a *)u.u_ap; |
263 | register struct file *fp; | |
2b4b57cd BJ |
264 | struct sockaddr sa; |
265 | COUNT(SRECEIVE); | |
cc15ab5d BJ |
266 | |
267 | fp = getf(uap->fdes); | |
268 | if (fp == 0) | |
269 | return; | |
270 | if ((fp->f_flag & FSOCKET) == 0) { | |
271 | u.u_error = ENOTSOCK; | |
272 | return; | |
273 | } | |
d6e7dc87 | 274 | u.u_base = uap->cbuf; |
cc15ab5d BJ |
275 | u.u_count = uap->count; |
276 | u.u_segflg = 0; | |
277 | if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || | |
2b4b57cd | 278 | uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { |
cc15ab5d BJ |
279 | u.u_error = EFAULT; |
280 | return; | |
281 | } | |
2b4b57cd BJ |
282 | u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0); |
283 | if (u.u_error) | |
284 | return; | |
285 | if (uap->asa) | |
286 | (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); | |
d6e7dc87 | 287 | u.u_r.r_val1 = uap->count - u.u_count; |
cc15ab5d | 288 | } |
a3076b07 BJ |
289 | |
290 | /* | |
291 | * Get socket address. | |
292 | */ | |
293 | ssocketaddr() | |
294 | { | |
295 | register struct a { | |
296 | int fdes; | |
297 | struct sockaddr *asa; | |
298 | } *uap = (struct a *)u.u_ap; | |
299 | register struct file *fp; | |
05d69517 SL |
300 | register struct socket *so; |
301 | struct sockaddr addr; | |
a3076b07 BJ |
302 | COUNT(SSOCKETADDR); |
303 | ||
304 | fp = getf(uap->fdes); | |
305 | if (fp == 0) | |
306 | return; | |
307 | if ((fp->f_flag & FSOCKET) == 0) { | |
308 | u.u_error = ENOTSOCK; | |
309 | return; | |
310 | } | |
05d69517 SL |
311 | so = fp->f_socket; |
312 | u.u_error = | |
313 | (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr); | |
314 | if (u.u_error) | |
2752c877 | 315 | return; |
05d69517 SL |
316 | if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr))) |
317 | u.u_error = EFAULT; | |
2752c877 | 318 | } |