According to
this page, the file_operations structure is sourced in linux/fs.h. The reference structure on the aforementioned page (from Linux 2.4.2) indicates that your code should be correct. However, the same structure from Linux 3.7 RC2 looks somewhat different.
/* These macros are for out of kernel modules to test that
* the kernel supports the unlocked_ioctl and compat_ioctl
* fields in struct file_operations. */
#define HAVE_COMPAT_IOCTL 1
#define HAVE_UNLOCKED_IOCTL 1
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
};
Notice in particular that there is no longer a member named
ioctl, but rather
unlocked_ioctl and
compat_ioctl. Also notice that the
ioctl function pointer prototypes are different.
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
versus
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
Theoretically, all you need to do is modify the existing FirewallIoctl function to conform to the new prototype and assign it to compat_ioctl.
/*
** init_firewall - Module entry routine.
*/
int init_firewall()
{
int rc;
myprintk(KERN_ALERT "entering module_init\n");
Firewall.FileOps.compat_ioctl = FirewallIoctlCompat;
Firewall.FileOps.open = FirewallOpen;
Firewall.FileOps.read = FirewallRead;
Firewall.FileOps.release = FirewallClose;
rc = FirewallInit();
if(rc == 0)
PS: If you're going to be writing kernel-level code, it might be a good idea to keep a local copy of the Linux git repository. That way you can see not only the code and comments for any version of Linux, but also the commit messages that go along with them.