Filing file with zeroes - c

My file should be filled with 0. I want to do that using aio_write As a result my file should look like 000000000.... but as a result I get that my file is filled with garbage
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#
s|▒^#^#^#^#^#^#^#^#^#^#^#^#▒r|▒^#^#^#^#▒▒^?▒(▒▒▒▒s|▒▒
y▒^P^#^#^#^X▒▒▒
s|▒^X^#^#^#▒.....
I don't even imagine what's wrong. First of all I'm using asynchronous write so I need to wait when da_aio_write is completed
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
Also here is my writing function
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
and my main
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
//memset(&aior, 0, sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}
Any ideas what I'm doing wrong?
EDIT:
I know that my da_aio write ends after main because ehen I compile I get
File created
dskr1 = 3
AIO complete, 1048576 bytes write.
closed
EDIT My full updated code
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
#include <aio.h>
#include <errno.h>
#define MB 1024
int da_open(const char *name);
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count);
int da_test_wait( struct aiocb *aiorp );
int da_close(int fd);
int da_open(const char *name){
int dskr;
int dskr2;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
printf("File created\n");
dskr2 = open( name, O_WRONLY | O_CREAT, 0644);
}else{
printf("End job!\n");
exit(1);
}
printf( "dskr1 = %d\n", dskr2 );
return dskr2;
}
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
int da_close(int fd){
int rv;
rv = close( fd );
if( rv != 0 ) perror ( "close() failed" );
else puts( "closed" );
return rv;
}
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
int size;
size = MB * MB * sk;
memset( buffer, '\0', size);
//memset(&aior, '\0', sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}

char buffer[MB * MB * sk];
Stack variables are not automatically initialiased. So your buffer contains garbage. memset it to 0 first if that's what you want to write to file.

Related

mmap and memcpy usage and Segmentation Fault (core dumped) error

I have two files and I want to copy one file content to other using memcpy. But I get this error Segmentation Fault (core dumped). My main
int main( int argc, char * argv[] ){
int d1;
int d2;
char *a;
char *b;
d1 = da_open_r(argv[1]); // open file READ ONLY
d2 = da_open_w(argv[2]); // open file to WRITE
a = (char*)da_mmap(d1); // map first file
b = (char*)da_mmap(d2); // map second file
memcpy(b, a, 10); // I think this line is bad
kp_test_munamp(a, 10 ); //
kp_test_munamp(b, 10 );
kp_test_close(d1); // close 1 file
kp_test_close(d2); // close 2 file
return 0;
}
and here are my da_mmap and kp_test_munamp
void *da_mmap(int d){
mmap(NULL, 10, PROT_READ|PROT_WRITE, MAP_SHARED, d, 0);
}
int kp_test_munamp( void *a, int size ){
int rv;
rv = munmap( a, size );
if( rv != 0 ){
puts( "munmap failed" );
abort();
}
return 1;
}
I have been trying to fix this almost two hours, but still I don't know what's wrong.
EDIT my full code
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
int da_open_r(const char *name);
int da_open_w(const char *name);
void *da_mmap(int d);
int kp_test_munamp( void *a, int size );
int kp_test_close(int fd);
int da_open_r(const char *name){
int dskr;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr1 = %d\n", dskr );
return dskr;
}
int da_open_w(const char *name){
int dskr;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr2 = %d\n", dskr );
return dskr;
}
void *da_mmap(int d){
void *a = NULL;
a = mmap(NULL, 10, PROT_WRITE, MAP_SHARED, d, 0);
if( a == MAP_FAILED ){
perror( "mmap failed" );
abort();
}
return a;
}
int kp_test_munamp( void *a, int size ){
int rv;
rv = munmap( a, size );
if( rv == -1 ){
puts( "munmap failed" );
abort();
}
return 1;
}
int kp_test_close(int fd){
int rv;
rv = close( fd );
if( rv != 0 ) perror ( "close() failed" );
else puts( "closed" );
return rv;
}
int main( int argc, char * argv[] ){
int d1;
int d2;
char *a;
char *b;
d1 = da_open_r(argv[1]); // read only
d2 = da_open_w(argv[2]); // WRITE
a = (char*)da_mmap(d1);
b = (char*)da_mmap(d2);
memcpy(b, a, 10); // I think this line is bad
kp_test_munamp(a, 10 );
kp_test_munamp(b, 10 );
kp_test_close(d1);
kp_test_close(d2);
return 0;
}
da_mmap() does not return anything! Which leads to the values of a and b being garbage and with this most probably pointing to invalid memory, which in turn makes memcpy() fail when acting on it.
Add return statement
void * da_mmap(int d) {
return mmap(NULL, 10, PROT_READ|PROT_WRITE, MAP_SHARED, d, 0);
}
Also you should test the outcome of the mapping by doing:
{
void * pvtmp = da_mmap(d1); // map first file
if (MAP_FAILED == pvtmp)
{
perror("da_mmap() failed");
exit(1);
}
a = pvtmp;
}
The same for b.
Referring the wrapper around munmap(). Correct error testing here. However by convention success is indicated by returning 0 (failure by returning -1).

