bwrite shouldn't clear B_AGE or brelse won't put it at the head
[unix-history] / usr / src / sys / kern / uipc_usrreq.c
CommitLineData
cce93e4b 1/* uipc_usrreq.c 1.5 82/12/14 */
d6213d15
BJ
2
3#include "../h/param.h"
4#include "../h/dir.h"
5#include "../h/user.h"
6#include "../h/mbuf.h"
7#include "../h/protosw.h"
8#include "../h/socket.h"
9#include "../h/socketvar.h"
10#include "../h/unpcb.h"
11#include "../h/un.h"
12#include "../h/inode.h"
4f083fd7 13#include "../h/nami.h"
d6213d15
BJ
14
15/*
16 * Unix communications domain.
17 */
18
19/*ARGSUSED*/
fca5570f 20uipc_usrreq(so, req, m, nam, opt)
d6213d15
BJ
21 struct socket *so;
22 int req;
fca5570f
BJ
23 struct mbuf *m, *nam;
24 struct socketopt *opt;
d6213d15
BJ
25{
26 struct unpcb *unp = sotounpcb(so);
27 register struct socket *so2;
28 int error = 0;
29
30 if (unp == 0 && req != PRU_ATTACH)
31 return (EINVAL); /* XXX */
32 switch (req) {
33
34 case PRU_ATTACH:
35 if (unp) {
4f083fd7 36 error = EISCONN;
d6213d15
BJ
37 break;
38 }
fca5570f 39 error = unp_attach(so);
d6213d15
BJ
40 break;
41
42 case PRU_DETACH:
43 unp_detach(unp);
44 break;
45
4f083fd7
SL
46 case PRU_BIND:
47 error = unp_bind(unp, nam);
48 break;
49
50 case PRU_LISTEN:
51 if (unp->unp_inode == 0)
52 error = EINVAL;
53 break;
54
d6213d15 55 case PRU_CONNECT:
fca5570f 56 error = unp_connect(so, nam);
d6213d15
BJ
57 break;
58
59 case PRU_DISCONNECT:
60 unp_disconnect(unp);
61 break;
62
4f083fd7
SL
63 case PRU_ACCEPT:
64 nam->m_len = unp->unp_remaddr->m_len;
65 bcopy(mtod(unp->unp_remaddr, caddr_t),
66 mtod(nam, caddr_t), (unsigned)nam->m_len);
d6213d15
BJ
67 break;
68
69 case PRU_SHUTDOWN:
70 socantsendmore(so);
71 unp_usrclosed(unp);
72 break;
d6213d15
BJ
73
74 case PRU_RCVD:
75 switch (so->so_type) {
76
77 case SOCK_DGRAM:
78 panic("uipc 1");
79
80 case SOCK_STREAM: {
81#define rcv (&so->so_rcv)
82#define snd (&so2->so_snd)
83 if (unp->unp_conn == 0)
84 break;
85 so2 = unp->unp_conn->unp_socket;
86 /*
87 * Transfer resources back to send port
88 * and wakeup any waiting to write.
89 */
90 snd->sb_mbmax += rcv->sb_mbmax - rcv->sb_mbcnt;
91 rcv->sb_mbmax = rcv->sb_mbcnt;
92 snd->sb_hiwat += rcv->sb_hiwat - rcv->sb_cc;
93 rcv->sb_hiwat = rcv->sb_cc;
94 sbwakeup(snd);
95#undef snd
96#undef rcv
97 }
98 break;
99
100 default:
101 panic("uipc 2");
102 }
103 break;
104
105 case PRU_SEND:
106 switch (so->so_type) {
107
108 case SOCK_DGRAM:
fca5570f 109 if (nam) {
d6213d15
BJ
110 if (unp->unp_conn) {
111 error = EISCONN;
112 break;
113 }
fca5570f 114 error = unp_connect(so, nam);
d6213d15
BJ
115 if (error)
116 break;
117 } else {
118 if (unp->unp_conn == 0) {
119 error = ENOTCONN;
120 break;
121 }
122 }
123 so2 = unp->unp_conn->unp_socket;
4f083fd7
SL
124 /* BEGIN XXX */
125 if (sbspace(&so2->so_rcv) > 0)
126 (void) sbappendaddr(&so2->so_rcv,
127 mtod(nam, struct sockaddr *), m);
128 /* END XXX */
fca5570f 129 if (nam)
4f083fd7 130 unp_disconnect(unp);
d6213d15
BJ
131 break;
132
133 case SOCK_STREAM:
134#define rcv (&so2->so_rcv)
135#define snd (&so->so_snd)
136 if (unp->unp_conn == 0)
137 panic("uipc 3");
138 so2 = unp->unp_conn->unp_socket;
139 /*
140 * Send to paired receive port, and then
141 * give it enough resources to hold what it already has.
142 * Wake up readers.
143 */
144 sbappend(rcv, m);
145 snd->sb_mbmax -= rcv->sb_mbcnt - rcv->sb_mbmax;
146 rcv->sb_mbmax = rcv->sb_mbcnt;
147 snd->sb_hiwat -= rcv->sb_cc - rcv->sb_hiwat;
148 rcv->sb_hiwat = rcv->sb_cc;
149 sbwakeup(rcv);
150#undef snd
151#undef rcv
152 break;
153
154 default:
155 panic("uipc 4");
156 }
157 break;
158
159 case PRU_ABORT:
160 unp_drop(unp, ECONNABORTED);
161 break;
162
163/* SOME AS YET UNIMPLEMENTED HOOKS */
164 case PRU_CONTROL:
165 error = EOPNOTSUPP;
166 break;
167
168 case PRU_SENSE:
169 error = EOPNOTSUPP;
170 break;
171/* END UNIMPLEMENTED HOOKS */
172
173 case PRU_RCVOOB:
174 break;
175
176 case PRU_SENDOOB:
177 break;
178
179 case PRU_SOCKADDR:
180 break;
181
182 case PRU_SLOWTIMO:
183 break;
184
185 default:
186 panic("piusrreq");
187 }
188 return (0);
189}
190
191int unp_sendspace = 1024*2;
192int unp_recvspace = 1024*2;
193
4f083fd7 194unp_attach(so)
d6213d15 195 struct socket *so;
d6213d15 196{
4f083fd7 197 register struct mbuf *m;
d6213d15 198 register struct unpcb *unp;
d6213d15
BJ
199 int error;
200
201 error = soreserve(so, unp_sendspace, unp_recvspace);
202 if (error)
203 goto bad;
cce93e4b 204 m = m_getclr(M_DONTWAIT, MT_PCB);
d6213d15
BJ
205 if (m == 0) {
206 error = ENOBUFS;
207 goto bad;
208 }
209 unp = mtod(m, struct unpcb *);
210 so->so_pcb = (caddr_t)unp;
211 unp->unp_socket = so;
d6213d15
BJ
212 return (0);
213bad:
214 return (error);
215}
216
d6213d15 217unp_detach(unp)
4f083fd7 218 register struct unpcb *unp;
d6213d15
BJ
219{
220
221 if (unp->unp_inode) {
222 irele(unp->unp_inode);
223 unp->unp_inode = 0;
224 }
225 if (unp->unp_conn)
226 unp_disconnect(unp);
227 while (unp->unp_refs)
228 unp_drop(unp->unp_refs, ECONNRESET);
229 soisdisconnected(unp->unp_socket);
230 unp->unp_socket->so_pcb = 0;
4f083fd7
SL
231 m_freem(unp->unp_remaddr);
232 (void) m_free(dtom(unp));
d6213d15
BJ
233}
234
4f083fd7 235unp_bind(unp, nam)
d6213d15 236 struct unpcb *unp;
4f083fd7 237 struct mbuf *nam;
d6213d15 238{
4f083fd7 239 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
d6213d15 240 register struct inode *ip;
d6213d15 241 extern schar();
4f083fd7 242 int error;
d6213d15
BJ
243
244 u.u_dirp = soun->sun_path;
245 soun->sun_path[sizeof(soun->sun_path)-1] = 0;
4f083fd7 246 ip = namei(schar, CREATE, 1);
d6213d15
BJ
247 if (ip) {
248 iput(ip);
249 return (EEXIST);
250 }
251 ip = maknode(IFSOCK | 0777);
252 if (ip == NULL) {
253 error = u.u_error; /* XXX */
254 u.u_error = 0; /* XXX */
255 return (error);
256 }
257 ip->i_socket = unp->unp_socket;
258 unp->unp_inode = ip;
259 iunlock(ip); /* but keep reference */
260 return (0);
261}
262
4f083fd7 263unp_connect(so, nam)
d6213d15 264 struct socket *so;
4f083fd7 265 struct mbuf *nam;
d6213d15 266{
4f083fd7
SL
267 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
268 struct unpcb *unp = sotounpcb(so);
269 register struct inode *ip;
d6213d15 270 int error;
4f083fd7
SL
271 struct socket *so2;
272 struct unpcb *unp2;
d6213d15
BJ
273
274 u.u_dirp = soun->sun_path;
275 soun->sun_path[sizeof(soun->sun_path)-1] = 0;
4f083fd7 276 ip = namei(schar, LOOKUP, 1);
d6213d15
BJ
277 if (ip == 0) {
278 error = u.u_error;
279 u.u_error = 0;
280 return (ENOENT);
281 }
d6213d15
BJ
282 if ((ip->i_mode&IFMT) != IFSOCK) {
283 error = ENOTSOCK;
284 goto bad;
285 }
286 so2 = ip->i_socket;
287 if (so2 == 0) {
288 error = ECONNREFUSED;
289 goto bad;
290 }
291 if (so2->so_type != so->so_type) {
292 error = EPROTOTYPE;
293 goto bad;
294 }
295 switch (so->so_type) {
296
297 case SOCK_DGRAM:
298 unp->unp_conn = sotounpcb(so2);
299 unp2 = sotounpcb(so2);
300 unp->unp_nextref = unp2->unp_refs;
301 unp2->unp_refs = unp;
302 break;
303
304 case SOCK_STREAM:
305 if ((so2->so_options&SO_ACCEPTCONN) == 0 ||
4f083fd7 306 (so2 = sonewconn(so2)) == 0) {
d6213d15
BJ
307 error = ECONNREFUSED;
308 goto bad;
309 }
4f083fd7
SL
310 unp2 = sotounpcb(so2);
311 unp->unp_conn = unp2;
312 unp2->unp_conn = unp;
313 unp2->unp_remaddr = m_copy(nam, 0, (int)M_COPYALL);
d6213d15
BJ
314 break;
315
316 default:
317 panic("uipc connip");
318 }
4f083fd7 319 soisconnected(so2);
d6213d15
BJ
320 soisconnected(so);
321 iput(ip);
322 return (0);
323bad:
324 iput(ip);
325 return (error);
326}
4f083fd7
SL
327
328unp_disconnect(unp)
329 struct unpcb *unp;
330{
331 register struct unpcb *unp2 = unp->unp_conn;
332
333 if (unp2 == 0)
334 return;
335 unp->unp_conn = 0;
336 soisdisconnected(unp->unp_socket);
337 switch (unp->unp_socket->so_type) {
338
339 case SOCK_DGRAM:
340 if (unp2->unp_refs == unp)
341 unp2->unp_refs = unp->unp_nextref;
342 else {
343 unp2 = unp2->unp_refs;
344 for (;;) {
345 if (unp2 == 0)
346 panic("unp_disconnect");
347 if (unp2->unp_nextref == unp)
348 break;
349 unp2 = unp2->unp_nextref;
350 }
351 unp2->unp_nextref = unp->unp_nextref;
352 }
353 unp->unp_nextref = 0;
354 break;
355
356 case SOCK_STREAM:
357 unp2->unp_conn = 0;
358 soisdisconnected(unp2->unp_socket);
4f083fd7
SL
359 break;
360 }
361}
362
363unp_abort(unp)
364 struct unpcb *unp;
365{
366
367 unp_detach(unp);
368}
369
370/*ARGSUSED*/
371unp_usrclosed(unp)
372 struct unpcb *unp;
373{
374
375}
376
377unp_drop(unp, errno)
378 struct unpcb *unp;
379 int errno;
380{
381
382 unp->unp_socket->so_error = errno;
383 unp_disconnect(unp);
384}
385
386unp_drain()
387{
388
389}