1 /* uipc_syscalls.c 4.20 82/06/20 */ 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 38 u.u_error = socreate(&rso, SOCK_STREAM, 39 &localproto, (struct sockaddr *)0, 0); 40 if (u.u_error) 41 return; 42 u.u_error = socreate(&wso, SOCK_STREAM, 43 &localproto, (struct sockaddr *)0, 0); 44 if (u.u_error) 45 goto free; 46 rf = falloc(); 47 if (rf == NULL) 48 goto free2; 49 r = u.u_r.r_val1; 50 rf->f_flag = FREAD|FSOCKET; 51 rf->f_socket = rso; 52 wf = falloc(); 53 if (wf == NULL) 54 goto free3; 55 wf->f_flag = FWRITE|FSOCKET; 56 wf->f_socket = wso; 57 u.u_r.r_val2 = u.u_r.r_val1; 58 u.u_r.r_val1 = r; 59 if (piconnect(wso, rso) == 0) 60 goto free4; 61 return; 62 free4: 63 wf->f_count = 0; 64 u.u_ofile[u.u_r.r_val2] = 0; 65 free3: 66 rf->f_count = 0; 67 u.u_ofile[r] = 0; 68 free2: 69 wso->so_state |= SS_USERGONE; 70 sofree(wso); 71 free: 72 rso->so_state |= SS_USERGONE; 73 sofree(rso); 74 } 75 76 /* 77 * Socket system call interface. Copy sa arguments 78 * set up file descriptor and call internal socket 79 * creation routine. 80 */ 81 ssocket() 82 { 83 register struct a { 84 int type; 85 struct sockproto *asp; 86 struct sockaddr *asa; 87 int options; 88 } *uap = (struct a *)u.u_ap; 89 struct sockproto sp; 90 struct sockaddr sa; 91 struct socket *so; 92 register struct file *fp; 93 94 if ((fp = falloc()) == NULL) 95 return; 96 fp->f_flag = FSOCKET|FREAD|FWRITE; 97 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) || 98 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 99 u.u_error = EFAULT; 100 return; 101 } 102 u.u_error = socreate(&so, uap->type, 103 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options); 104 if (u.u_error) 105 goto bad; 106 fp->f_socket = so; 107 return; 108 bad: 109 u.u_ofile[u.u_r.r_val1] = 0; 110 fp->f_count = 0; 111 } 112 113 /* 114 * Accept system call interface. 115 */ 116 saccept() 117 { 118 register struct a { 119 int fdes; 120 struct sockaddr *asa; 121 } *uap = (struct a *)u.u_ap; 122 struct sockaddr sa; 123 register struct file *fp; 124 struct socket *so; 125 int s; 126 127 if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) { 128 u.u_error = EFAULT; 129 return; 130 } 131 fp = getf(uap->fdes); 132 if (fp == 0) 133 return; 134 if ((fp->f_flag & FSOCKET) == 0) { 135 u.u_error = ENOTSOCK; 136 return; 137 } 138 s = splnet(); 139 so = fp->f_socket; 140 if ((so->so_state & SS_NBIO) && 141 (so->so_state & SS_CONNAWAITING) == 0) { 142 u.u_error = EWOULDBLOCK; 143 splx(s); 144 return; 145 } 146 while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) { 147 if (so->so_state & SS_CANTRCVMORE) { 148 so->so_error = ECONNABORTED; 149 break; 150 } 151 sleep((caddr_t)&so->so_timeo, PZERO+1); 152 } 153 if (so->so_error) { 154 u.u_error = so->so_error; 155 splx(s); 156 return; 157 } 158 u.u_error = soaccept(so, &sa); 159 if (u.u_error) { 160 splx(s); 161 return; 162 } 163 if (uap->asa) 164 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 165 /* deal with new file descriptor case */ 166 /* u.u_r.r_val1 = ... */ 167 splx(s); 168 } 169 170 /* 171 * Connect socket to foreign peer; system call 172 * interface. Copy sa arguments and call internal routine. 173 */ 174 sconnect() 175 { 176 register struct a { 177 int fdes; 178 struct sockaddr *a; 179 } *uap = (struct a *)u.u_ap; 180 struct sockaddr sa; 181 register struct file *fp; 182 register struct socket *so; 183 int s; 184 185 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) { 186 u.u_error = EFAULT; 187 return; 188 } 189 fp = getf(uap->fdes); 190 if (fp == 0) 191 return; 192 if ((fp->f_flag & FSOCKET) == 0) { 193 u.u_error = ENOTSOCK; 194 return; 195 } 196 so = fp->f_socket; 197 u.u_error = soconnect(so, &sa); 198 if (u.u_error) 199 return; 200 s = splnet(); 201 if ((so->so_state & SS_NBIO) && 202 (so->so_state & SS_ISCONNECTING)) { 203 u.u_error = EINPROGRESS; 204 splx(s); 205 return; 206 } 207 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 208 sleep((caddr_t)&so->so_timeo, PZERO+1); 209 u.u_error = so->so_error; 210 so->so_error = 0; 211 splx(s); 212 } 213 214 /* 215 * Send data on socket. 216 */ 217 ssend() 218 { 219 register struct a { 220 int fdes; 221 struct sockaddr *asa; 222 caddr_t cbuf; 223 unsigned count; 224 } *uap = (struct a *)u.u_ap; 225 register struct file *fp; 226 struct sockaddr sa; 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 261 fp = getf(uap->fdes); 262 if (fp == 0) 263 return; 264 if ((fp->f_flag & FSOCKET) == 0) { 265 u.u_error = ENOTSOCK; 266 return; 267 } 268 u.u_base = uap->cbuf; 269 u.u_count = uap->count; 270 u.u_segflg = 0; 271 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || 272 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { 273 u.u_error = EFAULT; 274 return; 275 } 276 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0); 277 if (u.u_error) 278 return; 279 if (uap->asa) 280 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); 281 u.u_r.r_val1 = uap->count - u.u_count; 282 } 283 284 /* 285 * Get socket address. 286 */ 287 ssocketaddr() 288 { 289 register struct a { 290 int fdes; 291 struct sockaddr *asa; 292 } *uap = (struct a *)u.u_ap; 293 register struct file *fp; 294 register struct socket *so; 295 struct sockaddr addr; 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 so = fp->f_socket; 305 u.u_error = 306 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr); 307 if (u.u_error) 308 return; 309 if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr))) 310 u.u_error = EFAULT; 311 } 312