Deleted Added
full compact
uipc_usrreq.c (25201) uipc_usrreq.c (28270)
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
34 * $Id: uipc_usrreq.c,v 1.22 1997/03/23 03:36:33 bde Exp $
34 * $Id: uipc_usrreq.c,v 1.23 1997/04/27 20:00:46 wollman Exp $
35 */
36
37#include <sys/param.h>
38#include <sys/queue.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/domain.h>
42#include <sys/fcntl.h>
43#include <sys/file.h>
44#include <sys/filedesc.h>
45#include <sys/mbuf.h>
46#include <sys/namei.h>
47#include <sys/proc.h>
48#include <sys/protosw.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/stat.h>
52#include <sys/sysctl.h>
53#include <sys/un.h>
54#include <sys/unpcb.h>
55#include <sys/vnode.h>
56
57/*
58 * Unix communications domain.
59 *
60 * TODO:
61 * SEQPACKET, RDM
62 * rethink name space problems
63 * need a proper out-of-band
64 */
65static struct sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL };
66static ino_t unp_ino; /* prototype for fake inode numbers */
67
68static int unp_attach __P((struct socket *));
69static void unp_detach __P((struct unpcb *));
35 */
36
37#include <sys/param.h>
38#include <sys/queue.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/domain.h>
42#include <sys/fcntl.h>
43#include <sys/file.h>
44#include <sys/filedesc.h>
45#include <sys/mbuf.h>
46#include <sys/namei.h>
47#include <sys/proc.h>
48#include <sys/protosw.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/stat.h>
52#include <sys/sysctl.h>
53#include <sys/un.h>
54#include <sys/unpcb.h>
55#include <sys/vnode.h>
56
57/*
58 * Unix communications domain.
59 *
60 * TODO:
61 * SEQPACKET, RDM
62 * rethink name space problems
63 * need a proper out-of-band
64 */
65static struct sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL };
66static ino_t unp_ino; /* prototype for fake inode numbers */
67
68static int unp_attach __P((struct socket *));
69static void unp_detach __P((struct unpcb *));
70static int unp_bind __P((struct unpcb *,struct mbuf *, struct proc *));
71static int unp_connect __P((struct socket *,struct mbuf *, struct proc *));
70static int unp_bind __P((struct unpcb *,struct sockaddr *, struct proc *));
71static int unp_connect __P((struct socket *,struct sockaddr *,
72 struct proc *));
72static void unp_disconnect __P((struct unpcb *));
73static void unp_shutdown __P((struct unpcb *));
74static void unp_drop __P((struct unpcb *, int));
75static void unp_gc __P((void));
76static void unp_scan __P((struct mbuf *, void (*)(struct file *)));
77static void unp_mark __P((struct file *));
78static void unp_discard __P((struct file *));
79static int unp_internalize __P((struct mbuf *, struct proc *));
80
81static int
82uipc_abort(struct socket *so)
83{
84 struct unpcb *unp = sotounpcb(so);
85
86 if (unp == 0)
87 return EINVAL;
88 unp_drop(unp, ECONNABORTED);
89 return 0;
90}
91
92static int
73static void unp_disconnect __P((struct unpcb *));
74static void unp_shutdown __P((struct unpcb *));
75static void unp_drop __P((struct unpcb *, int));
76static void unp_gc __P((void));
77static void unp_scan __P((struct mbuf *, void (*)(struct file *)));
78static void unp_mark __P((struct file *));
79static void unp_discard __P((struct file *));
80static int unp_internalize __P((struct mbuf *, struct proc *));
81
82static int
83uipc_abort(struct socket *so)
84{
85 struct unpcb *unp = sotounpcb(so);
86
87 if (unp == 0)
88 return EINVAL;
89 unp_drop(unp, ECONNABORTED);
90 return 0;
91}
92
93static int
93uipc_accept(struct socket *so, struct mbuf *nam)
94uipc_accept(struct socket *so, struct sockaddr **nam)
94{
95 struct unpcb *unp = sotounpcb(so);
96
97 if (unp == 0)
98 return EINVAL;
99
100 /*
101 * Pass back name of connected socket,
102 * if it was bound and we are still connected
103 * (our peer may have closed already!).
104 */
105 if (unp->unp_conn && unp->unp_conn->unp_addr) {
95{
96 struct unpcb *unp = sotounpcb(so);
97
98 if (unp == 0)
99 return EINVAL;
100
101 /*
102 * Pass back name of connected socket,
103 * if it was bound and we are still connected
104 * (our peer may have closed already!).
105 */
106 if (unp->unp_conn && unp->unp_conn->unp_addr) {
106 nam->m_len = unp->unp_conn->unp_addr->m_len;
107 bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),
108 mtod(nam, caddr_t), (unsigned)nam->m_len);
107 *nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr,
108 1);
109 } else {
109 } else {
110 nam->m_len = sizeof(sun_noname);
111 *(mtod(nam, struct sockaddr *)) = sun_noname;
110 *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
112 }
113 return 0;
114}
115
116static int
117uipc_attach(struct socket *so, int proto, struct proc *p)
118{
119 struct unpcb *unp = sotounpcb(so);
120
121 if (unp != 0)
122 return EISCONN;
123 return unp_attach(so);
124}
125
126static int
111 }
112 return 0;
113}
114
115static int
116uipc_attach(struct socket *so, int proto, struct proc *p)
117{
118 struct unpcb *unp = sotounpcb(so);
119
120 if (unp != 0)
121 return EISCONN;
122 return unp_attach(so);
123}
124
125static int
127uipc_bind(struct socket *so, struct mbuf *nam, struct proc *p)
126uipc_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
128{
129 struct unpcb *unp = sotounpcb(so);
130
131 if (unp == 0)
132 return EINVAL;
133
134 return unp_bind(unp, nam, p);
135}
136
137static int
127{
128 struct unpcb *unp = sotounpcb(so);
129
130 if (unp == 0)
131 return EINVAL;
132
133 return unp_bind(unp, nam, p);
134}
135
136static int
138uipc_connect(struct socket *so, struct mbuf *nam, struct proc *p)
137uipc_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
139{
140 struct unpcb *unp = sotounpcb(so);
141
142 if (unp == 0)
143 return EINVAL;
144 return unp_connect(so, nam, curproc);
145}
146
147static int
148uipc_connect2(struct socket *so1, struct socket *so2)
149{
150 struct unpcb *unp = sotounpcb(so1);
151
152 if (unp == 0)
153 return EINVAL;
154
155 return unp_connect2(so1, so2);
156}
157
158/* control is EOPNOTSUPP */
159
160static int
161uipc_detach(struct socket *so)
162{
163 struct unpcb *unp = sotounpcb(so);
164
165 if (unp == 0)
166 return EINVAL;
167
168 unp_detach(unp);
169 return 0;
170}
171
172static int
173uipc_disconnect(struct socket *so)
174{
175 struct unpcb *unp = sotounpcb(so);
176
177 if (unp == 0)
178 return EINVAL;
179 unp_disconnect(unp);
180 return 0;
181}
182
183static int
184uipc_listen(struct socket *so, struct proc *p)
185{
186 struct unpcb *unp = sotounpcb(so);
187
188 if (unp == 0 || unp->unp_vnode == 0)
189 return EINVAL;
190 return 0;
191}
192
193static int
138{
139 struct unpcb *unp = sotounpcb(so);
140
141 if (unp == 0)
142 return EINVAL;
143 return unp_connect(so, nam, curproc);
144}
145
146static int
147uipc_connect2(struct socket *so1, struct socket *so2)
148{
149 struct unpcb *unp = sotounpcb(so1);
150
151 if (unp == 0)
152 return EINVAL;
153
154 return unp_connect2(so1, so2);
155}
156
157/* control is EOPNOTSUPP */
158
159static int
160uipc_detach(struct socket *so)
161{
162 struct unpcb *unp = sotounpcb(so);
163
164 if (unp == 0)
165 return EINVAL;
166
167 unp_detach(unp);
168 return 0;
169}
170
171static int
172uipc_disconnect(struct socket *so)
173{
174 struct unpcb *unp = sotounpcb(so);
175
176 if (unp == 0)
177 return EINVAL;
178 unp_disconnect(unp);
179 return 0;
180}
181
182static int
183uipc_listen(struct socket *so, struct proc *p)
184{
185 struct unpcb *unp = sotounpcb(so);
186
187 if (unp == 0 || unp->unp_vnode == 0)
188 return EINVAL;
189 return 0;
190}
191
192static int
194uipc_peeraddr(struct socket *so, struct mbuf *nam)
193uipc_peeraddr(struct socket *so, struct sockaddr **nam)
195{
196 struct unpcb *unp = sotounpcb(so);
197
198 if (unp == 0)
199 return EINVAL;
194{
195 struct unpcb *unp = sotounpcb(so);
196
197 if (unp == 0)
198 return EINVAL;
200 if (unp->unp_conn && unp->unp_conn->unp_addr) {
201 nam->m_len = unp->unp_conn->unp_addr->m_len;
202 bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),
203 mtod(nam, caddr_t), (unsigned)nam->m_len);
204 } else
205 nam->m_len = 0;
199 if (unp->unp_conn && unp->unp_conn->unp_addr)
200 *nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr,
201 1);
206 return 0;
207}
208
209static int
210uipc_rcvd(struct socket *so, int flags)
211{
212 struct unpcb *unp = sotounpcb(so);
213 struct socket *so2;
214
215 if (unp == 0)
216 return EINVAL;
217 switch (so->so_type) {
218 case SOCK_DGRAM:
219 panic("uipc_rcvd DGRAM?");
220 /*NOTREACHED*/
221
222 case SOCK_STREAM:
223#define rcv (&so->so_rcv)
224#define snd (&so2->so_snd)
225 if (unp->unp_conn == 0)
226 break;
227 so2 = unp->unp_conn->unp_socket;
228 /*
229 * Adjust backpressure on sender
230 * and wakeup any waiting to write.
231 */
232 snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
233 unp->unp_mbcnt = rcv->sb_mbcnt;
234 snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
235 unp->unp_cc = rcv->sb_cc;
236 sowwakeup(so2);
237#undef snd
238#undef rcv
239 break;
240
241 default:
242 panic("uipc_rcvd unknown socktype");
243 }
244 return 0;
245}
246
247/* pru_rcvoob is EOPNOTSUPP */
248
249static int
202 return 0;
203}
204
205static int
206uipc_rcvd(struct socket *so, int flags)
207{
208 struct unpcb *unp = sotounpcb(so);
209 struct socket *so2;
210
211 if (unp == 0)
212 return EINVAL;
213 switch (so->so_type) {
214 case SOCK_DGRAM:
215 panic("uipc_rcvd DGRAM?");
216 /*NOTREACHED*/
217
218 case SOCK_STREAM:
219#define rcv (&so->so_rcv)
220#define snd (&so2->so_snd)
221 if (unp->unp_conn == 0)
222 break;
223 so2 = unp->unp_conn->unp_socket;
224 /*
225 * Adjust backpressure on sender
226 * and wakeup any waiting to write.
227 */
228 snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
229 unp->unp_mbcnt = rcv->sb_mbcnt;
230 snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
231 unp->unp_cc = rcv->sb_cc;
232 sowwakeup(so2);
233#undef snd
234#undef rcv
235 break;
236
237 default:
238 panic("uipc_rcvd unknown socktype");
239 }
240 return 0;
241}
242
243/* pru_rcvoob is EOPNOTSUPP */
244
245static int
250uipc_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
246uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
251 struct mbuf *control, struct proc *p)
252{
253 int error = 0;
254 struct unpcb *unp = sotounpcb(so);
255 struct socket *so2;
256
257 if (unp == 0) {
258 error = EINVAL;
259 goto release;
260 }
261 if (flags & PRUS_OOB) {
262 error = EOPNOTSUPP;
263 goto release;
264 }
265
266 if (control && (error = unp_internalize(control, p)))
267 goto release;
268
269 switch (so->so_type) {
270 case SOCK_DGRAM:
271 {
272 struct sockaddr *from;
273
274 if (nam) {
275 if (unp->unp_conn) {
276 error = EISCONN;
277 break;
278 }
279 error = unp_connect(so, nam, p);
280 if (error)
281 break;
282 } else {
283 if (unp->unp_conn == 0) {
284 error = ENOTCONN;
285 break;
286 }
287 }
288 so2 = unp->unp_conn->unp_socket;
289 if (unp->unp_addr)
247 struct mbuf *control, struct proc *p)
248{
249 int error = 0;
250 struct unpcb *unp = sotounpcb(so);
251 struct socket *so2;
252
253 if (unp == 0) {
254 error = EINVAL;
255 goto release;
256 }
257 if (flags & PRUS_OOB) {
258 error = EOPNOTSUPP;
259 goto release;
260 }
261
262 if (control && (error = unp_internalize(control, p)))
263 goto release;
264
265 switch (so->so_type) {
266 case SOCK_DGRAM:
267 {
268 struct sockaddr *from;
269
270 if (nam) {
271 if (unp->unp_conn) {
272 error = EISCONN;
273 break;
274 }
275 error = unp_connect(so, nam, p);
276 if (error)
277 break;
278 } else {
279 if (unp->unp_conn == 0) {
280 error = ENOTCONN;
281 break;
282 }
283 }
284 so2 = unp->unp_conn->unp_socket;
285 if (unp->unp_addr)
290 from = mtod(unp->unp_addr, struct sockaddr *);
286 from = (struct sockaddr *)unp->unp_addr;
291 else
292 from = &sun_noname;
293 if (sbappendaddr(&so2->so_rcv, from, m, control)) {
294 sorwakeup(so2);
295 m = 0;
296 control = 0;
297 } else
298 error = ENOBUFS;
299 if (nam)
300 unp_disconnect(unp);
301 break;
302 }
303
304 case SOCK_STREAM:
305#define rcv (&so2->so_rcv)
306#define snd (&so->so_snd)
307 /* Connect if not connected yet. */
308 /*
309 * Note: A better implementation would complain
310 * if not equal to the peer's address.
311 */
312 if ((so->so_state & SS_ISCONNECTED) == 0) {
313 if (nam) {
314 error = unp_connect(so, nam, p);
315 if (error)
316 break; /* XXX */
317 } else {
318 error = ENOTCONN;
319 break;
320 }
321 }
322
323 if (so->so_state & SS_CANTSENDMORE) {
324 error = EPIPE;
325 break;
326 }
327 if (unp->unp_conn == 0)
328 panic("uipc_send connected but no connection?");
329 so2 = unp->unp_conn->unp_socket;
330 /*
331 * Send to paired receive port, and then reduce
332 * send buffer hiwater marks to maintain backpressure.
333 * Wake up readers.
334 */
335 if (control) {
336 if (sbappendcontrol(rcv, m, control))
337 control = 0;
338 } else
339 sbappend(rcv, m);
340 snd->sb_mbmax -=
341 rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
342 unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
343 snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
344 unp->unp_conn->unp_cc = rcv->sb_cc;
345 sorwakeup(so2);
346 m = 0;
347#undef snd
348#undef rcv
349 break;
350
351 default:
352 panic("uipc_send unknown socktype");
353 }
354
355 /*
356 * SEND_EOF is equivalent to a SEND followed by
357 * a SHUTDOWN.
358 */
359 if (flags & PRUS_EOF) {
360 socantsendmore(so);
361 unp_shutdown(unp);
362 }
363
364release:
365 if (control)
366 m_freem(control);
367 if (m)
368 m_freem(m);
369 return error;
370}
371
372static int
373uipc_sense(struct socket *so, struct stat *sb)
374{
375 struct unpcb *unp = sotounpcb(so);
376 struct socket *so2;
377
378 if (unp == 0)
379 return EINVAL;
380 sb->st_blksize = so->so_snd.sb_hiwat;
381 if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {
382 so2 = unp->unp_conn->unp_socket;
383 sb->st_blksize += so2->so_rcv.sb_cc;
384 }
385 sb->st_dev = NODEV;
386 if (unp->unp_ino == 0)
387 unp->unp_ino = unp_ino++;
388 sb->st_ino = unp->unp_ino;
389 return (0);
390}
391
392static int
393uipc_shutdown(struct socket *so)
394{
395 struct unpcb *unp = sotounpcb(so);
396
397 if (unp == 0)
398 return EINVAL;
399 socantsendmore(so);
400 unp_shutdown(unp);
401 return 0;
402}
403
404static int
287 else
288 from = &sun_noname;
289 if (sbappendaddr(&so2->so_rcv, from, m, control)) {
290 sorwakeup(so2);
291 m = 0;
292 control = 0;
293 } else
294 error = ENOBUFS;
295 if (nam)
296 unp_disconnect(unp);
297 break;
298 }
299
300 case SOCK_STREAM:
301#define rcv (&so2->so_rcv)
302#define snd (&so->so_snd)
303 /* Connect if not connected yet. */
304 /*
305 * Note: A better implementation would complain
306 * if not equal to the peer's address.
307 */
308 if ((so->so_state & SS_ISCONNECTED) == 0) {
309 if (nam) {
310 error = unp_connect(so, nam, p);
311 if (error)
312 break; /* XXX */
313 } else {
314 error = ENOTCONN;
315 break;
316 }
317 }
318
319 if (so->so_state & SS_CANTSENDMORE) {
320 error = EPIPE;
321 break;
322 }
323 if (unp->unp_conn == 0)
324 panic("uipc_send connected but no connection?");
325 so2 = unp->unp_conn->unp_socket;
326 /*
327 * Send to paired receive port, and then reduce
328 * send buffer hiwater marks to maintain backpressure.
329 * Wake up readers.
330 */
331 if (control) {
332 if (sbappendcontrol(rcv, m, control))
333 control = 0;
334 } else
335 sbappend(rcv, m);
336 snd->sb_mbmax -=
337 rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
338 unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
339 snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
340 unp->unp_conn->unp_cc = rcv->sb_cc;
341 sorwakeup(so2);
342 m = 0;
343#undef snd
344#undef rcv
345 break;
346
347 default:
348 panic("uipc_send unknown socktype");
349 }
350
351 /*
352 * SEND_EOF is equivalent to a SEND followed by
353 * a SHUTDOWN.
354 */
355 if (flags & PRUS_EOF) {
356 socantsendmore(so);
357 unp_shutdown(unp);
358 }
359
360release:
361 if (control)
362 m_freem(control);
363 if (m)
364 m_freem(m);
365 return error;
366}
367
368static int
369uipc_sense(struct socket *so, struct stat *sb)
370{
371 struct unpcb *unp = sotounpcb(so);
372 struct socket *so2;
373
374 if (unp == 0)
375 return EINVAL;
376 sb->st_blksize = so->so_snd.sb_hiwat;
377 if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {
378 so2 = unp->unp_conn->unp_socket;
379 sb->st_blksize += so2->so_rcv.sb_cc;
380 }
381 sb->st_dev = NODEV;
382 if (unp->unp_ino == 0)
383 unp->unp_ino = unp_ino++;
384 sb->st_ino = unp->unp_ino;
385 return (0);
386}
387
388static int
389uipc_shutdown(struct socket *so)
390{
391 struct unpcb *unp = sotounpcb(so);
392
393 if (unp == 0)
394 return EINVAL;
395 socantsendmore(so);
396 unp_shutdown(unp);
397 return 0;
398}
399
400static int
405uipc_sockaddr(struct socket *so, struct mbuf *nam)
401uipc_sockaddr(struct socket *so, struct sockaddr **nam)
406{
407 struct unpcb *unp = sotounpcb(so);
408
409 if (unp == 0)
410 return EINVAL;
402{
403 struct unpcb *unp = sotounpcb(so);
404
405 if (unp == 0)
406 return EINVAL;
411 if (unp->unp_addr) {
412 nam->m_len = unp->unp_addr->m_len;
413 bcopy(mtod(unp->unp_addr, caddr_t),
414 mtod(nam, caddr_t), (unsigned)nam->m_len);
415 } else
416 nam->m_len = 0;
407 if (unp->unp_addr)
408 *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr, 1);
417 return 0;
418}
419
420struct pr_usrreqs uipc_usrreqs = {
421 uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect,
422 uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect,
423 uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp,
424 uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr,
425 sosend, soreceive, soselect
426};
427
428/*
429 * Both send and receive buffers are allocated PIPSIZ bytes of buffering
430 * for stream sockets, although the total for sender and receiver is
431 * actually only PIPSIZ.
432 * Datagram sockets really use the sendspace as the maximum datagram size,
433 * and don't really want to reserve the sendspace. Their recvspace should
434 * be large enough for at least one max-size datagram plus address.
435 */
436#ifndef PIPSIZ
437#define PIPSIZ 8192
438#endif
439static u_long unpst_sendspace = PIPSIZ;
440static u_long unpst_recvspace = PIPSIZ;
441static u_long unpdg_sendspace = 2*1024; /* really max datagram size */
442static u_long unpdg_recvspace = 4*1024;
443
444static int unp_rights; /* file descriptors in flight */
445
446SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
447 &unpst_sendspace, 0, "");
448SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
449 &unpst_recvspace, 0, "");
450SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
451 &unpdg_sendspace, 0, "");
452SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
453 &unpdg_recvspace, 0, "");
454SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
455
456static int
457unp_attach(so)
458 struct socket *so;
459{
460 register struct mbuf *m;
461 register struct unpcb *unp;
462 int error;
463
464 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
465 switch (so->so_type) {
466
467 case SOCK_STREAM:
468 error = soreserve(so, unpst_sendspace, unpst_recvspace);
469 break;
470
471 case SOCK_DGRAM:
472 error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
473 break;
474
475 default:
476 panic("unp_attach");
477 }
478 if (error)
479 return (error);
480 }
409 return 0;
410}
411
412struct pr_usrreqs uipc_usrreqs = {
413 uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect,
414 uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect,
415 uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp,
416 uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr,
417 sosend, soreceive, soselect
418};
419
420/*
421 * Both send and receive buffers are allocated PIPSIZ bytes of buffering
422 * for stream sockets, although the total for sender and receiver is
423 * actually only PIPSIZ.
424 * Datagram sockets really use the sendspace as the maximum datagram size,
425 * and don't really want to reserve the sendspace. Their recvspace should
426 * be large enough for at least one max-size datagram plus address.
427 */
428#ifndef PIPSIZ
429#define PIPSIZ 8192
430#endif
431static u_long unpst_sendspace = PIPSIZ;
432static u_long unpst_recvspace = PIPSIZ;
433static u_long unpdg_sendspace = 2*1024; /* really max datagram size */
434static u_long unpdg_recvspace = 4*1024;
435
436static int unp_rights; /* file descriptors in flight */
437
438SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
439 &unpst_sendspace, 0, "");
440SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
441 &unpst_recvspace, 0, "");
442SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
443 &unpdg_sendspace, 0, "");
444SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
445 &unpdg_recvspace, 0, "");
446SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
447
448static int
449unp_attach(so)
450 struct socket *so;
451{
452 register struct mbuf *m;
453 register struct unpcb *unp;
454 int error;
455
456 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
457 switch (so->so_type) {
458
459 case SOCK_STREAM:
460 error = soreserve(so, unpst_sendspace, unpst_recvspace);
461 break;
462
463 case SOCK_DGRAM:
464 error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
465 break;
466
467 default:
468 panic("unp_attach");
469 }
470 if (error)
471 return (error);
472 }
481 m = m_getclr(M_DONTWAIT, MT_PCB);
482 if (m == NULL)
473 MALLOC(unp, struct unpcb *, sizeof *unp, M_PCB, M_NOWAIT);
474 if (unp == NULL)
483 return (ENOBUFS);
475 return (ENOBUFS);
484 unp = mtod(m, struct unpcb *);
476 bzero(unp, sizeof *unp);
485 so->so_pcb = (caddr_t)unp;
486 unp->unp_socket = so;
487 return (0);
488}
489
490static void
491unp_detach(unp)
492 register struct unpcb *unp;
493{
477 so->so_pcb = (caddr_t)unp;
478 unp->unp_socket = so;
479 return (0);
480}
481
482static void
483unp_detach(unp)
484 register struct unpcb *unp;
485{
494
495 if (unp->unp_vnode) {
496 unp->unp_vnode->v_socket = 0;
497 vrele(unp->unp_vnode);
498 unp->unp_vnode = 0;
499 }
500 if (unp->unp_conn)
501 unp_disconnect(unp);
502 while (unp->unp_refs)
503 unp_drop(unp->unp_refs, ECONNRESET);
504 soisdisconnected(unp->unp_socket);
505 unp->unp_socket->so_pcb = 0;
506 if (unp_rights) {
507 /*
508 * Normally the receive buffer is flushed later,
509 * in sofree, but if our receive buffer holds references
510 * to descriptors that are now garbage, we will dispose
511 * of those descriptor references after the garbage collector
512 * gets them (resulting in a "panic: closef: count < 0").
513 */
514 sorflush(unp->unp_socket);
515 unp_gc();
516 }
486 if (unp->unp_vnode) {
487 unp->unp_vnode->v_socket = 0;
488 vrele(unp->unp_vnode);
489 unp->unp_vnode = 0;
490 }
491 if (unp->unp_conn)
492 unp_disconnect(unp);
493 while (unp->unp_refs)
494 unp_drop(unp->unp_refs, ECONNRESET);
495 soisdisconnected(unp->unp_socket);
496 unp->unp_socket->so_pcb = 0;
497 if (unp_rights) {
498 /*
499 * Normally the receive buffer is flushed later,
500 * in sofree, but if our receive buffer holds references
501 * to descriptors that are now garbage, we will dispose
502 * of those descriptor references after the garbage collector
503 * gets them (resulting in a "panic: closef: count < 0").
504 */
505 sorflush(unp->unp_socket);
506 unp_gc();
507 }
517 m_freem(unp->unp_addr);
518 (void) m_free(dtom(unp));
508 if (unp->unp_addr)
509 FREE(unp->unp_addr, M_SONAME);
510 FREE(unp, M_PCB);
519}
520
521static int
522unp_bind(unp, nam, p)
523 struct unpcb *unp;
511}
512
513static int
514unp_bind(unp, nam, p)
515 struct unpcb *unp;
524 struct mbuf *nam;
516 struct sockaddr *nam;
525 struct proc *p;
526{
517 struct proc *p;
518{
527 struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
519 struct sockaddr_un *soun = (struct sockaddr_un *)nam;
528 register struct vnode *vp;
529 struct vattr vattr;
520 register struct vnode *vp;
521 struct vattr vattr;
530 int error;
522 int error, namelen;
531 struct nameidata nd;
523 struct nameidata nd;
524 char buf[SOCK_MAXADDRLEN];
532
525
533 NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
534 soun->sun_path, p);
535 if (unp->unp_vnode != NULL)
536 return (EINVAL);
526 if (unp->unp_vnode != NULL)
527 return (EINVAL);
537 if (nam->m_len == MLEN) {
538 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)
539 return (EINVAL);
540 } else
541 *(mtod(nam, caddr_t) + nam->m_len) = 0;
528#define offsetof(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
529 namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
530 if (namelen <= 0)
531 return EINVAL;
532 strncpy(buf, soun->sun_path, namelen);
533 buf[namelen] = 0; /* null-terminate the string */
534 NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
535 buf, p);
542/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
543 error = namei(&nd);
544 if (error)
545 return (error);
546 vp = nd.ni_vp;
547 if (vp != NULL) {
548 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
549 if (nd.ni_dvp == vp)
550 vrele(nd.ni_dvp);
551 else
552 vput(nd.ni_dvp);
553 vrele(vp);
554 return (EADDRINUSE);
555 }
556 VATTR_NULL(&vattr);
557 vattr.va_type = VSOCK;
558 vattr.va_mode = (ACCESSPERMS & ~p->p_fd->fd_cmask);
559 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
560 if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr))
561 return (error);
562 vp = nd.ni_vp;
563 vp->v_socket = unp->unp_socket;
564 unp->unp_vnode = vp;
536/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
537 error = namei(&nd);
538 if (error)
539 return (error);
540 vp = nd.ni_vp;
541 if (vp != NULL) {
542 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
543 if (nd.ni_dvp == vp)
544 vrele(nd.ni_dvp);
545 else
546 vput(nd.ni_dvp);
547 vrele(vp);
548 return (EADDRINUSE);
549 }
550 VATTR_NULL(&vattr);
551 vattr.va_type = VSOCK;
552 vattr.va_mode = (ACCESSPERMS & ~p->p_fd->fd_cmask);
553 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
554 if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr))
555 return (error);
556 vp = nd.ni_vp;
557 vp->v_socket = unp->unp_socket;
558 unp->unp_vnode = vp;
565 unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL);
559 unp->unp_addr = (struct sockaddr_un *)dup_sockaddr(nam, 1);
566 VOP_UNLOCK(vp, 0, p);
567 return (0);
568}
569
570static int
571unp_connect(so, nam, p)
572 struct socket *so;
560 VOP_UNLOCK(vp, 0, p);
561 return (0);
562}
563
564static int
565unp_connect(so, nam, p)
566 struct socket *so;
573 struct mbuf *nam;
567 struct sockaddr *nam;
574 struct proc *p;
575{
568 struct proc *p;
569{
576 register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
570 register struct sockaddr_un *soun = (struct sockaddr_un *)nam;
577 register struct vnode *vp;
578 register struct socket *so2, *so3;
579 struct unpcb *unp2, *unp3;
571 register struct vnode *vp;
572 register struct socket *so2, *so3;
573 struct unpcb *unp2, *unp3;
580 int error;
574 int error, len;
581 struct nameidata nd;
575 struct nameidata nd;
576 char buf[SOCK_MAXADDRLEN];
582
577
583 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, soun->sun_path, p);
584 if (nam->m_data + nam->m_len == &nam->m_dat[MLEN]) { /* XXX */
585 if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)
586 return (EMSGSIZE);
587 } else
588 *(mtod(nam, caddr_t) + nam->m_len) = 0;
578 len = nam->sa_len - offsetof(struct sockaddr_un, sun_path);
579 if (len <= 0)
580 return EINVAL;
581 strncpy(buf, soun->sun_path, len);
582 buf[len] = 0;
583
584 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, p);
589 error = namei(&nd);
590 if (error)
591 return (error);
592 vp = nd.ni_vp;
593 if (vp->v_type != VSOCK) {
594 error = ENOTSOCK;
595 goto bad;
596 }
597 error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p);
598 if (error)
599 goto bad;
600 so2 = vp->v_socket;
601 if (so2 == 0) {
602 error = ECONNREFUSED;
603 goto bad;
604 }
605 if (so->so_type != so2->so_type) {
606 error = EPROTOTYPE;
607 goto bad;
608 }
609 if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
610 if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
611 (so3 = sonewconn(so2, 0)) == 0) {
612 error = ECONNREFUSED;
613 goto bad;
614 }
615 unp2 = sotounpcb(so2);
616 unp3 = sotounpcb(so3);
617 if (unp2->unp_addr)
585 error = namei(&nd);
586 if (error)
587 return (error);
588 vp = nd.ni_vp;
589 if (vp->v_type != VSOCK) {
590 error = ENOTSOCK;
591 goto bad;
592 }
593 error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p);
594 if (error)
595 goto bad;
596 so2 = vp->v_socket;
597 if (so2 == 0) {
598 error = ECONNREFUSED;
599 goto bad;
600 }
601 if (so->so_type != so2->so_type) {
602 error = EPROTOTYPE;
603 goto bad;
604 }
605 if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
606 if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
607 (so3 = sonewconn(so2, 0)) == 0) {
608 error = ECONNREFUSED;
609 goto bad;
610 }
611 unp2 = sotounpcb(so2);
612 unp3 = sotounpcb(so3);
613 if (unp2->unp_addr)
618 unp3->unp_addr =
619 m_copy(unp2->unp_addr, 0, (int)M_COPYALL);
614 unp3->unp_addr = (struct sockaddr_un *)
615 dup_sockaddr((struct sockaddr *)
616 unp2->unp_addr, 1);
620 so2 = so3;
621 }
622 error = unp_connect2(so, so2);
623bad:
624 vput(vp);
625 return (error);
626}
627
628int
629unp_connect2(so, so2)
630 register struct socket *so;
631 register struct socket *so2;
632{
633 register struct unpcb *unp = sotounpcb(so);
634 register struct unpcb *unp2;
635
636 if (so2->so_type != so->so_type)
637 return (EPROTOTYPE);
638 unp2 = sotounpcb(so2);
639 unp->unp_conn = unp2;
640 switch (so->so_type) {
641
642 case SOCK_DGRAM:
643 unp->unp_nextref = unp2->unp_refs;
644 unp2->unp_refs = unp;
645 soisconnected(so);
646 break;
647
648 case SOCK_STREAM:
649 unp2->unp_conn = unp;
650 soisconnected(so);
651 soisconnected(so2);
652 break;
653
654 default:
655 panic("unp_connect2");
656 }
657 return (0);
658}
659
660static void
661unp_disconnect(unp)
662 struct unpcb *unp;
663{
664 register struct unpcb *unp2 = unp->unp_conn;
665
666 if (unp2 == 0)
667 return;
668 unp->unp_conn = 0;
669 switch (unp->unp_socket->so_type) {
670
671 case SOCK_DGRAM:
672 if (unp2->unp_refs == unp)
673 unp2->unp_refs = unp->unp_nextref;
674 else {
675 unp2 = unp2->unp_refs;
676 for (;;) {
677 if (unp2 == 0)
678 panic("unp_disconnect");
679 if (unp2->unp_nextref == unp)
680 break;
681 unp2 = unp2->unp_nextref;
682 }
683 unp2->unp_nextref = unp->unp_nextref;
684 }
685 unp->unp_nextref = 0;
686 unp->unp_socket->so_state &= ~SS_ISCONNECTED;
687 break;
688
689 case SOCK_STREAM:
690 soisdisconnected(unp->unp_socket);
691 unp2->unp_conn = 0;
692 soisdisconnected(unp2->unp_socket);
693 break;
694 }
695}
696
697#ifdef notdef
698void
699unp_abort(unp)
700 struct unpcb *unp;
701{
702
703 unp_detach(unp);
704}
705#endif
706
707static void
708unp_shutdown(unp)
709 struct unpcb *unp;
710{
711 struct socket *so;
712
713 if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn &&
714 (so = unp->unp_conn->unp_socket))
715 socantrcvmore(so);
716}
717
718static void
719unp_drop(unp, errno)
720 struct unpcb *unp;
721 int errno;
722{
723 struct socket *so = unp->unp_socket;
724
725 so->so_error = errno;
726 unp_disconnect(unp);
727 if (so->so_head) {
728 so->so_pcb = (caddr_t) 0;
617 so2 = so3;
618 }
619 error = unp_connect2(so, so2);
620bad:
621 vput(vp);
622 return (error);
623}
624
625int
626unp_connect2(so, so2)
627 register struct socket *so;
628 register struct socket *so2;
629{
630 register struct unpcb *unp = sotounpcb(so);
631 register struct unpcb *unp2;
632
633 if (so2->so_type != so->so_type)
634 return (EPROTOTYPE);
635 unp2 = sotounpcb(so2);
636 unp->unp_conn = unp2;
637 switch (so->so_type) {
638
639 case SOCK_DGRAM:
640 unp->unp_nextref = unp2->unp_refs;
641 unp2->unp_refs = unp;
642 soisconnected(so);
643 break;
644
645 case SOCK_STREAM:
646 unp2->unp_conn = unp;
647 soisconnected(so);
648 soisconnected(so2);
649 break;
650
651 default:
652 panic("unp_connect2");
653 }
654 return (0);
655}
656
657static void
658unp_disconnect(unp)
659 struct unpcb *unp;
660{
661 register struct unpcb *unp2 = unp->unp_conn;
662
663 if (unp2 == 0)
664 return;
665 unp->unp_conn = 0;
666 switch (unp->unp_socket->so_type) {
667
668 case SOCK_DGRAM:
669 if (unp2->unp_refs == unp)
670 unp2->unp_refs = unp->unp_nextref;
671 else {
672 unp2 = unp2->unp_refs;
673 for (;;) {
674 if (unp2 == 0)
675 panic("unp_disconnect");
676 if (unp2->unp_nextref == unp)
677 break;
678 unp2 = unp2->unp_nextref;
679 }
680 unp2->unp_nextref = unp->unp_nextref;
681 }
682 unp->unp_nextref = 0;
683 unp->unp_socket->so_state &= ~SS_ISCONNECTED;
684 break;
685
686 case SOCK_STREAM:
687 soisdisconnected(unp->unp_socket);
688 unp2->unp_conn = 0;
689 soisdisconnected(unp2->unp_socket);
690 break;
691 }
692}
693
694#ifdef notdef
695void
696unp_abort(unp)
697 struct unpcb *unp;
698{
699
700 unp_detach(unp);
701}
702#endif
703
704static void
705unp_shutdown(unp)
706 struct unpcb *unp;
707{
708 struct socket *so;
709
710 if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn &&
711 (so = unp->unp_conn->unp_socket))
712 socantrcvmore(so);
713}
714
715static void
716unp_drop(unp, errno)
717 struct unpcb *unp;
718 int errno;
719{
720 struct socket *so = unp->unp_socket;
721
722 so->so_error = errno;
723 unp_disconnect(unp);
724 if (so->so_head) {
725 so->so_pcb = (caddr_t) 0;
729 m_freem(unp->unp_addr);
730 (void) m_free(dtom(unp));
726 if (unp->unp_addr)
727 FREE(unp->unp_addr, M_SONAME);
728 FREE(unp, M_PCB);
731 sofree(so);
732 }
733}
734
735#ifdef notdef
736void
737unp_drain()
738{
739
740}
741#endif
742
743int
744unp_externalize(rights)
745 struct mbuf *rights;
746{
747 struct proc *p = curproc; /* XXX */
748 register int i;
749 register struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
750 register struct file **rp = (struct file **)(cm + 1);
751 register struct file *fp;
752 int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int);
753 int f;
754
755 /*
756 * if the new FD's will not fit, then we free them all
757 */
758 if (!fdavail(p, newfds)) {
759 for (i = 0; i < newfds; i++) {
760 fp = *rp;
761 unp_discard(fp);
762 *rp++ = 0;
763 }
764 return (EMSGSIZE);
765 }
766 /*
767 * now change each pointer to an fd in the global table to
768 * an integer that is the index to the local fd table entry
769 * that we set up to point to the global one we are transferring.
770 * XXX this assumes a pointer and int are the same size...!
771 */
772 for (i = 0; i < newfds; i++) {
773 if (fdalloc(p, 0, &f))
774 panic("unp_externalize");
775 fp = *rp;
776 p->p_fd->fd_ofiles[f] = fp;
777 fp->f_msgcount--;
778 unp_rights--;
779 *(int *)rp++ = f;
780 }
781 return (0);
782}
783
784#ifndef MIN
785#define MIN(a,b) (((a)<(b))?(a):(b))
786#endif
787
788static int
789unp_internalize(control, p)
790 struct mbuf *control;
791 struct proc *p;
792{
793 struct filedesc *fdp = p->p_fd;
794 register struct cmsghdr *cm = mtod(control, struct cmsghdr *);
795 register struct file **rp;
796 register struct file *fp;
797 register int i, fd;
798 register struct cmsgcred *cmcred;
799 int oldfds;
800
801 if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) ||
802 cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len)
803 return (EINVAL);
804
805 /*
806 * Fill in credential information.
807 */
808 if (cm->cmsg_type == SCM_CREDS) {
809 cmcred = (struct cmsgcred *)(cm + 1);
810 cmcred->cmcred_pid = p->p_pid;
811 cmcred->cmcred_uid = p->p_cred->p_ruid;
812 cmcred->cmcred_gid = p->p_cred->p_rgid;
813 cmcred->cmcred_euid = p->p_ucred->cr_uid;
814 cmcred->cmcred_ngroups = MIN(p->p_ucred->cr_ngroups,
815 CMGROUP_MAX);
816 for (i = 0; i < cmcred->cmcred_ngroups; i++)
817 cmcred->cmcred_groups[i] = p->p_ucred->cr_groups[i];
818 return(0);
819 }
820
821 oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int);
822 /*
823 * check that all the FDs passed in refer to legal OPEN files
824 * If not, reject the entire operation.
825 */
826 rp = (struct file **)(cm + 1);
827 for (i = 0; i < oldfds; i++) {
828 fd = *(int *)rp++;
829 if ((unsigned)fd >= fdp->fd_nfiles ||
830 fdp->fd_ofiles[fd] == NULL)
831 return (EBADF);
832 }
833 /*
834 * Now replace the integer FDs with pointers to
835 * the associated global file table entry..
836 * XXX this assumes a pointer and an int are the same size!
837 */
838 rp = (struct file **)(cm + 1);
839 for (i = 0; i < oldfds; i++) {
840 fp = fdp->fd_ofiles[*(int *)rp];
841 *rp++ = fp;
842 fp->f_count++;
843 fp->f_msgcount++;
844 unp_rights++;
845 }
846 return (0);
847}
848
849static int unp_defer, unp_gcing;
850
851static void
852unp_gc()
853{
854 register struct file *fp, *nextfp;
855 register struct socket *so;
856 struct file **extra_ref, **fpp;
857 int nunref, i;
858
859 if (unp_gcing)
860 return;
861 unp_gcing = 1;
862 unp_defer = 0;
863 /*
864 * before going through all this, set all FDs to
865 * be NOT defered and NOT externally accessible
866 */
867 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next)
868 fp->f_flag &= ~(FMARK|FDEFER);
869 do {
870 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
871 /*
872 * If the file is not open, skip it
873 */
874 if (fp->f_count == 0)
875 continue;
876 /*
877 * If we already marked it as 'defer' in a
878 * previous pass, then try process it this time
879 * and un-mark it
880 */
881 if (fp->f_flag & FDEFER) {
882 fp->f_flag &= ~FDEFER;
883 unp_defer--;
884 } else {
885 /*
886 * if it's not defered, then check if it's
887 * already marked.. if so skip it
888 */
889 if (fp->f_flag & FMARK)
890 continue;
891 /*
892 * If all references are from messages
893 * in transit, then skip it. it's not
894 * externally accessible.
895 */
896 if (fp->f_count == fp->f_msgcount)
897 continue;
898 /*
899 * If it got this far then it must be
900 * externally accessible.
901 */
902 fp->f_flag |= FMARK;
903 }
904 /*
905 * either it was defered, or it is externally
906 * accessible and not already marked so.
907 * Now check if it is possibly one of OUR sockets.
908 */
909 if (fp->f_type != DTYPE_SOCKET ||
910 (so = (struct socket *)fp->f_data) == 0)
911 continue;
912 if (so->so_proto->pr_domain != &localdomain ||
913 (so->so_proto->pr_flags&PR_RIGHTS) == 0)
914 continue;
915#ifdef notdef
916 if (so->so_rcv.sb_flags & SB_LOCK) {
917 /*
918 * This is problematical; it's not clear
919 * we need to wait for the sockbuf to be
920 * unlocked (on a uniprocessor, at least),
921 * and it's also not clear what to do
922 * if sbwait returns an error due to receipt
923 * of a signal. If sbwait does return
924 * an error, we'll go into an infinite
925 * loop. Delete all of this for now.
926 */
927 (void) sbwait(&so->so_rcv);
928 goto restart;
929 }
930#endif
931 /*
932 * So, Ok, it's one of our sockets and it IS externally
933 * accessible (or was defered). Now we look
934 * to see if we hold any file descriptors in it's
935 * message buffers. Follow those links and mark them
936 * as accessible too.
937 */
938 unp_scan(so->so_rcv.sb_mb, unp_mark);
939 }
940 } while (unp_defer);
941 /*
942 * We grab an extra reference to each of the file table entries
943 * that are not otherwise accessible and then free the rights
944 * that are stored in messages on them.
945 *
946 * The bug in the orginal code is a little tricky, so I'll describe
947 * what's wrong with it here.
948 *
949 * It is incorrect to simply unp_discard each entry for f_msgcount
950 * times -- consider the case of sockets A and B that contain
951 * references to each other. On a last close of some other socket,
952 * we trigger a gc since the number of outstanding rights (unp_rights)
953 * is non-zero. If during the sweep phase the gc code un_discards,
954 * we end up doing a (full) closef on the descriptor. A closef on A
955 * results in the following chain. Closef calls soo_close, which
956 * calls soclose. Soclose calls first (through the switch
957 * uipc_usrreq) unp_detach, which re-invokes unp_gc. Unp_gc simply
958 * returns because the previous instance had set unp_gcing, and
959 * we return all the way back to soclose, which marks the socket
960 * with SS_NOFDREF, and then calls sofree. Sofree calls sorflush
961 * to free up the rights that are queued in messages on the socket A,
962 * i.e., the reference on B. The sorflush calls via the dom_dispose
963 * switch unp_dispose, which unp_scans with unp_discard. This second
964 * instance of unp_discard just calls closef on B.
965 *
966 * Well, a similar chain occurs on B, resulting in a sorflush on B,
967 * which results in another closef on A. Unfortunately, A is already
968 * being closed, and the descriptor has already been marked with
969 * SS_NOFDREF, and soclose panics at this point.
970 *
971 * Here, we first take an extra reference to each inaccessible
972 * descriptor. Then, we call sorflush ourself, since we know
973 * it is a Unix domain socket anyhow. After we destroy all the
974 * rights carried in messages, we do a last closef to get rid
975 * of our extra reference. This is the last close, and the
976 * unp_detach etc will shut down the socket.
977 *
978 * 91/09/19, bsy@cs.cmu.edu
979 */
980 extra_ref = malloc(nfiles * sizeof(struct file *), M_FILE, M_WAITOK);
981 for (nunref = 0, fp = filehead.lh_first, fpp = extra_ref; fp != 0;
982 fp = nextfp) {
983 nextfp = fp->f_list.le_next;
984 /*
985 * If it's not open, skip it
986 */
987 if (fp->f_count == 0)
988 continue;
989 /*
990 * If all refs are from msgs, and it's not marked accessible
991 * then it must be referenced from some unreachable cycle
992 * of (shut-down) FDs, so include it in our
993 * list of FDs to remove
994 */
995 if (fp->f_count == fp->f_msgcount && !(fp->f_flag & FMARK)) {
996 *fpp++ = fp;
997 nunref++;
998 fp->f_count++;
999 }
1000 }
1001 /*
1002 * for each FD on our hit list, do the following two things
1003 */
1004 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
1005 sorflush((struct socket *)(*fpp)->f_data);
1006 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
1007 closef(*fpp, (struct proc *) NULL);
1008 free((caddr_t)extra_ref, M_FILE);
1009 unp_gcing = 0;
1010}
1011
1012void
1013unp_dispose(m)
1014 struct mbuf *m;
1015{
1016
1017 if (m)
1018 unp_scan(m, unp_discard);
1019}
1020
1021static void
1022unp_scan(m0, op)
1023 register struct mbuf *m0;
1024 void (*op) __P((struct file *));
1025{
1026 register struct mbuf *m;
1027 register struct file **rp;
1028 register struct cmsghdr *cm;
1029 register int i;
1030 int qfds;
1031
1032 while (m0) {
1033 for (m = m0; m; m = m->m_next)
1034 if (m->m_type == MT_CONTROL &&
1035 m->m_len >= sizeof(*cm)) {
1036 cm = mtod(m, struct cmsghdr *);
1037 if (cm->cmsg_level != SOL_SOCKET ||
1038 cm->cmsg_type != SCM_RIGHTS)
1039 continue;
1040 qfds = (cm->cmsg_len - sizeof *cm)
1041 / sizeof (struct file *);
1042 rp = (struct file **)(cm + 1);
1043 for (i = 0; i < qfds; i++)
1044 (*op)(*rp++);
1045 break; /* XXX, but saves time */
1046 }
1047 m0 = m0->m_act;
1048 }
1049}
1050
1051static void
1052unp_mark(fp)
1053 struct file *fp;
1054{
1055
1056 if (fp->f_flag & FMARK)
1057 return;
1058 unp_defer++;
1059 fp->f_flag |= (FMARK|FDEFER);
1060}
1061
1062static void
1063unp_discard(fp)
1064 struct file *fp;
1065{
1066
1067 fp->f_msgcount--;
1068 unp_rights--;
1069 (void) closef(fp, (struct proc *)NULL);
1070}
729 sofree(so);
730 }
731}
732
733#ifdef notdef
734void
735unp_drain()
736{
737
738}
739#endif
740
741int
742unp_externalize(rights)
743 struct mbuf *rights;
744{
745 struct proc *p = curproc; /* XXX */
746 register int i;
747 register struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
748 register struct file **rp = (struct file **)(cm + 1);
749 register struct file *fp;
750 int newfds = (cm->cmsg_len - sizeof(*cm)) / sizeof (int);
751 int f;
752
753 /*
754 * if the new FD's will not fit, then we free them all
755 */
756 if (!fdavail(p, newfds)) {
757 for (i = 0; i < newfds; i++) {
758 fp = *rp;
759 unp_discard(fp);
760 *rp++ = 0;
761 }
762 return (EMSGSIZE);
763 }
764 /*
765 * now change each pointer to an fd in the global table to
766 * an integer that is the index to the local fd table entry
767 * that we set up to point to the global one we are transferring.
768 * XXX this assumes a pointer and int are the same size...!
769 */
770 for (i = 0; i < newfds; i++) {
771 if (fdalloc(p, 0, &f))
772 panic("unp_externalize");
773 fp = *rp;
774 p->p_fd->fd_ofiles[f] = fp;
775 fp->f_msgcount--;
776 unp_rights--;
777 *(int *)rp++ = f;
778 }
779 return (0);
780}
781
782#ifndef MIN
783#define MIN(a,b) (((a)<(b))?(a):(b))
784#endif
785
786static int
787unp_internalize(control, p)
788 struct mbuf *control;
789 struct proc *p;
790{
791 struct filedesc *fdp = p->p_fd;
792 register struct cmsghdr *cm = mtod(control, struct cmsghdr *);
793 register struct file **rp;
794 register struct file *fp;
795 register int i, fd;
796 register struct cmsgcred *cmcred;
797 int oldfds;
798
799 if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) ||
800 cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len)
801 return (EINVAL);
802
803 /*
804 * Fill in credential information.
805 */
806 if (cm->cmsg_type == SCM_CREDS) {
807 cmcred = (struct cmsgcred *)(cm + 1);
808 cmcred->cmcred_pid = p->p_pid;
809 cmcred->cmcred_uid = p->p_cred->p_ruid;
810 cmcred->cmcred_gid = p->p_cred->p_rgid;
811 cmcred->cmcred_euid = p->p_ucred->cr_uid;
812 cmcred->cmcred_ngroups = MIN(p->p_ucred->cr_ngroups,
813 CMGROUP_MAX);
814 for (i = 0; i < cmcred->cmcred_ngroups; i++)
815 cmcred->cmcred_groups[i] = p->p_ucred->cr_groups[i];
816 return(0);
817 }
818
819 oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int);
820 /*
821 * check that all the FDs passed in refer to legal OPEN files
822 * If not, reject the entire operation.
823 */
824 rp = (struct file **)(cm + 1);
825 for (i = 0; i < oldfds; i++) {
826 fd = *(int *)rp++;
827 if ((unsigned)fd >= fdp->fd_nfiles ||
828 fdp->fd_ofiles[fd] == NULL)
829 return (EBADF);
830 }
831 /*
832 * Now replace the integer FDs with pointers to
833 * the associated global file table entry..
834 * XXX this assumes a pointer and an int are the same size!
835 */
836 rp = (struct file **)(cm + 1);
837 for (i = 0; i < oldfds; i++) {
838 fp = fdp->fd_ofiles[*(int *)rp];
839 *rp++ = fp;
840 fp->f_count++;
841 fp->f_msgcount++;
842 unp_rights++;
843 }
844 return (0);
845}
846
847static int unp_defer, unp_gcing;
848
849static void
850unp_gc()
851{
852 register struct file *fp, *nextfp;
853 register struct socket *so;
854 struct file **extra_ref, **fpp;
855 int nunref, i;
856
857 if (unp_gcing)
858 return;
859 unp_gcing = 1;
860 unp_defer = 0;
861 /*
862 * before going through all this, set all FDs to
863 * be NOT defered and NOT externally accessible
864 */
865 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next)
866 fp->f_flag &= ~(FMARK|FDEFER);
867 do {
868 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
869 /*
870 * If the file is not open, skip it
871 */
872 if (fp->f_count == 0)
873 continue;
874 /*
875 * If we already marked it as 'defer' in a
876 * previous pass, then try process it this time
877 * and un-mark it
878 */
879 if (fp->f_flag & FDEFER) {
880 fp->f_flag &= ~FDEFER;
881 unp_defer--;
882 } else {
883 /*
884 * if it's not defered, then check if it's
885 * already marked.. if so skip it
886 */
887 if (fp->f_flag & FMARK)
888 continue;
889 /*
890 * If all references are from messages
891 * in transit, then skip it. it's not
892 * externally accessible.
893 */
894 if (fp->f_count == fp->f_msgcount)
895 continue;
896 /*
897 * If it got this far then it must be
898 * externally accessible.
899 */
900 fp->f_flag |= FMARK;
901 }
902 /*
903 * either it was defered, or it is externally
904 * accessible and not already marked so.
905 * Now check if it is possibly one of OUR sockets.
906 */
907 if (fp->f_type != DTYPE_SOCKET ||
908 (so = (struct socket *)fp->f_data) == 0)
909 continue;
910 if (so->so_proto->pr_domain != &localdomain ||
911 (so->so_proto->pr_flags&PR_RIGHTS) == 0)
912 continue;
913#ifdef notdef
914 if (so->so_rcv.sb_flags & SB_LOCK) {
915 /*
916 * This is problematical; it's not clear
917 * we need to wait for the sockbuf to be
918 * unlocked (on a uniprocessor, at least),
919 * and it's also not clear what to do
920 * if sbwait returns an error due to receipt
921 * of a signal. If sbwait does return
922 * an error, we'll go into an infinite
923 * loop. Delete all of this for now.
924 */
925 (void) sbwait(&so->so_rcv);
926 goto restart;
927 }
928#endif
929 /*
930 * So, Ok, it's one of our sockets and it IS externally
931 * accessible (or was defered). Now we look
932 * to see if we hold any file descriptors in it's
933 * message buffers. Follow those links and mark them
934 * as accessible too.
935 */
936 unp_scan(so->so_rcv.sb_mb, unp_mark);
937 }
938 } while (unp_defer);
939 /*
940 * We grab an extra reference to each of the file table entries
941 * that are not otherwise accessible and then free the rights
942 * that are stored in messages on them.
943 *
944 * The bug in the orginal code is a little tricky, so I'll describe
945 * what's wrong with it here.
946 *
947 * It is incorrect to simply unp_discard each entry for f_msgcount
948 * times -- consider the case of sockets A and B that contain
949 * references to each other. On a last close of some other socket,
950 * we trigger a gc since the number of outstanding rights (unp_rights)
951 * is non-zero. If during the sweep phase the gc code un_discards,
952 * we end up doing a (full) closef on the descriptor. A closef on A
953 * results in the following chain. Closef calls soo_close, which
954 * calls soclose. Soclose calls first (through the switch
955 * uipc_usrreq) unp_detach, which re-invokes unp_gc. Unp_gc simply
956 * returns because the previous instance had set unp_gcing, and
957 * we return all the way back to soclose, which marks the socket
958 * with SS_NOFDREF, and then calls sofree. Sofree calls sorflush
959 * to free up the rights that are queued in messages on the socket A,
960 * i.e., the reference on B. The sorflush calls via the dom_dispose
961 * switch unp_dispose, which unp_scans with unp_discard. This second
962 * instance of unp_discard just calls closef on B.
963 *
964 * Well, a similar chain occurs on B, resulting in a sorflush on B,
965 * which results in another closef on A. Unfortunately, A is already
966 * being closed, and the descriptor has already been marked with
967 * SS_NOFDREF, and soclose panics at this point.
968 *
969 * Here, we first take an extra reference to each inaccessible
970 * descriptor. Then, we call sorflush ourself, since we know
971 * it is a Unix domain socket anyhow. After we destroy all the
972 * rights carried in messages, we do a last closef to get rid
973 * of our extra reference. This is the last close, and the
974 * unp_detach etc will shut down the socket.
975 *
976 * 91/09/19, bsy@cs.cmu.edu
977 */
978 extra_ref = malloc(nfiles * sizeof(struct file *), M_FILE, M_WAITOK);
979 for (nunref = 0, fp = filehead.lh_first, fpp = extra_ref; fp != 0;
980 fp = nextfp) {
981 nextfp = fp->f_list.le_next;
982 /*
983 * If it's not open, skip it
984 */
985 if (fp->f_count == 0)
986 continue;
987 /*
988 * If all refs are from msgs, and it's not marked accessible
989 * then it must be referenced from some unreachable cycle
990 * of (shut-down) FDs, so include it in our
991 * list of FDs to remove
992 */
993 if (fp->f_count == fp->f_msgcount && !(fp->f_flag & FMARK)) {
994 *fpp++ = fp;
995 nunref++;
996 fp->f_count++;
997 }
998 }
999 /*
1000 * for each FD on our hit list, do the following two things
1001 */
1002 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
1003 sorflush((struct socket *)(*fpp)->f_data);
1004 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
1005 closef(*fpp, (struct proc *) NULL);
1006 free((caddr_t)extra_ref, M_FILE);
1007 unp_gcing = 0;
1008}
1009
1010void
1011unp_dispose(m)
1012 struct mbuf *m;
1013{
1014
1015 if (m)
1016 unp_scan(m, unp_discard);
1017}
1018
1019static void
1020unp_scan(m0, op)
1021 register struct mbuf *m0;
1022 void (*op) __P((struct file *));
1023{
1024 register struct mbuf *m;
1025 register struct file **rp;
1026 register struct cmsghdr *cm;
1027 register int i;
1028 int qfds;
1029
1030 while (m0) {
1031 for (m = m0; m; m = m->m_next)
1032 if (m->m_type == MT_CONTROL &&
1033 m->m_len >= sizeof(*cm)) {
1034 cm = mtod(m, struct cmsghdr *);
1035 if (cm->cmsg_level != SOL_SOCKET ||
1036 cm->cmsg_type != SCM_RIGHTS)
1037 continue;
1038 qfds = (cm->cmsg_len - sizeof *cm)
1039 / sizeof (struct file *);
1040 rp = (struct file **)(cm + 1);
1041 for (i = 0; i < qfds; i++)
1042 (*op)(*rp++);
1043 break; /* XXX, but saves time */
1044 }
1045 m0 = m0->m_act;
1046 }
1047}
1048
1049static void
1050unp_mark(fp)
1051 struct file *fp;
1052{
1053
1054 if (fp->f_flag & FMARK)
1055 return;
1056 unp_defer++;
1057 fp->f_flag |= (FMARK|FDEFER);
1058}
1059
1060static void
1061unp_discard(fp)
1062 struct file *fp;
1063{
1064
1065 fp->f_msgcount--;
1066 unp_rights--;
1067 (void) closef(fp, (struct proc *)NULL);
1068}