/* function called by chkr_x_x_x_x_chkr, at syscalls.
   Copyright 1993 Tristan Gingold
		  Written September 1993 Tristan Gingold

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License 
along with this program; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   The author may be reached (Email) at Tristan C/O marc@david.saclay.cea.fr,
   or (US/French mail) as Tristan Gingold 
   			  8 rue Parmentier
   			  F91120 PALAISEAU
   			  FRANCE 
*/
#include "checker.h"
#include "errlist.h"
#include "message.h"
#ifdef CHKR_USE_BITMAP
#include <sys/syscall.h>
#include <unistd.h>
#include <grp.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/signal.h>
#include <sys/times.h>
/* #include <sys/wait.h> */
#include <sys/utsname.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/vm86.h>
#include <utime.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <termios.h>
#include <linux/fs.h>
#include <linux/tty.h>
#include <sys/socketcall.h>
#include <linux/timex.h>

struct reg
{
  unsigned int eax;
  unsigned int ecx;
  unsigned int edx;
  unsigned int ebx;
  unsigned int esp;
  unsigned int ebp;
  unsigned int esi;
  unsigned int edi;
  unsigned int eip;
  unsigned char flags;
};

extern void make_syscall(void);
extern void fork_symtab_file(void);
extern void exec_symtab_file(void);
int check_ioctl(int cmd, int arg);
int check_ipc(unsigned long arg1, unsigned long arg2);
int check_socketcall(int call, unsigned long *args, unsigned int * const res);
int check_fcntl(int cmd, int arg);

#define RES  ((signed long)(regs->eax))
#define ARG1 (regs->ebx)
#define ARG2 (regs->ecx)
#define ARG3 (regs->edx)
#define ARG4 (regs->esi)
#define ARG5 (regs->edi)

#define PTR1 (__ptr_t)ARG1
#define PTR2 (__ptr_t)ARG2
#define PTR3 (__ptr_t)ARG3
#define PTR4 (__ptr_t)ARG4
#define PTR5 (__ptr_t)ARG5