C copy file with memcpy and mmap file to RAM

I have file1.txt
This is my file
and file2.txt
This is my second file
and I want copy file2.txt content to file1.txt using memcpy
int main( int argc, char * argv[] ){
int d;
int d2;
int p;
FILE *f1;
FILE *f2;
if(argc == 3){
f1 = fopen(argv[1], "r+");
f2 = fopen(argv[2], "r+");
d = da_open(argv[1]);
d2 = da_open2(argv[2]);
p = da_cp(f2, f1, 10);
da_map(d, 10);
da_map(d2, 10);
close(p);
//closef(d2);
}
}
I don't know why but when I run this I get file2.txt with lots of random symbols. Why? what I'm doing wrong?
EDIT:
my full code
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
int da_open(const char *name);
int da_open2(const char *name);
void *da_map(int d, int size);
int da_cp(void *str1, const void *str2, size_t n);
int da_open(const char *name){
int dskr;
dskr = open( name, O_RDONLY, 0640 );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr = %d\n", dskr );
return dskr;
}
int da_open2(const char *name){
int dskr;
dskr = open( name, O_RDWR, 0640 );
if( dskr == -1 ){
perror( name );
exit( 255 );
}
printf( "dskr = %d\n", dskr );
return dskr;
}
void *da_map(int d, int size){
void *a = NULL;
a = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, d, 0 );
if( a == MAP_FAILED ){
perror( "mmap failed" );
abort();
}
return a;
}
int da_cp(void *str1, const void *str2, size_t n){
memcpy(str1, str2, n);
}
int main( int argc, char * argv[] ){
int d;
int d2;
int p;
FILE *f1;
FILE *f2;
if(argc == 3){
f1 = fopen(argv[1], "r+");
f2 = fopen(argv[2], "r+");
d = da_open(argv[1]);
d2 = da_open2(argv[2]);
p = da_cp(f2, f1, 10);
da_map(d, 10);
da_map(d2, 10);
close(p);
//closef(d2);
}
}
d and d2 are not files, they're just file descriptors (something that stores the information about the file and its input/output states).
If you want to copy from 1 file to another, you have to read the first file first. That's the example of how you can do this:
#include <stdio.h>
#include <stdlib.h>
// Open the first text file
FILE *f = fopen("textfile1.txt", "rb");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
// Read it into buffer
char *buffer = malloc(fsize + 1);
fread(string, fsize, 1, f);
fclose(f);
buffer[fsize] = 0;
// Now write the string buffer into your second text file
FILE *f2 = fopen ("textfile2", "wb");
fwrite (buffer, sizeof(char), sizeof(buffer), f2);
fclose (f2);
So, as you see, the memcpy can only perform with memory in RAM and it has nothing to do with files in hard drive (unless you read it into your RAM memory)
memcpy doesn't work over a file descriptor, you can store the content of file1 in an array of chars (using fgets or fread) and then copy to file2 (using fputs or fwrite)
Also note that you need to use fclose() instead of close() with fopen()

