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