xref: /freebsd/sys/compat/linux/linux_ipc.c (revision e627b39baccd1ec9129690167cf5e6d860509655)
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 
42 static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *));
43 static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *));
44 static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *));
45 static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *));
46 static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *));
47 static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *));
48 static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *));
49 static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *));
50 static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *));
51 static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *));
52 
53 struct 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 
63 static void
64 linux_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 
76 static void
77 bsd_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 
88 struct 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 
102 static void
103 linux_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 
116 static void
117 bsd_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 
130 static int
131 linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
132 {
133     return ENOSYS;
134 }
135 
136 static int
137 linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
138 {
139     return ENOSYS;
140 }
141 
142 static int
143 linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
144 {
145     return ENOSYS;
146 }
147 
148 static int
149 linux_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 
165 static int
166 linux_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 
184 static int
185 linux_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 
197 static int
198 linux_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 
212 static int
213 linux_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 
233 static int
234 linux_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 
244 static int
245 linux_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 
259 static int
260 linux_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 
322 int
323 linux_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