void check_syscall(struct reg * const regs)  
{
  int error=0;
  switch(regs->eax)
  {
	case SYS_setup:
		error=1;
		break;	/* must not be called */
	case SYS_exit:
		chkr_do_end();
		break;
	case SYS_fork:
		make_syscall();
		if (RES == 0)
		  fork_symtab_file();
		break;
	case SYS_read:
		chkr_check_addr(PTR2, ARG3, CHKR_TW);
		make_syscall();
		if (RES > 0)
		  chkr_set_right(PTR2, RES, CHKR_RW);
		break;
	case SYS_write:
		chkr_check_addr(PTR2, ARG3, CHKR_RO);
		break;
	case SYS_open:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_close:
		break;
	case SYS_waitpid:
		error = 1;	/* replaced by wait4 */
		break;
	case SYS_creat:
		error = 1;
		break;		/* replaced by open */
	case SYS_link:	
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_str(PTR2, CHKR_RO);  
		break;
	case SYS_unlink:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_execve:
		{
		  char **ptr;
  
		  /* check path */
		  chkr_check_str(PTR1, CHKR_RO);
  
		  /* check arguments */
		  chkr_check_addr(PTR2, sizeof(char *), CHKR_RO);
		  ptr = (char **)ARG2;
		  while (*ptr != (char*)0)
		  {
		    chkr_check_addr(ptr, sizeof(char *), CHKR_RO);
		    chkr_check_str(*ptr, CHKR_RO);
		    ptr++;
		  }
		  chkr_check_addr(ptr, sizeof(char *), CHKR_RO);
  
		  /* check environnement */
		  chkr_check_addr(PTR3, sizeof(char *), CHKR_RO);
		  ptr = (char **)ARG3;
		  while (*ptr != (char*)0)
		  {
		    chkr_check_addr(ptr, sizeof(char *), CHKR_RO);
		    chkr_check_str(*ptr, CHKR_RO);
		    ptr++;
		  }
		  chkr_check_addr(ptr, sizeof(char *), CHKR_RO);
		}
		chkr_do_end();
		exec_symtab_file();
		break;
	case SYS_chdir:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_time:
		if (ARG1)
		  chkr_check_addr(PTR1, sizeof(time_t), CHKR_WO);
		break;
	case SYS_mknod:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_chmod:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_chown:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_break:
		error = 1;
		break;
	case SYS_oldstat:
		error = 1;
		break;
	case SYS_lseek:
		error = 0;
		break;
	case SYS_getpid:
		break;
	case SYS_mount:
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_str(PTR2, CHKR_RO);
		chkr_check_str(PTR3, CHKR_RO);
		break;
	case SYS_umount:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_setuid:
		break;
	case SYS_getuid:
		break;
	case SYS_stime:
		chkr_check_addr(PTR1, sizeof(time_t), CHKR_RO);
		break;
	case SYS_ptrace:
		error = 1;
		break;
	case SYS_alarm:
		break;
	case SYS_oldfstat:
		error = 1;
		break;
	case SYS_pause:
		break;
	case SYS_utime:
		chkr_check_addr(PTR2, sizeof(struct utimbuf), CHKR_RW);
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_stty:
		error = 1;
		break;		/* replaced by ioctl */
	case SYS_gtty:
		error = 1;
		break;		/* replaced by ioctl */
	case SYS_access:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_nice:
		error = 1;
		break;		/* replaced  by setpriority */
	case SYS_ftime:	
		break;
	case SYS_sync:
		break;
	case SYS_kill:
		break;
	case SYS_rename:
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_str(PTR2, CHKR_RO);
		break;
	case SYS_mkdir:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_rmdir:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_dup:
		break;
	case SYS_pipe:
		chkr_check_addr(PTR1, 2*sizeof(int), CHKR_WO);
		break;
	case SYS_times:
		chkr_check_addr(PTR1, sizeof(struct tms), CHKR_WO);
		break;
	case SYS_prof:
		error = 1;
		break;
	case SYS_brk:
		error = 1;
		break;		/* called only by checker */
	case SYS_setgid:
		break;
	case SYS_getgid:
		break;
	case SYS_signal:
		error = 1;
		break;		/* replaced by sigaction */
	case SYS_geteuid:
		break;
	case SYS_getegid:
		break;
	case SYS_acct:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_phys:
		error = 1;
		break;
	case SYS_lock:
		error = 1;
		break;
	case SYS_ioctl:
		error = check_ioctl(ARG2, ARG3);
		break;
	case SYS_fcntl:
		error = check_fcntl(ARG2, ARG3);
		break;
	case SYS_mpx:
		error = 1;
		break;
	case SYS_setpgid:
		break;
	case SYS_ulimit:
		error = 1;
		break;		/* replaced by rlimit */	
	case SYS_oldolduname:
		error = 1;
		break;
	case SYS_umask:
		break;
	case SYS_chroot:
		chkr_check_str(PTR1, CHKR_RO);	
		break;
	case SYS_ustat:
		chkr_check_addr(PTR2, sizeof(struct ustat), CHKR_WO);
		break;
	case SYS_dup2:
		break;
	case SYS_getppid:
		break;
	case SYS_getpgrp:
		break;
	case SYS_setsid:
		break;
	case SYS_sigaction:
#if 1
		__sigaction(ARG1,PTR2,PTR3);
#else
		if (ARG2)
		  chkr_check_addr(PTR2, sizeof(struct sigaction), CHKR_RO);
		if (ARG3)
		  chkr_check_addr(PTR3, sizeof(struct sigaction), CHKR_WO);
#endif
		break;
	case SYS_siggetmask:
		error = 1;	/* old syscall */
		break;
	case SYS_sigsetmask:
		error = 1;	/* old syscall */
		break;
	case SYS_setreuid:
		break;
	case SYS_setregid:
		break;
	case SYS_sigsuspend:
		break;
	case SYS_sigpending:
		break;
	case SYS_sethostname:
		chkr_check_addr(PTR1, ARG2, CHKR_RO);
		break;
	case SYS_setrlimit:
		chkr_check_addr(PTR2, sizeof(struct rlimit), CHKR_RO);
		break;
	case SYS_getrlimit:
		chkr_check_addr(PTR2, sizeof(struct rlimit), CHKR_WO);
		break;
	case SYS_getrusage:
		chkr_check_addr(PTR2, sizeof(struct rusage), CHKR_WO);
		break;
	case SYS_gettimeofday:
		chkr_check_addr(PTR1, sizeof(struct timeval), CHKR_WO);
		chkr_check_addr(PTR2, sizeof(struct timezone), CHKR_WO);
		break;
	case SYS_settimeofday:
		chkr_check_addr(PTR1, sizeof(struct timeval), CHKR_RO);
		chkr_check_addr(PTR2, sizeof(struct timezone), CHKR_RO);
		break;
	case SYS_getgroups:
		chkr_check_addr(PTR2, ARG1 * sizeof(__gid_t), CHKR_TW);
		make_syscall();
		chkr_set_right(PTR2, RES * sizeof(__gid_t), CHKR_WO);
		break;
	case SYS_setgroups:
		chkr_check_addr(PTR2, ARG1 * sizeof(__gid_t), CHKR_RO);
		break;
	case SYS_select:
		{
		  char **ptr;
		  
		  chkr_check_addr(PTR1, 5 * sizeof(int*), CHKR_RO);
		  ptr = (char**)PTR1;
		  if (ptr[1])
		    chkr_check_addr(ptr[1], sizeof(fd_set), CHKR_RW);
		  if (ptr[2])
		    chkr_check_addr(ptr[2], sizeof(fd_set), CHKR_RW);	
		  if (ptr[3])
		    chkr_check_addr(ptr[3], sizeof(fd_set), CHKR_RW);	
		  if (ptr[4])
		    chkr_check_addr(ptr[4], sizeof(struct timeval), CHKR_RW);
		}
		break;
	case SYS_symlink:
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_str(PTR2, CHKR_RO);
		break;
	case SYS_oldlstat:
		error = 1;
		break;
	case SYS_readlink:
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_addr(PTR2, ARG3, CHKR_TW);
		make_syscall();
		if (RES >= 0)
		  chkr_set_right(PTR2, RES, CHKR_WO);
		break;
	case SYS_uselib:
		break;		/* no check */
	case SYS_swapon:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_reboot:
		break;
	case SYS_readdir:
		chkr_check_addr(PTR2, sizeof(struct dirent), CHKR_WO);
		break;
	case SYS_mmap:
		error = 1;
		break;		/* not supported */
	case SYS_munmap:
		error = 1;
		break;		/* not supported */
	case SYS_truncate:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_ftruncate:
		break;
	case SYS_fchmod:
		break;
	case SYS_fchown:
		break;
	case SYS_getpriority:
		break;
	case SYS_setpriority:
		break;
	case SYS_profil:
		error = 1;
		break;		/* not supported */
	case SYS_statfs:
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_addr(PTR2, sizeof(struct statfs), CHKR_WO);
		break;
	case SYS_fstatfs:
		chkr_check_addr(PTR2, sizeof(struct statfs), CHKR_WO);
		break;
	case SYS_ioperm:
		break;
	case SYS_socketcall:
		error = check_socketcall(ARG1, (unsigned long*)ARG2, &(regs->eax));
		break;
	case SYS_klog:
		error = 1;
		break;		/* unknown to me, sorry */		
	case SYS_setitimer:
		chkr_check_addr(PTR2, sizeof(struct itimerval), CHKR_RO);
		if (ARG3)
		  chkr_check_addr(PTR3, sizeof(struct itimerval), CHKR_WO);
		break;
	case SYS_getitimer:
		chkr_check_addr(PTR2, sizeof(struct itimerval), CHKR_WO);
		break;
	case SYS_stat:
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_addr(PTR2, sizeof(struct stat), CHKR_WO);
		break;
	case SYS_lstat:
		chkr_check_str(PTR1, CHKR_RO);
		chkr_check_addr(PTR2, sizeof(struct stat), CHKR_WO);
		break;
	case SYS_fstat:
		chkr_check_addr(PTR2, sizeof(struct stat), CHKR_WO);
		break;
	case SYS_olduname:
		error = 1;
		break;
	case SYS_iopl:
		error = 1;
		break;
	case SYS_vhangup:
		break;
	case SYS_idle:
		break;
	case SYS_vm86:
		chkr_check_addr(PTR1, sizeof(struct vm86_struct), CHKR_RW);
		break;
	case SYS_wait4:
		if (ARG2)
		  chkr_check_addr(PTR2, sizeof(int *), CHKR_WO);  
		if (ARG4)
		  chkr_check_addr(PTR4, sizeof(struct rusage), CHKR_RO);
		break;
	case SYS_swapoff:
		chkr_check_str(PTR1, CHKR_RO);
		break;
	case SYS_sysinfo:
		error = 1;
		break;
	case SYS_ipc:
		error = check_ipc(ARG1, ARG2);
		break;
	case SYS_fsync:
		break;
	case SYS_sigreturn:
		break;
	case SYS_clone:
		break;
	case SYS_setdomainname:
		chkr_check_addr(PTR1, ARG2, CHKR_RO);
		break;
	case SYS_uname:
		chkr_check_addr(PTR1, sizeof(struct utsname), CHKR_WO);
		break;
	case SYS_modify_ldt:
		error = 1;
		break;
	case SYS_adjtimex:
		chkr_check_addr(PTR1, sizeof(struct timex), CHKR_RW);
		break;
	case SYS_mprotect:
		error = 1;	/* see mmap */
		break;
	case SYS_sigprocmask:
		if (ARG2)
		  chkr_check_addr(PTR2, sizeof(sigset_t), CHKR_RO); 
		if (ARG3)
		  chkr_check_addr(PTR3, sizeof(sigset_t), CHKR_WO);
		break;
	default:
		error = 1;
  }
  if (error)
  {
    chkr_errno = E_IE_BSYSCALL;
    chkr_perror();
    chkr_abort();
  }
}