Fill file ASCII values

I want to create a file filled with 0 or other letters. Here's my function
int fill(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) ); // <-here second paramether is 0
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
return rv;
}
Here's my main
int main(int argc, char * argv[]){
int des;
int rv;
struct aiocb aior;
char buffer[1000];
if(argc == 3){
printf("just %s\n", argv[1]);
des = createFile(argv[1]);
rv = fill(des, &aior, buffer, sizeof(buffer));
}
return 0;
}
So my output should be file filled with zero values, but my fle is filled with garbage
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#$
y▒^X^#^#^#^#^#^#^#
s|▒^#^#^#^#^#^#^#^#^#^#^#^#▒r|▒^#^#^#^#▒▒^?▒(▒▒▒▒▒{▒▒
y▒^P^#^#^#▒
y▒^A^#^#^#d^Cy▒^#^#^#^#▒
y▒^T
y▒^P▒▒▒^#^#^#^#^#^#^#^
...
Why? What's wrong?
Here's the code :
sukurti - create new file if that file don't exist and
fill - fill created file
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <aio.h>
#define MB 1024
int sukurti(char *name);
int fill(const int d, struct aiocb *aiorp, void *buf, const int count);
int sukurti(char *name){
int dskr;
dskr = open( name, O_RDONLY );
if( dskr == -1 ){
printf("Failas sukurtas, nes jo nebuvo\n");
dskr = open( name, O_WRONLY | O_CREAT, 0644);
}else{
printf("Jau yra toks failas!\n");
exit(1);
}
return dskr;
}
int fill(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 'A', sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
return rv;
}
int main(int argc, char * argv[]){
int des;
int rv;
struct aiocb aior;
int x = atoi(argv[2]);
printf("%d\n", x);
int size = MB * MB * x;
char buffer[size];
if(argc == 3){
printf("just %s\n", argv[1]);
des = sukurti(argv[1]);
rv = fill(des, &aior, buffer, sizeof(buffer));
}else{
printf("Blogas\n");
}
return 0;
}
EDIT:
I know that my writting to file ends
Three ssues here:
buffer is not initalised. Do this using
memset(buffer,
<what ever 8bit value you want the file to be filled with>,
sizeof buffer);
right after defining it in main().
aior is initialise wrongly. Initialise it to all 0 using
memset(aiorb, 0, sizeof aior);
right after defining it in main() and remove the call to memset() in fill().
Finally the program most likely ends before the buffer had been asynchronously written to disk.
To fix this define a notification method as mentioned under man 7 aio. And make the program wait for this notification to be received before ending the program.
This for example can be done by asking for completion notification via signal and wait for this signal.
To do so modify your code as follows:
Add the following two lines to the intialisation of what aiorp is pointing to in fill():
aiorp->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
aiorp->aio_sigevent.sigev_signo = SIGUSR1;
To be able to handle the notifying signal sent (without ending the program) a signal handler needs to be setup:
void handler(int sig)
{
/* Do nothing. */
}
Install this handler by calling
signal(handler, SIGUSR1);
right at the beginning of the program.
Before returning from main() call wait_for_completion(SIGUSR1) which might look like this:
void wait_for_completion(int sig)
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, sig);
sigwait(&set, &sig); /* This blocks until sig had
been received by the program. */
printf("Completion notification for asynchronous 'write'-operation received.\n");
}
Add error handling as appropriate. I left it out for the sake of readability.
memset( (void *)aiorp, '0', sizeof( struct aiocb ) );
0 is not '0', you need to actually use the ASCII value (48 if i recall correctly.)

C file filled with garbage

