1 /* uipc_syscalls.c 4.16 82/03/19 */ 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 * Socket system call interface. Copy sa arguments 79 * set up file descriptor and call internal socket 80 * creation routine. 81 */ 82 ssocket() 83 { 84 register struct a { 85 int type; 86 struct sockproto *asp; 87 struct sockaddr *asa; 88 int options; 89 } *uap = (struct a *)u.u_ap; 90 struct sockproto sp; 91 struct sockaddr sa; 92 struct socket *so; 93 register struct file *fp; 94 COUNT(SSOCKET); 95 96 if ((fp = falloc()) == NULL) 97 return; 98 fp->f_flag = FSOCKET|FREAD|FWRITE; 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))) { 101 u.u_error = EFAULT; 102 return; 103 } 104 u.u_error = socreate(&so, uap->type, 105 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options); 106 if (u.u_error) 107 goto bad; 108 fp->f_socket = so; 109 return; 110 bad: 111 u.u_ofile[u.u_r.r_val1] = 0; 112 fp->f_count = 0; 113 } 114 115 /* 116 * Accept system call interface. 117 */ 118 saccept() 119 { 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); 129 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; 143 if ((so->so_state & SS_NBIO) && 144 (so->so_state & SS_CONNAWAITING) == 0) { 145 u.u_error = EWOULDBLOCK; 146 splx(s); 147 return; 148 } 149 while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) 150 sleep((caddr_t)&so->so_timeo, PZERO+1); 151 if (so->so_error) { 152 u.u_error = so->so_error; 153 splx(s); 154 return; 155 } 156 u.u_error = soaccept(so, &sa); 157 if (u.u_error) { 158 splx(s); 159 return; 160 } 161 if (uap->asa) 162 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 163 /* deal with new file descriptor case */ 164 /* u.u_r.r_val1 = ... */ 165 splx(s); 166 } 167 168 /* 169 * Connect socket to foreign peer; system call 170 * interface. Copy sa arguments and call internal routine. 171 */ 172 sconnect() 173 { 174 register struct a { 175 int fdes; 176 struct sockaddr *a; 177 } *uap = (struct a *)u.u_ap; 178 struct sockaddr sa; 179 register struct file *fp; 180 register struct socket *so; 181 int s; 182 COUNT(SCONNECT); 183 184 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) { 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; 196 u.u_error = soconnect(so, &sa); 197 if (u.u_error) 198 return; 199 s = splnet(); 200 if ((so->so_state & SS_NBIO) && 201 (so->so_state & SS_ISCONNECTING)) { 202 u.u_error = EINPROGRESS; 203 splx(s); 204 return; 205 } 206 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 207 sleep((caddr_t)&so->so_timeo, PZERO+1); 208 u.u_error = so->so_error; 209 so->so_error = 0; 210 splx(s); 211 } 212 213 /* 214 * Send data on socket. 215 */ 216 ssend() 217 { 218 register struct a { 219 int fdes; 220 struct sockaddr *asa; 221 caddr_t cbuf; 222 unsigned count; 223 } *uap = (struct a *)u.u_ap; 224 register struct file *fp; 225 struct sockaddr sa; 226 COUNT(SSEND); 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 } 235 u.u_base = uap->cbuf; 236 u.u_count = uap->count; 237 u.u_segflg = 0; 238 if (useracc(uap->cbuf, uap->count, B_READ) == 0 || 239 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 240 u.u_error = EFAULT; 241 return; 242 } 243 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0); 244 u.u_r.r_val1 = uap->count - u.u_count; 245 } 246 247 /* 248 * Receive data on socket. 249 */ 250 sreceive() 251 { 252 register struct a { 253 int fdes; 254 struct sockaddr *asa; 255 caddr_t cbuf; 256 u_int count; 257 } *uap = (struct a *)u.u_ap; 258 register struct file *fp; 259 struct sockaddr sa; 260 COUNT(SRECEIVE); 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 } 269 u.u_base = uap->cbuf; 270 u.u_count = uap->count; 271 u.u_segflg = 0; 272 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || 273 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 274 u.u_error = EFAULT; 275 return; 276 } 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)); 282 u.u_r.r_val1 = uap->count - u.u_count; 283 } 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; 295 COUNT(SSOCKETADDR); 296 297 fp = getf(uap->fdes); 298 if (fp == 0) 299 return; 300 if ((fp->f_flag & FSOCKET) == 0) { 301 u.u_error = ENOTSOCK; 302 return; 303 } 304 if (copyout((caddr_t)&fp->f_socket->so_addr, (caddr_t)uap->asa, 305 sizeof (struct sockaddr))) { 306 u.u_error = EFAULT; 307 return; 308 } 309 } 310