int check_ioctl(int cmd, int arg)
{
  switch(cmd)
  {
	case TCGETS:
		chkr_check_addr((__ptr_t)arg, sizeof(struct termios), CHKR_WO);
		break;
	case TCSETSW:
	case TCSETSF:	    
	case TCSETS:
		chkr_check_addr((__ptr_t)arg, sizeof(struct termios), CHKR_RO);
		break;
	case TCGETA:
		chkr_check_addr((__ptr_t)arg, sizeof(struct termio), CHKR_WO);
		break;
	case TCSETAW:
	case TCSETAF:	    	  
	case TCSETA:
		chkr_check_addr((__ptr_t)arg, sizeof(struct termio), CHKR_RO);
		break;
	case TCSBRK:
	case TCSBRKP:	  
		chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_RO);
		break;	  
	case TCFLSH:	  
	case TCXONC:
	case TIOCSCTTY:	  
		chkr_check_addr((__ptr_t)arg, sizeof(int), CHKR_RO);
		break;
	case TIOCEXCL:
	case TIOCNXCL:
	  	break;
	case TIOCGPGRP:
	  	chkr_check_addr((__ptr_t)arg, sizeof(pid_t), CHKR_WO);
	  	break;
	case TIOCSPGRP:
	  	chkr_check_addr((__ptr_t)arg, sizeof(pid_t), CHKR_RO);
	  	break;
	case TIOCOUTQ:
	  	chkr_check_addr((__ptr_t)arg, 4, CHKR_WO);
	  	break;	  	
	case TIOCSTI:
	  	break;
	case TIOCGWINSZ:
	  	chkr_check_addr((__ptr_t)arg, sizeof(struct winsize), CHKR_WO);
	  	break;
	case TIOCSWINSZ:
	  	chkr_check_addr((__ptr_t)arg, sizeof(struct winsize), CHKR_RO);
	  	break;
	case TIOCMGET:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_WO);
	  	break;	  
	case TIOCMBIS:
	case TIOCMBIC:
	case TIOCMSET:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_RO);
	  	break;	  
	case TIOCGSOFTCAR:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_WO);
	  	break;	  
	case TIOCSSOFTCAR:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_WO);
	  	break;	  
	case FIONREAD:
	  	break;
	case TIOCCONS:
	  	break;
	case TIOCGSERIAL:
	  	chkr_check_addr((__ptr_t)arg, sizeof(struct serial_struct), CHKR_WO);
	  	break;	  
	case TIOCSSERIAL:
	  	chkr_check_addr((__ptr_t)arg, sizeof(struct serial_struct), CHKR_RO);
	  	break;	  
	case TIOCPKT:
	case FIONBIO:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_RO);
	  	break;	  		  
	case TIOCNOTTY:
	  	break;
	case TIOCSETD:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_RO);
	  	break;	  		  
	case TIOCGETD:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_WO);
	  	break;
	case TIOCSERCONFIG:
	  	break;
	case TIOCSERGWILD:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_WO);
	  	break;	  
	case TIOCSERSWILD:
	  	chkr_check_addr((__ptr_t)arg, sizeof(long), CHKR_RO);
	  	break;	  
	case TIOCGLCKTRMIOS:
	  	chkr_check_addr((__ptr_t)arg, sizeof(__ptr_t), CHKR_RO);
	  	chkr_check_addr(*((__ptr_t*)arg), sizeof(struct termios), CHKR_RO);
	  	break;
	case TIOCSLCKTRMIOS:
	  	chkr_check_addr((__ptr_t)arg, sizeof(__ptr_t), CHKR_RO);
	  	chkr_check_addr(*((__ptr_t*)arg), sizeof(struct termios), CHKR_WO);
	  	break;	  
	case TIOCLINUX:	/* I don't really know */	  	
	case FIONCLEX:
	case FIOCLEX:
	case FIOASYNC:
	default:	/* some other ioctl are not here */
	 	chkr_header(M_IOCTL_UNIMPLEMENT);
  		chkr_printf(M_SEND_DESCRIPTION);
	  	return 1;
  }
  return 0;
}