I need to fill my file with same numbers for example 00000.... I want to use asynchronous aio_write function. But here what I get
^# w▒(▒▒▒▒▒l▒#^#Y▒^#^#^#^#▒▒▒▒u▒l▒#*`▒^# w▒h▒▒▒ ......
Here's my code
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
memset(&aior, 0, sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}
and here's my asynchronous writing function (I think this function is bad)
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
Also here's I wait for asyncronius function to end
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
Also here's my full program
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
#include <aio.h>
#include <errno.h>
#define MB 1024
int da_open(const char *name);
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count);
int da_test_wait( struct aiocb *aiorp );
int da_close(int fd);
int da_open(const char *name){
int dskr;
int dskr2;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
printf("File created\n");
dskr2 = open( name, O_WRONLY | O_CREAT, 0644);
}else{
printf("End job!\n");
exit(1);
}
printf( "dskr1 = %d\n", dskr2 );
return dskr2;
}
int da_aio_write(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
if( rv == -1) {
perror("Error da_aio_write\n");
exit(1);
return rv;
}
return rv;
}
int da_test_wait( struct aiocb *aiorp ){
const struct aiocb *aioptr[1];
int rv;
aioptr[0] = aiorp;
rv = aio_suspend( aioptr, 1, NULL );
if( rv != 0 ){
perror( "aio_suspend failed" );
abort();
}
rv = aio_return( aiorp );
printf( "AIO complete, %d bytes write.\n", rv );
return 1;
}
int da_close(int fd){
int rv;
rv = close( fd );
if( rv != 0 ) perror ( "close() failed" );
else puts( "closed" );
return rv;
}
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
if(argc == 3){
sk = atoi(argv[2]);
char buffer[MB * MB * sk];
memset(&aior, 0, sizeof( struct aiocb ));
d = da_open(argv[1]);
da_aio_write( d, &aior, buffer, sizeof(buffer) );
da_test_wait( &aior );
da_close( d );
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
#include <aio.h>
int da_open(const char *name);
int da_aio_read(const int d, struct aiocb *aiorp, void *buf, const int count);
int da_open(const char *name){
int dskr;
int dskr2;
dskr = open( name, O_RDWR );
if( dskr == -1 ){
dskr2 = open( name, O_WRONLY | O_CREAT, 0644);
}else{
exit(1);
}
return dskr2;
}
What is going on here? Is this an obfuscated way to make sure you don't write to a file if it already exists? It is obviously incorrect as the file could have appeared before the second open. You can use O_EXCL instead.
The code is additionaly obfuscted by not handling exit earlier.
int da_aio_read(const int d, struct aiocb *aiorp, void *buf, const int count){
int rv = 0;
memset( (void *)aiorp, 0, sizeof( struct aiocb ) );
//memset(buf, 0, sizeof( buf) );
aiorp->aio_fildes = d;
aiorp->aio_buf = buf;
aiorp->aio_nbytes = count;
aiorp->aio_offset = 0;
rv = aio_write( aiorp );
return rv;
}
First off, what the fsck. Why are you calling a writing function something_read?
What's the use of rv?
If you read any docs on aio you will see you have to explicitly wait for event completion.
int main(int argc, char *argv[] ){
int sk;
int d;
struct aiocb aior;
char buffer[100];
memset(buffer, 0, sizeof buffer);
if(argc == 3){
sk = atoi(argv[2]);
d = da_open(argv[1]);
da_aio_read( d, &aior, buffer, sizeof(buffer) );
}
return 0;
}

inotify_add_watch fails on /sys/class/net/eth0/operstate

I have used inotify in Linux, to get the event raised when ever the network interface link changes. whenever interface link changes, /sys/class/net/eth40/operstate/ file gets modified. But in the below code snippet even though the file is getting modified, read function is still in blocked state.
#include <stdio.h>
#include <sys/inotify.h>
#include <stdlib.h>
#include <limits.h>
#include <signal.h>
#define FILE_TO_WATCH "/sys/class/net/eth40/operstate"
#define EVENT_SIZE (sizeof (struct inotify_event))
#define EVENT_BUFFER_LENGTH (1024 * EVENT_SIZE + NAME_MAX + 1)
void print_event(struct inotify_event *event) {
int ret = 0;
if (event->mask & IN_CREATE)
printf("file created in directory\n");
if (event->mask & IN_DELETE)
printf("file deleted in directory\n");
if (event->mask & IN_ACCESS)
printf("file accessed\n");
if (event->mask & IN_CLOSE)
printf("file closed after reading or writing \n");
if (event->mask & IN_OPEN)
printf("file opened\n");
if (event->len)
printf("name: %s\n", event->name);
}
int main(int argc, char** argv)
{
int notify_fd;
int watch_fd;
long input_len;
char *ptr;
char buffer[EVENT_BUFFER_LENGTH];
struct inotify_event *event;
notify_fd = inotify_init();
if (notify_fd < 0) {
perror("cannot init inotify");
exit(EXIT_FAILURE);
}
printf("done1\n");
watch_fd = inotify_add_watch(notify_fd,FILE_TO_WATCH,IN_ACCESS|IN_MODIFY);
if (watch_fd < 0) {
perror("cannot add file");
exit(EXIT_FAILURE);
}
printf("done2\n");
while (1) {
input_len = read(notify_fd, buffer, EVENT_BUFFER_LENGTH);
if (input_len <= 0) {
perror("error reading from inotify fd");
exit(EXIT_FAILURE);
}
printf("done3\n");
ptr = buffer;
while (ptr < buffer + input_len) {
event = (struct inotify_event *) ptr;
print_event(event);
ptr += sizeof (struct inotify_event) +event->len;
}
}
}
am'I missing something?
/sys is not a regular file system, but a special in-memory file system called sysfs
To quote a kernel developer:
inotify does not and will not work on sysfs. Or procfs. Or devpts.
Or any number of network filesystems. No matter how hard somebody
might wish it to work, that's simply not feasible.
For network link events you can use rtnetlink, though stuff like this is hardly documented, here's an starting point example that will show you link (and a few other) events, you'll have to figure out which events/flags and similar that is relevant for your particular case.
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <asm/types.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#define ENTRY(x) {x, #x}
struct {
unsigned flag;
const char *name;
} ifi_flag_map[] = {
ENTRY(IFF_UP),
ENTRY(IFF_BROADCAST),
ENTRY(IFF_DEBUG),
ENTRY(IFF_LOOPBACK),
ENTRY(IFF_POINTOPOINT),
ENTRY(IFF_NOTRAILERS),
ENTRY(IFF_RUNNING),
ENTRY(IFF_NOARP),
ENTRY(IFF_PROMISC),
ENTRY(IFF_ALLMULTI),
ENTRY(IFF_MASTER),
ENTRY(IFF_SLAVE),
ENTRY(IFF_MULTICAST),
ENTRY(IFF_PORTSEL),
ENTRY(IFF_AUTOMEDIA),
ENTRY(IFF_DYNAMIC),
ENTRY(IFF_LOWER_UP),
ENTRY(IFF_DORMANT),
ENTRY(IFF_ECHO),
};
struct {
unsigned type;
const char *name;
} nlmrt_type_map[] = {
ENTRY(RTM_NEWLINK ),
ENTRY(RTM_DELLINK),
ENTRY(RTM_GETLINK),
ENTRY(RTM_SETLINK),
ENTRY(RTM_NEWADDR ),
ENTRY(RTM_DELADDR),
ENTRY(RTM_GETADDR),
ENTRY(RTM_NEWROUTE ),
ENTRY(RTM_DELROUTE),
ENTRY(RTM_GETROUTE),
ENTRY(RTM_NEWNEIGH ),
ENTRY(RTM_DELNEIGH),
ENTRY(RTM_GETNEIGH),
ENTRY(RTM_NEWRULE ),
ENTRY(RTM_DELRULE),
ENTRY(RTM_GETRULE),
ENTRY(RTM_NEWQDISC ),
ENTRY(RTM_DELQDISC),
ENTRY(RTM_GETQDISC),
ENTRY(RTM_NEWTCLASS ),
ENTRY(RTM_DELTCLASS),
ENTRY(RTM_GETTCLASS),
ENTRY(RTM_NEWTFILTER ),
ENTRY(RTM_DELTFILTER),
ENTRY(RTM_NEWACTION ),
ENTRY(RTM_DELACTION),
ENTRY(RTM_GETACTION),
ENTRY(RTM_NEWPREFIX ),
ENTRY(RTM_GETMULTICAST ),
ENTRY(RTM_GETANYCAST ),
ENTRY(RTM_NEWNEIGHTBL ),
ENTRY(RTM_GETNEIGHTBL ),
ENTRY(RTM_SETNEIGHTBL),
ENTRY(RTM_NEWNDUSEROPT ),
ENTRY(RTM_NEWADDRLABEL ),
ENTRY(RTM_DELADDRLABEL),
ENTRY(RTM_GETADDRLABEL),
ENTRY(RTM_GETDCB ),
ENTRY(RTM_SETDCB),
ENTRY(RTM_NEWNETCONF ),
ENTRY(RTM_GETNETCONF ),
ENTRY(RTM_NEWMDB ),
ENTRY(RTM_DELMDB ),
ENTRY(RTM_GETMDB ),
};
void print_type(unsigned type)
{
size_t i;
for (i = 0; i < sizeof nlmrt_type_map/sizeof nlmrt_type_map[0]; i++) {
if (type == nlmrt_type_map[i].type) {
printf("\t\tMsg Type: %s\n", nlmrt_type_map[i].name);
return;
}
}
printf("\t\tMsg Type: unknown(%d)\n", type);
}
void print_flags(unsigned flags, unsigned change)
{
size_t i;
printf("\t\tflags: ");
for (i = 0; i < sizeof ifi_flag_map/sizeof ifi_flag_map[0]; i++) {
if (flags & ifi_flag_map[i].flag) {
if (change & ifi_flag_map[i].flag) {
printf("%s(C) ", ifi_flag_map[i].name);
} else {
printf("%s ", ifi_flag_map[i].name);
}
}
}
puts("");
}
oid read_msg(int fd)
{
int len;
char buf[4096];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl sa;
struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
struct nlmsghdr *nh;
len = recvmsg(fd, &msg, 0);
if(len == -1) {
perror("recvmsg");
return;
}
for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
nh = NLMSG_NEXT (nh, len)) {
struct ifinfomsg *ifimsg;
/* The end of multipart message. */
printf("netlink message: len = %u, type = %u, flags = 0x%X, seq = %u, pid = %u\n",
nh->nlmsg_len,
nh->nlmsg_type,
nh->nlmsg_flags,
nh->nlmsg_seq,
nh->nlmsg_pid);
if (nh->nlmsg_type == NLMSG_DONE)
return;
if (nh->nlmsg_type == NLMSG_ERROR) {
continue;
}
ifimsg = NLMSG_DATA(nh);
printf("\tifi_family = %u, ifi_type = %u, ifi_index = %u, ifi_flags = 0x%X, ifi_change = 0x%X\n",
ifimsg->ifi_family ,
ifimsg->ifi_type ,
ifimsg->ifi_index ,
ifimsg->ifi_flags ,
ifimsg->ifi_change);
print_type(nh->nlmsg_type);
print_flags(ifimsg->ifi_flags, ifimsg->ifi_change);
}
}
int main(int argc, char *argv[])
{
struct sockaddr_nl sa;
int fd;
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(fd == -1) {
perror("socket");
return 1;
}
if(bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("bind");
return 1;
}
for(;;) {
read_msg(fd);
}
return 0;
}

Resources