1 /* uipc_syscalls.c 4.13 82/01/13 */ 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) 189 sleep((caddr_t)&so->so_timeo, PZERO+1); 190 u.u_error = soaccept(so, &sa); 191 if (u.u_error) { 192 splx(s); 193 return; 194 } 195 if (uap->asa) 196 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 197 /* deal with new file descriptor case */ 198 /* u.u_r.r_val1 = ... */ 199 splx(s); 200 } 201 202 /* 203 * Connect socket to foreign peer; system call 204 * interface. Copy sa arguments and call internal routine. 205 */ 206 sconnect() 207 { 208 register struct a { 209 int fdes; 210 struct sockaddr *a; 211 } *uap = (struct a *)u.u_ap; 212 struct sockaddr sa; 213 register struct file *fp; 214 register struct socket *so; 215 int s; 216 COUNT(SCONNECT); 217 218 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) { 219 u.u_error = EFAULT; 220 return; 221 } 222 fp = getf(uap->fdes); 223 if (fp == 0) 224 return; 225 if ((fp->f_flag & FSOCKET) == 0) { 226 u.u_error = ENOTSOCK; 227 return; 228 } 229 so = fp->f_socket; 230 u.u_error = soconnect(so, &sa); 231 if (u.u_error) 232 return; 233 s = splnet(); 234 if ((so->so_options & SO_NONBLOCKING) && 235 (so->so_state & SS_ISCONNECTING)) { 236 u.u_error = EINPROGRESS; 237 splx(s); 238 return; 239 } 240 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 241 sleep((caddr_t)&so->so_timeo, PZERO+1); 242 u.u_error = so->so_error; 243 so->so_error = 0; 244 splx(s); 245 } 246 247 /* 248 * Disconnect socket from foreign peer; system call 249 * interface. Copy sa arguments and call internal routine. 250 */ 251 sdisconnect() 252 { 253 register struct a { 254 int fdes; 255 struct sockaddr *asa; 256 } *uap = (struct a *)u.u_ap; 257 struct sockaddr sa; 258 register struct file *fp; 259 register struct socket *so; 260 int s; 261 COUNT(SDISCONNECT); 262 263 if (uap->asa && 264 copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 265 u.u_error = EFAULT; 266 return; 267 } 268 fp = getf(uap->fdes); 269 if (fp == 0) 270 return; 271 if ((fp->f_flag & FSOCKET) == 0) { 272 u.u_error = ENOTSOCK; 273 return; 274 } 275 so = fp->f_socket; 276 u.u_error = sodisconnect(so, uap->asa ? &sa : 0); 277 if (u.u_error) 278 return; 279 s = splnet(); 280 if ((so->so_options&SO_NONBLOCKING) && (so->so_state&SS_ISDISCONNECTING)) { 281 u.u_error = EINPROGRESS; 282 splx(s); 283 return; 284 } 285 while ((so->so_state & SS_ISDISCONNECTING) && so->so_error == 0) 286 sleep((caddr_t)&so->so_timeo, PZERO+1); 287 u.u_error = so->so_error; 288 so->so_error = 0; 289 splx(s); 290 } 291 292 /* 293 * Send data on socket. 294 */ 295 ssend() 296 { 297 register struct a { 298 int fdes; 299 struct sockaddr *asa; 300 caddr_t cbuf; 301 unsigned count; 302 } *uap = (struct a *)u.u_ap; 303 register struct file *fp; 304 struct sockaddr sa; 305 COUNT(SSEND); 306 307 fp = getf(uap->fdes); 308 if (fp == 0) 309 return; 310 if ((fp->f_flag & FSOCKET) == 0) { 311 u.u_error = ENOTSOCK; 312 return; 313 } 314 u.u_base = uap->cbuf; 315 u.u_count = uap->count; 316 u.u_segflg = 0; 317 if (useracc(uap->cbuf, uap->count, B_READ) == 0 || 318 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 319 u.u_error = EFAULT; 320 return; 321 } 322 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0); 323 u.u_r.r_val1 = uap->count - u.u_count; 324 } 325 326 /* 327 * Receive data on socket. 328 */ 329 sreceive() 330 { 331 register struct a { 332 int fdes; 333 struct sockaddr *asa; 334 caddr_t cbuf; 335 u_int count; 336 } *uap = (struct a *)u.u_ap; 337 register struct file *fp; 338 struct sockaddr sa; 339 COUNT(SRECEIVE); 340 341 fp = getf(uap->fdes); 342 if (fp == 0) 343 return; 344 if ((fp->f_flag & FSOCKET) == 0) { 345 u.u_error = ENOTSOCK; 346 return; 347 } 348 u.u_base = uap->cbuf; 349 u.u_count = uap->count; 350 u.u_segflg = 0; 351 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || 352 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 353 u.u_error = EFAULT; 354 return; 355 } 356 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0); 357 if (u.u_error) 358 return; 359 if (uap->asa) 360 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 361 u.u_r.r_val1 = uap->count - u.u_count; 362 } 363 364 /* 365 * Get socket address. 366 */ 367 ssocketaddr() 368 { 369 register struct a { 370 int fdes; 371 struct sockaddr *asa; 372 } *uap = (struct a *)u.u_ap; 373 register struct file *fp; 374 COUNT(SSOCKETADDR); 375 376 fp = getf(uap->fdes); 377 if (fp == 0) 378 return; 379 if ((fp->f_flag & FSOCKET) == 0) { 380 u.u_error = ENOTSOCK; 381 return; 382 } 383 if (copyout((caddr_t)&fp->f_socket->so_addr, (caddr_t)uap->asa, 384 sizeof (struct sockaddr))) { 385 u.u_error = EFAULT; 386 return; 387 } 388 } 389