1 /* uipc_syscalls.c 4.14 82/02/25 */ 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" 12 #include "../h/protosw.h" 13 #include "../h/socket.h" 14 #include "../h/socketvar.h" 15 #include "../net/in.h" 16 #include "../net/in_systm.h" 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 * 24 * TODO: 25 * SO_INTNOTIFY 26 */ 27 28 static struct sockproto localproto = { PF_UNIX, 0 }; 29 /* 30 * Pipe system call interface. 31 */ 32 spipe() 33 { 34 register struct file *rf, *wf; 35 struct socket *rso, *wso; 36 int r; 37 COUNT(SPIPE); 38 39 u.u_error = socreate(&rso, SOCK_STREAM, 40 &localproto, (struct sockaddr *)0, 0); 41 if (u.u_error) 42 return; 43 u.u_error = socreate(&wso, SOCK_STREAM, 44 &localproto, (struct sockaddr *)0, 0); 45 if (u.u_error) 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; 60 if (piconnect(wso, rso) == 0) 61 goto free4; 62 return; 63 free4: 64 wf->f_count = 0; 65 u.u_ofile[u.u_r.r_val1] = 0; 66 free3: 67 rf->f_count = 0; 68 u.u_ofile[r] = 0; 69 free2: 70 wso->so_state |= SS_USERGONE; 71 sofree(wso); 72 free: 73 rso->so_state |= SS_USERGONE; 74 sofree(rso); 75 } 76 77 /* 78 * Splice system call interface. 79 */ 80 ssplice() 81 { 82 register struct a { 83 int fd1; 84 int fd2; 85 } *ap = (struct a *)u.u_ap; 86 struct file *f1, *f2; 87 COUNT(SSPLICE); 88 89 f1 = getf(ap->fd1); 90 if (f1 == NULL) 91 return; 92 f2 = getf(ap->fd2); 93 if (f2 == NULL) 94 return; 95 if (f1 == f2) { 96 u.u_error = EINVAL; 97 return; 98 } 99 if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) { 100 u.u_error = ENOTSOCK; 101 return; 102 } 103 if (f1->f_count > 1 || f2->f_count > 1) { 104 u.u_error = ETOOMANYREFS; 105 return; 106 } 107 u.u_error = sosplice(f1->f_socket, f2->f_socket); 108 if (u.u_error) 109 return; 110 u.u_ofile[ap->fd1] = 0; 111 u.u_ofile[ap->fd2] = 0; 112 f1->f_count = 0; 113 f2->f_count = 0; 114 } 115 116 /* 117 * Socket system call interface. Copy sa arguments 118 * set up file descriptor and call internal socket 119 * creation routine. 120 */ 121 ssocket() 122 { 123 register struct a { 124 int type; 125 struct sockproto *asp; 126 struct sockaddr *asa; 127 int options; 128 } *uap = (struct a *)u.u_ap; 129 struct sockproto sp; 130 struct sockaddr sa; 131 struct socket *so; 132 register struct file *fp; 133 COUNT(SSOCKET); 134 135 if ((fp = falloc()) == NULL) 136 return; 137 fp->f_flag = FSOCKET|FREAD|FWRITE; 138 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) || 139 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 140 u.u_error = EFAULT; 141 return; 142 } 143 u.u_error = socreate(&so, uap->type, 144 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options); 145 if (u.u_error) 146 goto bad; 147 fp->f_socket = so; 148 return; 149 bad: 150 u.u_ofile[u.u_r.r_val1] = 0; 151 fp->f_count = 0; 152 } 153 154 /* 155 * Accept system call interface. 156 */ 157 saccept() 158 { 159 register struct a { 160 int fdes; 161 struct sockaddr *asa; 162 } *uap = (struct a *)u.u_ap; 163 struct sockaddr sa; 164 register struct file *fp; 165 struct socket *so; 166 int s; 167 COUNT(SACCEPT); 168 169 if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) { 170 u.u_error = EFAULT; 171 return; 172 } 173 fp = getf(uap->fdes); 174 if (fp == 0) 175 return; 176 if ((fp->f_flag & FSOCKET) == 0) { 177 u.u_error = ENOTSOCK; 178 return; 179 } 180 s = splnet(); 181 so = fp->f_socket; 182 if ((so->so_options & SO_NONBLOCKING) && 183 (so->so_state & SS_CONNAWAITING) == 0) { 184 u.u_error = EWOULDBLOCK; 185 splx(s); 186 return; 187 } 188 while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) 189 sleep((caddr_t)&so->so_timeo, PZERO+1); 190 if (so->so_error) { 191 u.u_error = so->so_error; 192 splx(s); 193 return; 194 } 195 u.u_error = soaccept(so, &sa); 196 if (u.u_error) { 197 splx(s); 198 return; 199 } 200 if (uap->asa) 201 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 202 /* deal with new file descriptor case */ 203 /* u.u_r.r_val1 = ... */ 204 splx(s); 205 } 206 207 /* 208 * Connect socket to foreign peer; system call 209 * interface. Copy sa arguments and call internal routine. 210 */ 211 sconnect() 212 { 213 register struct a { 214 int fdes; 215 struct sockaddr *a; 216 } *uap = (struct a *)u.u_ap; 217 struct sockaddr sa; 218 register struct file *fp; 219 register struct socket *so; 220 int s; 221 COUNT(SCONNECT); 222 223 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) { 224 u.u_error = EFAULT; 225 return; 226 } 227 fp = getf(uap->fdes); 228 if (fp == 0) 229 return; 230 if ((fp->f_flag & FSOCKET) == 0) { 231 u.u_error = ENOTSOCK; 232 return; 233 } 234 so = fp->f_socket; 235 u.u_error = soconnect(so, &sa); 236 if (u.u_error) 237 return; 238 s = splnet(); 239 if ((so->so_options & SO_NONBLOCKING) && 240 (so->so_state & SS_ISCONNECTING)) { 241 u.u_error = EINPROGRESS; 242 splx(s); 243 return; 244 } 245 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 246 sleep((caddr_t)&so->so_timeo, PZERO+1); 247 u.u_error = so->so_error; 248 so->so_error = 0; 249 splx(s); 250 } 251 252 /* 253 * Disconnect socket from foreign peer; system call 254 * interface. Copy sa arguments and call internal routine. 255 */ 256 sdisconnect() 257 { 258 register struct a { 259 int fdes; 260 struct sockaddr *asa; 261 } *uap = (struct a *)u.u_ap; 262 struct sockaddr sa; 263 register struct file *fp; 264 register struct socket *so; 265 int s; 266 COUNT(SDISCONNECT); 267 268 if (uap->asa && 269 copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 270 u.u_error = EFAULT; 271 return; 272 } 273 fp = getf(uap->fdes); 274 if (fp == 0) 275 return; 276 if ((fp->f_flag & FSOCKET) == 0) { 277 u.u_error = ENOTSOCK; 278 return; 279 } 280 so = fp->f_socket; 281 u.u_error = sodisconnect(so, uap->asa ? &sa : 0); 282 if (u.u_error) 283 return; 284 s = splnet(); 285 if ((so->so_options&SO_NONBLOCKING) && (so->so_state&SS_ISDISCONNECTING)) { 286 u.u_error = EINPROGRESS; 287 splx(s); 288 return; 289 } 290 while ((so->so_state & SS_ISDISCONNECTING) && so->so_error == 0) 291 sleep((caddr_t)&so->so_timeo, PZERO+1); 292 u.u_error = so->so_error; 293 so->so_error = 0; 294 splx(s); 295 } 296 297 /* 298 * Send data on socket. 299 */ 300 ssend() 301 { 302 register struct a { 303 int fdes; 304 struct sockaddr *asa; 305 caddr_t cbuf; 306 unsigned count; 307 } *uap = (struct a *)u.u_ap; 308 register struct file *fp; 309 struct sockaddr sa; 310 COUNT(SSEND); 311 312 fp = getf(uap->fdes); 313 if (fp == 0) 314 return; 315 if ((fp->f_flag & FSOCKET) == 0) { 316 u.u_error = ENOTSOCK; 317 return; 318 } 319 u.u_base = uap->cbuf; 320 u.u_count = uap->count; 321 u.u_segflg = 0; 322 if (useracc(uap->cbuf, uap->count, B_READ) == 0 || 323 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 324 u.u_error = EFAULT; 325 return; 326 } 327 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0); 328 u.u_r.r_val1 = uap->count - u.u_count; 329 } 330 331 /* 332 * Receive data on socket. 333 */ 334 sreceive() 335 { 336 register struct a { 337 int fdes; 338 struct sockaddr *asa; 339 caddr_t cbuf; 340 u_int count; 341 } *uap = (struct a *)u.u_ap; 342 register struct file *fp; 343 struct sockaddr sa; 344 COUNT(SRECEIVE); 345 346 fp = getf(uap->fdes); 347 if (fp == 0) 348 return; 349 if ((fp->f_flag & FSOCKET) == 0) { 350 u.u_error = ENOTSOCK; 351 return; 352 } 353 u.u_base = uap->cbuf; 354 u.u_count = uap->count; 355 u.u_segflg = 0; 356 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || 357 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 358 u.u_error = EFAULT; 359 return; 360 } 361 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0); 362 if (u.u_error) 363 return; 364 if (uap->asa) 365 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 366 u.u_r.r_val1 = uap->count - u.u_count; 367 } 368 369 /* 370 * Get socket address. 371 */ 372 ssocketaddr() 373 { 374 register struct a { 375 int fdes; 376 struct sockaddr *asa; 377 } *uap = (struct a *)u.u_ap; 378 register struct file *fp; 379 COUNT(SSOCKETADDR); 380 381 fp = getf(uap->fdes); 382 if (fp == 0) 383 return; 384 if ((fp->f_flag & FSOCKET) == 0) { 385 u.u_error = ENOTSOCK; 386 return; 387 } 388 if (copyout((caddr_t)&fp->f_socket->so_addr, (caddr_t)uap->asa, 389 sizeof (struct sockaddr))) { 390 u.u_error = EFAULT; 391 return; 392 } 393 } 394