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