1 /* uipc_socket.c 4.4 81/11/15 */ 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 support routines. 22 * 23 * DEAL WITH INTERRUPT NOTIFICATION. 24 * DO NEWFD STUFF 25 */ 26 27 /* 28 * Create a socket. 29 */ 30 socket(aso, type, iap, options) 31 struct socket **aso; 32 int type; 33 register struct in_addr *iap; 34 int options; 35 { 36 register struct protosw *prp; 37 register struct socket *so; 38 struct mbuf *m; 39 int pf, proto, error; 40 41 /* 42 * Use process standard protocol/protocol family if none 43 * specified by address argument. 44 */ 45 if (iap == 0) { 46 pf = PF_INET; /* should be u.u_protof */ 47 proto = 0; 48 } else { 49 pf = iap->ia_pf; 50 proto = iap->ia_proto; 51 } 52 53 /* 54 * If protocol specified, look for it, otherwise 55 * for a protocol of the correct type in the right family. 56 */ 57 if (proto) 58 prp = pffindproto(pf, proto); 59 else 60 prp = pffindtype(pf, type); 61 if (prp == 0) 62 return (EPROTONOSUPPORT); 63 64 /* 65 * Get a socket structure. 66 */ 67 m = m_getclr(M_WAIT); 68 if (m == 0) 69 return (ENOBUFS); 70 so = mtod(m, struct socket *); 71 so->so_options = options; 72 73 /* 74 * Attach protocol to socket, initializing 75 * and reserving resources. 76 */ 77 so->so_proto = prp; 78 (*prp->pr_usrreq)(so, PRU_ATTACH, 0, 0); 79 if (so->so_error) { 80 error = so->so_error; 81 m_free(dtom(so)); 82 return (error); 83 } 84 *aso = so; 85 return (0); 86 } 87 88 /* 89 * Close a socket on last file table reference removal. 90 * Initiate disconnect if connected. 91 * Free socket when disconnect complete. 92 */ 93 soclose(so) 94 register struct socket *so; 95 { 96 int s = splnet(); /* conservative */ 97 98 if (so->so_pcb == 0) 99 goto discard; 100 if (so->so_state & SS_ISCONNECTED) { 101 if ((so->so_state & SS_ISDISCONNECTING) == 0) { 102 u.u_error = disconnect(so, 0); 103 if (u.u_error) { 104 splx(s); 105 return; 106 } 107 } 108 if ((so->so_state & SS_ISDISCONNECTING) && 109 (so->so_options & SO_NBIO)) { 110 u.u_error = EINPROGRESS; 111 splx(s); 112 return; 113 } 114 while (so->so_state & SS_ISCONNECTED) 115 sleep((caddr_t)&so->so_timeo, PZERO+1); 116 } 117 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); 118 discard: 119 if (so->so_pcb == 0) 120 sofree(so); 121 splx(s); 122 } 123 124 sostat(so, sb) 125 struct socket *so; 126 struct stat *sb; 127 { 128 129 return (EOPNOTSUPP); 130 } 131 132 /* 133 * Connect socket to a specified address. 134 * If already connected or connecting, then avoid 135 * the protocol entry, to keep its job simpler. 136 */ 137 connect(so, iap) 138 struct socket *so; 139 struct in_addr *iap; 140 { 141 int s = splnet(); 142 int error; 143 144 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 145 error = EISCONN; 146 goto bad; 147 } 148 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)iap); 149 bad: 150 splx(s); 151 return (error); 152 } 153 154 /* 155 * Disconnect from a socket. 156 * Address parameter is from system call for later multicast 157 * protocols. Check to make sure that connected and no disconnect 158 * in progress (for protocol's sake), and then invoke protocol. 159 */ 160 disconnect(so, iap) 161 struct socket *so; 162 struct in_addr *iap; 163 { 164 int s = splnet(); 165 int error; 166 167 if ((so->so_state & SS_ISCONNECTED) == 0) { 168 error = ENOTCONN; 169 goto bad; 170 } 171 if (so->so_state & SS_ISDISCONNECTING) { 172 error = EALREADY; 173 goto bad; 174 } 175 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, 0); 176 bad: 177 splx(s); 178 return (error); 179 } 180 181 /* 182 * Send on a socket. 183 * If send must go all at once and message is larger than 184 * send buffering, then hard error. 185 * Lock against other senders. 186 * If must go all at once and not enough room now, then 187 * inform user that this would block and do nothing. 188 */ 189 send(so, iap) 190 register struct socket *so; 191 struct in_addr *iap; 192 { 193 struct mbuf *top = 0; 194 register struct mbuf *m, **mp = ⊤ 195 register int bufs; 196 register int len; 197 int error = 0; 198 int s; 199 200 if (so->so_state & SS_CANTSENDMORE) 201 return (EPIPE); 202 if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) 203 return (EMSGSIZE); 204 if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_options & SO_NBIO)) 205 return (EWOULDBLOCK); 206 sblock(&so->so_snd); 207 #define snderr(errno) { error = errno; splx(s); goto release; } 208 209 s = splnet(); 210 again: 211 if ((so->so_state & SS_ISCONNECTED) == 0) { 212 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 213 snderr(ENOTCONN); 214 if (iap == 0) 215 snderr(EDESTADDRREQ); 216 } 217 if (so->so_error) 218 snderr(so->so_error); 219 if (top) { 220 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, iap); 221 if (error) { 222 splx(s); 223 goto release; 224 } 225 top = 0; 226 mp = ⊤ 227 } 228 if (sosendallatonce(so) && sbspace(&so->so_snd) < u.u_count) { 229 if (so->so_options & SO_NBIO) 230 snderr(EWOULDBLOCK); 231 sbunlock(&so->so_snd); 232 sbwait(&so->so_snd); 233 splx(s); 234 goto again; 235 } 236 splx(s); 237 while (u.u_count > 0 && sbspace(&so->so_snd) > 0) { 238 MGET(m, 1); 239 if (m == NULL) { 240 error = ENOBUFS; 241 m_freem(top); 242 goto release; 243 } 244 if (u.u_count >= PGSIZE && bufs >= NMBPG) { 245 register struct mbuf *p; 246 MPGET(p, 1); 247 if (p == 0) 248 goto nopages; 249 m->m_off = (int)p - (int)m; 250 len = PGSIZE; 251 } else { 252 nopages: 253 m->m_off = MMINOFF; 254 len = MIN(MLEN, u.u_count); 255 } 256 iomove(mtod(m, caddr_t), len, B_WRITE); 257 m->m_len = len; 258 *mp = m; 259 mp = &m->m_next; 260 } 261 s = splnet(); 262 goto again; 263 264 release: 265 sbunlock(&so->so_snd); 266 return (error); 267 } 268 269 receive(so, iap) 270 register struct socket *so; 271 struct in_addr *iap; 272 { 273 register struct mbuf *m, *n; 274 register int len; 275 int eor, s, error = 0; 276 277 restart: 278 sblock(&so->so_rcv); 279 s = splnet(); 280 281 #define rcverr(errno) { error = errno; splx(s); goto release; } 282 if (so->so_rcv.sb_cc == 0) { 283 if ((so->so_state & SS_ISCONNECTED) == 0 && 284 (so->so_proto->pr_flags & PR_CONNREQUIRED)) 285 rcverr(ENOTCONN); 286 if (so->so_state & SS_CANTRCVMORE) { 287 splx(s); 288 goto release; 289 } 290 if (so->so_options & SO_NBIO) 291 rcverr(EWOULDBLOCK); 292 sbunlock(&so->so_rcv); 293 sleep((caddr_t)&so->so_rcv.sb_cc, PZERO+1); 294 goto restart; 295 } 296 m = so->so_rcv.sb_mb; 297 if (m == 0) 298 panic("receive"); 299 300 /* 301 * Pull address off receive chain, if protocol 302 * put one there. 303 */ 304 if ((so->so_proto->pr_flags & PR_ADDR)) { 305 so->so_rcv.sb_mb = m->m_next; 306 if (iap) { 307 so->so_rcv.sb_cc -= m->m_len; 308 len = MIN(m->m_len, sizeof (struct in_addr)); 309 bcopy(mtod(m, caddr_t), (caddr_t)iap, len); 310 } else 311 bzero((caddr_t)iap, sizeof (*iap)); 312 m = so->so_rcv.sb_mb; 313 if (m == 0) 314 panic("receive 2"); 315 } 316 317 /* 318 * Next pull data off the chain. 319 * Stop at eor or when run out of space in user buffer. 320 */ 321 eor = 0; 322 do { 323 len = MIN(m->m_len, u.u_count); 324 if (len == m->m_len) { 325 eor = (int)m->m_act; 326 sbfree(&so->so_rcv, m); 327 } 328 splx(s); 329 iomove(mtod(m, caddr_t), len, B_READ); 330 s = splnet(); 331 if (len == m->m_len) { 332 MFREE(m, n); 333 } else { 334 m->m_off += len; 335 m->m_len -= len; 336 so->so_rcv.sb_cc -= len; 337 } 338 } while ((m = so->so_rcv.sb_mb) && u.u_count && !eor); 339 340 /* 341 * If atomic protocol discard rest of record. 342 */ 343 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 344 do { 345 if (m == 0) 346 panic("receive 3"); 347 sbfree(&so->so_rcv, m); 348 eor = (int)m->m_act; 349 so->so_rcv.sb_mb = m->m_next; 350 MFREE(m, n); 351 m = n; 352 } while (eor == 0); 353 354 /* 355 * If protocol cares, inform it that 356 * there is more space in the receive buffer. 357 */ 358 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 359 (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); 360 361 release: 362 sounlock(&so->so_rcv); 363 splx(s); 364 } 365 366 skioctl(so, cmd, cmdp) 367 register struct socket *so; 368 int cmd; 369 register caddr_t cmdp; 370 { 371 372 switch (cmdp) { 373 374 } 375 switch (so->so_type) { 376 377 case SOCK_STREAM: 378 break; 379 380 case SOCK_DGRAM: 381 break; 382 383 case SOCK_RDM: 384 break; 385 386 case SOCK_RAW: 387 break; 388 389 } 390 } 391