xref: /freebsd/sys/compat/linux/linux_ipc.c (revision 7573cb47cf4b1f33b6794f82a8a5e0bcbdcc1ada)
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 
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_msgop __P((struct proc *, struct linux_ipc_args *, int *));
48 static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *));
49 static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *));
50 static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *));
51 static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *));
52 static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *));
53 
54 struct 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 
64 static void
65 linux_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 
77 static void
78 bsd_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 
89 struct 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 
103 static void
104 linux_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 
117 static void
118 bsd_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 
131 static int
132 linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
133 {
134     return ENOSYS;
135 }
136 
137 static int
138 linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
139 {
140     return ENOSYS;
141 }
142 
143 static int
144 linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
145 {
146     return ENOSYS;
147 }
148 
149 static int
150 linux_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 
166 static int
167 linux_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 
185 static int
186 linux_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 
198 static int
199 linux_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 
213 static int
214 linux_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 
234 static int
235 linux_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 
245 static int
246 linux_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 
260 static int
261 linux_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 
323 int
324 linux_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