1*4829Swnj /* uipc_socket.c 4.2 81/11/08 */ 24786Swnj 34786Swnj #include "../h/param.h" 4*4829Swnj #include "../h/systm.h" 54786Swnj #include "../h/dir.h" 64786Swnj #include "../h/user.h" 7*4829Swnj #include "../h/proc.h" 8*4829Swnj #include "../h/file.h" 94786Swnj #include "../h/inode.h" 10*4829Swnj #include "../h/buf.h" 114786Swnj #include "../h/mbuf.h" 12*4829Swnj #include "../h/protocol.h" 13*4829Swnj #include "../h/protosw.h" 14*4829Swnj #include "../h/socket.h" 15*4829Swnj #include "../h/socketvar.h" 16*4829Swnj #include "../h/inaddr.h" 17*4829Swnj #include "../net/inet.h" 18*4829Swnj #include "../net/inet_systm.h" 194786Swnj 204786Swnj struct socket zerosocket; 214786Swnj struct in_addr zeroin_addr; 224786Swnj 234786Swnj /* 244786Swnj * Socket system call interface. Copy in arguments 254786Swnj * set up file descriptor and call internal socket 264786Swnj * creation routine. 274786Swnj */ 284786Swnj ssocket() 294786Swnj { 304786Swnj register struct a { 31*4829Swnj int type; 32*4829Swnj struct in_addr *ain; 33*4829Swnj int options; 344786Swnj } *uap = (struct a *)u.u_ap; 35*4829Swnj struct in_addr in; 364786Swnj struct socket *so0; 374786Swnj register struct socket *so; 384786Swnj register struct file *fp; 394786Swnj 404786Swnj if ((fp = falloc()) == NULL) 414786Swnj return; 424786Swnj fp->f_flag = FSOCKET|FREAD|FWRITE; 434786Swnj if (copyin((caddr_t)uap->ain, &in, sizeof (in))) { 444786Swnj u.u_error = EFAULT; 454786Swnj return; 464786Swnj } 47*4829Swnj u.u_error = socket(&so0, uap->type, &in, uap->options); 484786Swnj if (u.u_error) 494786Swnj goto bad; 504786Swnj fp->f_socket = so; 514786Swnj return; 524786Swnj bad: 534786Swnj u.u_ofile[u.u_r.r_val1] = 0; 544786Swnj fp->f_count = 0; 554786Swnj } 564786Swnj 574786Swnj /* 584786Swnj * Create a socket. 594786Swnj */ 60*4829Swnj socket(aso, type, iap, options) 614786Swnj struct socket **aso; 624786Swnj int type; 634786Swnj register struct in_addr *iap; 64*4829Swnj int options; 654786Swnj { 664786Swnj register struct protosw *prp; 674786Swnj register struct socket *so; 684786Swnj struct mbuf *m; 694786Swnj int pf, proto; 704786Swnj 714786Swnj /* 724786Swnj * Pin down protocol if possible. 734786Swnj * If no address specified, use a generic protocol. 744786Swnj */ 754786Swnj if (iap == 0) { 764786Swnj pf = PF_GENERIC; 774786Swnj proto = 0; 784786Swnj } else { 794786Swnj pf = iap->ia_pf; 804786Swnj proto = iap->ia_proto; 814786Swnj } 824786Swnj if (proto) { 834786Swnj /* 844786Swnj * A specific protocol was requested. Look 854786Swnj * for the protocol. If not found, then we 864786Swnj * don't support it. 874786Swnj */ 884786Swnj prp = pf_findproto(pf, proto); 894786Swnj if (prp == 0) 90*4829Swnj return (EPROTONOSUPPORT); 914786Swnj } else { 924786Swnj /* 934786Swnj * No specific protocol was requested. Look 944786Swnj * in the specified (or generic) protocol set 954786Swnj * for a protocol of this type. 964786Swnj */ 974786Swnj prp = pf_findtype(pf, type); 984786Swnj if (prp == 0) 99*4829Swnj return (pf == PF_GENERIC ? 100*4829Swnj ESOCKTNOSUPPORT : EPROTONOSUPPORT); 1014786Swnj } 1024786Swnj 1034786Swnj /* 1044786Swnj * Get a socket structure. 1054786Swnj */ 1064786Swnj m = m_get(M_WAIT); 1074786Swnj if (m == 0) 1084786Swnj return (ENOBUFS); 1094786Swnj m->m_off = MMINOFF; 1104786Swnj so = mtod(m, struct socket *); 1114786Swnj *so = zerosocket; 112*4829Swnj so->so_options = options; 1134786Swnj 1144786Swnj /* 1154786Swnj * An early call to protocol initialization. If protocol 1164786Swnj * actually hasn't been decided on yet (till we know 1174786Swnj * peer), then the generic protocol allocated so far can 1184786Swnj * just make sure a reasonable amount of resources will 1194786Swnj * be available to it (say by allocating liberally now 1204786Swnj * and returning some of the resources later). 1214786Swnj */ 1224786Swnj so->so_proto = prp; 1234786Swnj (*prp->pr_usrreq)(so, PRU_ATTACH, 0, 0); 1244786Swnj if (so->so_error) { 1254786Swnj m_free(dtom(so)); 1264786Swnj return (u.u_error); 1274786Swnj } 1284786Swnj *aso = so; 1294786Swnj return (0); 1304786Swnj } 1314786Swnj 132*4829Swnj spipe() 133*4829Swnj { 134*4829Swnj 135*4829Swnj } 136*4829Swnj 137*4829Swnj skclose(so) 138*4829Swnj register struct socket *so; 139*4829Swnj { 140*4829Swnj 141*4829Swnj if (so->so_pcb) 142*4829Swnj (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 143*4829Swnj } 144*4829Swnj 1454786Swnj /* 146*4829Swnj * Select a socket. 147*4829Swnj */ 148*4829Swnj soselect(so, flag) 149*4829Swnj register struct socket *so; 150*4829Swnj int flag; 151*4829Swnj { 152*4829Swnj register struct proc *p; 153*4829Swnj 154*4829Swnj if (so->so_rcv.sb_cc) 155*4829Swnj return (1); 156*4829Swnj if ((p = so->so_rcv.sb_sel) && p->p_wchan == (caddr_t)select) 157*4829Swnj so->so_rcv.sb_flags |= SB_COLL; 158*4829Swnj else 159*4829Swnj so->so_rcv.sb_sel = u.u_procp; 160*4829Swnj return (0); 161*4829Swnj } 162*4829Swnj 163*4829Swnj /* 164*4829Swnj * Wakeup read sleep/select'ers. 165*4829Swnj */ 166*4829Swnj sowakeup(so) 167*4829Swnj struct socket *so; 168*4829Swnj { 169*4829Swnj 170*4829Swnj if (so->so_rcv.sb_cc && so->so_rcv.sb_sel) { 171*4829Swnj selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL); 172*4829Swnj so->so_rcv.sb_sel = 0; 173*4829Swnj so->so_rcv.sb_flags &= ~SB_COLL; 174*4829Swnj } 175*4829Swnj if (so->so_rcv.sb_flags & SB_WAIT) { 176*4829Swnj so->so_rcv.sb_flags &= ~SB_WAIT; 177*4829Swnj wakeup((caddr_t)&so->so_rcv.sb_cc); 178*4829Swnj } 179*4829Swnj } 180*4829Swnj 181*4829Swnj /* 1824786Swnj * Connect socket to foreign peer; system call 1834786Swnj * interface. Copy in arguments and call internal routine. 1844786Swnj */ 1854786Swnj sconnect() 1864786Swnj { 1874786Swnj register struct a { 1884786Swnj int fdes; 189*4829Swnj struct in_addr *a; 1904786Swnj } *uap = (struct a *)u.u_ap; 1914786Swnj in_addr in; 192*4829Swnj register struct file *fp; 193*4829Swnj register struct socket *so; 194*4829Swnj int s; 1954786Swnj 196*4829Swnj if (copyin((caddr_t)uap->a, &in, sizeof (in))) { 1974786Swnj u.u_error = EFAULT; 1984786Swnj return; 1994786Swnj } 2004786Swnj fp = getf(uap->fdes); 2014786Swnj if (fp == 0) 2024786Swnj return; 2034786Swnj if ((fp->f_flag & FSOCKET) == 0) { 2044786Swnj u.u_error = ENOTSOCK; 2054786Swnj return; 2064786Swnj } 207*4829Swnj so = fp->f_socket; 208*4829Swnj u.u_error = connect(so, &in); 2094786Swnj if (u.u_error) 2104786Swnj return; 2114786Swnj s = splnet(); 2124786Swnj for (;;) { 2134786Swnj /* should use tsleep here */ 2144786Swnj if ((*so->so_proto->pr_usrreq)(so, PRU_ISCONN, 0, &in) == 0) 2154786Swnj break; 2164786Swnj sleep((caddr_t)&so->so_timeo, PZERO+1); 2174786Swnj } 2184786Swnj splx(s); 2194786Swnj } 2204786Swnj 2214786Swnj connect(so, iap) 2224786Swnj struct socket *so; 2234786Swnj struct in_addr *iap; 2244786Swnj { 2254786Swnj 226*4829Swnj return ((*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, iap)); 2274786Swnj } 2284786Swnj 2294786Swnj /* 2304786Swnj * Disconnect socket from foreign peer; system call 2314786Swnj * interface. Copy in arguments and call internal routine. 2324786Swnj */ 2334786Swnj sdisconnect() 2344786Swnj { 2354786Swnj register struct a { 236*4829Swnj int fdes; 237*4829Swnj in_addr *addr; 2384786Swnj } *uap = (struct a *)u.u_ap; 2394786Swnj in_addr in; 240*4829Swnj register struct file *fp; 2414786Swnj 242*4829Swnj if (uap->addr && 243*4829Swnj copyin((caddr_t)uap->addr, (caddr_t)&in, sizeof (in))) { 2444786Swnj u.u_error = EFAULT; 2454786Swnj return; 2464786Swnj } 2474786Swnj fp = getf(uap->fdes); 2484786Swnj if (fp == 0) 2494786Swnj return; 2504786Swnj if ((fp->f_flag & FSOCKET) == 0) { 2514786Swnj u.u_error = ENOTSOCK; 2524786Swnj return; 2534786Swnj } 254*4829Swnj disconnect(fp->f_socket, uap->addr ? &in : 0); 2554786Swnj } 2564786Swnj 2574786Swnj disconnect(so, iap) 2584786Swnj struct socket *so; 2594786Swnj struct in_addr *iap; 2604786Swnj { 2614786Swnj 262*4829Swnj u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, iap); 2634786Swnj } 2644786Swnj 2654786Swnj /* 2664786Swnj * Send data on socket. 2674786Swnj */ 2684786Swnj ssend() 2694786Swnj { 2704786Swnj register struct a { 271*4829Swnj int fdes; 272*4829Swnj in_addr *ain; 273*4829Swnj caddr_t cbuf; 274*4829Swnj int count; 2754786Swnj } *uap = (struct a *)u.u_ap; 276*4829Swnj register struct file *fp; 277*4829Swnj struct in_addr in; 2784786Swnj 2794786Swnj fp = getf(uap->fdes); 2804786Swnj if (fp == 0) 2814786Swnj return; 2824786Swnj if ((fp->f_flag & FSOCKET) == 0) { 2834786Swnj u.u_error = ENOTSOCK; 2844786Swnj return; 2854786Swnj } 2864786Swnj if (uap->count < 0) { 2874786Swnj u.u_error = EINVAL; 2884786Swnj return; 2894786Swnj } 290*4829Swnj u.u_base = uap->cbuf; 291*4829Swnj u.u_count = uap->count; 2924786Swnj u.u_segflg = 0; 2934786Swnj if (useracc(u.u_base, u.u_count, B_READ) == 0 || 2944786Swnj uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 2954786Swnj u.u_error = EFAULT; 2964786Swnj return; 2974786Swnj } 2984786Swnj u.u_error = send(fp->f_socket, uap->ain ? &in : 0); 2994786Swnj } 3004786Swnj 3014786Swnj send(so, iap) 3024786Swnj register struct socket *so; 3034786Swnj struct in_addr *iap; 3044786Swnj { 3054786Swnj register struct mbuf *m, **mp; 3064786Swnj struct mbuf *top; 3074786Swnj int error = 0; 3084786Swnj 3094786Swnj if (so->so_proto->pr_flags & PR_ATOMIC) { 3104786Swnj if (u.u_count > so->so_snd.sb_hiwat) { 3114786Swnj error = EMSGSIZE; 3124786Swnj goto release; 3134786Swnj } 3144786Swnj } 3154786Swnj again: 3164786Swnj while (so->so_snd.sb_flags & SB_LOCK) { 3174786Swnj so->so_snd.sb_flags |= SB_WANT; 3184786Swnj sleep((caddr_t)&so->so_snd.sb_flags, PZERO+1); 3194786Swnj } 3204786Swnj if (so->so_snd.sb_hiwat - so->so_snd.sb_cc < u.u_count) { 3214786Swnj so->so_snd.sb_flags |= SB_WAIT; 3224786Swnj sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1); 3234786Swnj goto again; 3244786Swnj } 3254786Swnj so->so_snd.sb_flags |= SB_LOCK; 3264786Swnj while (u.u_count > 0) { 327*4829Swnj register int bufs = so->so_snd.sb_mbmax - so->so_snd.sb_mbcnt; 3284786Swnj while (bufs == 0) { 3294786Swnj so->so_snd.sb_flags |= SB_WAIT; 3304786Swnj sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1); 3314786Swnj } 3324786Swnj mp = ⊤ 3334786Swnj top = 0; 3344786Swnj while (--bufs >= 0 && u.u_count > 0) { 335*4829Swnj register int len; 3364786Swnj MGET(m, 1); 3374786Swnj if (m == NULL) { 3384786Swnj error = ENOBUFS; 3394786Swnj m_freem(top); 3404786Swnj goto release; 3414786Swnj } 3424786Swnj if (u.u_count >= PGSIZE && bufs >= NMBPG) { 343*4829Swnj register struct mbuf *p; 3444786Swnj MPGET(p, 1); 3454786Swnj if (p == 0) 346*4829Swnj goto nopages; 3474786Swnj m->m_off = (int)p - (int)m; 3484786Swnj len = PGSIZE; 3494786Swnj } else { 3504786Swnj nopages: 3514786Swnj m->m_off = MMINOFF; 3524786Swnj len = MIN(MLEN, u.u_count); 3534786Swnj } 3544786Swnj iomove(mtod(m, caddr_t), len, B_WRITE); 3554786Swnj m->m_len = len; 3564786Swnj *mp = m; 3574786Swnj mp = &m->m_next; 3584786Swnj } 359*4829Swnj { register int s = splnet(); 360*4829Swnj error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, iap); 361*4829Swnj splx(s); } 3624786Swnj if (error) 3634786Swnj break; 3644786Swnj } 3654786Swnj release: 3664786Swnj so->so_snd.sb_flags &= ~SB_LOCK; 3674786Swnj if (so->so_snd.sb_flags & SB_WANT) 368*4829Swnj wakeup((caddr_t)&so->so_snd.sb_flags); 3694786Swnj return (error); 3704786Swnj } 3714786Swnj 3724786Swnj /* 3734786Swnj * Receive data on socket. 3744786Swnj */ 3754786Swnj sreceive() 3764786Swnj { 3774786Swnj register struct a { 378*4829Swnj int fdes; 379*4829Swnj in_addr *ain; 380*4829Swnj caddr_t cbuf; 381*4829Swnj int count; 3824786Swnj } *uap = (struct a *)u.u_ap; 383*4829Swnj register struct file *fp; 384*4829Swnj struct in_addr *in; 3854786Swnj 3864786Swnj fp = getf(uap->fdes); 3874786Swnj if (fp == 0) 3884786Swnj return; 3894786Swnj if ((fp->f_flag & FSOCKET) == 0) { 3904786Swnj u.u_error = ENOTSOCK; 3914786Swnj return; 3924786Swnj } 3934786Swnj if (uap->count < 0) { 3944786Swnj u.u_error = EINVAL; 3954786Swnj return; 3964786Swnj } 397*4829Swnj u.u_base = uap->cbuf; 398*4829Swnj u.u_count = uap->count; 3994786Swnj u.u_segflg = 0; 4004786Swnj if (useracc(u.u_base, u.u_count, B_WRITE) == 0 || 4014786Swnj uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 4024786Swnj u.u_error = EFAULT; 4034786Swnj return; 4044786Swnj } 4054786Swnj receive(fp->f_socket, uap->ain ? &in : 0); 4064786Swnj } 4074786Swnj 4084786Swnj receive(so, iap) 4094786Swnj register struct socket *so; 4104786Swnj struct in_addr *iap; 4114786Swnj { 4124786Swnj register struct mbuf *m, *n; 4134786Swnj register int eor, len, s; 4144786Swnj 4154786Swnj again: 4164786Swnj while (so->so_rcv.sb_flags & SB_LOCK) { 4174786Swnj so->so_rcv.sb_flags |= SB_WANT; 4184786Swnj sleep((caddr_t)&so->so_rcv.sb_flags, PZERO+1); 4194786Swnj } 4204786Swnj if (so->so_rcv.sb_cc == 0) { 421*4829Swnj if ((so->so_proto->pr_usrreq)(so, PRU_ISDISCONN, 0, 0) == 0) 4224786Swnj return; 4234786Swnj so->so_rcv.sb_flags |= SB_WAIT; 4244786Swnj sleep((caddr_t)&so->so_rcv.sb_cc, PZERO+1); 4254786Swnj goto again; 4264786Swnj } 4274786Swnj so->so_rcv.sb_flags |= SB_LOCK; 428*4829Swnj m = so->so_rcv.sb_mb; 4294786Swnj if (m == 0) 4304786Swnj panic("receive"); 4314786Swnj eor = 0; 4324786Swnj do { 4334786Swnj len = MIN(m->m_len, u.u_count); 4344786Swnj if (len == m->m_len) { 4354786Swnj eor = (int)m->m_act; 436*4829Swnj so->so_rcv.sb_mb = m->m_next; 437*4829Swnj so->so_rcv.sb_cc -= len; 438*4829Swnj if (so->so_rcv.sb_cc < 0) 4394786Swnj panic("receive 2"); 4404786Swnj } 4414786Swnj splx(s); 4424786Swnj iomove(mtod(m, caddr_t), len, B_READ); 4434786Swnj s = splnet(); 4444786Swnj if (len == m->m_len) { 4454786Swnj MFREE(m, n); 4464786Swnj } else { 4474786Swnj m->m_off += len; 4484786Swnj m->m_len -= len; 449*4829Swnj so->so_rcv.sb_cc -= len; 450*4829Swnj if (so->so_rcv.sb_cc < 0) 4514786Swnj panic("receive 3"); 4524786Swnj } 453*4829Swnj } while ((m = so->so_rcv.sb_mb) && u.u_count && !eor); 4544786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4554786Swnj do { 4564786Swnj m = so->so_rcv.sb_mb; 4574786Swnj if (m == 0) 4584786Swnj panic("receive 4"); 459*4829Swnj so->so_rcv.sb_cc -= m->m_len; 460*4829Swnj if (so->so_rcv.sb_cc < 0) 4614786Swnj panic("receive 5"); 4624786Swnj eor = (int)m->m_act; 4634786Swnj so->so_rcv.sb_mb = m->m_next; 4644786Swnj MFREE(m, n); 4654786Swnj } while (eor == 0); 4664786Swnj if (iap) 467*4829Swnj if ((so->so_proto->pr_flags & PR_ADDR)) { 468*4829Swnj m = so->so_rcv.sb_mb; 4694786Swnj if (m == 0) 4704786Swnj panic("receive 6"); 471*4829Swnj so->so_rcv.sb_mb = m->m_next; 472*4829Swnj so->so_rcv.sb_cc -= m->m_len; 4734786Swnj len = MIN(m->m_len, sizeof (struct in_addr)); 4744786Swnj bcopy(mtod(m, caddr_t), (caddr_t)iap, len); 4754786Swnj } else 4764786Swnj *iap = zeroin_addr; 477*4829Swnj (*so->so_proto->pr_usrreq)(so, PRU_RCVD, m, 0); 4784786Swnj } 4794786Swnj 480*4829Swnj skioctl(so, cmd, cmdp) 481*4829Swnj register struct socket *so; 482*4829Swnj int cmd; 483*4829Swnj register caddr_t cmdp; 4844786Swnj { 4854786Swnj 486*4829Swnj switch (cmdp) { 487*4829Swnj 488*4829Swnj } 489*4829Swnj switch (so->so_type) { 490*4829Swnj 491*4829Swnj case SOCK_STREAM: 492*4829Swnj break; 493*4829Swnj 494*4829Swnj case SOCK_DGRAM: 495*4829Swnj break; 496*4829Swnj 497*4829Swnj case SOCK_RDM: 498*4829Swnj break; 499*4829Swnj 500*4829Swnj case SOCK_RAW: 501*4829Swnj break; 502*4829Swnj 503*4829Swnj } 5044786Swnj } 505*4829Swnj 506*4829Swnj sostat(so) 507*4829Swnj struct socket *so; 508*4829Swnj { 509*4829Swnj 510*4829Swnj } 511*4829Swnj 512*4829Swnj /* 513*4829Swnj * Generic protocol handler. 514*4829Swnj */ 515*4829Swnj gen_usrreq() 516*4829Swnj { 517*4829Swnj 518*4829Swnj } 519