1 /* uipc_socket.c 4.2 81/11/08 */ 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 struct socket zerosocket; 21 struct in_addr zeroin_addr; 22 23 /* 24 * Socket system call interface. Copy in arguments 25 * set up file descriptor and call internal socket 26 * creation routine. 27 */ 28 ssocket() 29 { 30 register struct a { 31 int type; 32 struct in_addr *ain; 33 int options; 34 } *uap = (struct a *)u.u_ap; 35 struct in_addr in; 36 struct socket *so0; 37 register struct socket *so; 38 register struct file *fp; 39 40 if ((fp = falloc()) == NULL) 41 return; 42 fp->f_flag = FSOCKET|FREAD|FWRITE; 43 if (copyin((caddr_t)uap->ain, &in, sizeof (in))) { 44 u.u_error = EFAULT; 45 return; 46 } 47 u.u_error = socket(&so0, uap->type, &in, uap->options); 48 if (u.u_error) 49 goto bad; 50 fp->f_socket = so; 51 return; 52 bad: 53 u.u_ofile[u.u_r.r_val1] = 0; 54 fp->f_count = 0; 55 } 56 57 /* 58 * Create a socket. 59 */ 60 socket(aso, type, iap, options) 61 struct socket **aso; 62 int type; 63 register struct in_addr *iap; 64 int options; 65 { 66 register struct protosw *prp; 67 register struct socket *so; 68 struct mbuf *m; 69 int pf, proto; 70 71 /* 72 * Pin down protocol if possible. 73 * If no address specified, use a generic protocol. 74 */ 75 if (iap == 0) { 76 pf = PF_GENERIC; 77 proto = 0; 78 } else { 79 pf = iap->ia_pf; 80 proto = iap->ia_proto; 81 } 82 if (proto) { 83 /* 84 * A specific protocol was requested. Look 85 * for the protocol. If not found, then we 86 * don't support it. 87 */ 88 prp = pf_findproto(pf, proto); 89 if (prp == 0) 90 return (EPROTONOSUPPORT); 91 } else { 92 /* 93 * No specific protocol was requested. Look 94 * in the specified (or generic) protocol set 95 * for a protocol of this type. 96 */ 97 prp = pf_findtype(pf, type); 98 if (prp == 0) 99 return (pf == PF_GENERIC ? 100 ESOCKTNOSUPPORT : EPROTONOSUPPORT); 101 } 102 103 /* 104 * Get a socket structure. 105 */ 106 m = m_get(M_WAIT); 107 if (m == 0) 108 return (ENOBUFS); 109 m->m_off = MMINOFF; 110 so = mtod(m, struct socket *); 111 *so = zerosocket; 112 so->so_options = options; 113 114 /* 115 * An early call to protocol initialization. If protocol 116 * actually hasn't been decided on yet (till we know 117 * peer), then the generic protocol allocated so far can 118 * just make sure a reasonable amount of resources will 119 * be available to it (say by allocating liberally now 120 * and returning some of the resources later). 121 */ 122 so->so_proto = prp; 123 (*prp->pr_usrreq)(so, PRU_ATTACH, 0, 0); 124 if (so->so_error) { 125 m_free(dtom(so)); 126 return (u.u_error); 127 } 128 *aso = so; 129 return (0); 130 } 131 132 spipe() 133 { 134 135 } 136 137 skclose(so) 138 register struct socket *so; 139 { 140 141 if (so->so_pcb) 142 (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 143 } 144 145 /* 146 * Select a socket. 147 */ 148 soselect(so, flag) 149 register struct socket *so; 150 int flag; 151 { 152 register struct proc *p; 153 154 if (so->so_rcv.sb_cc) 155 return (1); 156 if ((p = so->so_rcv.sb_sel) && p->p_wchan == (caddr_t)select) 157 so->so_rcv.sb_flags |= SB_COLL; 158 else 159 so->so_rcv.sb_sel = u.u_procp; 160 return (0); 161 } 162 163 /* 164 * Wakeup read sleep/select'ers. 165 */ 166 sowakeup(so) 167 struct socket *so; 168 { 169 170 if (so->so_rcv.sb_cc && so->so_rcv.sb_sel) { 171 selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL); 172 so->so_rcv.sb_sel = 0; 173 so->so_rcv.sb_flags &= ~SB_COLL; 174 } 175 if (so->so_rcv.sb_flags & SB_WAIT) { 176 so->so_rcv.sb_flags &= ~SB_WAIT; 177 wakeup((caddr_t)&so->so_rcv.sb_cc); 178 } 179 } 180 181 /* 182 * Connect socket to foreign peer; system call 183 * interface. Copy in arguments and call internal routine. 184 */ 185 sconnect() 186 { 187 register struct a { 188 int fdes; 189 struct in_addr *a; 190 } *uap = (struct a *)u.u_ap; 191 in_addr in; 192 register struct file *fp; 193 register struct socket *so; 194 int s; 195 196 if (copyin((caddr_t)uap->a, &in, sizeof (in))) { 197 u.u_error = EFAULT; 198 return; 199 } 200 fp = getf(uap->fdes); 201 if (fp == 0) 202 return; 203 if ((fp->f_flag & FSOCKET) == 0) { 204 u.u_error = ENOTSOCK; 205 return; 206 } 207 so = fp->f_socket; 208 u.u_error = connect(so, &in); 209 if (u.u_error) 210 return; 211 s = splnet(); 212 for (;;) { 213 /* should use tsleep here */ 214 if ((*so->so_proto->pr_usrreq)(so, PRU_ISCONN, 0, &in) == 0) 215 break; 216 sleep((caddr_t)&so->so_timeo, PZERO+1); 217 } 218 splx(s); 219 } 220 221 connect(so, iap) 222 struct socket *so; 223 struct in_addr *iap; 224 { 225 226 return ((*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, iap)); 227 } 228 229 /* 230 * Disconnect socket from foreign peer; system call 231 * interface. Copy in arguments and call internal routine. 232 */ 233 sdisconnect() 234 { 235 register struct a { 236 int fdes; 237 in_addr *addr; 238 } *uap = (struct a *)u.u_ap; 239 in_addr in; 240 register struct file *fp; 241 242 if (uap->addr && 243 copyin((caddr_t)uap->addr, (caddr_t)&in, sizeof (in))) { 244 u.u_error = EFAULT; 245 return; 246 } 247 fp = getf(uap->fdes); 248 if (fp == 0) 249 return; 250 if ((fp->f_flag & FSOCKET) == 0) { 251 u.u_error = ENOTSOCK; 252 return; 253 } 254 disconnect(fp->f_socket, uap->addr ? &in : 0); 255 } 256 257 disconnect(so, iap) 258 struct socket *so; 259 struct in_addr *iap; 260 { 261 262 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, iap); 263 } 264 265 /* 266 * Send data on socket. 267 */ 268 ssend() 269 { 270 register struct a { 271 int fdes; 272 in_addr *ain; 273 caddr_t cbuf; 274 int count; 275 } *uap = (struct a *)u.u_ap; 276 register struct file *fp; 277 struct in_addr in; 278 279 fp = getf(uap->fdes); 280 if (fp == 0) 281 return; 282 if ((fp->f_flag & FSOCKET) == 0) { 283 u.u_error = ENOTSOCK; 284 return; 285 } 286 if (uap->count < 0) { 287 u.u_error = EINVAL; 288 return; 289 } 290 u.u_base = uap->cbuf; 291 u.u_count = uap->count; 292 u.u_segflg = 0; 293 if (useracc(u.u_base, u.u_count, B_READ) == 0 || 294 uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 295 u.u_error = EFAULT; 296 return; 297 } 298 u.u_error = send(fp->f_socket, uap->ain ? &in : 0); 299 } 300 301 send(so, iap) 302 register struct socket *so; 303 struct in_addr *iap; 304 { 305 register struct mbuf *m, **mp; 306 struct mbuf *top; 307 int error = 0; 308 309 if (so->so_proto->pr_flags & PR_ATOMIC) { 310 if (u.u_count > so->so_snd.sb_hiwat) { 311 error = EMSGSIZE; 312 goto release; 313 } 314 } 315 again: 316 while (so->so_snd.sb_flags & SB_LOCK) { 317 so->so_snd.sb_flags |= SB_WANT; 318 sleep((caddr_t)&so->so_snd.sb_flags, PZERO+1); 319 } 320 if (so->so_snd.sb_hiwat - so->so_snd.sb_cc < u.u_count) { 321 so->so_snd.sb_flags |= SB_WAIT; 322 sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1); 323 goto again; 324 } 325 so->so_snd.sb_flags |= SB_LOCK; 326 while (u.u_count > 0) { 327 register int bufs = so->so_snd.sb_mbmax - so->so_snd.sb_mbcnt; 328 while (bufs == 0) { 329 so->so_snd.sb_flags |= SB_WAIT; 330 sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1); 331 } 332 mp = ⊤ 333 top = 0; 334 while (--bufs >= 0 && u.u_count > 0) { 335 register int len; 336 MGET(m, 1); 337 if (m == NULL) { 338 error = ENOBUFS; 339 m_freem(top); 340 goto release; 341 } 342 if (u.u_count >= PGSIZE && bufs >= NMBPG) { 343 register struct mbuf *p; 344 MPGET(p, 1); 345 if (p == 0) 346 goto nopages; 347 m->m_off = (int)p - (int)m; 348 len = PGSIZE; 349 } else { 350 nopages: 351 m->m_off = MMINOFF; 352 len = MIN(MLEN, u.u_count); 353 } 354 iomove(mtod(m, caddr_t), len, B_WRITE); 355 m->m_len = len; 356 *mp = m; 357 mp = &m->m_next; 358 } 359 { register int s = splnet(); 360 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, iap); 361 splx(s); } 362 if (error) 363 break; 364 } 365 release: 366 so->so_snd.sb_flags &= ~SB_LOCK; 367 if (so->so_snd.sb_flags & SB_WANT) 368 wakeup((caddr_t)&so->so_snd.sb_flags); 369 return (error); 370 } 371 372 /* 373 * Receive data on socket. 374 */ 375 sreceive() 376 { 377 register struct a { 378 int fdes; 379 in_addr *ain; 380 caddr_t cbuf; 381 int count; 382 } *uap = (struct a *)u.u_ap; 383 register struct file *fp; 384 struct in_addr *in; 385 386 fp = getf(uap->fdes); 387 if (fp == 0) 388 return; 389 if ((fp->f_flag & FSOCKET) == 0) { 390 u.u_error = ENOTSOCK; 391 return; 392 } 393 if (uap->count < 0) { 394 u.u_error = EINVAL; 395 return; 396 } 397 u.u_base = uap->cbuf; 398 u.u_count = uap->count; 399 u.u_segflg = 0; 400 if (useracc(u.u_base, u.u_count, B_WRITE) == 0 || 401 uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 402 u.u_error = EFAULT; 403 return; 404 } 405 receive(fp->f_socket, uap->ain ? &in : 0); 406 } 407 408 receive(so, iap) 409 register struct socket *so; 410 struct in_addr *iap; 411 { 412 register struct mbuf *m, *n; 413 register int eor, len, s; 414 415 again: 416 while (so->so_rcv.sb_flags & SB_LOCK) { 417 so->so_rcv.sb_flags |= SB_WANT; 418 sleep((caddr_t)&so->so_rcv.sb_flags, PZERO+1); 419 } 420 if (so->so_rcv.sb_cc == 0) { 421 if ((so->so_proto->pr_usrreq)(so, PRU_ISDISCONN, 0, 0) == 0) 422 return; 423 so->so_rcv.sb_flags |= SB_WAIT; 424 sleep((caddr_t)&so->so_rcv.sb_cc, PZERO+1); 425 goto again; 426 } 427 so->so_rcv.sb_flags |= SB_LOCK; 428 m = so->so_rcv.sb_mb; 429 if (m == 0) 430 panic("receive"); 431 eor = 0; 432 do { 433 len = MIN(m->m_len, u.u_count); 434 if (len == m->m_len) { 435 eor = (int)m->m_act; 436 so->so_rcv.sb_mb = m->m_next; 437 so->so_rcv.sb_cc -= len; 438 if (so->so_rcv.sb_cc < 0) 439 panic("receive 2"); 440 } 441 splx(s); 442 iomove(mtod(m, caddr_t), len, B_READ); 443 s = splnet(); 444 if (len == m->m_len) { 445 MFREE(m, n); 446 } else { 447 m->m_off += len; 448 m->m_len -= len; 449 so->so_rcv.sb_cc -= len; 450 if (so->so_rcv.sb_cc < 0) 451 panic("receive 3"); 452 } 453 } while ((m = so->so_rcv.sb_mb) && u.u_count && !eor); 454 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 455 do { 456 m = so->so_rcv.sb_mb; 457 if (m == 0) 458 panic("receive 4"); 459 so->so_rcv.sb_cc -= m->m_len; 460 if (so->so_rcv.sb_cc < 0) 461 panic("receive 5"); 462 eor = (int)m->m_act; 463 so->so_rcv.sb_mb = m->m_next; 464 MFREE(m, n); 465 } while (eor == 0); 466 if (iap) 467 if ((so->so_proto->pr_flags & PR_ADDR)) { 468 m = so->so_rcv.sb_mb; 469 if (m == 0) 470 panic("receive 6"); 471 so->so_rcv.sb_mb = m->m_next; 472 so->so_rcv.sb_cc -= m->m_len; 473 len = MIN(m->m_len, sizeof (struct in_addr)); 474 bcopy(mtod(m, caddr_t), (caddr_t)iap, len); 475 } else 476 *iap = zeroin_addr; 477 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, m, 0); 478 } 479 480 skioctl(so, cmd, cmdp) 481 register struct socket *so; 482 int cmd; 483 register caddr_t cmdp; 484 { 485 486 switch (cmdp) { 487 488 } 489 switch (so->so_type) { 490 491 case SOCK_STREAM: 492 break; 493 494 case SOCK_DGRAM: 495 break; 496 497 case SOCK_RDM: 498 break; 499 500 case SOCK_RAW: 501 break; 502 503 } 504 } 505 506 sostat(so) 507 struct socket *so; 508 { 509 510 } 511 512 /* 513 * Generic protocol handler. 514 */ 515 gen_usrreq() 516 { 517 518 } 519