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