xref: /csrg-svn/sys/kern/uipc_socket.c (revision 4829)
1 /*	uipc_socket.c	4.2	81/11/08	*/
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/protocol.h"
13 #include "../h/protosw.h"
14 #include "../h/socket.h"
15 #include "../h/socketvar.h"
16 #include "../h/inaddr.h"
17 #include "../net/inet.h"
18 #include "../net/inet_systm.h"
19 
20 struct	socket zerosocket;
21 struct	in_addr zeroin_addr;
22 
23 /*
24  * Socket system call interface.  Copy in arguments
25  * set up file descriptor and call internal socket
26  * creation routine.
27  */
28 ssocket()
29 {
30 	register struct a {
31 		int	type;
32 		struct	in_addr *ain;
33 		int	options;
34 	} *uap = (struct a *)u.u_ap;
35 	struct in_addr in;
36 	struct socket *so0;
37 	register struct socket *so;
38 	register struct file *fp;
39 
40 	if ((fp = falloc()) == NULL)
41 		return;
42 	fp->f_flag = FSOCKET|FREAD|FWRITE;
43 	if (copyin((caddr_t)uap->ain, &in, sizeof (in))) {
44 		u.u_error = EFAULT;
45 		return;
46 	}
47 	u.u_error = socket(&so0, uap->type, &in, uap->options);
48 	if (u.u_error)
49 		goto bad;
50 	fp->f_socket = so;
51 	return;
52 bad:
53 	u.u_ofile[u.u_r.r_val1] = 0;
54 	fp->f_count = 0;
55 }
56 
57 /*
58  * Create a socket.
59  */
60 socket(aso, type, iap, options)
61 	struct socket **aso;
62 	int type;
63 	register struct in_addr *iap;
64 	int options;
65 {
66 	register struct protosw *prp;
67 	register struct socket *so;
68 	struct mbuf *m;
69 	int pf, proto;
70 
71 	/*
72 	 * Pin down protocol if possible.
73 	 * If no address specified, use a generic protocol.
74 	 */
75 	if (iap == 0) {
76 		pf = PF_GENERIC;
77 		proto = 0;
78 	} else {
79 		pf = iap->ia_pf;
80 		proto = iap->ia_proto;
81 	}
82 	if (proto) {
83 		/*
84 		 * A specific protocol was requested.  Look
85 		 * for the protocol.  If not found, then we
86 		 * don't support it.
87 		 */
88 		prp = pf_findproto(pf, proto);
89 		if (prp == 0)
90 			return (EPROTONOSUPPORT);
91 	} else {
92 		/*
93 		 * No specific protocol was requested.  Look
94 		 * in the specified (or generic) protocol set
95 		 * for a protocol of this type.
96 		 */
97 		prp = pf_findtype(pf, type);
98 		if (prp == 0)
99 			return (pf == PF_GENERIC ?
100 			    ESOCKTNOSUPPORT : EPROTONOSUPPORT);
101 	}
102 
103 	/*
104 	 * Get a socket structure.
105 	 */
106 	m = m_get(M_WAIT);
107 	if (m == 0)
108 		return (ENOBUFS);
109 	m->m_off = MMINOFF;
110 	so = mtod(m, struct socket *);
111 	*so = zerosocket;
112 	so->so_options = options;
113 
114 	/*
115 	 * An early call to protocol initialization.  If protocol
116 	 * actually hasn't been decided on yet (till we know
117 	 * peer), then the generic protocol allocated so far can
118 	 * just make sure a reasonable amount of resources will
119 	 * be available to it (say by allocating liberally now
120 	 * and returning some of the resources later).
121 	 */
122 	so->so_proto = prp;
123 	(*prp->pr_usrreq)(so, PRU_ATTACH, 0, 0);
124 	if (so->so_error) {
125 		m_free(dtom(so));
126 		return (u.u_error);
127 	}
128 	*aso = so;
129 	return (0);
130 }
131 
132 spipe()
133 {
134 
135 }
136 
137 skclose(so)
138 	register struct socket *so;
139 {
140 
141 	if (so->so_pcb)
142 		(*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0);
143 }
144 
145 /*
146  * Select a socket.
147  */
148 soselect(so, flag)
149 	register struct socket *so;
150 	int flag;
151 {
152 	register struct proc *p;
153 
154 	if (so->so_rcv.sb_cc)
155 		return (1);
156 	if ((p = so->so_rcv.sb_sel) && p->p_wchan == (caddr_t)select)
157 		so->so_rcv.sb_flags |= SB_COLL;
158 	else
159 		so->so_rcv.sb_sel = u.u_procp;
160 	return (0);
161 }
162 
163 /*
164  * Wakeup read sleep/select'ers.
165  */
166 sowakeup(so)
167 	struct socket *so;
168 {
169 
170 	if (so->so_rcv.sb_cc && so->so_rcv.sb_sel) {
171 		selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
172 		so->so_rcv.sb_sel = 0;
173 		so->so_rcv.sb_flags &= ~SB_COLL;
174 	}
175 	if (so->so_rcv.sb_flags & SB_WAIT) {
176 		so->so_rcv.sb_flags &= ~SB_WAIT;
177 		wakeup((caddr_t)&so->so_rcv.sb_cc);
178 	}
179 }
180 
181 /*
182  * Connect socket to foreign peer; system call
183  * interface.  Copy in arguments and call internal routine.
184  */
185 sconnect()
186 {
187 	register struct a {
188 		int fdes;
189 		struct in_addr *a;
190 	} *uap = (struct a *)u.u_ap;
191 	in_addr in;
192 	register struct file *fp;
193 	register struct socket *so;
194 	int s;
195 
196 	if (copyin((caddr_t)uap->a, &in, sizeof (in))) {
197 		u.u_error = EFAULT;
198 		return;
199 	}
200 	fp = getf(uap->fdes);
201 	if (fp == 0)
202 		return;
203 	if ((fp->f_flag & FSOCKET) == 0) {
204 		u.u_error = ENOTSOCK;
205 		return;
206 	}
207 	so = fp->f_socket;
208 	u.u_error = connect(so, &in);
209 	if (u.u_error)
210 		return;
211 	s = splnet();
212 	for (;;) {
213 		/* should use tsleep here */
214 		if ((*so->so_proto->pr_usrreq)(so, PRU_ISCONN, 0, &in) == 0)
215 			break;
216 		sleep((caddr_t)&so->so_timeo, PZERO+1);
217 	}
218 	splx(s);
219 }
220 
221 connect(so, iap)
222 	struct socket *so;
223 	struct in_addr *iap;
224 {
225 
226 	return ((*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, iap));
227 }
228 
229 /*
230  * Disconnect socket from foreign peer; system call
231  * interface.  Copy in arguments and call internal routine.
232  */
233 sdisconnect()
234 {
235 	register struct a {
236 		int	fdes;
237 		in_addr	 *addr;
238 	} *uap = (struct a *)u.u_ap;
239 	in_addr in;
240 	register struct file *fp;
241 
242 	if (uap->addr &&
243 	    copyin((caddr_t)uap->addr, (caddr_t)&in, sizeof (in))) {
244 		u.u_error = EFAULT;
245 		return;
246 	}
247 	fp = getf(uap->fdes);
248 	if (fp == 0)
249 		return;
250 	if ((fp->f_flag & FSOCKET) == 0) {
251 		u.u_error = ENOTSOCK;
252 		return;
253 	}
254 	disconnect(fp->f_socket, uap->addr ? &in : 0);
255 }
256 
257 disconnect(so, iap)
258 	struct socket *so;
259 	struct in_addr *iap;
260 {
261 
262 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, iap);
263 }
264 
265 /*
266  * Send data on socket.
267  */
268 ssend()
269 {
270 	register struct a {
271 		int	fdes;
272 		in_addr	*ain;
273 		caddr_t	cbuf;
274 		int	count;
275 	} *uap = (struct a *)u.u_ap;
276 	register struct file *fp;
277 	struct in_addr in;
278 
279 	fp = getf(uap->fdes);
280 	if (fp == 0)
281 		return;
282 	if ((fp->f_flag & FSOCKET) == 0) {
283 		u.u_error = ENOTSOCK;
284 		return;
285 	}
286 	if (uap->count < 0) {
287 		u.u_error = EINVAL;
288 		return;
289 	}
290 	u.u_base = uap->cbuf;
291 	u.u_count = uap->count;
292 	u.u_segflg = 0;
293 	if (useracc(u.u_base, u.u_count, B_READ) == 0 ||
294 	    uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) {
295 		u.u_error = EFAULT;
296 		return;
297 	}
298 	u.u_error = send(fp->f_socket, uap->ain ? &in : 0);
299 }
300 
301 send(so, iap)
302 	register struct socket *so;
303 	struct in_addr *iap;
304 {
305 	register struct mbuf *m, **mp;
306 	struct mbuf *top;
307 	int error = 0;
308 
309 	if (so->so_proto->pr_flags & PR_ATOMIC) {
310 		if (u.u_count > so->so_snd.sb_hiwat) {
311 			error = EMSGSIZE;
312 			goto release;
313 		}
314 	}
315 again:
316 	while (so->so_snd.sb_flags & SB_LOCK) {
317 		so->so_snd.sb_flags |= SB_WANT;
318 		sleep((caddr_t)&so->so_snd.sb_flags, PZERO+1);
319 	}
320 	if (so->so_snd.sb_hiwat - so->so_snd.sb_cc < u.u_count) {
321 		so->so_snd.sb_flags |= SB_WAIT;
322 		sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1);
323 		goto again;
324 	}
325 	so->so_snd.sb_flags |= SB_LOCK;
326 	while (u.u_count > 0) {
327 		register int bufs = so->so_snd.sb_mbmax - so->so_snd.sb_mbcnt;
328 		while (bufs == 0) {
329 			so->so_snd.sb_flags |= SB_WAIT;
330 			sleep((caddr_t)&so->so_snd.sb_cc, PZERO+1);
331 		}
332 		mp = &top;
333 		top = 0;
334 		while (--bufs >= 0 && u.u_count > 0) {
335 			register int len;
336 			MGET(m, 1);
337 			if (m == NULL) {
338 				error = ENOBUFS;
339 				m_freem(top);
340 				goto release;
341 			}
342 			if (u.u_count >= PGSIZE && bufs >= NMBPG) {
343 				register struct mbuf *p;
344 				MPGET(p, 1);
345 				if (p == 0)
346 					goto nopages;
347 				m->m_off = (int)p - (int)m;
348 				len = PGSIZE;
349 			} else {
350 nopages:
351 				m->m_off = MMINOFF;
352 				len = MIN(MLEN, u.u_count);
353 			}
354 			iomove(mtod(m, caddr_t), len, B_WRITE);
355 			m->m_len = len;
356 			*mp = m;
357 			mp = &m->m_next;
358 		}
359 		{ register int s = splnet();
360 		  error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, iap);
361 		  splx(s); }
362 		if (error)
363 			break;
364 	}
365 release:
366 	so->so_snd.sb_flags &= ~SB_LOCK;
367 	if (so->so_snd.sb_flags & SB_WANT)
368 		wakeup((caddr_t)&so->so_snd.sb_flags);
369 	return (error);
370 }
371 
372 /*
373  * Receive data on socket.
374  */
375 sreceive()
376 {
377 	register struct a {
378 		int	fdes;
379 		in_addr	*ain;
380 		caddr_t	cbuf;
381 		int	count;
382 	} *uap = (struct a *)u.u_ap;
383 	register struct file *fp;
384 	struct in_addr *in;
385 
386 	fp = getf(uap->fdes);
387 	if (fp == 0)
388 		return;
389 	if ((fp->f_flag & FSOCKET) == 0) {
390 		u.u_error = ENOTSOCK;
391 		return;
392 	}
393 	if (uap->count < 0) {
394 		u.u_error = EINVAL;
395 		return;
396 	}
397 	u.u_base = uap->cbuf;
398 	u.u_count = uap->count;
399 	u.u_segflg = 0;
400 	if (useracc(u.u_base, u.u_count, B_WRITE) == 0 ||
401 	    uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) {
402 		u.u_error = EFAULT;
403 		return;
404 	}
405 	receive(fp->f_socket, uap->ain ? &in : 0);
406 }
407 
408 receive(so, iap)
409 	register struct socket *so;
410 	struct in_addr *iap;
411 {
412 	register struct mbuf *m, *n;
413 	register int eor, len, s;
414 
415 again:
416 	while (so->so_rcv.sb_flags & SB_LOCK) {
417 		so->so_rcv.sb_flags |= SB_WANT;
418 		sleep((caddr_t)&so->so_rcv.sb_flags, PZERO+1);
419 	}
420 	if (so->so_rcv.sb_cc == 0) {
421 		if ((so->so_proto->pr_usrreq)(so, PRU_ISDISCONN, 0, 0) == 0)
422 			return;
423 		so->so_rcv.sb_flags |= SB_WAIT;
424 		sleep((caddr_t)&so->so_rcv.sb_cc, PZERO+1);
425 		goto again;
426 	}
427 	so->so_rcv.sb_flags |= SB_LOCK;
428 	m = so->so_rcv.sb_mb;
429 	if (m == 0)
430 		panic("receive");
431 	eor = 0;
432 	do {
433 		len = MIN(m->m_len, u.u_count);
434 		if (len == m->m_len) {
435 			eor = (int)m->m_act;
436 			so->so_rcv.sb_mb = m->m_next;
437 			so->so_rcv.sb_cc -= len;
438 			if (so->so_rcv.sb_cc < 0)
439 				panic("receive 2");
440 		}
441 		splx(s);
442 		iomove(mtod(m, caddr_t), len, B_READ);
443 		s = splnet();
444 		if (len == m->m_len) {
445 			MFREE(m, n);
446 		} else {
447 			m->m_off += len;
448 			m->m_len -= len;
449 			so->so_rcv.sb_cc -= len;
450 			if (so->so_rcv.sb_cc < 0)
451 				panic("receive 3");
452 		}
453 	} while ((m = so->so_rcv.sb_mb) && u.u_count && !eor);
454 	if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
455 		do {
456 			m = so->so_rcv.sb_mb;
457 			if (m == 0)
458 				panic("receive 4");
459 			so->so_rcv.sb_cc -= m->m_len;
460 			if (so->so_rcv.sb_cc < 0)
461 				panic("receive 5");
462 			eor = (int)m->m_act;
463 			so->so_rcv.sb_mb = m->m_next;
464 			MFREE(m, n);
465 		} while (eor == 0);
466 	if (iap)
467 		if ((so->so_proto->pr_flags & PR_ADDR)) {
468 			m = so->so_rcv.sb_mb;
469 			if (m == 0)
470 				panic("receive 6");
471 			so->so_rcv.sb_mb = m->m_next;
472 			so->so_rcv.sb_cc -= m->m_len;
473 			len = MIN(m->m_len, sizeof (struct in_addr));
474 			bcopy(mtod(m, caddr_t), (caddr_t)iap, len);
475 		} else
476 			*iap = zeroin_addr;
477 	(*so->so_proto->pr_usrreq)(so, PRU_RCVD, m, 0);
478 }
479 
480 skioctl(so, cmd, cmdp)
481 	register struct socket *so;
482 	int cmd;
483 	register caddr_t cmdp;
484 {
485 
486 	switch (cmdp) {
487 
488 	}
489 	switch (so->so_type) {
490 
491 	case SOCK_STREAM:
492 		break;
493 
494 	case SOCK_DGRAM:
495 		break;
496 
497 	case SOCK_RDM:
498 		break;
499 
500 	case SOCK_RAW:
501 		break;
502 
503 	}
504 }
505 
506 sostat(so)
507 	struct socket *so;
508 {
509 
510 }
511 
512 /*
513  * Generic protocol handler.
514  */
515 gen_usrreq()
516 {
517 
518 }
519