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