int check_fcntl(int cmd, int arg)
{
	switch(cmd)
	{
	 case F_DUPFD: /* arg is used as a value */
	 case F_GETFD:
	 case F_GETFL:
	 case F_SETFD: /* arg is used as a value */
	 case F_SETFL: /* arg is used as a value */
	 	break;
	 case F_GETLK:
	 	chkr_check_addr((__ptr_t)arg, sizeof(struct flock), CHKR_WO);
	 	break;
	 case F_SETLK:
	 case F_SETLKW:	/* TG: what is the difference ? */
	 	chkr_check_addr((__ptr_t)arg, sizeof(struct flock), CHKR_RO);
	 	break;
	 case F_SETOWN:  /* arg is used as a value */
	 case F_GETOWN:
	 	break;
	 default:
	  	chkr_header(M_FCNTL_UNIMPLEMENT);
  		chkr_printf(M_SEND_DESCRIPTION);
	 	return 1;
	}
	return 0;
}

int check_socketcall(int call, unsigned long *args, unsigned int * const res)
{
  /* check_socketcall assumes args[] is good */
  switch(call)
  {
	case SYS_ACCEPT:
		chkr_check_addr((__ptr_t)args[2], sizeof (int), CHKR_RO);
		chkr_check_addr((__ptr_t)args[1], *(int*)args[2], CHKR_TW);
		make_syscall();
		chkr_set_right((__ptr_t)args[1], *(int*)args[2], CHKR_RW);
		break;
	case SYS_BIND:
		chkr_check_addr((__ptr_t)args[1], args[3], CHKR_RO);
		break;
	case SYS_CONNECT:
		chkr_check_addr((__ptr_t)args[1], args[2], CHKR_RO);
		break;
	case SYS_GETPEERNAME:
		chkr_check_addr((__ptr_t)args[2], sizeof(int), CHKR_RW);
		chkr_check_addr((__ptr_t)args[1], *(int*)args[2], CHKR_TW);
		make_syscall();
		chkr_set_right((__ptr_t)args[1], *(int*)args[2], CHKR_RW);
		break;
	case SYS_GETSOCKNAME:
		chkr_check_addr((__ptr_t)args[2], sizeof(int), CHKR_RW);
		chkr_check_addr((__ptr_t)args[1], *(int*)args[2], CHKR_TW);
		make_syscall();
		chkr_set_right((__ptr_t)args[1], *(int*)args[2], CHKR_RW);
		break;
	case SYS_GETSOCKOPT:
		chkr_check_addr((__ptr_t)args[4], sizeof(int), CHKR_RW);
		chkr_check_addr((__ptr_t)args[3], *(int*)args[4], CHKR_TW);
		make_syscall();
		chkr_set_right((__ptr_t)args[3], *(int*)args[4], CHKR_RW);
		break;
	case SYS_LISTEN:
		break;
	case SYS_RECV:
		chkr_check_addr((__ptr_t)args[1], args[2], CHKR_TW);
		make_syscall();
		chkr_set_right((__ptr_t)args[1], *res, CHKR_WO);
		break;
	case SYS_RECVFROM:
		chkr_check_addr((__ptr_t)args[1], args[2], CHKR_TW);
		if (args[4])
		{
		  chkr_check_addr((__ptr_t)args[5], sizeof(int), CHKR_RO);
		  chkr_check_addr((__ptr_t)args[4], *(int*)args[5], CHKR_TW);
		}
		make_syscall();
		if (*res > 0)
		{
		  chkr_set_right((__ptr_t)args[1], args[2], CHKR_RW);
		  if (args[4])
		    chkr_set_right((__ptr_t)args[4], *(int*)args[5], CHKR_RW);
		}
		break;
	case SYS_SEND:
		chkr_check_addr((__ptr_t)args[1], args[2], CHKR_RO);
		break;
	case SYS_SENDTO:
		chkr_check_addr((__ptr_t)args[1], args[2], CHKR_RO);
		chkr_check_addr((__ptr_t)args[4], args[5], CHKR_RO);
		break;
	case SYS_SETSOCKOPT:
		chkr_check_addr((__ptr_t)args[4], args[5], CHKR_RO);
		break;
	case SYS_SHUTDOWN:
		break;
	case SYS_SOCKET:
		break;
	case SYS_SOCKETPAIR:
		chkr_check_addr((__ptr_t)args[3], 2*sizeof(int), CHKR_WO);
		break;
 	default:
 		chkr_header(M_SYSCALL_UNIMPLEM);
  		chkr_printf(M_SEND_DESCRIPTION);
 		return 1;
  }
  return 0;
}

int check_ipc(unsigned long arg1, unsigned long arg2)
{
  chkr_header(M_IPC_UNIMPLEMENT);
  chkr_printf(M_SEND_DESCRIPTION);
  return 1;	/* means error */
}
#endif