linux_ipc.c revision 16322
1/*-
2 * Copyright (c) 1994-1995 S�ren Schmidt
3 * 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 *    in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software withough specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 *  $Id: linux_ipc.c,v 1.7 1996/03/02 19:37:56 peter Exp $
29 */
30
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/sysproto.h>
35#include <sys/proc.h>
36#include <sys/shm.h>
37
38#include <i386/linux/linux.h>
39#include <i386/linux/linux_proto.h>
40#include <i386/linux/linux_util.h>
41
42static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *));
43static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *));
44static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *));
45static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *));
46static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *));
47static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *));
48static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *));
49static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *));
50static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *));
51static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *));
52
53struct linux_ipc_perm {
54    linux_key_t key;
55    unsigned short uid;
56    unsigned short gid;
57    unsigned short cuid;
58    unsigned short cgid;
59    unsigned short mode;
60    unsigned short seq;
61};
62
63static void
64linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
65{
66    bpp->key = lpp->key;
67    bpp->uid = lpp->uid;
68    bpp->gid = lpp->gid;
69    bpp->cuid = lpp->cuid;
70    bpp->cgid = lpp->cgid;
71    bpp->mode = lpp->mode;
72    bpp->seq = lpp->seq;
73}
74
75
76static void
77bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
78{
79    lpp->key = bpp->key;
80    lpp->uid = bpp->uid;
81    lpp->gid = bpp->gid;
82    lpp->cuid = bpp->cuid;
83    lpp->cgid = bpp->cgid;
84    lpp->mode = bpp->mode;
85    lpp->seq = bpp->seq;
86}
87
88struct linux_shmid_ds {
89    struct linux_ipc_perm shm_perm;
90    int shm_segsz;
91    linux_time_t shm_atime;
92    linux_time_t shm_dtime;
93    linux_time_t shm_ctime;
94    ushort shm_cpid;
95    ushort shm_lpid;
96    short shm_nattch;
97    ushort private1;
98    void *private2;
99    void *private3;
100};
101
102static void
103linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
104{
105    linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
106    bsp->shm_segsz = lsp->shm_segsz;
107    bsp->shm_lpid = lsp->shm_lpid;
108    bsp->shm_cpid = lsp->shm_cpid;
109    bsp->shm_nattch = lsp->shm_nattch;
110    bsp->shm_atime = lsp->shm_atime;
111    bsp->shm_dtime = lsp->shm_dtime;
112    bsp->shm_ctime = lsp->shm_ctime;
113    bsp->shm_internal = lsp->private3;	/* this goes (yet) SOS */
114}
115
116static void
117bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
118{
119    bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
120    lsp->shm_segsz = bsp->shm_segsz;
121    lsp->shm_lpid = bsp->shm_lpid;
122    lsp->shm_cpid = bsp->shm_cpid;
123    lsp->shm_nattch = bsp->shm_nattch;
124    lsp->shm_atime = bsp->shm_atime;
125    lsp->shm_dtime = bsp->shm_dtime;
126    lsp->shm_ctime = bsp->shm_ctime;
127    lsp->private3 = bsp->shm_internal;	/* this goes (yet) SOS */
128}
129
130static int
131linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
132{
133    return ENOSYS;
134}
135
136static int
137linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
138{
139    return ENOSYS;
140}
141
142static int
143linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
144{
145    return ENOSYS;
146}
147
148static int
149linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
150{
151    struct msgsnd_args /* {
152	int     msqid;
153	void    *msgp;
154	size_t  msgsz;
155	int     msgflg;
156    } */ bsd_args;
157
158    bsd_args.msqid = args->arg1;
159    bsd_args.msgp = args->ptr;
160    bsd_args.msgsz = args->arg2;
161    bsd_args.msgflg = args->arg3;
162    return msgsnd(p, &bsd_args, retval);
163}
164
165static int
166linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
167{
168    struct msgrcv_args /* {
169        int 	msqid;
170	void	*msgp;
171	size_t	msgsz;
172	long	msgtyp;
173	int	msgflg;
174    } */ bsd_args;
175
176    bsd_args.msqid = args->arg1;
177    bsd_args.msgp = args->ptr;
178    bsd_args.msgsz = args->arg2;
179    bsd_args.msgtyp = 0;
180    bsd_args.msgflg = args->arg3;
181    return msgrcv(p, &bsd_args, retval);
182}
183
184static int
185linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
186{
187    struct msgget_args /* {
188	key_t	key;
189        int 	msgflg;
190    } */ bsd_args;
191
192    bsd_args.key = args->arg1;
193    bsd_args.msgflg = args->arg2;
194    return msgget(p, &bsd_args, retval);
195}
196
197static int
198linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
199{
200    struct msgctl_args /* {
201	int     msqid;
202	int     cmd;
203	struct	msqid_ds *buf;
204    } */ bsd_args;
205
206    bsd_args.msqid = args->arg1;
207    bsd_args.cmd = args->arg2;
208    bsd_args.buf = (struct msqid_ds *)args->ptr;
209    return msgctl(p, &bsd_args, retval);
210}
211
212static int
213linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
214{
215    struct shmat_args /* {
216	int shmid;
217	void *shmaddr;
218	int shmflg;
219    } */ bsd_args;
220    int error;
221
222    bsd_args.shmid = args->arg1;
223    bsd_args.shmaddr = args->ptr;
224    bsd_args.shmflg = args->arg2;
225    if ((error = shmat(p, &bsd_args, retval)))
226	return error;
227    if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int))))
228	return error;
229    retval[0] = 0;
230    return 0;
231}
232
233static int
234linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
235{
236    struct shmdt_args /* {
237	void *shmaddr;
238    } */ bsd_args;
239
240    bsd_args.shmaddr = args->ptr;
241    return shmdt(p, &bsd_args, retval);
242}
243
244static int
245linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
246{
247    struct shmget_args /* {
248	key_t key;
249	int size;
250	int shmflg;
251    } */ bsd_args;
252
253    bsd_args.key = args->arg1;
254    bsd_args.size = args->arg2;
255    bsd_args.shmflg = args->arg3;
256    return shmget(p, &bsd_args, retval);
257}
258
259static int
260linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
261{
262    struct shmid_ds bsd_shmid;
263    struct linux_shmid_ds linux_shmid;
264    struct shmctl_args /* {
265	int shmid;
266	int cmd;
267	struct shmid_ds *buf;
268    } */ bsd_args;
269    int error;
270    caddr_t sg = stackgap_init();
271
272    switch (args->arg2) {
273    case LINUX_IPC_STAT:
274	bsd_args.shmid = args->arg1;
275	bsd_args.cmd = IPC_STAT;
276	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
277	if ((error = shmctl(p, &bsd_args, retval)))
278	    return error;
279	if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
280		    	    sizeof(struct shmid_ds))))
281	    return error;
282	bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
283	return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
284
285    case LINUX_IPC_SET:
286	if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
287		    	    sizeof(linux_shmid))))
288	    return error;
289	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
290	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
291	if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
292		     	     sizeof(struct shmid_ds))))
293	    return error;
294	bsd_args.shmid = args->arg1;
295	bsd_args.cmd = IPC_SET;
296	return shmctl(p, &bsd_args, retval);
297
298    case LINUX_IPC_RMID:
299	bsd_args.shmid = args->arg1;
300	bsd_args.cmd = IPC_RMID;
301	if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
302		    	    sizeof(linux_shmid))))
303	    return error;
304	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
305	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
306	if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
307		     	     sizeof(struct shmid_ds))))
308	    return error;
309	return shmctl(p, &bsd_args, retval);
310
311    case LINUX_IPC_INFO:
312    case LINUX_SHM_STAT:
313    case LINUX_SHM_INFO:
314    case LINUX_SHM_LOCK:
315    case LINUX_SHM_UNLOCK:
316    default:
317	uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
318	return EINVAL;
319    }
320}
321
322int
323linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval)
324{
325    switch (args->what) {
326    case LINUX_SEMOP:
327	return linux_semop(p, args, retval);
328    case LINUX_SEMGET:
329	return linux_semget(p, args, retval);
330    case LINUX_SEMCTL:
331	return linux_semctl(p, args, retval);
332    case LINUX_MSGSND:
333	return linux_msgsnd(p, args, retval);
334    case LINUX_MSGRCV:
335	return linux_msgrcv(p, args, retval);
336    case LINUX_MSGGET:
337	return linux_msgget(p, args, retval);
338    case LINUX_MSGCTL:
339	return linux_msgctl(p, args, retval);
340    case LINUX_SHMAT:
341	return linux_shmat(p, args, retval);
342    case LINUX_SHMDT:
343	return linux_shmdt(p, args, retval);
344    case LINUX_SHMGET:
345	return linux_shmget(p, args, retval);
346    case LINUX_SHMCTL:
347	return linux_shmctl(p, args, retval);
348    default:
349	uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
350	return ENOSYS;
351    }
352}
353