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