1 /* uipc_socket.c 4.1 81/11/07 */ 2 3 #include "../h/param.h" 4 #include "../h/dir.h" 5 #include "../h/user.h" 6 #include "file.h" 7 #include "../h/inode.h" 8 #include "../h/mbuf.h" 9 #include "protocol.h" 10 #include "protocolsw.h" 11 #include "socket.h" 12 #include "socketvar.h" 13 14 struct socket zerosocket; 15 struct in_addr zeroin_addr; 16 17 /* 18 * Socket system call interface. Copy in arguments 19 * set up file descriptor and call internal socket 20 * creation routine. 21 */ 22 ssocket() 23 { 24 register struct a { 25 int type; 26 in_addr *ain; 27 int flags; 28 } *uap = (struct a *)u.u_ap; 29 in_addr in; 30 struct socket *so0; 31 register struct socket *so; 32 register struct file *fp; 33 34 if ((fp = falloc()) == NULL) 35 return; 36 fp->f_flag = FSOCKET|FREAD|FWRITE; 37 if (copyin((caddr_t)uap->ain, &in, sizeof (in))) { 38 u.u_error = EFAULT; 39 return; 40 } 41 u.u_error = socket(&so0, a->type, &in, a->flags); 42 if (u.u_error) 43 goto bad; 44 fp->f_socket = so; 45 return; 46 bad: 47 u.u_ofile[u.u_r.r_val1] = 0; 48 fp->f_count = 0; 49 } 50 51 /* 52 * Create a socket. 53 */ 54 socket(aso, type, iap, flags) 55 struct socket **aso; 56 int type; 57 register struct in_addr *iap; 58 int flags; 59 { 60 register struct protosw *prp; 61 register struct socket *so; 62 struct mbuf *m; 63 int pf, proto; 64 65 /* 66 * Pin down protocol if possible. 67 * If no address specified, use a generic protocol. 68 */ 69 if (iap == 0) { 70 pf = PF_GENERIC; 71 proto = 0; 72 } else { 73 pf = iap->ia_pf; 74 proto = iap->ia_proto; 75 } 76 if (proto) { 77 /* 78 * A specific protocol was requested. Look 79 * for the protocol. If not found, then we 80 * don't support it. 81 */ 82 prp = pf_findproto(pf, proto); 83 if (prp == 0) 84 return (EPROTONOTSUPP); 85 } else { 86 /* 87 * No specific protocol was requested. Look 88 * in the specified (or generic) protocol set 89 * for a protocol of this type. 90 */ 91 prp = pf_findtype(pf, type); 92 if (prp == 0) 93 return (ESOCKTYPENOTSUPP); 94 } 95 96 /* 97 * Get a socket structure. 98 */ 99 m = m_get(M_WAIT); 100 if (m == 0) 101 return (ENOBUFS); 102 m->m_off = MMINOFF; 103 so = mtod(m, struct socket *); 104 *so = zerosocket; 105 so->so_flags = flags; 106 107 /* 108 * An early call to protocol initialization. If protocol 109 * actually hasn't been decided on yet (till we know 110 * peer), then the generic protocol allocated so far can 111 * just make sure a reasonable amount of resources will 112 * be available to it (say by allocating liberally now 113 * and returning some of the resources later). 114 */ 115 so->so_proto = prp; 116 (*prp->pr_usrreq)(so, PRU_ATTACH, 0, 0); 117 if (so->so_error) { 118 m_free(dtom(so)); 119 return (u.u_error); 120 } 121 *aso = so; 122 return (0); 123 } 124 125 /* 126 * Connect socket to foreign peer; system call 127 * interface. Copy in arguments and call internal routine. 128 */ 129 sconnect() 130 { 131 register struct a { 132 int fdes; 133 in_addr *a; 134 } *uap = (struct a *)u.u_ap; 135 in_addr in; 136 137 if (copyin((caddr_t)uap->aaddr, &in, sizeof (in))) { 138 u.u_error = EFAULT; 139 return; 140 } 141 fp = getf(uap->fdes); 142 if (fp == 0) 143 return; 144 if ((fp->f_flag & FSOCKET) == 0) { 145 u.u_error = ENOTSOCK; 146 return; 147 } 148 u.u_error = connect(fp->f_socket, &in); 149 if (u.u_error) 150 return; 151 s = splnet(); 152 for (;;) { 153 /* should use tsleep here */ 154 if ((*so->so_proto->pr_usrreq)(so, PRU_ISCONN, 0, &in) == 0) 155 break; 156 sleep((caddr_t)&so->so_timeo, PZERO+1); 157 } 158 splx(s); 159 } 160 161 connect(so, iap) 162 struct socket *so; 163 struct in_addr *iap; 164 { 165 166 return ((*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, &in)); 167 } 168 169 /* 170 * Disconnect socket from foreign peer; system call 171 * interface. Copy in arguments and call internal routine. 172 */ 173 sdisconnect() 174 { 175 register struct a { 176 int fdes; 177 in_addr *a; 178 } *uap = (struct a *)u.u_ap; 179 in_addr in; 180 181 if (uap->a && copyin((caddr_t)uap->aaddr, &in, sizeof (in))) { 182 u.u_error = EFAULT; 183 return; 184 } 185 fp = getf(uap->fdes); 186 if (fp == 0) 187 return; 188 if ((fp->f_flag & FSOCKET) == 0) { 189 u.u_error = ENOTSOCK; 190 return; 191 } 192 disconnect(fp->f_socket, uap->a ? &in : 0); 193 } 194 195 disconnect(so, iap) 196 struct socket *so; 197 struct in_addr *iap; 198 { 199 200 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, &in); 201 } 202 203 /* 204 * Send data on socket. 205 */ 206 ssend() 207 { 208 register struct a { 209 int fdes; 210 in_addr *ain; 211 caddr_t cbuf; 212 int count; 213 } *uap = (struct a *)u.u_ap; 214 215 fp = getf(uap->fdes); 216 if (fp == 0) 217 return; 218 if ((fp->f_flag & FSOCKET) == 0) { 219 u.u_error = ENOTSOCK; 220 return; 221 } 222 if (uap->count < 0) { 223 u.u_error = EINVAL; 224 return; 225 } 226 u.u_base = uap->buf; 227 u.u_count = uap->len; 228 u.u_segflg = 0; 229 if (useracc(u.u_base, u.u_count, B_READ) == 0 || 230 uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 231 u.u_error = EFAULT; 232 return; 233 } 234 u.u_error = send(fp->f_socket, uap->ain ? &in : 0); 235 } 236 237 send(so, iap) 238 register struct socket *so; 239 struct in_addr *iap; 240 { 241 register struct mbuf *m, **mp; 242 struct mbuf *top; 243 int error = 0; 244 245 if (so->so_proto->pr_flags & PR_ATOMIC) { 246 if (u.u_count > so->so_snd.sb_hiwat) { 247 error = EMSGSIZE; 248 goto release; 249 } 250 } 251 again: 252 while (so->so_snd.sb_flags & SB_LOCK) { 253 so->so_snd.sb_flags |= SB_WANT; 254 sleep((caddr_t)&so->so_snd.sb_flags, PZERO+1); 255 } 256 if (so->so_snd.sb_hiwat - so->so_snd.sb_cc < u.u_count) { 257 so->so_snd.sb_flags |= SB_WAIT; 258 sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1); 259 goto again; 260 } 261 so->so_snd.sb_flags |= SB_LOCK; 262 while (u.u_count > 0) { 263 bufs = so->so_snd.sb_mbmax - so->so_snd.sb_mbcnt; 264 while (bufs == 0) { 265 so->so_snd.sb_flags |= SB_WAIT; 266 sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1); 267 } 268 mp = ⊤ 269 top = 0; 270 while (--bufs >= 0 && u.u_count > 0) { 271 MGET(m, 1); 272 if (m == NULL) { 273 error = ENOBUFS; 274 m_freem(top); 275 goto release; 276 } 277 if (u.u_count >= PGSIZE && bufs >= NMBPG) { 278 MPGET(p, 1); 279 if (p == 0) 280 goto nopage; 281 m->m_off = (int)p - (int)m; 282 len = PGSIZE; 283 } else { 284 nopages: 285 m->m_off = MMINOFF; 286 len = MIN(MLEN, u.u_count); 287 } 288 iomove(mtod(m, caddr_t), len, B_WRITE); 289 m->m_len = len; 290 *mp = m; 291 mp = &m->m_next; 292 } 293 s = splnet(); 294 error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, iap); 295 splx(s); 296 if (error) 297 break; 298 } 299 release: 300 so->so_snd.sb_flags &= ~SB_LOCK; 301 if (so->so_snd.sb_flags & SB_WANT) 302 wakeup((caddr_t)&so->so_sb.sb_flags); 303 return (error); 304 } 305 306 /* 307 * Receive data on socket. 308 */ 309 sreceive() 310 { 311 register struct a { 312 int fdes; 313 in_addr *ain; 314 caddr_t cbuf; 315 int count; 316 } *uap = (struct a *)u.u_ap; 317 318 fp = getf(uap->fdes); 319 if (fp == 0) 320 return; 321 if ((fp->f_flag & FSOCKET) == 0) { 322 u.u_error = ENOTSOCK; 323 return; 324 } 325 if (uap->count < 0) { 326 u.u_error = EINVAL; 327 return; 328 } 329 u.u_base = uap->buf; 330 u.u_count = uap->len; 331 u.u_segflg = 0; 332 if (useracc(u.u_base, u.u_count, B_WRITE) == 0 || 333 uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) { 334 u.u_error = EFAULT; 335 return; 336 } 337 receive(fp->f_socket, uap->ain ? &in : 0); 338 } 339 340 receive(so, iap) 341 register struct socket *so; 342 struct in_addr *iap; 343 { 344 register struct mbuf *m, *n; 345 register int eor, len, s; 346 347 again: 348 while (so->so_rcv.sb_flags & SB_LOCK) { 349 so->so_rcv.sb_flags |= SB_WANT; 350 sleep((caddr_t)&so->so_rcv.sb_flags, PZERO+1); 351 } 352 if (so->so_rcv.sb_cc == 0) { 353 if ((so->so_proto->pr_usrreq)(so, PR_ISDISCONN, 0, 0) == 0) 354 return; 355 so->so_rcv.sb_flags |= SB_WAIT; 356 sleep((caddr_t)&so->so_rcv.sb_cc, PZERO+1); 357 goto again; 358 } 359 so->so_rcv.sb_flags |= SB_LOCK; 360 m = up->uc_rcv.sb_mb; 361 if (m == 0) 362 panic("receive"); 363 eor = 0; 364 do { 365 len = MIN(m->m_len, u.u_count); 366 if (len == m->m_len) { 367 eor = (int)m->m_act; 368 up->uc_rcv.sb_mb = m->m_next; 369 up->uc_rcv.sb_cc -= len; 370 if (up->uc_rcv.sb_cc < 0) 371 panic("receive 2"); 372 } 373 splx(s); 374 iomove(mtod(m, caddr_t), len, B_READ); 375 s = splnet(); 376 if (len == m->m_len) { 377 MFREE(m, n); 378 } else { 379 m->m_off += len; 380 m->m_len -= len; 381 up->uc_rcv.sb_cc -= len; 382 if (up->uc_rcv.sb_cc < 0) 383 panic("receive 3"); 384 } 385 } while ((m = up->uc_rcv.sb_mb) && u.u_count && !eor); 386 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 387 do { 388 m = so->so_rcv.sb_mb; 389 if (m == 0) 390 panic("receive 4"); 391 up->uc_rcv.sb_cc -= m->m_len; 392 if (up->uc_rcv.sb_cc < 0) 393 panic("receive 5"); 394 eor = (int)m->m_act; 395 so->so_rcv.sb_mb = m->m_next; 396 MFREE(m, n); 397 } while (eor == 0); 398 if (iap) 399 if ((so->so_proto->pr_flags & PR_PROVIDEADDR)) { 400 m = up->uc_rcv.sb_mb; 401 if (m == 0) 402 panic("receive 6"); 403 up->uc_rcv.sb_mb = m->m_next; 404 up->uc_rcv.sb_cc -= m->m_len; 405 len = MIN(m->m_len, sizeof (struct in_addr)); 406 bcopy(mtod(m, caddr_t), (caddr_t)iap, len); 407 } else 408 *iap = zeroin_addr; 409 (*so->so_proto->pr_usrreq)(up, PRU_RCVD, m, 0); 410 } 411 412 skioctl() 413 { 414 415 /* switch out based on socket type */ 416 } 417