xref: /csrg-svn/sys/kern/uipc_socket.c (revision 4971)
1 /*	uipc_socket.c	4.8	81/11/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 "../net/inet.h"
17 #include "../net/inet_systm.h"
18 
19 /*
20  * Socket support routines.
21  *
22  * DEAL WITH INTERRUPT NOTIFICATION.
23  */
24 
25 /*
26  * Create a socket.
27  */
28 socreate(aso, type, asp, asa, options)
29 	struct socket **aso;
30 	int type;
31 	struct sockproto *asp;
32 	struct sockaddr *asa;
33 	int options;
34 {
35 	register struct protosw *prp;
36 	register struct socket *so;
37 	struct mbuf *m;
38 	int pf, proto, error;
39 COUNT(SOCREATE);
40 
41 	/*
42 	 * Use process standard protocol/protocol family if none
43 	 * specified by address argument.
44 	 */
45 	if (asp == 0) {
46 		pf = PF_INET;		/* should be u.u_protof */
47 		proto = 0;
48 	} else {
49 		pf = asp->sp_family;
50 		proto = asp->sp_protocol;
51 	}
52 
53 	/*
54 	 * If protocol specified, look for it, otherwise
55 	 * for a protocol of the correct type in the right family.
56 	 */
57 	if (proto)
58 		prp = pffindproto(pf, proto);
59 	else
60 		prp = pffindtype(pf, type);
61 	if (prp == 0)
62 		return (EPROTONOSUPPORT);
63 
64 	/*
65 	 * Get a socket structure.
66 	 */
67 	m = m_getclr(M_WAIT);
68 	if (m == 0)
69 		return (ENOBUFS);
70 	so = mtod(m, struct socket *);
71 	so->so_options = options;
72 
73 	/*
74 	 * Attach protocol to socket, initializing
75 	 * and reserving resources.
76 	 */
77 	so->so_proto = prp;
78 	(*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa);
79 	if (so->so_error) {
80 		error = so->so_error;
81 		(void) m_free(dtom(so));
82 		return (error);
83 	}
84 	*aso = so;
85 	return (0);
86 }
87 
88 sofree(so)
89 	struct socket *so;
90 {
91 
92 COUNT(SOFREE);
93 	if (so->so_pcb || (so->so_state & SS_USERGONE) == 0)
94 		return;
95 	sbrelease(&so->so_snd);
96 	sbrelease(&so->so_rcv);
97 	(void) m_free(dtom(so));
98 }
99 
100 /*
101  * Close a socket on last file table reference removal.
102  * Initiate disconnect if connected.
103  * Free socket when disconnect complete.
104  */
105 soclose(so)
106 	register struct socket *so;
107 {
108 	int s = splnet();		/* conservative */
109 
110 COUNT(SOCLOSE);
111 	if (so->so_pcb == 0)
112 		goto discard;
113 	if (so->so_state & SS_ISCONNECTED) {
114 		if ((so->so_state & SS_ISDISCONNECTING) == 0) {
115 			u.u_error = sodisconnect(so, (struct sockaddr *)0);
116 			if (u.u_error) {
117 				splx(s);
118 				return;
119 			}
120 		}
121 		if ((so->so_state & SS_ISDISCONNECTING) &&
122 		    (so->so_options & SO_NBIO)) {
123 			u.u_error = EINPROGRESS;
124 			splx(s);
125 			return;
126 		}
127 		while (so->so_state & SS_ISCONNECTED)
128 			sleep((caddr_t)&so->so_timeo, PZERO+1);
129 	}
130 	u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0);
131 discard:
132 	so->so_state |= SS_USERGONE;
133 	sofree(so);
134 	splx(s);
135 }
136 
137 sosplice(pso, so)
138 	struct socket *pso, *so;
139 {
140 
141 COUNT(SOSPLICE);
142 	if (pso->so_proto->pr_family != PF_LOCAL) {
143 		struct socket *tso;
144 		tso = pso; pso = so; so = tso;
145 	}
146 	if (pso->so_proto->pr_family != PF_LOCAL)
147 		return (EOPNOTSUPP);
148 	/* check types and buffer space */
149 	/* merge buffers */
150 	return (0);
151 }
152 
153 /*ARGSUSED*/
154 sostat(so, sb)
155 	struct socket *so;
156 	struct stat *sb;
157 {
158 
159 COUNT(SOSTAT);
160 	return (EOPNOTSUPP);
161 }
162 
163 /*
164  * Accept connection on a socket.
165  */
166 soaccept(so, asa)
167 	struct socket *so;
168 	struct sockaddr *asa;
169 {
170 	int s = splnet();
171 	int error;
172 
173 COUNT(SOACCEPT);
174 	if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
175 		error = EISCONN;
176 		goto bad;
177 	}
178 	if ((so->so_options & SO_ACCEPTCONN) == 0) {
179 		error = EINVAL;			/* XXX */
180 		goto bad;
181 	}
182 	error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa);
183 bad:
184 	splx(s);
185 	return (error);
186 }
187 
188 /*
189  * Connect socket to a specified address.
190  * If already connected or connecting, then avoid
191  * the protocol entry, to keep its job simpler.
192  */
193 soconnect(so, asa)
194 	struct socket *so;
195 	struct sockaddr *asa;
196 {
197 	int s = splnet();
198 	int error;
199 
200 COUNT(SOCONNECT);
201 	if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
202 		error = EISCONN;
203 		goto bad;
204 	}
205 	error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa);
206 bad:
207 	splx(s);
208 	return (error);
209 }
210 
211 /*
212  * Disconnect from a socket.
213  * Address parameter is from system call for later multicast
214  * protocols.  Check to make sure that connected and no disconnect
215  * in progress (for protocol's sake), and then invoke protocol.
216  */
217 sodisconnect(so, asa)
218 	struct socket *so;
219 	struct sockaddr *asa;
220 {
221 	int s = splnet();
222 	int error;
223 
224 COUNT(SODISCONNECT);
225 	if ((so->so_state & SS_ISCONNECTED) == 0) {
226 		error = ENOTCONN;
227 		goto bad;
228 	}
229 	if (so->so_state & SS_ISDISCONNECTING) {
230 		error = EALREADY;
231 		goto bad;
232 	}
233 	error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa);
234 bad:
235 	splx(s);
236 	return (error);
237 }
238 
239 /*
240  * Send on a socket.
241  * If send must go all at once and message is larger than
242  * send buffering, then hard error.
243  * Lock against other senders.
244  * If must go all at once and not enough room now, then
245  * inform user that this would block and do nothing.
246  */
247 sosend(so, asa)
248 	register struct socket *so;
249 	struct sockaddr *asa;
250 {
251 	struct mbuf *top = 0;
252 	register struct mbuf *m, **mp = ⊤
253 	register u_int len;
254 	int error = 0, space, s;
255 
256 COUNT(SOSEND);
257 	if (so->so_state & SS_CANTSENDMORE)
258 		return (EPIPE);
259 	if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat)
260 		return (EMSGSIZE);
261 	if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_options & SO_NBIO))
262 		return (EWOULDBLOCK);
263 	sblock(&so->so_snd);
264 #define	snderr(errno)	{ error = errno; splx(s); goto release; }
265 
266 	s = splnet();
267 again:
268 	if ((so->so_state & SS_ISCONNECTED) == 0) {
269 		if (so->so_proto->pr_flags & PR_CONNREQUIRED)
270 			snderr(ENOTCONN);
271 		if (asa == 0)
272 			snderr(EDESTADDRREQ);
273 	}
274 	if (so->so_error)
275 		snderr(so->so_error);
276 	if (top) {
277 		error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa);
278 		if (error) {
279 			splx(s);
280 			goto release;
281 		}
282 		top = 0;
283 		mp = ⊤
284 	}
285 	if (sosendallatonce(so) && sbspace(&so->so_snd) < u.u_count) {
286 		if (so->so_options & SO_NBIO)
287 			snderr(EWOULDBLOCK);
288 		sbunlock(&so->so_snd);
289 		sbwait(&so->so_snd);
290 		splx(s);
291 		goto again;
292 	}
293 	splx(s);
294 	while (u.u_count && (space = sbspace(&so->so_snd)) > 0) {
295 		MGET(m, 1);
296 		if (m == NULL) {
297 			error = ENOBUFS;
298 			m_freem(top);
299 			goto release;
300 		}
301 		if (u.u_count >= PGSIZE && space >= NMBPG) {
302 			register struct mbuf *p;
303 			MPGET(p, 1);
304 			if (p == 0)
305 				goto nopages;
306 			m->m_off = (int)p - (int)m;
307 			len = PGSIZE;
308 		} else {
309 nopages:
310 			m->m_off = MMINOFF;
311 			len = MIN(MLEN, u.u_count);
312 		}
313 		iomove(mtod(m, caddr_t), len, B_WRITE);
314 		m->m_len = len;
315 		*mp = m;
316 		mp = &m->m_next;
317 	}
318 	s = splnet();
319 	goto again;
320 
321 release:
322 	sbunlock(&so->so_snd);
323 	return (error);
324 }
325 
326 soreceive(so, asa)
327 	register struct socket *so;
328 	struct sockaddr *asa;
329 {
330 	register struct mbuf *m, *n;
331 	u_int len;
332 	int eor, s, error = 0;
333 
334 COUNT(SORECEIVE);
335 restart:
336 	sblock(&so->so_rcv);
337 	s = splnet();
338 
339 #define	rcverr(errno)	{ error = errno; splx(s); goto release; }
340 	if (so->so_rcv.sb_cc == 0) {
341 		if ((so->so_state & SS_ISCONNECTED) == 0 &&
342 		    (so->so_proto->pr_flags & PR_CONNREQUIRED))
343 			rcverr(ENOTCONN);
344 		if (so->so_state & SS_CANTRCVMORE) {
345 			splx(s);
346 			goto release;
347 		}
348 		if (so->so_options & SO_NBIO)
349 			rcverr (EWOULDBLOCK);
350 		sbunlock(&so->so_rcv);
351 		sbwait(&so->so_rcv);
352 		goto restart;
353 	}
354 	m = so->so_rcv.sb_mb;
355 	if (m == 0)
356 		panic("receive");
357 	if ((so->so_proto->pr_flags & PR_ADDR)) {
358 		so->so_rcv.sb_mb = m->m_next;
359 		if (asa) {
360 			so->so_rcv.sb_cc -= m->m_len;
361 			len = MIN(m->m_len, sizeof (struct sockaddr));
362 			bcopy(mtod(m, caddr_t), (caddr_t)asa, len);
363 		} else
364 			bzero((caddr_t)asa, sizeof (*asa));
365 		m = so->so_rcv.sb_mb;
366 		if (m == 0)
367 			panic("receive 2");
368 	}
369 	eor = 0;
370 	do {
371 		len = MIN(m->m_len, u.u_count);
372 		if (len == m->m_len) {
373 			eor = (int)m->m_act;
374 			sbfree(&so->so_rcv, m);
375 		}
376 		splx(s);
377 		iomove(mtod(m, caddr_t), len, B_READ);
378 		s = splnet();
379 		if (len == m->m_len) {
380 			MFREE(m, n);
381 		} else {
382 			m->m_off += len;
383 			m->m_len -= len;
384 			so->so_rcv.sb_cc -= len;
385 		}
386 	} while ((m = so->so_rcv.sb_mb) && u.u_count && !eor);
387 	if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
388 		do {
389 			if (m == 0)
390 				panic("receive 3");
391 			sbfree(&so->so_rcv, m);
392 			eor = (int)m->m_act;
393 			so->so_rcv.sb_mb = m->m_next;
394 			MFREE(m, n);
395 			m = n;
396 		} while (eor == 0);
397 	if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
398 		(*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0);
399 release:
400 	sbunlock(&so->so_rcv);
401 	splx(s);
402 	return (error);
403 }
404 
405 /*ARGSUSED*/
406 soioctl(so, cmd, cmdp)
407 	register struct socket *so;
408 	int cmd;
409 	register caddr_t cmdp;
410 {
411 
412 COUNT(SOIOCTL);
413 	switch (cmdp) {
414 
415 	}
416 	switch (so->so_type) {
417 
418 	case SOCK_STREAM:
419 		break;
420 
421 	case SOCK_DGRAM:
422 		break;
423 
424 	case SOCK_RDM:
425 		break;
426 
427 	case SOCK_RAW:
428 		break;
429 
430 	}
431 }
432