First of all I am showing the code for my c file ..
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <memory.h>
#include <string.h>
#include <ctype.h>
#include "sendip_module.h"
#include "ipv6ext.h"
#include "../ipv6.h"
#include "../ipv4.h"
#include "ah.h"
#include "esp.h"
#include "crypto_module.h"
#include <openssl/hmac.h>
#include <openssl/md5.h>
/*
code for hmac_md5 here....
void
hmac_md5(text, text_len, key, key_len, digest)
unsigned char* text; /* pointer to data stream */
int text_len; /* length of data stream */
unsigned char* key; /* pointer to authentication key */
int key_len; /* length of authentication key */
caddr_t digest; /* caller digest to be filled in */
{
MD5_CTX context;
unsigned char k_ipad[65]; /* inner padding -
* key XORd with ipad
*/
unsigned char k_opad[65]; /* outer padding -
* key XORd with opad
*/
unsigned char tk[16];
int i;
/* if key is longer than 64 bytes reset it to key=MD5(key) */
if (key_len > 64) {
MD5_CTX tctx;
MD5Init(&tctx);
MD5Update(&tctx, key, key_len);
MD5Final(tk, &tctx);
key = tk;
key_len = 16;
}
/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/* start out by storing key in pads */
bzero( k_ipad, sizeof k_ipad);
bzero( k_opad, sizeof k_opad);
bcopy( key, k_ipad, key_len);
bcopy( key, k_opad, key_len);
/* XOR key with ipad and opad values */
for (i=0; i<64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner MD5
*/
MD5Init(&context); /* init context for 1st
* pass */
MD5Update(&context, k_ipad, 64); /* start with inner pad */
MD5Update(&context, text, text_len); /* then text of datagram */
MD5Final(digest, &context); /* finish up 1st pass */
/*
* perform outer MD5
*/
MD5Init(&context); /* init context for 2nd
* pass */
MD5Update(&context, k_opad, 64); /* start with outer pad */
MD5Update(&context, digest, 16); /* then results of 1st
* hash */
MD5Final(digest, &context); /* finish up 2nd pass */
}
*/
/*
rest of the program logic...
*/
I have already included ...<.path where openssl is installed.....>../openssl/include to C_INCLUDE_PATH and exported it.
and now when i try to compile it getting error :
$ make
gcc -o xorauth.so -I.. -fPIC -fsigned-char -pipe -Wall -Wpointer-arith -Wwrite-strings
wstrict-prototypes -Wnested-externs -Winline -Werror -g -Wcast-align -
DSENDIP_LIBS=\"/usr/local/lib/sendip\" -shared xorauth.c ../libsendipaux.a
../libsendipaux.a
cc1: warnings being treated as errors
xorauth.c:34:1: error: function declaration isn’t a prototype
xorauth.c: In function ‘hmac_md5’:
xorauth.c:56:17: error: implicit declaration of function ‘MD5Init’
xorauth.c:56:17: error: nested extern declaration of ‘MD5Init’
xorauth.c:57:17: error: implicit declaration of function ‘MD5Update’
xorauth.c:57:17: error: nested extern declaration of ‘MD5Update’
xorauth.c:58:17: error: implicit declaration of function ‘MD5Final’
xorauth.c:58:17: error: nested extern declaration of ‘MD5Final’
make: *** [xorauth.so] Error 1
if required I will edit the other implementation details I have skiped them just to make the post small because I think there is something which i need to do regarding include path and header files and i am unaware of it.
What is going wrong please help me ???
There is no MD5Init function in OpenSSL. (There is in the BSD implementation.)
man MD5_Init (note the underscore), or see here.
EDIT:
Now that you've shown us the offending code, I can also help with the "not a prototype" message.
You have (edited a bit):
void hmac_md5(text, text_len, key, key_len, digest)
unsigned char* text;
int text_len;
unsigned char* key;
int key_len;
caddr_t digest;
{
/* ... */
}
That's an old-style, or "K&R", function definition. It's still valid, but only for backward compatibility, and it means that the compiler won't be able to warn you about calls with the wrong number or type(s) of arguments. The modern (since 1989) version is:
void hmac_md5(unsigned char *text,
int text_len,
unsigned char *key,
int key_len,
caddr_t digest)
{
/* ... */
}
When converting old-style function declarations and definitions to use prototypes, you sometimes have to be careful about parameters with narrow types (float, and integer types narrower than int or unsigned int) due to the promotion rules. That doesn't apply in this particular case.
Note that you can leave the definition as it is if you like. Since you got the code from an internet draft, that might even be a good idea (if it ain't broke, don't fix it) -- but as I said you'll get no help from the compiler if you call it with the wrong number or type(s) of arguments.
Related
I want to assemble a char array that contains one byte with a compile time constant value and a string, which is also compile time constant. Solution would be:
char packet[] = "\x42" __DATE__;
That works but is not very readable and maintainable, as that 0x42 is a message opcode that is used elsewhere, making this a magic number. Now, I could put a dummy x into the string and follow this definition with an assignment like this:
#define OPCODE 0x42
char packet[] = "x" __DATE__;
packet[0] = OPCODE;
But I have the feeling that could be done in a purely constant string literal, I just can't find how to do it. Any idea?
__DATE__ should mostly have exactly Mmm dd yyyy format, so 11 characters. You can do this:
char packet[] = {
OPCODE,
__DATE__[0],
__DATE__[1],
__DATE__[2],
__DATE__[3],
__DATE__[4],
__DATE__[5],
__DATE__[6],
__DATE__[7],
__DATE__[8],
__DATE__[9],
__DATE__[10],
__DATE__[11],
0,
};
As the C preprocessor cannot help here, this might be a case for an additional preprocessor to be added to the build system.
Whether you choose a second stage of C preprocessor, m4, a shell or python script or whatever else is up to you.
Or you go another route and change the packet type from char array to a struct with a flexible array member, something like the following:
/* foo.c
* Compile with something like
* avr-gcc -mmcu=atmega328 -Os -Wall -Wextra -Werror \
* -save-temps=obj -Wa,-adhlns=foo.lst,-gstabs -c foo.c
*/
#include <stddef.h>
#include <stdint.h>
#include <avr/pgmspace.h>
#define OPCODE_DATE 0x42
struct packet_descr {
uint8_t opcode;
uint16_t size;
};
struct string_packet {
struct packet_descr descr;
char string[];
};
#define STRING_PACKET_P(IDENTIFIER, OPCODE, STRING) \
const struct string_packet IDENTIFIER PROGMEM = { \
{ (OPCODE), \
sizeof(STRING)-1 \
}, \
(STRING) \
}
STRING_PACKET_P(packet_date_P, OPCODE_DATE, __DATE__);
void uart_send_char(const char ch);
void uart_send_char(const char ch)
{
UDR0 = ch;
}
/* Send string packet in the following format:
* uint8_t opcode;
* uint16_t len; // in AVR endianness
* char string[len]; // string of "len" characters, unterminated
*/
extern
void string_packet_send_P(const struct string_packet *string_packet_P);
void string_packet_send_P(const struct string_packet *string_packet_P)
{
const uint8_t opcode = pgm_read_byte(&string_packet_P->descr.opcode);
uart_send_char(opcode);
size_t len = pgm_read_word(&string_packet_P->descr.size);
for (PGM_P byte_P = (PGM_P)&string_packet_P->string; len > 0; len--, byte_P++) {
uart_send_char(pgm_read_byte(byte_P));
}
}
int main(void)
{
string_packet_send_P(&packet_date_P);
return 0;
}
One obvious disadvantage of a struct with a flexible array member is that sizeof(packet) will only yield the size of the non-array part. However, depending on your actual packet format (the receiver of the packet also needs to know when a packet starts and finishes, right?), recording the size separately might be feasible.
I'm trying to compile "Example 11-9. Source code to the SYNplescan tool" from this NetworkSecurityTools book on Ubuntu 18.04:
http://books.gigatux.nl/mirror/networksecuritytools/0596007949/networkst-CHP-11-SECT-4.html
But it says
error: dereferencing pointer to incomplete type ‘struct tcphdr’
if (tcp->th_flags == 0x14)
^~
How do I fix this?
People change and includes come and go, after the following changes:
## -1,9 +1,12 ##
+#define _DEFAULT_SOURCE 1
#define _BSD_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <libnet.h>
#include <pcap.h>
+#include <netinet/tcp.h>
+#include <netinet/ip.h>
int answer = 0; /* flag for scan timeout */
## -42,7 +45,7 ##
int
main (int argc, char *argv[])
{
- char *device = NULL; /* device for sniffing/sending */
+ const char *device = NULL; /* device for sniffing/sending */
char o; /* for option processing */
in_addr_t ipaddr; /* ip address to scan */
u_int32_t myipaddr; /* ip address of this host */
I was able to compile with:
gcc -Wall 1.c -lnet -lpcap
with no compiler messages. I guess that once netinet/tcp.h was included by libnet.h or maybe by pcap.h - seems not be the case anymore and you have to include netinet/tcp.h yourself for struct tcphdr.
I am very new to C (had one semester class like 5 years ago). To summarize my problem, I have code written in C that compiles on Raspbian Jessie, but not Buster Lite.
I'm using a Raspberry Pi Zero W + ADCs to input an analog signal, digitize it, and transmit it wirelessly and the code I'm having issues with takes the data from the GPIOs and stores it in a buffer that I can read from. I previously was running Raspbian Jessie on my pi and I had NO issues compiling the code (no warnings, no errors). It was correctly reading data from the ADCs and storing it in the buffer. When I installed Raspbian Buster Lite on my Pi, and have been getting multiple errors/warnings when compiling. (I'm not concerned about the warnings/notes, know how to fix them, just the errors. partly included because I don't understand why they appeared on Buster but not on Jessie)
make -C /lib/modules/4.19.97+/build M=/home/pi modules
make[1]: Entering directory '/usr/src/linux-headers-4.19.97+'
CC [M] /home/pi/adc.o
/home/pi/adc.c:132:9: warning: useless storage class specifier in empty declaration
};
^
/home/pi/adc.c: In function ‘readScope’:
/home/pi/adc.c:176:13: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
struct timespec ts_start,ts_stop;
^~~~~~
/home/pi/adc.c:218:29: error: assignment to ‘unsigned char *’ from incompatible pointer type ‘struct DataStruct *’ [-Werror=incompatible-pointer-types]
ScopeBufferStart=&dataStruct;
^
/home/pi/adc.c: At top level:
/home/pi/adc.c:225:9: warning: "/*" within comment [-Wcomment]
/*
In file included from ./include/linux/printk.h:7,
from ./include/linux/kernel.h:14,
from /home/pi/adc.c:1:
/home/pi/adc.c: In function ‘init_module’:
./include/linux/kern_levels.h:5:18: warning: too many arguments for format [-Wformat-extra-args]
#define KERN_SOH "\001" /* ASCII Start Of Header */
^~~~~~
./include/linux/kern_levels.h:9:20: note: in expansion of macro ‘KERN_SOH’
#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */
^~~~~~~~
/home/pi/adc.c:248:24: note: in expansion of macro ‘KERN_ALERT’
printk(KERN_ALERT,"Failed to map the physical GPIO registers into the virtual memory space.\n");
^~~~~~~~~~
/home/pi/adc.c:283:13: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
struct bcm2835_peripheral *p=&myclock;
^~~~~~
/home/pi/adc.c:290:13: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int speed_id = 6; //1 for to start with 19Mhz or 6 to start with 500 MHz
^~~
/home/pi/adc.c: In function ‘device_read’:
/home/pi/adc.c:359:35: warning: comparison of distinct pointer types lacks a cast
while (length && buf_p<ScopeBufferStop) {
^
In file included from /home/pi/adc.c:4:
./arch/arm/include/asm/uaccess.h:387:33: error: incompatible types when initializing type ‘char’ using type ‘struct DataStruct’
__typeof__(*(ptr)) __pu_val = (x); \
^
./arch/arm/include/asm/uaccess.h:404:2: note: in expansion of macro ‘__put_user_switch’
__put_user_switch((x), (ptr), __pu_err, __put_user_check); \
^~~~~~~~~~~~~~~~~
/home/pi/adc.c:361:23: note: in expansion of macro ‘put_user’
if(0!=put_user(*(buf_p++), buffer++))
^~~~~~~~
At top level:
/home/pi/adc.c:111:26: warning: ‘ScopeBuffer_Ptr’ defined but not used [-Wunused-variable]
static uint32_t *ScopeBuffer_Ptr;
^~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:310: /home/pi/adc.o] Error 1
make[1]: *** [Makefile:1522: _module_/home/pi] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.19.97+'
make: *** [Makefile:4: all] Error 2
What I've tried:
One of the first errors I got (code updated since then, used to have buf_ declared as const char *buf_p;) is that I'm using incompatible pointer types:
/home/pi/adc.c:262:19: error: assignment to ‘unsigned char *’ from incompatible pointer type ‘struct DataStruct *’ [-Werror=incompatible-pointer-types]
ScopeBufferStart=&dataStruct;
When I fix this (by redefining the variable buf_p as a struct DataStruct), I get a new error in the device_read function that I haven't been able to fix:
In file included from /home/pi/adc.c:13:
./arch/arm/include/asm/uaccess.h:387:33: error: incompatible types when initializing type ‘char’ using type ‘struct DataStruct’
__typeof__(*(ptr)) __pu_val = (x); \
I also noticed that the output from the Makefile on Buster Lite I get
make -C /lib/modules/4.19.97+/build M=/home/pi modules
make[1]: Entering directory '/usr/src/linux-headers-4.19.97+'
...
...
make[1]: Leaving directory '/usr/src/linux-headers-4.19.97+'
while on Jessie I get
make -C /lib/modules/`uname -r`/build M=$PWD
make[1]: Entering directory '/usr/src/linux-source-4.4.50+'
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory '/usr/src/linux-source-4.4.50+'
Here is my code...
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/fcntl.h> /*Helps fix O_ACCMODE*/
#include <linux/sched.h> /*Helps fix TASK_UNINTERRUPTIBLE */
#include <linux/fs.h> /*Helps fix the struct intializer */
int __init init_module(void);
void __exit cleanup_module(void);
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
#define SUCCESS 0
#define DEVICE_NAME "stdin"// Dev name
#define BUF_LEN 80//Max length of device message
//---------------------------------------------------------------------------------------------------------
//Things for the GPIO Port
#define BCM2708_PERI_BASE 0x20000000
//if you're using a RPi3, PERIBASE value should be changed to 0x3F000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) // GPIO controller
// depends on the RPi
#define INP_GPIO(g) *(gpio.addr + ((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio.addr + ((g)/10)) |= (1<<(((g)%10)*3)) //001
//alternative function
#define SET_GPIO_ALT(g,a) *(gpio.addr + (((g)/10))) |= (((a)<=3?(a) + 4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET *(gpio.addr + 7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio.addr + 10) // clears bits which are 1 ignores bits which are 0
#define GPIO_READ(g) *(gpio.addr + 13) &= (1<<(g))
//GPIO Clock
#define CLOCK_BASE (BCM2708_PERI_BASE + 0x00101000)
#define GZ_CLK_BUSY (1 << 7)
//---------------------------------------------------------------------------------------------------------
//How many samples to capture
#define SAMPLE_SIZE 10000 // 2x2500 pts in one line
#define REPEAT_SIZE 10 // 10 captures
//Define GPIO Pins
//ADC 1
#define BIT0_ADC1 16
#define BIT1_ADC1 17
#define BIT2_ADC1 18
#define BIT3_ADC1 19
#define BIT4_ADC1 20
#define BIT5_ADC1 22
#define BIT6_ADC1 25
#define BIT7_ADC1 26
#define BIT8_ADC1 27
//ADC 2
#define BIT0_ADC2 7
#define BIT1_ADC2 8
#define BIT2_ADC2 9
#define BIT3_ADC2 10
#define BIT4_ADC2 11
#define BIT5_ADC2 12
#define BIT6_ADC2 13
#define BIT7_ADC2 14
#define BIT8_ADC2 15
// Pulser
#define Puls_ON 23
#define Puls_OFF 24
#define PPWWMM 6
#define MY_NOP(__N) __asm ("nop"); // or sth like "MOV R0,R0"
//---------------------------------------------------------------------------------------------------------
// IO Acces
struct bcm2835_peripheral {
unsigned long addr_p;
int mem_fd;
void *map;
volatile unsigned int *addr;
};
static int map_peripheral(struct bcm2835_peripheral *p);
static void unmap_peripheral(struct bcm2835_peripheral *p);
static void readScope(void);
static int Major; /* Major number assigned to our device driver */
static int Device_Open = 0; /* Is device open?
* Used to prevent multiple access to device */
static char msg[BUF_LEN]; /* The msg the device will give when asked */
static char *msg_Ptr;
static uint32_t *ScopeBuffer_Ptr;
// static unsigned char *buf_p;
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
//--------------------------------------------------------------------------------------------------------
static struct bcm2835_peripheral myclock = {CLOCK_BASE};
static struct bcm2835_peripheral gpio = {GPIO_BASE};
static struct DataStruct{
uint32_t Buffer[REPEAT_SIZE*SAMPLE_SIZE];
uint32_t time;
};
struct DataStruct dataStruct;
struct DataStruct *buf_p;
static unsigned char *ScopeBufferStart;
static unsigned char *ScopeBufferStop;
//---------------------------------------------------------------------------------------------------------
static int map_peripheral(struct bcm2835_peripheral *p)
{
p->addr=(uint32_t *)ioremap(GPIO_BASE, 41*4); //41 GPIO register with 32 bit (4*8)
return 0;
}
static void unmap_peripheral(struct bcm2835_peripheral *p) {
iounmap(p->addr);//unmap the address
}
//---------------------------------------------------------------------------------------------------------
static void readScope(){
int counter=0;
int counterline = 0;
int limit = 0;
int Pon=0;
int Poff=0;
//int Fail=0;
OUT_GPIO(Puls_ON);
OUT_GPIO(Puls_OFF);
GPIO_SET = 1 << Puls_ON;
GPIO_CLR = 1 << Puls_OFF;
msleep(10);
//disable IRQ
local_irq_disable();
local_fiq_disable();
struct timespec ts_start,ts_stop;
//Start time
set_current_state(TASK_UNINTERRUPTIBLE);
getnstimeofday(&ts_start);
while(counterline<REPEAT_SIZE){
Pon = 0;
Poff = 0;
limit = (counterline+1)*SAMPLE_SIZE;
while(counter<(limit) ){
dataStruct.Buffer[counter++]= *(gpio.addr + 13);
}
// to avoid freezes
// msleep(0.5);
counterline++;
}
//Stop time
getnstimeofday(&ts_stop);
INP_GPIO(Puls_ON);
INP_GPIO(Puls_OFF);
set_current_state(TASK_INTERRUPTIBLE);
//enable IRQ
local_fiq_enable();
local_irq_enable();
//save the time difference
dataStruct.time=timespec_to_ns(&ts_stop)-timespec_to_ns(&ts_start);//ns resolution
// buf_p=&dataStruct;//cound maybe removed
buf_p=&dataStruct;//cound maybe removed
ScopeBufferStart=&dataStruct;
ScopeBufferStop=ScopeBufferStart+sizeof(struct DataStruct);
}
//---------------------------------------------------------------------------------------------------------
/*
/*
* This function is called when the module is loaded
*/
int init_module(void)
{
Major = register_chrdev(0, DEVICE_NAME, &fops);
if (Major < 0) {
printk(KERN_ALERT "Registering char device failed with %d\n", Major);
return Major;
}
printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
printk(KERN_INFO "the driver, create a dev file with\n");
printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
printk(KERN_INFO "the device file.\n");
printk(KERN_INFO "Remove the device file and module when done.\n");
//Map GPIO
if(map_peripheral(&gpio) == -1)
{
printk(KERN_ALERT,"Failed to map the physical GPIO registers into the virtual memory space.\n");
return -1;
}
//Define Scope pins
// ADC1
INP_GPIO(BIT0_ADC1);
INP_GPIO(BIT1_ADC1);
INP_GPIO(BIT2_ADC1);
INP_GPIO(BIT3_ADC1);
INP_GPIO(BIT4_ADC1);
INP_GPIO(BIT5_ADC1);
INP_GPIO(BIT6_ADC1);
INP_GPIO(BIT7_ADC1);
INP_GPIO(BIT8_ADC1);
// ADC2
INP_GPIO(BIT0_ADC2);
INP_GPIO(BIT1_ADC2);
INP_GPIO(BIT2_ADC2);
INP_GPIO(BIT3_ADC2);
INP_GPIO(BIT4_ADC2);
INP_GPIO(BIT5_ADC2);
INP_GPIO(BIT6_ADC2);
INP_GPIO(BIT7_ADC2);
INP_GPIO(BIT8_ADC2);
// Setting pins for pulser
OUT_GPIO(Puls_ON);
OUT_GPIO(Puls_OFF);
GPIO_CLR = 1 << Puls_ON; // set pulser at 0
GPIO_SET = 1 << Puls_OFF; // set damper at 1
//Set a clock signal on Pin 4
struct bcm2835_peripheral *p=&myclock;
p->addr=(uint32_t *)ioremap(CLOCK_BASE, 41*4);
INP_GPIO(4);
SET_GPIO_ALT(4,0);
// Preparing the clock
int speed_id = 6; //1 for to start with 19Mhz or 6 to start with 500 MHz
*(myclock.addr+28)=0x5A000000 | speed_id; //Turn off the clock
while (*(myclock.addr+28) & GZ_CLK_BUSY) {}; //Wait until clock is no longer busy (BUSY flag)
*(myclock.addr+29)= 0x5A000000 | (0x29 << 12) | 0;//Set divider //divide by 50 (0x32) -- ideally 41 (29) to fall on 12MHz clock
*(myclock.addr+28)=0x5A000010 | speed_id;//Turn clock on
return SUCCESS;
}
//---------------------------------------------------------------------------------------------------------
/*
* This function is called when the module is unloaded
*/
void cleanup_module(void)
{
unregister_chrdev(Major, DEVICE_NAME);
unmap_peripheral(&gpio);
unmap_peripheral(&myclock);
}
//---------------------------------------------------------------------------------------------------------
/*
* Called when a process tries to open the device file, like
* "cat /dev/mycharfile"
*/
static int device_open(struct inode *inode, struct file *file)
{
static int counter = 0;
if (Device_Open)
return -EBUSY;
Device_Open++;
sprintf(msg, "I already told you %d times Hello world!\n", counter++);
msg_Ptr = msg;
readScope();//Read n Samples into memory
try_module_get(THIS_MODULE);
return SUCCESS;
}
//---------------------------------------------------------------------------------------------------------
/*
* Called when a process closes the device file.
*/
static int device_release(struct inode *inode, struct file *file)
{
Device_Open--; /* We're now ready for our next caller */
module_put(THIS_MODULE);
return 0;
}
//---------------------------------------------------------------------------------------------------------
/*
* Called when a process, which already opened the dev file, attempts to
* read from it.
*/
static ssize_t device_read(struct file *filp,
char *buffer,
size_t length,
loff_t * offset)
{
// Number of bytes actually written to the buffer
int bytes_read = 0;
if (*msg_Ptr == 0)
return 0;
//Check that we do not overfill the buffer
while (length && buf_p<ScopeBufferStop) {
if(0!=put_user(*(buf_p++), buffer++))
printk(KERN_INFO "Problem with copy\n");
length--;
bytes_read++;
}
return bytes_read;
}
//---------------------------------------------------------------------------------------------------------
/*
* Called when a process writes to dev file: echo "hi" > /dev/hello
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EINVAL;
}
Thank you
So I think I have an answer. I realized I need to compile the linux kernel module on Buster before I can compile my adc code. On the Jessie disk image version I was using, I realized the linux kernel module had already been compiled, I think that's why on Jessie it's able to enter the linux source directory to compile while on Buster it enters the linux headers directory. Thank you
I have a struct where I put all the information about the players. That's my struct:
struct player{
int startingCapital;
int currentCapital;
int startingPosition;
int currentPosition;
int activePlayer;
int canPlay;
};
And that's my main:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
int main(int argc, char *argv[])
{ int s,i,numOfPlayers;
struct player *players;
printf("Give the number of players: \n");
scanf("%d",&numOfPlayers);
players = (struct player *)calloc(numOfPlayers,sizeof(struct player));
system("PAUSE");
return 0;
}
I'm asking the user to give the number of players and then I try to allocate the needed memory. But I'm getting this compiler error that I can't figure out:
invalid application of `sizeof' to incomplete type `player'
It means the file containing main doesn't have access to the player structure definition (i.e. doesn't know what it looks like).
Try including it in header.h or make a constructor-like function that allocates it if it's to be an opaque object.
EDIT
If your goal is to hide the implementation of the structure, do this in a C file that has access to the struct:
struct player *
init_player(...)
{
struct player *p = calloc(1, sizeof *p);
/* ... */
return p;
}
However if the implementation shouldn't be hidden - i.e. main should legally say p->canPlay = 1 it would be better to put the definition of the structure in header.h.
The cause of errors such as "Invalid application of sizeof to incomplete type with a struct ... " is always lack of an include statement. Try to find the right library to include.
Your error is also shown when trying to access the sizeof() of an non-initialized extern array:
extern int a[];
sizeof(a);
>> error: invalid application of 'sizeof' to incomplete type 'int[]'
Note that you would get an array size missing error without the extern keyword.
I think that the problem is that you put #ifdef instead of #ifndef at the top of your header.h file.
I am a beginner and may not clear syntax.
To refer above information, I still not clear.
/*
* main.c
*
* Created on: 15 Nov 2019
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "dummy.h"
char arrA[] = {
0x41,
0x43,
0x45,
0x47,
0x00,
};
#define sizeA sizeof(arrA)
int main(void){
printf("\r\n%s",arrA);
printf("\r\nsize of = %d", sizeof(arrA));
printf("\r\nsize of = %d", sizeA);
printf("\r\n%s",arrB);
//printf("\r\nsize of = %d", sizeof(arrB));
printf("\r\nsize of = %d", sizeB);
while(1);
return 0;
};
/*
* dummy.c
*
* Created on: 29 Nov 2019
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "dummy.h"
char arrB[] = {
0x42,
0x44,
0x45,
0x48,
0x00,
};
/*
* dummy.h
*
* Created on: 29 Nov 2019
*/
#ifndef DUMMY_H_
#define DUMMY_H_
extern char arrB[];
#define sizeB sizeof(arrB)
#endif /* DUMMY_H_ */
15:16:56 **** Incremental Build of configuration Debug for project T3 ****
Info: Internal Builder is used for build
gcc -O0 -g3 -Wall -c -fmessage-length=0 -o main.o "..\\main.c"
In file included from ..\main.c:12:
..\main.c: In function 'main':
..\dummy.h:13:21: **error: invalid application of 'sizeof' to incomplete type 'char[]'**
#define sizeB sizeof(arrB)
^
..\main.c:32:29: note: in expansion of macro 'sizeB'
printf("\r\nsize of = %d", sizeB);
^~~~~
15:16:57 Build Failed. 1 errors, 0 warnings. (took 384ms)
Both "arrA" & "arrB" can be accessed (print it out). However, can't get a size of "arrB".
What is a problem there?
Is 'char[]' incomplete type? or
'sizeof' does not accept the extern variable/ label?
In my program, "arrA" & "arrB" are constant lists and fixed before to compile. I would like to use a label(let me easy to maintenance & save RAM memory).
Really late to the party here, but a special case of the reasons for this error cited above would simply be to reference a structure with sizeof() above where the structure is defined:
int numElements = sizeof(myArray)/sizeof(myArray[0]);
.
.
.
myArray[] =
{
{Element1},
{Element2},
{Element3}
};
I want to use parameter inside a kernel (3.x) module:
static char param = 0xff;
module_param(param, ushort, S_IRUGO | S_IWUGO);
MODULE_PARM_DESC(param, "a parameter");
Is there any possibility to detect changes on this parameter? Is there a signal which can use to call a service routine?
Best regards
Alex
Additional information to module_param(name,type,perm):
possible values for type:
bool
invbool
charp
int
long
short
uint
ulong
ushort
defines for perm at linux/stat.h
#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
Here a full code example:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
static int param = 1;
module_param(param, int, S_IRUGO|S_IWUGO);
static int __init mod_init(void){
printk(KERN_INFO "param %d\n", param);
return 0;
}
static void __exit mod_exit(void){
printk(KERN_INFO "Goodbye!\n");
}
module_init(mod_init);
module_exit(mod_exit);
The compiler returns this error I don't understand why:
make -C /lib/modules/3.19.0-47-generic/build/ M=/tmp/gt modules
make[1]: change to »/usr/src/linux-headers-3.19.0-47-generic«
CC [M] /tmp/gt/ebb.o
In file included from include/linux/thread_info.h:11:0,
from ./arch/x86/include/asm/preempt.h:6,
from include/linux/preempt.h:18,
from include/linux/spinlock.h:50,
from include/linux/seqlock.h:35,
from include/linux/time.h:5,
from include/linux/stat.h:18,
from include/linux/module.h:10,
from /tmp/gt/ebb.c:2:
include/linux/bug.h:33:45: error: negative width in bit-field ‘<anonymous>’
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
^
include/linux/kernel.h:830:3: note: in expansion of macro ‘BUILD_BUG_ON_ZERO’
BUILD_BUG_ON_ZERO((perms) & 2) + \
^
include/linux/moduleparam.h:223:31: note: in expansion of macro ‘VERIFY_OCTAL_PERMISSIONS’
= { __param_str_##name, ops, VERIFY_OCTAL_PERMISSIONS(perm), \
^
include/linux/moduleparam.h:166:2: note: in expansion of macro ‘__module_param_call’
__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0)
^
include/linux/moduleparam.h:146:2: note: in expansion of macro ‘module_param_cb’
module_param_cb(name, ¶m_ops_##type, &value, perm); \
^
include/linux/moduleparam.h:125:2: note: in expansion of macro ‘module_param_named’
module_param_named(name, name, type, perm)
^
/tmp/gt/ebb.c:11:1: note: in expansion of macro ‘module_param’
module_param(param, int, S_IRUGO|S_IWUGO);
^
make[2]: *** [/tmp/gt/ebb.o] Fehler 1
make[1]: *** [_module_/tmp/gt] Fehler 2
make[1]: leaving »/usr/src/linux-headers-3.19.0-47-generic«
make: *** [all] Fehler 2
and here the Makefile
obj-m+=ebb.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
regarding to the answer from #Tsyvarev
Writing rights are only allowed to root. So here the change:
module_param(param, int, S_IRUGO|S_IWUSR);
Now you can find the parameter under /sys/module//parameters/ and you can change the parameter like this:
sudo echo 2 > /sys/module/ebb/parameters/param
next step regarding to #Tsyvarev
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
// int (*set)(const char *val, const struct kernel_param *kp);
// int (*get)(char *buffer, const struct kernel_param *kp);
int my_param_set_ushort(const char *val, const struct kernel_param *kp)
{
unsigned short* pvalue = kp->arg; // Pointer to actual parameter variable.
int res = param_set_ushort(val, kp); // Use helper for write variable
printk(KERN_INFO "setter talks\n");
if( res==0 )
{
// Here you may execute additional actions when you write parameter.
printk(KERN_INFO "set param %d\n", *pvalue);
}
return res;
}
const struct kernel_param_ops my_param_ops_ushort =
{
.set = &my_param_set_ushort, // Use our setter ...
.get = ¶m_get_ushort, // .. and standard getter
};
unsigned short param = 0xff;
module_param_cb(param, /*filename*/
&my_param_ops_ushort, /*operations*/
¶m, /* pointer to variable, contained parameter's value */
S_IRUGO | S_IWUSR /*permissions on file*/
);
static int __init mod_init(void){
printk(KERN_INFO "param %d\n", param);
return 0;
}
static void __exit mod_exit(void){
printk(KERN_INFO "Goodbye! (%d)\n",param);
}
module_init(mod_init);
module_exit(mod_exit);
as root I give this commands:
# insmod par.ko
# echo 146 > /sys/module/par/parameters/param
# rmmod par
and the kernel log /var/log/kernel.log says:
Jan 23 14:27:37 alex-XMG kernel: [ 8332.492912] param 255
Jan 23 14:27:39 alex-XMG kernel: [ 8334.520044] setter talks
Jan 23 14:27:39 alex-XMG kernel: [ 8334.520052] set param 146
Jan 23 14:27:40 alex-XMG kernel: [ 8335.804338] Goodbye! (146)
Works like a charme!
Generic way for create kernel module parameter is using macro module_param_cb:
/**
* module_param_cb - general callback for a module/cmdline parameter
* #name: a valid C identifier which is the parameter name.
* #ops: the set & get operations for this parameter.
* #perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define module_param_cb(name, ops, arg, perm)
Parameter ops is a pointer to structure struct kernel_param_ops, which contains operations for given parameter. Functions called when parameter is written and read have followed definition in this structure:
int (*set)(const char *val, const struct kernel_param *kp);
int (*get)(char *buffer, const struct kernel_param *kp);
Here char* parameter is a NULL-terminated string, which is written to/read from the sysfs file, denoted given parameter. And kp is a pointer to parameter descriptor, where the most interested field is .arg: it is a 3rd argument to macro module_param_cb call. Using this field, setter and getter can be implemented per-type of the module parameter, that is having 5 int parameters for module doesn't require to write setters and getters for each of them.
Moreover, getters and setters for standard parameter types are already implemented, and they are actually used when you call module_param macro. So, if you want to add some functionality for the parameter's setter, you may reuse existed helpers:
int my_param_set_ushort(const char *val, const struct kernel_param *kp)
{
unsigned short* pvalue = kp->arg; // Pointer to actual parameter variable.
int res = param_set_ushort(val, kp); // Use helper for write variable
if(!res)
{
// Here you may execute additional actions when you write parameter.
printk(KERN_INFO "set param %d\n", *pvalue);
}
return res;
}
const struct kernel_param_ops my_param_ops_ushort =
{
.set = &my_param_set_ushort, // Use our setter ...
.get = ¶m_get_ushort, // .. and standard getter
};
// Usage
unsigned short param = 0xff;
module_param_cb(param, /*filename*/
&my_param_ops_ushort, /*operations*/
¶m, /* pointer to variable, contained parameter's value */
S_IRUGO | S_IWUSR /*permissions on file*/
);
Having module parameter's writable by non-priveledged user normally is not good for security reasons. And kernel macros, which create module parameters, check that. That is why you have cryptic error in your module parameter's definition. Note, that in the example above S_IWUSR is used instead of S_IWUGO.
If you make your module parameter writable you can change that parameter via sysfs. Once loaded, find your module under /sys, then find the module parameter and verify that it is writable (by root). Try writing to it and see if it changes.
There are a few ways to detect changes to this variable. You can use a kernel thread as one mechanism.
A better approach might be to use a sysfs or procfs entry. Those have read/write handlers which are called upon reads and writes.
See here for an sysfs-tutorial