2

I'm trying to write a simple sniffer-driver for linux, which will redirect all the requests to the real serial port (and also will print all the messages into system log). I found some examples on the Internet and implemented few functions. For example, function that invokes when ouw fake device is opened:

static int dev_open(struct inode *inodep, struct file *filep) {
   numberOpens++;
   printk(KERN_INFO "sniffer: Device has been opened %d time(s)\n", numberOpens);

   /// Connecting to real device   
   fd = open (real_device, O_RDWR | O_NOCTTY | O_SYNC);
   if (fd < 0) {
      printk(KERN_INFO "sniffer: cannot open device %s\n", real_device);
     return 1;
   }

   set_interface_attribs (fd, B115200, 0);  // set speed to 115,200 bps, 8n1 (no parity)
   set_blocking (fd, 0);                     // set no blocking
   return 0;
}

As you can see, this function just opens the real device using standart linux open system call. Or function that sets real device settings (speed and parity):

int set_interface_attribs (int fd, int speed, int parity) {
    struct termios tty;
    memset (&tty, 0, sizeof tty);
    if (tcgetattr (fd, &tty) != 0) {
        // error_message ("error %d from tcgetattr", errno);
        printk(KERN_INFO "sniffer: cannot get device attributes\n");
        return -1;
    }

    cfsetospeed (&tty, speed);
    cfsetispeed (&tty, speed);

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
    // disable IGNBRK for mismatched speed tests; otherwise receive break
    // as \000 chars
    tty.c_iflag &= ~IGNBRK;         // disable break processing
    tty.c_lflag = 0;                // no signaling chars, no echo,
                                // no canonical processing
    tty.c_oflag = 0;                // no remapping, no delays
    tty.c_cc[VMIN]  = 0;            // read doesn't block
    tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

    tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                    // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
    tty.c_cflag |= parity;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr (fd, TCSANOW, &tty) != 0) {
        printk(KERN_INFO "sniffer: cannot set device attributes\n");
        return -1;
    }
    return -1;
}

It uses tcgetattr and tcsetattr system calls.

I included all required header files:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/fcntl.h> 
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/termios.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

But when I try to compile this module i get "implicit declaration of function" errors for this system calls.

My Makefile:

obj-m += sniffer.o

all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Compile errors:

sniffer.c: In function ‘set_interface_attribs’:
sniffer.c:51:9: error: implicit declaration of function ‘tcgetattr’ [-Werror=implicit-function-declaration]
     if (tcgetattr (fd, &tty) != 0) {
         ^
sniffer.c:57:5: error: implicit declaration of function ‘cfsetospeed’ [-Werror=implicit-function-declaration]
     cfsetospeed (&tty, speed);
     ^
sniffer.c:58:5: error: implicit declaration of function ‘cfsetispeed’ [-Werror=implicit-function-declaration]
     cfsetispeed (&tty, speed);
     ^
sniffer.c:79:9: error: implicit declaration of function ‘tcsetattr’ [-Werror=implicit-function-declaration]
     if (tcsetattr (fd, TCSANOW, &tty) != 0) {
         ^
sniffer.c: In function ‘dev_open’:
sniffer.c:151:9: error: implicit declaration of function ‘open’ [-Werror=implicit-function-declaration]
    fd = open (real_device, O_RDWR | O_NOCTTY | O_SYNC);
         ^
sniffer.c: In function ‘dev_read’:
sniffer.c:164:18: error: implicit declaration of function ‘read’ [-Werror=implicit-function-declaration]
    error_count = read(fd, buffer, len);
                  ^
sniffer.c: In function ‘dev_write’:
sniffer.c:177:4: error: implicit declaration of function ‘write’ [-Werror=implicit-function-declaration]
    write (fd, buffer, len);
    ^
sniffer.c: In function ‘dev_release’:
sniffer.c:184:4: error: implicit declaration of function ‘close’ [-Werror=implicit-function-declaration]
    close(fd);
    ^

What can it be? All the examples that i found just say that I should include <linux/unistd.h> and <linux/termios.h>.

kivi
  • 379
  • 1
  • 5
  • 17
  • 1
    You can't just translate user space code into the kernel and have it work. You will need to find out what the kernel-internal equivalent of each and every one of the missing functions is. Be prepared to do _significantly_ more work. – zwol Apr 12 '17 at 18:03
  • (I don't know what the equivalents are, but I do know that it doesn't actually make sense to call the "standar[d] linux `open` system call" from inside a device driver, and that the various termios functions you are trying to call are userspace C library wrappers around `ioctl` operations which, again, probably don't even make sense inside a device driver.) – zwol Apr 12 '17 at 18:04
  • @zwol yes, i'm starting to realize that now, thank you. I found kernel equivalents for file operations. But don't kwon what to do with termios functions yet – kivi Apr 12 '17 at 18:12
  • 2
    Functions `tcgetattr` and `tcsetattr` are actually wrappers around `ioctl` requests. In kernel you may use `file->f_ops->unlocked_ioctl()` as analogue for ioctl syscall. For determine exact ioctl codes used by *termios*, write some code in user space, and run it under `trace` tool. – Tsyvarev Apr 12 '17 at 18:52
  • why return -1 on both success and failure – user3629249 Apr 13 '17 at 00:00

1 Answers1

1

I had the similar problem, what I found out is that adding

#include <linux/uaccess.h> 

to the list of includes solved my problem on Ubuntu 18.04(Linux Kernel Version : 4.15.0).

NOTE: leave #include <asm/uaccess.h> as well

There is a case where reordering of the include statements can help. See the answers in this question:

warning: implicit declaration of function

Srđan Popić
  • 1,191
  • 13
  • 25