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