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