xref: /csrg-svn/sys/kern/uipc_socket.c (revision 8594)
1 /*	uipc_socket.c	4.56	82/10/17	*/
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/protosw.h"
13 #include "../h/socket.h"
14 #include "../h/socketvar.h"
15 #include "../h/stat.h"
16 #include "../h/ioctl.h"
17 #include "../h/uio.h"
18 #include "../net/route.h"
19 
20 /*
21  * Socket operation routines.
22  * These routines are called by the routines in
23  * sys_socket.c or from a system process, and
24  * implement the semantics of socket operations by
25  * switching out to the protocol specific routines.
26  */
27 
28 /*ARGSUSED*/
29 socreate(dom, aso, type, proto, opt)
30 	struct socket **aso;
31 	int type, proto;
32 	struct socketopt *opt;
33 {
34 	register struct protosw *prp;
35 	register struct socket *so;
36 	struct mbuf *m;
37 	int pf, error;
38 
39 	pf = dom ? PF_UNIX : PF_INET;		/* should be u.u_protof */
40 	if (proto)
41 		prp = pffindproto(pf, proto);
42 	else
43 		prp = pffindtype(pf, type);
44 	if (prp == 0)
45 		return (EPROTONOSUPPORT);
46 	if (prp->pr_type != type)
47 		return (EPROTOTYPE);
48 	m = m_getclr(M_WAIT);
49 	if (m == 0)
50 		return (ENOBUFS);
51 	so = mtod(m, struct socket *);
52 	so->so_options = 0;
53 	so->so_state = 0;
54 	if (u.u_uid == 0)
55 		so->so_state = SS_PRIV;
56 	so->so_proto = prp;
57 	error = (*prp->pr_usrreq)(so, PRU_ATTACH,
58 	    (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
59 	if (error) {
60 		so->so_state |= SS_NOFDREF;
61 		sofree(so);
62 		return (error);
63 	}
64 	*aso = so;
65 	return (0);
66 }
67 
68 sobind(so, nam, opt)
69 	struct socket *so;
70 	struct mbuf *nam;
71 	struct socketopt *opt;
72 {
73 	int s = splnet();
74 	int error;
75 
76 	error =
77 	    (*so->so_proto->pr_usrreq)(so, PRU_BIND,
78 		(struct mbuf *)0, nam, opt);
79 	splx(s);
80 	return (error);
81 }
82 
83 solisten(so, backlog)
84 	struct socket *so;
85 	int backlog;
86 {
87 	int s = splnet();
88 	int error;
89 
90 	error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
91 	    (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
92 	if (error) {
93 		splx(s);
94 		return (error);
95 	}
96 	if (so->so_q == 0) {
97 		so->so_q = so;
98 		so->so_q0 = so;
99 		so->so_options |= SO_ACCEPTCONN;
100 	}
101 	if (backlog < 0)
102 		backlog = 0;
103 	so->so_qlimit = backlog < 5 ? backlog : 5;
104 	so->so_options |= SO_NEWFDONCONN;
105 	return (0);
106 }
107 
108 sofree(so)
109 	struct socket *so;
110 {
111 
112 	if (so->so_head) {
113 		if (!soqremque(so, 0) && !soqremque(so, 1))
114 			panic("sofree dq");
115 		so->so_head = 0;
116 	}
117 	if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
118 		return;
119 	sbrelease(&so->so_snd);
120 	sbrelease(&so->so_rcv);
121 	(void) m_free(dtom(so));
122 }
123 
124 /*
125  * Close a socket on last file table reference removal.
126  * Initiate disconnect if connected.
127  * Free socket when disconnect complete.
128  */
129 soclose(so, exiting)
130 	register struct socket *so;
131 	int exiting;
132 {
133 	int s = splnet();		/* conservative */
134 
135 	if (so->so_options & SO_ACCEPTCONN) {
136 		while (so->so_q0 != so)
137 			soclose(so->so_q0, 1);
138 		while (so->so_q != so)
139 			soclose(so->so_q, 1);
140 	}
141 	if (so->so_pcb == 0)
142 		goto discard;
143 	if (exiting)
144 		so->so_options |= SO_KEEPALIVE;
145 	if (so->so_state & SS_ISCONNECTED) {
146 		if ((so->so_state & SS_ISDISCONNECTING) == 0) {
147 			u.u_error = sodisconnect(so, (struct sockaddr *)0);
148 			if (u.u_error) {
149 				if (exiting)
150 					goto drop;
151 				splx(s);
152 				return;
153 			}
154 		}
155 		if ((so->so_options & SO_DONTLINGER) == 0) {
156 			if ((so->so_state & SS_ISDISCONNECTING) &&
157 			    (so->so_state & SS_NBIO) &&
158 			    exiting == 0) {
159 				u.u_error = EINPROGRESS;
160 				splx(s);
161 				return;
162 			}
163 			/* should use tsleep here, for at most linger */
164 			while (so->so_state & SS_ISCONNECTED)
165 				sleep((caddr_t)&so->so_timeo, PZERO+1);
166 		}
167 	}
168 drop:
169 	if (so->so_pcb) {
170 		u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
171 		    (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
172 		if (exiting == 0 && u.u_error) {
173 			splx(s);
174 			return;
175 		}
176 	}
177 discard:
178 	so->so_state |= SS_NOFDREF;
179 	sofree(so);
180 	splx(s);
181 }
182 
183 /*ARGSUSED*/
184 sostat(so, sb)
185 	struct socket *so;
186 	struct stat *sb;
187 {
188 
189 	bzero((caddr_t)sb, sizeof (*sb));		/* XXX */
190 	return (0);					/* XXX */
191 }
192 
193 soaccept(so, nam, opt)
194 	struct socket *so;
195 	struct mbuf *nam;
196 	struct socketopt *opt;
197 {
198 	int s = splnet();
199 	int error;
200 
201 	error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
202 	    (struct mbuf *)0, nam, opt);
203 	splx(s);
204 	return (error);
205 }
206 
207 soconnect(so, nam, opt)
208 	struct socket *so;
209 	struct mbuf *nam;
210 	struct socketopt *opt;
211 {
212 	int s = splnet();
213 	int error;
214 
215 	if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
216 		error = EISCONN;
217 		goto bad;
218 	}
219 	error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
220 	    (struct mbuf *)0, nam, opt);
221 bad:
222 	splx(s);
223 	return (error);
224 }
225 
226 sodisconnect(so, nam)
227 	struct socket *so;
228 	struct mbuf *nam;
229 {
230 	int s = splnet();
231 	int error;
232 
233 	if ((so->so_state & SS_ISCONNECTED) == 0) {
234 		error = ENOTCONN;
235 		goto bad;
236 	}
237 	if (so->so_state & SS_ISDISCONNECTING) {
238 		error = EALREADY;
239 		goto bad;
240 	}
241 	error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
242 	    (struct mbuf *)0, nam, (struct socketopt *)0);
243 bad:
244 	splx(s);
245 	return (error);
246 }
247 
248 /*
249  * Send on a socket.
250  * If send must go all at once and message is larger than
251  * send buffering, then hard error.
252  * Lock against other senders.
253  * If must go all at once and not enough room now, then
254  * inform user that this would block and do nothing.
255  */
256 sosend(so, nam, uio, flags)
257 	register struct socket *so;
258 	struct mbuf *nam;
259 	struct uio *uio;
260 	int flags;
261 {
262 	struct mbuf *top = 0;
263 	register struct mbuf *m, **mp = &top;
264 	register u_int len;
265 	int error = 0, space, s;
266 
267 	if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
268 		return (EMSGSIZE);
269 restart:
270 	sblock(&so->so_snd);
271 #define	snderr(errno)	{ error = errno; splx(s); goto release; }
272 
273 	u.u_ru.ru_msgsnd++;
274 again:
275 	s = splnet();
276 	if (so->so_state & SS_CANTSENDMORE) {
277 		psignal(u.u_procp, SIGPIPE);
278 		snderr(EPIPE);
279 	}
280 	if (so->so_error) {
281 		error = so->so_error;
282 		so->so_error = 0;				/* ??? */
283 		splx(s);
284 		goto release;
285 	}
286 	if ((so->so_state & SS_ISCONNECTED) == 0) {
287 		if (so->so_proto->pr_flags & PR_CONNREQUIRED)
288 			snderr(ENOTCONN);
289 		if (nam == 0)
290 			snderr(EDESTADDRREQ);
291 	}
292 	if (top) {
293 		error = (*so->so_proto->pr_usrreq)(so,
294 		    (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND,
295 		    top, (caddr_t)nam, (struct socketopt *)0);
296 		top = 0;
297 		if (error) {
298 			splx(s);
299 			goto release;
300 		}
301 		mp = &top;
302 	}
303 	if (uio->uio_resid == 0) {
304 		splx(s);
305 		goto release;
306 	}
307 	if (flags & SOF_OOB)
308 		space = 1024;
309 	else {
310 		space = sbspace(&so->so_snd);
311 		if (space <= 0 ||
312 		    sosendallatonce(so) && space < uio->uio_resid) {
313 			if (so->so_state & SS_NBIO)
314 				snderr(EWOULDBLOCK);
315 			sbunlock(&so->so_snd);
316 			sbwait(&so->so_snd);
317 			splx(s);
318 			goto restart;
319 		}
320 	}
321 	splx(s);
322 	while (uio->uio_resid > 0 && space > 0) {
323 		register struct iovec *iov = uio->uio_iov;
324 
325 		if (iov->iov_len == 0) {
326 			uio->uio_iov++;
327 			uio->uio_iovcnt--;
328 			if (uio->uio_iovcnt < 0)
329 				panic("sosend");
330 			continue;
331 		}
332 		MGET(m, 1);
333 		if (m == NULL) {
334 			error = ENOBUFS;			/* SIGPIPE? */
335 			goto release;
336 		}
337 		if (iov->iov_len >= CLBYTES && space >= CLBYTES) {
338 			register struct mbuf *p;
339 			MCLGET(p, 1);
340 			if (p == 0)
341 				goto nopages;
342 			m->m_off = (int)p - (int)m;
343 			len = CLBYTES;
344 		} else {
345 nopages:
346 			len = MIN(MLEN, iov->iov_len);
347 		}
348 		uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
349 		m->m_len = len;
350 		*mp = m;
351 		mp = &m->m_next;
352 		if (flags & SOF_OOB)
353 			space -= len;
354 		else
355 			space = sbspace(&so->so_snd);
356 	}
357 	goto again;
358 
359 release:
360 	sbunlock(&so->so_snd);
361 	if (top)
362 		m_freem(top);
363 	return (error);
364 }
365 
366 soreceive(so, aname, uio, flags)
367 	register struct socket *so;
368 	struct mbuf **aname;
369 	struct uio *uio;
370 	int flags;
371 {
372 	register struct mbuf *m, *n;
373 	u_int len;
374 	int eor, s, error = 0, moff, tomark;
375 
376 	if (flags & SOF_OOB) {
377 		m = m_get(M_WAIT);
378 		error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
379 		    m, (struct mbuf *)0, (struct socketopt *)0);
380 		if (error)
381 			return;
382 		len = uio->uio_resid;
383 		do {
384 			if (len > m->m_len)
385 				len = m->m_len;
386 			error =
387 			    uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
388 			m = m_free(m);
389 		} while (uio->uio_resid && error == 0 && m);
390 		if (m)
391 			(void) m_freem(m);
392 		return (error);
393 	}
394 
395 restart:
396 	sblock(&so->so_rcv);
397 SBCHECK(&so->so_rcv, "soreceive restart");
398 	s = splnet();
399 
400 #define	rcverr(errno)	{ error = errno; splx(s); goto release; }
401 	if (so->so_rcv.sb_cc == 0) {
402 		if (so->so_error) {
403 			error = so->so_error;
404 			so->so_error = 0;
405 			splx(s);
406 			goto release;
407 		}
408 		if (so->so_state & SS_CANTRCVMORE) {
409 			splx(s);
410 			goto release;
411 		}
412 		if ((so->so_state & SS_ISCONNECTED) == 0 &&
413 		    (so->so_proto->pr_flags & PR_CONNREQUIRED))
414 			rcverr(ENOTCONN);
415 		if (so->so_state & SS_NBIO)
416 			rcverr(EWOULDBLOCK);
417 		sbunlock(&so->so_rcv);
418 		sbwait(&so->so_rcv);
419 		splx(s);
420 		goto restart;
421 	}
422 	u.u_ru.ru_msgrcv++;
423 	m = so->so_rcv.sb_mb;
424 	if (m == 0)
425 		panic("receive");
426 SBCHECK(&so->so_snd, "soreceive havecc");
427 	if (so->so_proto->pr_flags & PR_ADDR) {
428 		if ((flags & SOF_PREVIEW) == 0) {
429 			so->so_rcv.sb_cc -= m->m_len;
430 			so->so_rcv.sb_mbcnt -= MSIZE;
431 		}
432 		if (aname) {
433 			if (flags & SOF_PREVIEW)
434 				*aname = m_copy(m, 0, m->m_len);
435 			else
436 				*aname = m;
437 			m = m->m_next;
438 			(*aname)->m_next = 0;
439 		} else
440 			if (flags & SOF_PREVIEW)
441 				m = m->m_next;
442 			else
443 				m = m_free(m);
444 		if (m == 0)
445 			panic("receive 2");
446 		if ((flags & SOF_PREVIEW) == 0)
447 			so->so_rcv.sb_mb = m;
448 SBCHECK(&so->so_snd, "soreceive afteraddr");
449 	}
450 	eor = 0;
451 	moff = 0;
452 	tomark = so->so_oobmark;
453 	do {
454 		if (uio->uio_resid <= 0)
455 			break;
456 		len = uio->uio_resid;
457 		so->so_state &= ~SS_RCVATMARK;
458 		if (tomark && len > tomark)
459 			len = tomark;
460 		if (moff+len > m->m_len - moff)
461 			len = m->m_len - moff;
462 		splx(s);
463 		error =
464 		    uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
465 		s = splnet();
466 		if (len == m->m_len) {
467 			eor = (int)m->m_act;
468 			if (flags & SOF_PREVIEW)
469 				m = m->m_next;
470 			else {
471 				sbfree(&so->so_rcv, m);
472 				MFREE(m, n);
473 				m = n;
474 				so->so_rcv.sb_mb = m;
475 			}
476 			moff = 0;
477 		} else {
478 			if (flags & SOF_PREVIEW)
479 				moff += len;
480 			else {
481 				m->m_off += len;
482 				m->m_len -= len;
483 				so->so_rcv.sb_cc -= len;
484 			}
485 		}
486 		if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) {
487 			so->so_oobmark -= len;
488 			if (so->so_oobmark == 0) {
489 				so->so_state |= SS_RCVATMARK;
490 				break;
491 			}
492 		}
493 		if (tomark) {
494 			tomark -= len;
495 			if (tomark == 0)
496 				break;
497 		}
498 SBCHECK(&so->so_snd, "soreceive rcvloop");
499 	} while (m && error == 0 && !eor);
500 	if (flags & SOF_PREVIEW)
501 		goto release;
502 	if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
503 		do {
504 			if (m == 0)
505 				panic("receive 3");
506 			sbfree(&so->so_rcv, m);
507 			eor = (int)m->m_act;
508 			so->so_rcv.sb_mb = m->m_next;
509 			MFREE(m, n);
510 			m = n;
511 SBCHECK(&so->so_snd, "soreceive atomicloop");
512 		} while (eor == 0);
513 	if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
514 		(*so->so_proto->pr_usrreq)(so, PRU_RCVD,
515 		    (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
516 release:
517 	sbunlock(&so->so_rcv);
518 	splx(s);
519 	return (error);
520 }
521 
522 sohasoutofband(so)
523 	struct socket *so;
524 {
525 
526 	if (so->so_pgrp == 0)
527 		return;
528 	if (so->so_pgrp > 0)
529 		gsignal(so->so_pgrp, SIGURG);
530 	else {
531 		struct proc *p = pfind(-so->so_pgrp);
532 
533 		if (p)
534 			psignal(p, SIGURG);
535 	}
536 }
537 
538 /*ARGSUSED*/
539 soioctl(so, cmd, data)
540 	register struct socket *so;
541 	int cmd;
542 	register char *data;
543 {
544 
545 	switch (cmd) {
546 
547 	case FIONBIO:
548 		if (*(int *)data)
549 			so->so_state |= SS_NBIO;
550 		else
551 			so->so_state &= ~SS_NBIO;
552 		break;
553 
554 	case FIOASYNC:
555 		if (*(int *)data)
556 			so->so_state |= SS_ASYNC;
557 		else
558 			so->so_state &= ~SS_ASYNC;
559 		break;
560 
561 	case SIOCSKEEP:
562 		if (*(int *)data)
563 			so->so_options &= ~SO_KEEPALIVE;
564 		else
565 			so->so_options |= SO_KEEPALIVE;
566 		break;
567 
568 	case SIOCGKEEP:
569 		*(int *)data = (so->so_options & SO_KEEPALIVE) != 0;
570 		break;
571 
572 	case SIOCSLINGER:
573 		so->so_linger = *(int *)data;
574 		if (so->so_linger)
575 			so->so_options &= ~SO_DONTLINGER;
576 		else
577 			so->so_options |= SO_DONTLINGER;
578 		break;
579 
580 	case SIOCGLINGER:
581 		*(int *)data = so->so_linger;
582 		break;
583 
584 	case SIOCSPGRP:
585 		so->so_pgrp = *(int *)data;
586 		break;
587 
588 	case SIOCGPGRP:
589 		*(int *)data = so->so_pgrp;
590 		break;
591 
592 	case SIOCDONE: {
593 		int flags = *(int *)data;
594 
595 		flags++;
596 		if (flags & FREAD) {
597 			int s = splimp();
598 			socantrcvmore(so);
599 			sbflush(&so->so_rcv);
600 			splx(s);
601 		}
602 		if (flags & FWRITE)
603 			return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN,
604 			    (struct mbuf *)0, (struct mbuf *)0,
605 			    (struct socketopt *)0));
606 		break;
607 	}
608 
609 	case SIOCSENDOOB: {
610 		char oob = *(char *)data;
611 		struct mbuf *m = m_get(M_DONTWAIT);
612 
613 		if (m == 0)
614 			return (ENOBUFS);
615 		m->m_len = 1;
616 		*mtod(m, char *) = oob;
617 		return ((*so->so_proto->pr_usrreq)(so, PRU_SENDOOB,
618 		    m, (struct mbuf *)0, (struct socketopt *)0));
619 	}
620 
621 	case SIOCRCVOOB: {
622 		struct mbuf *m = m_get(M_WAIT);
623 
624 		if (m == 0)
625 			return (ENOBUFS);
626 		*mtod(m, caddr_t) = 0;
627 		(*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
628 		    m, (struct mbuf *)0, (struct socketopt *)0);
629 		*(char *)data = *mtod(m, char *);
630 		(void) m_free(m);
631 		break;
632 	}
633 
634 	case SIOCATMARK:
635 		*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
636 		break;
637 
638 	/* routing table update calls */
639 	case SIOCADDRT:
640 	case SIOCDELRT:
641 		if (!suser())
642 			return (u.u_error);		/* XXX */
643 		return (rtrequest(cmd, (struct rtentry *)data));
644 
645 	/* type/protocol specific ioctls */
646 	default:
647 		return (ENOTTY);
648 	}
649 	return (0);
650 }
651