asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim) { struct rlimit new_rlim, *old_rlim; int err; if (resource >= RLIM_NLIMITS) return -EINVAL; err = verify_area(VERIFY_READ, rlim, sizeof(*rlim)); if (err) return err; memcpy_fromfs(&new_rlim, rlim, sizeof(*rlim)); if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0) return -EINVAL; old_rlim = current->rlim + resource; if (((new_rlim.rlim_cur > old_rlim->rlim_max) || (new_rlim.rlim_max > old_rlim->rlim_max)) && !suser()) return -EPERM; if (resource == RLIMIT_NOFILE) { if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) return -EPERM; } *old_rlim = new_rlim; return 0; }
int cnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int error; /* * Superuser can always use this to wrest control of console * output from the "virtual" console. */ if (cmd == TIOCCONS && constty != NULL) { error = suser(p, SUSER_NOACCT); if (error) return (error); constty = NULL; return (0); } /* * Redirect the ioctl, if that's appropriate. * Note that strange things can happen, if a program does * ioctls on /dev/console, then the console is redirected * out from under it. */ if (constty != NULL) dev = constty->t_dev; else if (cn_tab == NULL) return ENXIO; else dev = cn_tab->cn_dev; return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag, p)); }
int minix_rmdir(register struct inode *dir, char *name, size_t len) { int retval; register struct inode *inode; struct buffer_head *bh; struct minix_dir_entry *de; inode = NULL; bh = minix_find_entry(dir, name, len, &de); retval = -ENOENT; if (!bh) goto end_rmdir; retval = -EPERM; if (!(inode = iget(dir->i_sb, (ino_t) de->inode))) goto end_rmdir; if ((dir->i_mode & S_ISVTX) && !suser() && current->euid != inode->i_uid && current->euid != dir->i_uid) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; if (inode == dir) /* we may not delete ".", but "../dir" is ok */ goto end_rmdir; if (!S_ISDIR(inode->i_mode)) { retval = -ENOTDIR; goto end_rmdir; } if (!empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } if (de->inode != inode->i_ino) { retval = -ENOENT; goto end_rmdir; } if (inode->i_count > 1) { retval = -EBUSY; goto end_rmdir; } if (inode->i_nlink != 2) printk("empty directory has nlink!=2 (%u)\n", inode->i_nlink); de->inode = 0; #ifdef BLOAT_FS dir->i_version = ++event; #endif mark_buffer_dirty(bh, 1); inode->i_nlink = 0; inode->i_dirt = 1; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_nlink--; dir->i_dirt = 1; retval = 0; end_rmdir: iput(dir); iput(inode); unmap_brelse(bh); return retval; }
/* * Reboot system call: for obvious reasons only root may call it, * and even root needs to set up some magic numbers in the registers * so that some mistake won't make this reboot the whole machine. * You can also set the meaning of the ctrl-alt-del-key here. * * reboot doesn't sync: do that yourself before calling this. */ asmlinkage int sys_reboot(int magic, int magic_too, int flag) { if (!suser()) return -EPERM; if (magic != 0xfee1dead || magic_too != 672274793) return -EINVAL; if (flag == 0x01234567) { #ifdef CONFIG_SCSI_GDTH gdth_halt(); #endif hard_reset_now(); } else if (flag == 0x89ABCDEF) C_A_D = 1; else if (!flag) C_A_D = 0; else if (flag == 0xCDEF0123) { #ifdef CONFIG_SCSI_GDTH gdth_halt(); #endif printk(KERN_EMERG "System halted\n"); sys_kill(-1, SIGKILL); #if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) apm_power_off(); #endif do_exit(0); } else return -EINVAL; return (0); }
/* * Perform process accounting functions. */ void sysacct(void) { register struct inode *ip; register struct a { char *fname; } *uap; uap = (struct a *)u.u_ap; if (suser()) { if (uap->fname==NULL) { if (acctp) { plock(acctp); iput(acctp); acctp = NULL; } return; } if (acctp) { u.u_error = EBUSY; return; } u.u_dirp = uap->fname; ip = namei(uchar, 0); if (ip == NULL) { return; } if ((ip->i_mode & IFMT) != IFREG) { u.u_error = EACCES; iput(ip); return; } acctp = ip; prele(ip); } }
/* afs_put_super * Called from unmount to release super_block. */ static void afs_put_super(struct super_block *sbp) { AFS_GLOCK(); AFS_STATCNT(afs_unmount); if (!suser()) { AFS_GUNLOCK(); return; } afs_globalVFS = 0; afs_globalVp = 0; afs_shutdown(); #if defined(AFS_LINUX24_ENV) mntput(afs_cacheMnt); #endif osi_linux_verify_alloced_memory(); AFS_GUNLOCK(); sbp->s_dev = 0; MOD_DEC_USE_COUNT; }
int sys_munlock(struct proc *p, void *v, register_t *retval) { struct sys_munlock_args /* { syscallarg(const void *) addr; syscallarg(size_t) len; } */ *uap = v; vaddr_t addr; vsize_t size, pageoff; int error; /* * extract syscall args from uap */ addr = (vaddr_t)SCARG(uap, addr); size = (vsize_t)SCARG(uap, len); /* * align the address to a page boundary, and adjust the size accordingly */ ALIGN_ADDR(addr, size, pageoff); if (addr > SIZE_MAX - size) return (EINVAL); /* disallow wrap-around. */ #ifndef pmap_wired_count if ((error = suser(p, 0)) != 0) return (error); #endif error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, TRUE, 0); return (error == 0 ? 0 : ENOMEM); }
static int wan_ioctl(struct ifnet *ifp, int cmd, struct ifreq *ifr) { sdla_t *card; wanpipe_common_t *common = WAN_IFP_TO_COMMON(ifp); int err; SAN_ASSERT(common == NULL); SAN_ASSERT(common->card == NULL); if ((err = suser(curproc, 0)) != 0) return err; switch (cmd) { case SIOC_WANPIPE_HWPROBE: err = wan_ioctl_hwprobe(ifp, ifr->ifr_data); break; case SIOC_WANPIPE_DUMP: err = wan_ioctl_dump(card, ifr->ifr_data); break; default: err = ENOTTY; break; } return err; }
static int lpx_USER_r_attach( struct socket *so, int proto, struct proc *td ) { int error = 0; int s; struct lpxpcb *lpxp = sotolpxpcb(so); if (td != NULL && (error = suser(td->p_ucred, &td->p_acflag)) != 0) return (error); s = splnet(); error = Lpx_PCB_alloc(so, &lpxrawpcb, td); splx(s); if (error) return (error); error = soreserve(so, lpxsendspace, lpxrecvspace); if (error) return (error); lpxp = sotolpxpcb(so); lpxp->lpxp_faddr.x_host = lpx_broadhost; lpxp->lpxp_flags = LPXP_RAWIN | LPXP_RAWOUT; return (error); }
int send_sig(unsigned long sig,struct task_struct * p,int priv) { if (!p || sig > 32) return -EINVAL; if (!priv && ((sig != SIGCONT) || (current->session != p->session)) && (current->euid ^ p->suid) && (current->euid ^ p->uid) && (current->uid ^ p->suid) && (current->uid ^ p->uid) && !suser()) return -EPERM; if (!sig) return 0; /* * Forget it if the process is already zombie'd. */ if (!p->sig) return 0; if ((sig == SIGKILL) || (sig == SIGCONT)) { if (p->state == TASK_STOPPED) wake_up_process(p); p->exit_code = 0; p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) | (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) ); } if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) p->signal &= ~(1<<(SIGCONT-1)); /* Actually generate the signal */ generate(sig,p); return 0; }
int sbbcopen(dev_t dev, int flag, int mode, struct proc *p) { struct sbbc_softc *sc; struct tty *tp; int unit = minor(dev); if (unit >= sbbc_cd.cd_ndevs) return (ENXIO); sc = sbbc_cd.cd_devs[unit]; if (sc == NULL) return (ENXIO); if (sc->sc_tty) tp = sc->sc_tty; else tp = sc->sc_tty = ttymalloc(0); tp->t_oproc = sbbcstart; tp->t_param = sbbcparam; tp->t_dev = dev; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) && suser(p, 0)) return (EBUSY); tp->t_state |= TS_CARR_ON; return ((*linesw[tp->t_line].l_open)(dev, tp, p)); }
/* afs_put_super * Called from unmount to release super_block. */ static void afs_put_super(struct super_block *sbp) { AFS_GLOCK(); AFS_STATCNT(afs_unmount); if (!suser()) { AFS_GUNLOCK(); return; } afs_globalVFS = 0; afs_globalVp = 0; osi_linux_free_inode_pages(); /* invalidate and release remaining AFS inodes. */ afs_shutdown(); #if defined(AFS_LINUX24_ENV) mntput(afs_cacheMnt); #endif osi_linux_verify_alloced_memory(); AFS_GUNLOCK(); sbp->s_dev = 0; MOD_DEC_USE_COUNT; }
int reboot(struct proc *p, register struct reboot_args *uap, __unused int32_t *retval) { char command[64]; int error=0; size_t dummy=0; #if CONFIG_MACF kauth_cred_t my_cred; #endif AUDIT_ARG(cmd, uap->opt); command[0] = '\0'; if ((error = suser(kauth_cred_get(), &p->p_acflag))) return(error); if (uap->opt & RB_COMMAND) error = copyinstr(uap->command, (void *)command, sizeof(command), (size_t *)&dummy); #if CONFIG_MACF if (error) return (error); my_cred = kauth_cred_proc_ref(p); error = mac_system_check_reboot(my_cred, uap->opt); kauth_cred_unref(&my_cred); #endif if (!error) { OSBitOrAtomic(P_REBOOT, &p->p_flag); /* No more signals for this proc */ boot(RB_BOOT, uap->opt, command); } return(error); }
int scull_u_open (struct inode *inode, struct file *filp) { Scull_Dev *dev = &scull_u_device; /* device information */ int num = NUM(inode->i_rdev); if (num > 0) return -ENODEV; /* 1 device only */ if (scull_u_count && (scull_u_owner != current->uid) && /* allow user */ (scull_u_owner != current->euid) && /* allow whoever did su */ !suser()) /* still allow root */ return -EBUSY; /* -EPERM would confuse the user */ if (scull_u_count == 0) scull_u_owner = current->uid; /* grab it */ scull_u_count++; /* then, everything else is copied from the bare scull device */ if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) scull_trim(dev); filp->private_data = dev; MOD_INC_USE_COUNT; return 0; /* success */ }
/*ARGSUSED*/ int mmopen(dev_t dev, int flag, int mode, struct proc *p) { switch (minor(dev)) { case 0: case 1: case 2: case 12: break; #ifdef APERTURE case 4: if (suser(p, 0) != 0 || !allowaperture) return (EPERM); /* authorize only one simultaneous open() */ if (ap_open_count > 0) return(EPERM); ap_open_count++; break; #endif default: return (ENXIO); } return (0); }
static int ip_proto_bind (struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in addr; volatile struct sock *sk, *sk2; unsigned short snum; sk = sock->data; if (sk == NULL) { printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } /* check this error. */ if (sk->state != TCP_CLOSE) return (-EIO); verify_area (uaddr, addr_len); memcpy_fromfs (&addr, uaddr, min (sizeof (addr), addr_len)); if (addr.sin_family && addr.sin_family != AF_INET) return (-EIO); /* this needs to be changed. */ snum = net16(addr.sin_port); PRINTK ("bind sk =%X to port = %d\n", sk, snum); print_sk (sk); sk = sock->data; /* we can't just leave the socket bound wherever it is, it might be bound to a priveledged port. However, since there seems to be a bug here, we will leave it if the port is not priveledged(sp?) */ if (snum == 0) { if ( sk->num > PROT_SOCK) return (0); snum = get_new_socknum (sk->prot, 0); } if (snum <= PROT_SOCK && !suser()) return (-EPERM); if (my_ip_addr(addr.sin_addr.s_addr) || addr.sin_addr.s_addr == 0) sk->saddr = addr.sin_addr.s_addr; PRINTK ("sock_array[%d] = %X:\n", snum & (SOCK_ARRAY_SIZE -1), sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]); print_sk (sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]); /* make sure we are allowed to bind here. */ for (sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]; sk2 != NULL; sk2 = sk2->next) { if (sk2->num != snum) continue; if (sk2->saddr != sk->saddr) continue; if (!sk->reuse) return (-EADDRINUSE); if (!sk2->reuse) return (-EADDRINUSE); } remove_sock (sk); put_sock(snum, sk); sk->dummy_th.source = net16(sk->num); sk->daddr = 0; sk->dummy_th.dest = 0; return (0); }
/* ARGSUSED */ int sys_setegid(struct proc *p, void *v, register_t *retval) { struct sys_setegid_args /* { syscallarg(gid_t) egid; } */ *uap = v; struct pcred *pc = p->p_cred; gid_t egid; int error; egid = SCARG(uap, egid); if (pc->pc_ucred->cr_gid == egid) return (0); if (egid != pc->p_rgid && egid != pc->p_svgid && (error = suser(p, 0))) return (error); /* * Copy credentials so other references do not see our changes. */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_gid = egid; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); }
int afmioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag, struct lwp *l) { int error = 0; struct atm_flowmap *flowmap; struct ifnet *ifp; /* check cmd for superuser only */ switch (cmd) { case AFM_GETFMAP: break; default: #if (__FreeBSD_version > 400000) error = suser(p); #else error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_ALTQ, KAUTH_REQ_NETWORK_ALTQ_AFMAP, NULL, NULL, NULL); #endif if (error) return (error); break; } /* lookup interface */ flowmap = (struct atm_flowmap *)addr; flowmap->af_ifname[IFNAMSIZ-1] = '\0'; ifp = ifunit(flowmap->af_ifname); if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) error = ENXIO; else error = ifp->if_ioctl(ifp, cmd, addr); return error; }
/* * Credential check based on process requesting service, and per-attribute * permissions. */ static int ufs_extattr_credcheck(struct vnode *vp, struct ufs_extattr_list_entry *uele, struct ucred *cred, struct proc *p, int access) { /* * Kernel-invoked always succeeds. */ if (cred == NULL) return (0); /* * Do not allow privileged processes in jail to directly * manipulate system attributes. * * XXX What capability should apply here? * Probably CAP_SYS_SETFFLAG. */ switch (uele->uele_attrnamespace) { case EXTATTR_NAMESPACE_SYSTEM: return (suser(cred, &p->p_acflag)); case EXTATTR_NAMESPACE_USER: return (VOP_ACCESS(vp, access, cred, p)); default: return (EPERM); } }
int sys_mlockall(struct proc *p, void *v, register_t *retval) { struct sys_mlockall_args /* { syscallarg(int) flags; } */ *uap = v; int error, flags; flags = SCARG(uap, flags); if (flags == 0 || (flags & ~(MCL_CURRENT|MCL_FUTURE)) != 0) return (EINVAL); #ifndef pmap_wired_count if ((error = suser(p, 0)) != 0) return (error); #endif error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); if (error != 0 && error != ENOMEM) return (EAGAIN); return (error); }
/* * Written 01/25/92 by Simmule Turner, heavily changed by Linus. * * The swapon system call */ asmlinkage int sys_swapon(const char * specialfile, int swap_flags) { struct swap_info_struct * p; struct inode * swap_inode; unsigned int type; int i, j, prev; int error; struct file filp; static int least_priority = 0; memset(&filp, 0, sizeof(filp)); if (!suser()) return -EPERM; p = swap_info; for (type = 0 ; type < nr_swapfiles ; type++,p++) if (!(p->flags & SWP_USED)) break; if (type >= MAX_SWAPFILES) return -EPERM; if (type >= nr_swapfiles) nr_swapfiles = type+1; p->flags = SWP_USED; p->swap_file = NULL; p->swap_device = 0; p->swap_map = NULL; p->swap_lockmap = NULL; p->lowest_bit = 0; p->highest_bit = 0; p->cluster_nr = 0; p->max = 1; p->next = -1; if (swap_flags & SWAP_FLAG_PREFER) { p->prio = (swap_flags & SWAP_FLAG_PRIO_MASK)>>SWAP_FLAG_PRIO_SHIFT; } else {
int i386_iopl(struct proc *p, void *args, register_t *retval) { int error; struct trapframe *tf = p->p_md.md_regs; struct i386_iopl_args ua; if ((error = suser(p, 0)) != 0) return error; #ifdef APERTURE if (!allowaperture && securelevel > 0) return EPERM; #else if (securelevel > 0) return EPERM; #endif if ((error = copyin(args, &ua, sizeof(ua))) != 0) return error; if (ua.iopl) tf->tf_eflags |= PSL_IOPL; else tf->tf_eflags &= ~PSL_IOPL; return 0; }
/* Some basic sanity checks on the arguments passed to divert_ioctl() */ int check_args(struct divert_cf *div_cf, struct net_device **dev) { char devname[32]; if (dev == NULL) return -EFAULT; /* GETVERSION: all other args are unused */ if (div_cf->cmd == DIVCMD_GETVERSION) return 0; /* Network device index should reasonably be between 0 and 1000 :) */ if (div_cf->dev_index < 0 || div_cf->dev_index > 1000) return -EINVAL; /* Let's try to find the ifname */ sprintf(devname, "eth%d", div_cf->dev_index); *dev = dev_get_by_name(devname); /* dev should NOT be null */ if (*dev == NULL) return -EINVAL; /* user issuing the ioctl must be a super one :) */ if (!suser()) return -EPERM; /* Device must have a divert_blk member NOT null */ if ((*dev)->divert == NULL) return -EFAULT; return 0; }
/* ARGSUSED */ int sys_setgroups(struct proc *p, void *v, register_t *retval) { struct sys_setgroups_args /* { syscallarg(int) gidsetsize; syscallarg(const gid_t *) gidset; } */ *uap = v; struct pcred *pc = p->p_cred; u_int ngrp; int error; if ((error = suser(p, 0)) != 0) return (error); ngrp = SCARG(uap, gidsetsize); if (ngrp > NGROUPS) return (EINVAL); pc->pc_ucred = crcopy(pc->pc_ucred); error = copyin((caddr_t)SCARG(uap, gidset), (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)); if (error) return (error); pc->pc_ucred->cr_ngroups = ngrp; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); }
int sys_stime(long * tptr) { if (!suser()) return -EPERM; startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ; return 0; }
/* * Routine: macx_backing_store_recovery * Function: * Syscall interface to set a tasks privilege * level so that it is not subject to * macx_backing_store_suspend */ int macx_backing_store_recovery( struct macx_backing_store_recovery_args *args) { int pid = args->pid; int error; struct proc *p = current_proc(); boolean_t funnel_state; funnel_state = thread_funnel_set(kernel_flock, TRUE); if ((error = suser(kauth_cred_get(), 0))) goto backing_store_recovery_return; /* for now restrict backing_store_recovery */ /* usage to only present task */ if(pid != proc_selfpid()) { error = EINVAL; goto backing_store_recovery_return; } task_backing_store_privileged(p->task); backing_store_recovery_return: (void) thread_funnel_set(kernel_flock, FALSE); return(error); }
/* these should be distributed to the different protocol routines. */ static int ip_proto_ioctl (struct socket *sock, unsigned int cmd, unsigned long arg) { volatile struct sock *sk; sk = sock->data; if (sk == NULL) { printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } PRINTK ("in ip_proto_ioctl\n"); switch (cmd) { case IP_SET_DEV: if (!suser()) return (-EPERM); return (ip_set_dev((struct ip_config *)arg)); #if 0 case IP_ADD_ROUTE: ip_add_route ((struct rtable *) arg); return (0); #endif default: if (!sk->prot->ioctl) return (-EINVAL); return (sk->prot->ioctl (sk, cmd, arg)); } }
int scull_w_open (struct inode *inode, struct file *filp) { Scull_Dev *dev = &scull_w_device; /* device information */ int num = NUM(inode->i_rdev); if (num > 0) return -ENODEV; /* 1 device only */ while (scull_w_count && (scull_w_owner != current->uid) && /* allow user */ (scull_w_owner != current->euid) && /* allow whoever did su */ !suser()) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; interruptible_sleep_on(&scull_w_wait); if (current->signal & ~current->blocked) /* a signal arrived */ return -ERESTARTSYS; /* tell the fs layer to handle it */ /* else, loop */ } if (scull_w_count == 0) scull_w_owner = current->uid; /* grab it */ scull_w_count++; /* then, everything else is copied from the bare scull device */ if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) scull_trim(dev); filp->private_data = dev; MOD_INC_USE_COUNT; return 0; /* success */ }
/* ARGSUSED */ int sys_setuid(struct proc *p, void *v, register_t *retval) { struct sys_setuid_args /* { syscallarg(uid_t) uid; } */ *uap = v; struct pcred *pc = p->p_cred; uid_t uid; int error; uid = SCARG(uap, uid); if (pc->pc_ucred->cr_uid == uid && pc->p_ruid == uid && pc->p_svuid == uid) return (0); if (uid != pc->p_ruid && uid != pc->p_svuid && uid != pc->pc_ucred->cr_uid && (error = suser(p, 0))) return (error); /* * Everything's okay, do it. */ if (uid == pc->pc_ucred->cr_uid || suser(p, 0) == 0) { /* * Transfer proc count to new user. */ if (uid != pc->p_ruid) { (void)chgproccnt(pc->p_ruid, -p->p_p->ps_refcnt); (void)chgproccnt(uid, p->p_p->ps_refcnt); } pc->p_ruid = uid; pc->p_svuid = uid; } /* * Copy credentials so other references do not see our changes. */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_uid = uid; atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); }
static int rtmac_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct rtmac_config cfg; struct rtnet_device *rtdev; if( !suser() ) return -EPERM; if( copy_from_user(&cfg, (void*)arg, sizeof(struct rtmac_config)) ) return -EFAULT; rtdev = rtdev_get_by_name(cfg.if_name); if( !rtdev ) { rt_printk("RTmac: invalid interface %s\n", cfg.if_name); return -ENODEV; } if( !(rtdev->rtmac && rtdev->rtmac->ioctl_ops) ) { return -ENOTTY; } switch( cmd ) { case RTMAC_IOC_CLIENT: return rtmac_ioctl_client(rtdev); break; case RTMAC_IOC_MASTER: return rtmac_ioctl_master(rtdev, cfg.cycle, cfg.mtu); break; case RTMAC_IOC_UP: return rtmac_ioctl_up(rtdev); break; case RTMAC_IOC_DOWN: return rtmac_ioctl_down(rtdev); break; case RTMAC_IOC_ADD: return rtmac_ioctl_add(rtdev, cfg.ip_addr); break; case RTMAC_IOC_REMOVE: return rtmac_ioctl_remove(rtdev, cfg.ip_addr); break; case RTMAC_IOC_ADD_NRT: return rtmac_ioctl_add_nrt(rtdev, cfg.ip_addr); break; case RTMAC_IOC_REMOVE_NRT: return rtmac_ioctl_remove_nrt(rtdev, cfg.ip_addr); break; case RTMAC_IOC_CYCLE: return rtmac_ioctl_cycle(rtdev, cfg.cycle); break; case RTMAC_IOC_MTU: return rtmac_ioctl_mtu(rtdev, cfg.mtu); break; case RTMAC_IOC_OFFSET: return rtmac_ioctl_offset(rtdev, cfg.ip_addr, cfg.offset); default: return -ENOTTY; } }