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