linux_ipc.c revision 14331
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.6 1996/01/08 04:34:54 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_msgop __P((struct proc *, struct linux_ipc_args *, int *));
48static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *));
49static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *));
50static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *));
51static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *));
52static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *));
53
54struct linux_ipc_perm {
55    linux_key_t key;
56    unsigned short uid;
57    unsigned short gid;
58    unsigned short cuid;
59    unsigned short cgid;
60    unsigned short mode;
61    unsigned short seq;
62};
63
64static void
65linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
66{
67    bpp->key = lpp->key;
68    bpp->uid = lpp->uid;
69    bpp->gid = lpp->gid;
70    bpp->cuid = lpp->cuid;
71    bpp->cgid = lpp->cgid;
72    bpp->mode = lpp->mode;
73    bpp->seq = lpp->seq;
74}
75
76
77static void
78bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
79{
80    lpp->key = bpp->key;
81    lpp->uid = bpp->uid;
82    lpp->gid = bpp->gid;
83    lpp->cuid = bpp->cuid;
84    lpp->cgid = bpp->cgid;
85    lpp->mode = bpp->mode;
86    lpp->seq = bpp->seq;
87}
88
89struct linux_shmid_ds {
90    struct linux_ipc_perm shm_perm;
91    int shm_segsz;
92    linux_time_t shm_atime;
93    linux_time_t shm_dtime;
94    linux_time_t shm_ctime;
95    ushort shm_cpid;
96    ushort shm_lpid;
97    short shm_nattch;
98    ushort private1;
99    void *private2;
100    void *private3;
101};
102
103static void
104linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
105{
106    linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
107    bsp->shm_segsz = lsp->shm_segsz;
108    bsp->shm_lpid = lsp->shm_lpid;
109    bsp->shm_cpid = lsp->shm_cpid;
110    bsp->shm_nattch = lsp->shm_nattch;
111    bsp->shm_atime = lsp->shm_atime;
112    bsp->shm_dtime = lsp->shm_dtime;
113    bsp->shm_ctime = lsp->shm_ctime;
114    bsp->shm_internal = lsp->private3;	/* this goes (yet) SOS */
115}
116
117static void
118bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
119{
120    bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
121    lsp->shm_segsz = bsp->shm_segsz;
122    lsp->shm_lpid = bsp->shm_lpid;
123    lsp->shm_cpid = bsp->shm_cpid;
124    lsp->shm_nattch = bsp->shm_nattch;
125    lsp->shm_atime = bsp->shm_atime;
126    lsp->shm_dtime = bsp->shm_dtime;
127    lsp->shm_ctime = bsp->shm_ctime;
128    lsp->private3 = bsp->shm_internal;	/* this goes (yet) SOS */
129}
130
131static int
132linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
133{
134    return ENOSYS;
135}
136
137static int
138linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
139{
140    return ENOSYS;
141}
142
143static int
144linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
145{
146    return ENOSYS;
147}
148
149static int
150linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
151{
152    struct msgsnd_args /* {
153	int     msqid;
154	void    *msgp;
155	size_t  msgsz;
156	int     msgflg;
157    } */ bsd_args;
158
159    bsd_args.msqid = args->arg1;
160    bsd_args.msgp = args->ptr;
161    bsd_args.msgsz = args->arg2;
162    bsd_args.msgflg = args->arg3;
163    return msgsnd(p, &bsd_args, retval);
164}
165
166static int
167linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
168{
169    struct msgrcv_args /* {
170        int 	msqid;
171	void	*msgp;
172	size_t	msgsz;
173	long	msgtyp;
174	int	msgflg;
175    } */ bsd_args;
176
177    bsd_args.msqid = args->arg1;
178    bsd_args.msgp = args->ptr;
179    bsd_args.msgsz = args->arg2;
180    bsd_args.msgtyp = 0;
181    bsd_args.msgflg = args->arg3;
182    return msgrcv(p, &bsd_args, retval);
183}
184
185static int
186linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
187{
188    struct msgget_args /* {
189	key_t	key;
190        int 	msgflg;
191    } */ bsd_args;
192
193    bsd_args.key = args->arg1;
194    bsd_args.msgflg = args->arg2;
195    return msgget(p, &bsd_args, retval);
196}
197
198static int
199linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
200{
201    struct msgctl_args /* {
202	int     msqid;
203	int     cmd;
204	struct	msqid_ds *buf;
205    } */ bsd_args;
206
207    bsd_args.msqid = args->arg1;
208    bsd_args.cmd = args->arg2;
209    bsd_args.buf = (struct msqid_ds *)args->ptr;
210    return msgctl(p, &bsd_args, retval);
211}
212
213static int
214linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
215{
216    struct shmat_args /* {
217	int shmid;
218	void *shmaddr;
219	int shmflg;
220    } */ bsd_args;
221    int error;
222
223    bsd_args.shmid = args->arg1;
224    bsd_args.shmaddr = args->ptr;
225    bsd_args.shmflg = args->arg2;
226    if ((error = shmat(p, &bsd_args, retval)))
227	return error;
228    if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int))))
229	return error;
230    retval[0] = 0;
231    return 0;
232}
233
234static int
235linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
236{
237    struct shmdt_args /* {
238	void *shmaddr;
239    } */ bsd_args;
240
241    bsd_args.shmaddr = args->ptr;
242    return shmdt(p, &bsd_args, retval);
243}
244
245static int
246linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
247{
248    struct shmget_args /* {
249	key_t key;
250	int size;
251	int shmflg;
252    } */ bsd_args;
253
254    bsd_args.key = args->arg1;
255    bsd_args.size = args->arg2;
256    bsd_args.shmflg = args->arg3;
257    return shmget(p, &bsd_args, retval);
258}
259
260static int
261linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
262{
263    struct shmid_ds bsd_shmid;
264    struct linux_shmid_ds linux_shmid;
265    struct shmctl_args /* {
266	int shmid;
267	int cmd;
268	struct shmid_ds *buf;
269    } */ bsd_args;
270    int error;
271    caddr_t sg = stackgap_init();
272
273    switch (args->arg2) {
274    case LINUX_IPC_STAT:
275	bsd_args.shmid = args->arg1;
276	bsd_args.cmd = IPC_STAT;
277	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
278	if ((error = shmctl(p, &bsd_args, retval)))
279	    return error;
280	if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
281		    	    sizeof(struct shmid_ds))))
282	    return error;
283	bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
284	return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
285
286    case LINUX_IPC_SET:
287	if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
288		    	    sizeof(linux_shmid))))
289	    return error;
290	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
291	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
292	if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
293		     	     sizeof(struct shmid_ds))))
294	    return error;
295	bsd_args.shmid = args->arg1;
296	bsd_args.cmd = IPC_SET;
297	return shmctl(p, &bsd_args, retval);
298
299    case LINUX_IPC_RMID:
300	bsd_args.shmid = args->arg1;
301	bsd_args.cmd = IPC_RMID;
302	if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
303		    	    sizeof(linux_shmid))))
304	    return error;
305	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
306	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
307	if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
308		     	     sizeof(struct shmid_ds))))
309	    return error;
310	return shmctl(p, &bsd_args, retval);
311
312    case LINUX_IPC_INFO:
313    case LINUX_SHM_STAT:
314    case LINUX_SHM_INFO:
315    case LINUX_SHM_LOCK:
316    case LINUX_SHM_UNLOCK:
317    default:
318	uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
319	return EINVAL;
320    }
321}
322
323int
324linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval)
325{
326    switch (args->what) {
327    case LINUX_SEMOP:
328	return linux_semop(p, args, retval);
329    case LINUX_SEMGET:
330	return linux_semget(p, args, retval);
331    case LINUX_SEMCTL:
332	return linux_semctl(p, args, retval);
333    case LINUX_MSGSND:
334	return linux_msgsnd(p, args, retval);
335    case LINUX_MSGRCV:
336	return linux_msgrcv(p, args, retval);
337    case LINUX_MSGGET:
338	return linux_msgget(p, args, retval);
339    case LINUX_MSGCTL:
340	return linux_msgctl(p, args, retval);
341    case LINUX_SHMAT:
342	return linux_shmat(p, args, retval);
343    case LINUX_SHMDT:
344	return linux_shmdt(p, args, retval);
345    case LINUX_SHMGET:
346	return linux_shmget(p, args, retval);
347    case LINUX_SHMCTL:
348	return linux_shmctl(p, args, retval);
349    default:
350	uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
351	return ENOSYS;
352    }
353}
354