1 /* uipc_syscalls.c 4.4 81/11/18 */ 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/inet.h" 16 #include "../net/inet_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_LOCAL, 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(rso, wso) == 0) 61 goto free4; 62 rso->so_isfilerefd = wso->so_isfilerefd = 1; 63 return; 64 free4: 65 wf->f_count = 0; 66 u.u_ofile[u.u_r.r_val1] = 0; 67 free3: 68 rf->f_count = 0; 69 u.u_ofile[r] = 0; 70 free2: 71 sofree(wso); 72 free: 73 sofree(rso); 74 } 75 76 /* 77 * Splice system call interface. 78 */ 79 ssplice() 80 { 81 register struct a { 82 int fd1; 83 int fd2; 84 } *ap = (struct a *)u.u_ap; 85 struct file *f1, *f2; 86 COUNT(SSPLICE); 87 88 f1 = getf(ap->fd1); 89 if (f1 == NULL) 90 return; 91 f2 = getf(ap->fd2); 92 if (f2 == NULL) 93 return; 94 if (f1 == f2) { 95 u.u_error = EINVAL; 96 return; 97 } 98 if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) { 99 u.u_error = ENOTSOCK; 100 return; 101 } 102 if (f1->f_count > 1 || f2->f_count > 1) { 103 u.u_error = ETOOMANYREFS; 104 return; 105 } 106 u.u_error = sosplice(f1->f_socket, f2->f_socket); 107 if (u.u_error) 108 return; 109 u.u_ofile[ap->fd1] = 0; 110 u.u_ofile[ap->fd2] = 0; 111 f1->f_count = 0; 112 f2->f_count = 0; 113 } 114 115 /* 116 * Socket system call interface. Copy sa arguments 117 * set up file descriptor and call internal socket 118 * creation routine. 119 */ 120 ssocket() 121 { 122 register struct a { 123 int type; 124 struct sockproto *asp; 125 struct sockaddr *asa; 126 int options; 127 } *uap = (struct a *)u.u_ap; 128 struct sockproto sp; 129 struct sockaddr sa; 130 struct socket *so; 131 register struct file *fp; 132 COUNT(SSOCKET); 133 134 if ((fp = falloc()) == NULL) 135 return; 136 fp->f_flag = FSOCKET|FREAD|FWRITE; 137 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) || 138 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 139 u.u_error = EFAULT; 140 return; 141 } 142 u.u_error = socreate(&so, uap->type, 143 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options); 144 if (u.u_error) 145 goto bad; 146 fp->f_socket = so; 147 so->so_isfilerefd = 1; 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_NBIO) && 183 (so->so_state & SS_CONNAWAITING) == 0) { 184 u.u_error = EWOULDBLOCK; 185 splx(s); 186 return; 187 } 188 u.u_error = soaccept(so, &sa); 189 if (u.u_error) { 190 splx(s); 191 return; 192 } 193 /* deal with new file descriptor case */ 194 /* u.u_r.r_val1 = ... */ 195 splx(s); 196 } 197 198 /* 199 * Connect socket to foreign peer; system call 200 * interface. Copy sa arguments and call internal routine. 201 */ 202 sconnect() 203 { 204 register struct a { 205 int fdes; 206 struct sockaddr *a; 207 } *uap = (struct a *)u.u_ap; 208 struct sockaddr sa; 209 register struct file *fp; 210 register struct socket *so; 211 int s; 212 COUNT(SCONNECT); 213 214 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) { 215 u.u_error = EFAULT; 216 return; 217 } 218 fp = getf(uap->fdes); 219 if (fp == 0) 220 return; 221 if ((fp->f_flag & FSOCKET) == 0) { 222 u.u_error = ENOTSOCK; 223 return; 224 } 225 so = fp->f_socket; 226 u.u_error = soconnect(so, &sa); 227 if (u.u_error) 228 return; 229 s = splnet(); 230 if ((so->so_options & SO_NBIO) && 231 (so->so_state & SS_ISCONNECTING)) { 232 u.u_error = EINPROGRESS; 233 splx(s); 234 return; 235 } 236 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 237 sleep((caddr_t)&so->so_timeo, PZERO+1); 238 u.u_error = so->so_error; 239 so->so_error = 0; 240 splx(s); 241 } 242 243 /* 244 * Disconnect socket from foreign peer; system call 245 * interface. Copy sa arguments and call internal routine. 246 */ 247 sdisconnect() 248 { 249 register struct a { 250 int fdes; 251 struct sockaddr *asa; 252 } *uap = (struct a *)u.u_ap; 253 struct sockaddr sa; 254 register struct file *fp; 255 register struct socket *so; 256 int s; 257 COUNT(SDISCONNECT); 258 259 if (uap->asa && 260 copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 261 u.u_error = EFAULT; 262 return; 263 } 264 fp = getf(uap->fdes); 265 if (fp == 0) 266 return; 267 if ((fp->f_flag & FSOCKET) == 0) { 268 u.u_error = ENOTSOCK; 269 return; 270 } 271 so = fp->f_socket; 272 u.u_error = sodisconnect(so, uap->asa ? &sa : 0); 273 if (u.u_error) 274 return; 275 s = splnet(); 276 if ((so->so_options&SO_NBIO) && (so->so_state&SS_ISDISCONNECTING)) { 277 u.u_error = EINPROGRESS; 278 splx(s); 279 return; 280 } 281 while (so->so_state & SS_ISDISCONNECTING) 282 sleep((caddr_t)&so->so_timeo, PZERO+1); 283 u.u_error = so->so_error; 284 so->so_error = 0; 285 splx(s); 286 } 287 288 /* 289 * Send data on socket. 290 */ 291 ssend() 292 { 293 register struct a { 294 int fdes; 295 struct sockaddr *asa; 296 caddr_t cbuf; 297 unsigned count; 298 } *uap = (struct a *)u.u_ap; 299 register struct file *fp; 300 struct sockaddr sa; 301 COUNT(SSEND); 302 303 fp = getf(uap->fdes); 304 if (fp == 0) 305 return; 306 if ((fp->f_flag & FSOCKET) == 0) { 307 u.u_error = ENOTSOCK; 308 return; 309 } 310 u.u_count = uap->count; 311 u.u_segflg = 0; 312 if (useracc(uap->cbuf, uap->count, B_READ) == 0 || 313 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 314 u.u_error = EFAULT; 315 return; 316 } 317 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0); 318 } 319 320 /* 321 * Receive data on socket. 322 */ 323 sreceive() 324 { 325 register struct a { 326 int fdes; 327 struct sockaddr *asa; 328 caddr_t cbuf; 329 u_int count; 330 } *uap = (struct a *)u.u_ap; 331 register struct file *fp; 332 struct sockaddr sa; 333 COUNT(SRECEIVE); 334 335 fp = getf(uap->fdes); 336 if (fp == 0) 337 return; 338 if ((fp->f_flag & FSOCKET) == 0) { 339 u.u_error = ENOTSOCK; 340 return; 341 } 342 u.u_count = uap->count; 343 u.u_segflg = 0; 344 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || 345 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 346 u.u_error = EFAULT; 347 return; 348 } 349 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0); 350 if (u.u_error) 351 return; 352 if (uap->asa) 353 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 354 } 355