Commit | Line | Data |
---|---|---|
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 | 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 | } | |
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 | */ |
172 | sconnect() | |
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 | 182 | COUNT(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 | */ | |
216 | ssend() | |
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; |
226 | COUNT(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 | */ | |
250 | sreceive() | |
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; |
260 | COUNT(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 | */ | |
288 | ssocketaddr() | |
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 |
297 | COUNT(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 | } |