1 /* uipc_syscalls.c 4.2 81/11/14 */ 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/protocol.h" 13 #include "../h/protosw.h" 14 #include "../h/socket.h" 15 #include "../h/socketvar.h" 16 #include "../h/inaddr.h" 17 #include "../net/inet.h" 18 #include "../net/inet_systm.h" 19 20 /* 21 * Socket system call interface. 22 * 23 * These routines interface the socket routines to UNIX, 24 * isolating the system interface from the socket-protocol interface. 25 * 26 * TODO: 27 * SO_NEWFDONCONN 28 * SO_INTNOTIFY 29 */ 30 31 static struct in_addr localaddr = { PF_LOCAL }; 32 /* 33 * Pipe system call interface. 34 */ 35 spipe() 36 { 37 register struct file *rf, *wf; 38 struct socket *rso, *wso; 39 int r; 40 struct in_addr waddr; 41 42 u.u_error = socket(&rso, SOCK_STREAM, &localaddr, SO_ACCEPTCONN); 43 if (u.u_error) 44 return; 45 u.u_error = socket(&wso, SOCK_STREAM, &localaddr, 0); 46 if (u.u_error) 47 goto free; 48 rf = falloc(); 49 if (rf == NULL) 50 goto free2; 51 r = u.u_r.r_val1; 52 rf->f_flag = FREAD|FSOCKET; 53 rf->f_socket = rso; 54 wf = falloc(); 55 if (wf == NULL) 56 goto free3; 57 wf->f_flag = FWRITE|FSOCKET; 58 wf->f_socket = wso; 59 u.u_r.r_val2 = u.u_r.r_val1; 60 u.u_r.r_val1 = r; 61 if (pi_connect(rso, wso) == 0) 62 goto free4; 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 * Portal system call interface. 78 * 79 * This call creates a portal. 80 * All the difficulty here is in dealing with errors. 81 * A long sequence of steps is necessary: 82 * 1. a socket must be allocated 83 * 2. the server name length must be determined 84 * 3. the portal must be entered into the file system 85 * 4. the portal type and server must be entered into the portals' file 86 * 5. a file descriptor referencing the socket+inode must be returned 87 * If any errors occur in this process we must back it all out. 88 */ 89 sportal() 90 { 91 register struct a { 92 caddr_t name; 93 int mode; 94 caddr_t server; 95 int kind; 96 } *ap = (struct a *)u.u_ap; 97 struct socket *so; 98 struct inode *ip; 99 struct file *fp; 100 int err, len; 101 char ch; 102 103 /* 104 * Allocate the socket for the portal. 105 */ 106 u.u_error = socket(&so, SOCK_STREAM, &localaddr, SO_NEWFDONCONN); 107 if (u.u_error) 108 return; 109 110 /* 111 * Check that server name fis in a file system buffer. 112 * This to simplify the creation of the portal service process. 113 */ 114 if (ap->server) { 115 u.u_dirp = ap->server; 116 for (len = 0; len < BSIZE-2; len++) { 117 register c = uchar(); 118 if (c < 0) 119 goto bad; 120 if (c == 0) 121 break; 122 } 123 if (len == BSIZE - 2) { 124 u.u_error = EINVAL; 125 goto bad; 126 } 127 } 128 129 /* 130 * Make sure that nothing with the portal's name exists. 131 */ 132 u.u_dirp = ap->name; 133 ip = namei(uchar, 1); 134 if (ip != NULL) { 135 iput(ip); 136 u.u_error = EEXIST; 137 } 138 if (u.u_error) 139 goto bad; 140 141 /* 142 * Make a node in the file system for the portal. 143 */ 144 ip = maknode((ap->mode & 0x7777) | IFPORTAL); 145 if (ip == NULL) 146 goto bad; 147 148 /* 149 * Make the first character of the contents of the 150 * portal be the portal type and the rest of the portal be 151 * the pathname of the server (if one was given). 152 */ 153 ch = (char)ap->kind; 154 u.u_base = (caddr_t)&ch; 155 u.u_count = 1; 156 u.u_offset = 0; 157 u.u_segflg = 1; 158 writei(ip); 159 if (ap->server) { 160 u.u_base = ap->server; 161 u.u_count = len; 162 u.u_segflg = 0; 163 writei(ip); 164 } 165 if (u.u_error) 166 goto bad2; 167 168 /* 169 * Allocate a file descriptor and make it reference both 170 * the inode representing the portal and the call director 171 * socket for the portal. 172 */ 173 fp = falloc(); 174 if (fp == NULL) 175 goto bad2; 176 fp->f_flag = FPORTAL|FSOCKET; 177 fp->f_inode = ip; 178 fp->f_socket = so; 179 180 /* 181 * Make the in-core inode reference the socket. 182 */ 183 ip->i_un.i_socket = so; 184 irele(ip); 185 return; 186 bad2: 187 err = u.u_error; 188 iput(ip); 189 u.u_dirp = ap->name; 190 unlink(); 191 u.u_error = err; 192 bad: 193 sofree(so); 194 } 195 196 /* 197 * Splice system call interface. 198 */ 199 ssplice() 200 { 201 register struct a { 202 int fd1; 203 int fd2; 204 } *ap = (struct a *)u.u_ap; 205 struct file *f1, *f2; 206 struct socket *pso, *pso2; 207 208 f1 = getf(ap->fd1); 209 if (f1 == NULL) 210 return; 211 f2 = getf(ap->fd2); 212 if (f2 == NULL) 213 return; 214 if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) { 215 u.u_error = ENOTSOCK; 216 return; 217 } 218 if (f1->f_count > 1 || f2->f_count > 1) { 219 u.u_error = ETOOMANYREFS; 220 return; 221 } 222 u.u_error = pi_splice(f1->f_socket, f2->f_socket); 223 if (u.u_error) 224 return; 225 u.u_ofile[ap->fd1] = 0; 226 u.u_ofile[ap->fd2] = 0; 227 f1->f_count = 0; 228 f2->f_count = 0; 229 } 230 231 /* 232 * Socket system call interface. Copy in arguments 233 * set up file descriptor and call internal socket 234 * creation routine. 235 */ 236 ssocket() 237 { 238 register struct a { 239 int type; 240 struct in_addr *ain; 241 int options; 242 } *uap = (struct a *)u.u_ap; 243 struct in_addr in; 244 struct socket *so0; 245 register struct file *fp; 246 247 if ((fp = falloc()) == NULL) 248 return; 249 fp->f_flag = FSOCKET|FREAD|FWRITE; 250 if (copyin((caddr_t)uap->ain, &in, sizeof (in))) { 251 u.u_error = EFAULT; 252 return; 253 } 254 u.u_error = socket(&so0, uap->type, &in, uap->options); 255 if (u.u_error) 256 goto bad; 257 fp->f_socket = so0; 258 return; 259 bad: 260 u.u_ofile[u.u_r.r_val1] = 0; 261 fp->f_count = 0; 262 } 263 /* 264 * Connect socket to foreign peer; system call 265 * interface. Copy in arguments and call internal routine. 266 */ 267 sconnect() 268 { 269 register struct a { 270 int fdes; 271 struct in_addr *a; 272 } *uap = (struct a *)u.u_ap; 273 in_addr in; 274 register struct file *fp; 275 register struct socket *so; 276 int s; 277 278 if (copyin((caddr_t)uap->a, &in, sizeof (in))) { 279 u.u_error = EFAULT; 280 return; 281 } 282 fp = getf(uap->fdes); 283 if (fp == 0) 284 return; 285 if ((fp->f_flag & FSOCKET) == 0) { 286 u.u_error = ENOTSOCK; 287 return; 288 } 289 so = fp->f_socket; 290 u.u_error = connect(so, &in); 291 if (u.u_error) 292 return; 293 s = splnet(); 294 if ((so->so_options & SO_NBIO) && 295 (so->so_state & SS_ISCONNECTING)) { 296 u.u_error = EINPROGRESS; 297 splx(s); 298 return; 299 } 300 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 301 sleep((caddr_t)&so->so_timeo, PZERO+1); 302 u.u_error = so->so_error; 303 so->so_error = 0; 304 splx(s); 305 } 306 307 /* 308 * Disconnect socket from foreign peer; system call 309 * interface. Copy in arguments and call internal routine. 310 */ 311 sdisconnect() 312 { 313 register struct a { 314 int fdes; 315 in_addr *addr; 316 } *uap = (struct a *)u.u_ap; 317 in_addr in; 318 register struct file *fp; 319 register struct socket *so; 320 int s; 321 322 if (uap->addr && 323 copyin((caddr_t)uap->addr, (caddr_t)&in, sizeof (in))) { 324 u.u_error = EFAULT; 325 return; 326 } 327 fp = getf(uap->fdes); 328 if (fp == 0) 329 return; 330 if ((fp->f_flag & FSOCKET) == 0) { 331 u.u_error = ENOTSOCK; 332 return; 333 } 334 so = fp->f_socket; 335 u.u_error = disconnect(so, uap->addr ? &in : 0); 336 if (u.u_error) 337 return; 338 s = splnet(); 339 if ((so->so_options&SO_NBIO) && (so->so_state&SS_ISDISCONNECTING)) { 340 u.u_error = EINPROGRESS; 341 splx(s); 342 return; 343 } 344 while (so->so_state & SS_ISDISCONNECTING) 345 sleep((caddr_t)&so->so_timeo, PZERO+1); 346 u.u_error = so->so_error; 347 so->so_error = 0; 348 splx(s); 349 } 350 351 /* 352 * Send data on socket. 353 */ 354 ssend() 355 { 356 register struct a { 357 int fdes; 358 in_addr *ain; 359 caddr_t cbuf; 360 int count; 361 } *uap = (struct a *)u.u_ap; 362 register struct file *fp; 363 struct in_addr in; 364 365 fp = getf(uap->fdes); 366 if (fp == 0) 367 return; 368 if ((fp->f_flag & FSOCKET) == 0) { 369 u.u_error = ENOTSOCK; 370 return; 371 } 372 if (uap->count < 0) { 373 u.u_error = EINVAL; 374 return; 375 } 376 u.u_base = uap->cbuf; 377 u.u_count = uap->count; 378 u.u_segflg = 0; 379 if (useracc(uap->cbuf, uap->count, B_READ) == 0 || 380 uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 381 u.u_error = EFAULT; 382 return; 383 } 384 u.u_error = send(fp->f_socket, uap->ain ? &in : 0); 385 } 386 387 /* 388 * Receive data on socket. 389 */ 390 sreceive() 391 { 392 register struct a { 393 int fdes; 394 in_addr *ain; 395 caddr_t cbuf; 396 int count; 397 } *uap = (struct a *)u.u_ap; 398 register struct file *fp; 399 struct in_addr *in; 400 401 fp = getf(uap->fdes); 402 if (fp == 0) 403 return; 404 if ((fp->f_flag & FSOCKET) == 0) { 405 u.u_error = ENOTSOCK; 406 return; 407 } 408 if (uap->count < 0) { 409 u.u_error = EINVAL; 410 return; 411 } 412 u.u_base = uap->cbuf; 413 u.u_count = uap->count; 414 u.u_segflg = 0; 415 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || 416 uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 417 u.u_error = EFAULT; 418 return; 419 } 420 receive(fp->f_socket, uap->ain ? &in : 0); 421 } 422