Store file into a buffer to send it through a socket

Hello,

I'm doing a very simple program which reads a file and sends whatever is in the file through a socket. Like the program "file2cable".

Let's say i have a file containing the following, which is a hex dump of an ARP request frame:

ff ff ff ff ff ff 00 1b 24 79 5a 73 08 06 
00 01 08 00 06 04 00 01 00 1b 24 79 5a 73 
c0 a8 00 04 00 00 00 00 00 00 c0 a8 00 01

Right now, i have to fill the buffer manulally doing this, for example, if i want to transmit the first line of the file:

buffer[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x1B,0x24,0x79,0x5A,0x73,0x08,0x06};

So, how do i store all of the bytes contained in the file into a buffer so sendto() can send it?

Please help!
Thanks and excuse me for my poor english

You want to program at the kernel level and filter below the packet level but don't know how to open a file? You have ambitions. :slight_smile:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
  ssize_t bytes;
  char buf[512];
  int fd=open("path/to/file", O_RDONLY);
  if(fd < 0)
  {
    perror("Couldn't open file");
    return(1);
  }

  bytes=read(fd, buf, 512);
  if(bytes <= 0)
  {
    perror("Couldn't read");
    close(fd);
    return(2);
  }

  close(file);


  // You now have 'bytes' bytes of data read into the buffer 'buf'.

  // Do other stuff here

  return(0);
}

Thank you for your reply Corona688,
Haha it's not what you think, i learned RAW, TCP/IP and UNIX domain socket programming first because that's what i work with the most, but now i'm trying to learn FILE I/O and that's the reason of coding programs like this one. :slight_smile:

Thank you again for your code, i appreciate it.

You can also use "sendfile()". That's a lot more efficient because it cuts the number of memory copies by half.

When you read data from a file into the address space of a process, usually the data is copied into a kernel buffer as it comes in off disk, and it get copied again from that kernel buffer into the process buffer. To send that data out a socket, the data is first copied into a kernel buffer, and the data in that buffer is copied out to the socket.

The sendfile() library call will bypass the copying of data into and out of the address space of the process.

For example (I left off all error checking for clarity):

    struct stat sb;
    off_t offset = 0L;
    int fd;

    fd = open( filename, O_RDONLY );
    fstat( fd, &sb );
    sendfile( socket_fd, fd, &offset, sb.st_size );
    close( fd );

Hey achenle, thanks for the reply,
I did the code as following:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
if(argc !=3){
printf("Usage: %s <iface> <raw filename>\n", argv[0]);
exit(1);
}

int sfd,ffd;
ssize_t bytes;
unsigned char *buffer;
struct stat sizb;
struct sockaddr from;
from.sa_family = 1;
strcpy(from.sa_data, argv[1]);

if((stat(argv[2],&sizb))!=0){
perror("stat() failed: ");
exit(1);
}

buffer=(unsigned char *)malloc(sizb.st_size);
if((ffd=open(argv[2], O_RDONLY))<0){
perror("open() failed: ");
exit(1);
}

if((bytes = read(ffd, buffer, sizb.st_size))<= 0){
perror("read() failed: ");
close(ffd);
exit(1);
} else {
close(ffd);
}

if((sfd=socket(AF_INET,SOCK_PACKET,ntohs(ETH_P_ALL)))<0){
perror("socket() failed: ");
exit(1);
}

if((sendto(sfd, buffer, sizb.st_size,0,(struct sockaddr *)&from,sizeof(from)))<0){
perror("send() failed: ");
exit(1);
}

printf("%i bytes transmitted.\n", sizb.st_size);
close(sfd);
return 0;
}

If you create a file with a hex editor, it will successfully transmit to the medium the frame :D.

I'll test your way, thank you.

Oh, if you're using stdio anyway, you might as well try this so as to include a few dozen less headers:

#include <stdio.h>

int main(void)
{
  size_t bytes;
  char buf[512];
  FILE *fp=fopen("filename", "rb");
  if(fp == NULL)
  {
    fprintf(stderr, "Couldn't open file\n");
    return(1);
  }

  bytes=fread(buf, 1, 512, fp);
  if(bytes <= 0)
  {
    fprintf(stderr, "Couldn't read from file\n");
    fclose(fp);
    return(2);
  }
  fclose(fp);
  fprintf(stderr, "Read %d bytes into buffer\n", bytes);


  return(0);
}

sendfile() is more efficient in some circumstances, but is also 100% linux-specific and nonportable, as well as subject to certain limitations -- the data source must be a file, and the destination must be a socket. It used to be less arbitrary, leading to a few bits of new code taking advantage of it breaking when this behavior was changed. I'm not sure if it behaves the same with all sockets or not, particularly raw sockets which as I understand it must be packet-based.