SocketCAN read from socket only returns 11cobid - c

I am trying to read from a socketCAN and the msg is always filtered for the 11bit identifier.
This should be a problem fixable with setting the rpoper flags for the 29bit identifier but I can`t find where if anyone can help...
struct can_frame message;
struct sockaddr_can addr;
struct ifreq ifr;
int fd = -1; // file descriptor (it´s a socket)
if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
LE_INFO("cannot open socket");
return;
}
strcpy(ifr.ifr_name, "can0");
ioctl(fd, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("cannot bind socket\n");
return;
}
uint8_t nbytes;
message.can_id |= CAN_EFF_FLAG;
while(1)
{
nbytes = read(fd, &message, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return;
}
printf("READ COB_ID:%x\n",message.can_id | CAN_EFF_FLAG);
}
return;
I am sending a CAN frame with idx x901 and this is what is printed:
READ COB_ID:80000101
READ COB_ID:80000101
READ COB_ID:80000101
I have troubleshooted this in many different ways and it seems that the C code is working as it should, but I suspect the problem to be with the kernel module for either mcp251x which is not correctly receiving the extended flag? Or it may be with some initialization I need to do before running the kernel module???
Thank you in advance to anyone who can help.

Your understanding of CAN flags and filtering is not correct. Take a look at extract from linux can.h:
/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
#define CAN_ERR_FLAG 0x20000000U /* error message frame */
/* valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
Here is an example that works for both SFF and EFF messages:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int main(int argc, char **argv)
{
struct can_frame message;
struct sockaddr_can addr;
struct ifreq ifr;
int fd = -1; // file descriptor (it´s a socket)
if((fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
printf("cannot open socket");
return -9;
}
strcpy(ifr.ifr_name, "vcan0");
ioctl(fd, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("cannot bind socket\n");
return -1;
}
u_int8_t nbytes;
message.can_id |= CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK;
while(1)
{
nbytes = read(fd, &message, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return -2;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return -3;
}
printf("READ COB_ID: %x\n", message.can_id & CAN_EFF_MASK);
}
return 0;
}
Now sending these messages:
cansend vcan0 00000123#FFFFFFFFFFFFFFFF
cansend vcan0 12345678#FFFFFFFFFFFFFFFF
gives correct output:
READ COB_ID: 123
READ COB_ID: 12345678

Related

Transmitting audio through socket (UDP) but not playing back properly

I'm trying to transmit from the client side a wav file through socket (UDP) and have the server playing the wav file by means of the ALSA library.
Since my coding level in C is very low I've first learnt how to set up a communication between client and server via sockets and interchange text messages.
Afterwards I've learnt how to play a wav file with ALSA by redirecting the stdin when running the playback app.
I've tried to joint both code (UDPServer.c + playback.c) files and when I pass the stdin to the UDPClient.c file it sends it to the UDPServer.c but it's just a pure tone instead of the actual music file that I'm trying to pass.
I don't know how exactly to pass the file into the UDPClient.c in order for it to send it to the socket to the server.
UDPServer.c
// Server side implementation of UDP client-server model
// Libraries
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <alsa/asoundlib.h>
// CONSTANTS
#define PORT 8080
#define MAXLINE 2048
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
// FUNCTION DECLARATION
int audio_play (char signal);
// Main code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "AUDIO PLAYBACK FINISH";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
perror("bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr); //len is value/result
// Receive a mesage from the socket
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);
buffer[n] = '\0';
//printf("Client : %s\n", buffer);
audio_play(buffer);
// Send a message on the socket
sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len);
printf("PLAYING AUDIO???.\n");
return 0;
}
// FUNCTIONS
int audio_play (char s)
{
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
/* Open PCM device for playback. */
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 2);
/* 48000 bits/second sampling rate */
val = 48000;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
/* Set period size to 32 frames. */
frames = 32;
snd_ pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 4; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);
/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(params, &val, &dir);
/* 5 seconds in microseconds divided by
* period time */
loops = 5000000 / val;
while (loops > 0) {
loops--;
// rc = read(0, buffer, size);
rc = s;
if (rc == 0) {
fprintf(stderr, "end of file on input\n");
break;
} else if (rc != size) {
fprintf(stderr, "short read: read %d bytes\n", rc);
}
rc = snd_pcm_writei(handle, buffer, frames);
if (rc == -EPIPE) {
/* EPIPE means underrun */
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr, "error from writei: %s\n", snd_strerror(rc));
} else if (rc != (int)frames) {
fprintf(stderr, "short write, write %d frames\n", rc);
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
}
UDPClient.c
// Client side implementation of UDP client-server model
// Libraries
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
// CONSTANTS
#define PORT 8080
#define MAXLINE 2048
// Main code
int main(int argc, char **argv) {
int sockfd;
char buffer[MAXLINE];
char *data = "Here is where the file of audio should be?";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
int n, len;
// Send a message on the socket
sendto(sockfd, (const char *)data, strlen(data), MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
printf("AUDIO SENT.\n");
// Receive a message from the socket
n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
close(sockfd);
return 0;
}

Reading CAN bus in C displays incorrect CAN ID for 29-bit CAN ID

I wrote some code in C to read CAN bus data. Everything works correctly when I read 11-bit CAN IDs. As soon as I try to read 29-bit IDs it displays the ID incorrectly.
Example:
Receiving message with 29-bit ID:
0x01F0A020
And print it with
printf("%X\n", frame.can_id);
it prints 81F0A020.
11-bit ID message
0x7DF
and print it with
printf("%X\n", frame.can_id);
It prints correctly 7DF.
Why is this the case?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <net/if.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#define MAX_DATA_LEN 8
#define MAX_FIELDS 23
#define MAX_FIELD_LEN 64
#include <limits.h>
char data_str[MAX_FIELDS][MAX_FIELD_LEN];
int i;
int
main(void)
{
int s;
int nbytes;
struct sockaddr_can addr;
struct can_frame frame;
unsigned short data[MAX_FIELDS];
int sockfd = 0;
int bcast = 1;
struct sockaddr_in src_addr;
struct sockaddr_in dst_addr;
int numbytes;
int fa;
struct ifreq ifr;
fa = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
ioctl(fa, SIOCGIFHWADDR, &ifr);
close(fa);
//
if((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("Udp sockfd create failed");
exit(1);
}
//Enabled broadcast mode for udp
if((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
&bcast, sizeof bcast)) == -1)
{
perror("setsockopt failed for broadcast mode ");
exit(1);
}
src_addr.sin_family = AF_INET;
src_addr.sin_port = htons(8888);
src_addr.sin_addr.s_addr = INADDR_ANY;
memset(src_addr.sin_zero, '\0', sizeof src_addr.sin_zero);
if(bind(sockfd, (struct sockaddr*) &src_addr, sizeof src_addr) == -1)
{
perror("bind");
exit(1);
}
dst_addr.sin_family = AF_INET;
dst_addr.sin_port = htons(45454);
dst_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(dst_addr.sin_zero, '\0', sizeof dst_addr.sin_zero);
if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("Error while opening socket");
return -1;
}
addr.can_family = AF_CAN;
addr.can_ifindex = 0;
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("Error in socket bind");
return -2;
}
//struct can_frame frame;
while(1)
{
nbytes = read(s, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return 1;
}
/* Paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
// Print the received CAN ID
printf("%X\n", frame.can_id);
}
return 0;
}
The field can_id of struct can_frame contains the CAN ID and the EFF/RTR/ERR flags. The extended ID has 29 bits, so there are 3 free bits that are used to represent 3 flags.
Your example ID 0x01F0A020 must be an extended frame, but ID 0x7DF can be sent as a base frame or as an extended frame. These are different messages. To distinguish between a base frame or an extended frame with the same ID you need the EFF flag.
In your example you see the value 0x81F0A020 which is the combination of ID 0x01F0A020 and CAN_EFF_FLAG (0x80000000U).
Extract from https://github.com/torvalds/linux/blob/master/include/uapi/linux/can.h
/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
#define CAN_ERR_FLAG 0x20000000U /* error message frame */
/* valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
...
/**
* struct can_frame - basic CAN frame structure
* #can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
* #can_dlc: frame payload length in byte (0 .. 8) aka data length code
* N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1
* mapping of the 'data length code' to the real payload length
* #__pad: padding
* #__res0: reserved / padding
* #__res1: reserved / padding
* #data: CAN frame payload (up to 8 byte)
*/
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
__u8 __pad; /* padding */
__u8 __res0; /* reserved / padding */
__u8 __res1; /* reserved / padding */
__u8 data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};
To get the ID only without flags, you should apply CAN_SFF_MASK or CAN_EFF_MASK depending on the value of the CAN_EFF_FLAG bit.
Example code:
//Print the received CAN ID
printf("%X\n",
(frame.can_id & CAN_EFF_FLAG) ? (frame.can_id & CAN_EFF_MASK)
: (frame.can_id & CAN_SFF_MASK));

How to read/write from existing TAP interface in C

I have an existing tap device (tap0) that I created on command line.
# ip tuntap add dev tap0 mode tap
I want to read any data coming in on that interface using a C program. I checked other SO questions, but found code that create an interface by opening /dev/net/tun.
Can anyone provide some direction on how to open and read existing interface ? I'm not sure which file I should open for tap0 ?
Open the existing tun/tap interface similar way than creating a new one.
Just give name for the interface when ioctl(TUNSETIFF) is used:
const int fd = open("/dev/net/tun", O_RDWR);
if (fd != -1)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, "tun0", IFNAMSIZ); // <<<<=== THIS WAY
if (ioctl(fd, TUNSETIFF, &ifr) != -1)
{
Without the strncpy line, the code creates a new interface with some free number.
With the line, it tries to open tun0. Note: it fails if the tun0 is already opened by some other process.
Above is tested with IFF_TUN. I haven't tried IFF_TAP.
You can use the file descriptor (fd) for reading and writing:
Example for tun:
char buffer[0x1000];
const int len = read(fd, buffer, sizeof(buffer));
if (len > 0)
{
static const char IPV6_VER_MASK = 0x60;
if ((buffer[0] & IPV6_VER_MASK) == IPV6_VER_MASK)
{
handle_ipv6_packet((const struct ip6_hdr*)buffer, len);
}
}
You can implement like a tcpdump to capture packets, can use libpcap or
use socket RAW_SOCKET
sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)
Of course you can also add the bpf filter
setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, ...
simple sample:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
int n;
int ret = 0;
int sock;
char buf[2048];
struct ifreq ifreq;
struct sockaddr_ll saddr;
// create socket
if((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
ret = errno;
goto error_exit;
}
// bind tap0
snprintf(ifreq.ifr_name, sizeof(ifreq.ifr_name), "tap0");
if (ioctl(sock, SIOCGIFINDEX, &ifreq)) {
ret = errno;
goto error_exit;
}
memset(&saddr, 0, sizeof(saddr));
saddr.sll_family = AF_PACKET;
saddr.sll_protocol = htons(ETH_P_ALL);
saddr.sll_ifindex = ifreq.ifr_ifindex;
saddr.sll_pkttype = PACKET_HOST;
if(bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
ret = errno;
goto error_exit;
}
// recv data
while(1) {
n = recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL);
printf("%d bytes recieved\n", n);
}
error_exit:
if (ret) {
printf("error: %s (%d)\n", strerror(ret), ret);
}
close(sock);
return ret;
}

How to listen to IGMPv3 frames

I need to get IGMPv3 Frames for this I'm using a socket like following:
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
the problem is that my program is filtring IGMPv3 Frames, i don't know why !! I don't get IGMP frames although I'm getting them when using wireshark. I tried also to use :
sockfd = socket(PF_PACKET, SOCK_RAW, htons(0x0800));
but I was capable of getting only ICMP frames and not IGMP ones.
PS: I tried my program on another machine and it worked, so I think the problem is with my kernel, does anyone know if there is any configuration to do with the socket ?
Here is the whole code:
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <unistd.h>
#define DEST_MAC0 0x01
#define DEST_MAC1 0x00
#define DEST_MAC2 0x5e
#define DEST_MAC3 0x00
#define DEST_MAC4 0x00
#define DEST_MAC5 0x16
#define ETHER_TYPE 0x0800
#define DEFAULT_IF "eth1"
#define BUF_SIZ 1024
int main(int argc, char *argv[])
{
char sender[INET6_ADDRSTRLEN];
int sockfd, ret, i, counter;
int sockopt;
ssize_t numbytes;
struct ifreq ifopts; /* set promiscuous mode */
struct ifreq if_ip; /* get ip addr */
struct sockaddr_storage their_addr;
uint8_t buf[BUF_SIZ];
char ifName[IFNAMSIZ];
/* Get interface name */
if (argc > 1)
strcpy(ifName, argv[1]);
else
strcpy(ifName, DEFAULT_IF);
/* Header structures */
struct ether_header *eh = (struct ether_header *) buf;
struct iphdr *iph = (struct iphdr *) (buf + sizeof(struct ether_header));
struct udphdr *udph = (struct udphdr *) (buf + sizeof(struct iphdr) + sizeof(struct ether_header));
memset(&if_ip, 0, sizeof(struct ifreq));
/* Open PF_PACKET socket, listening for EtherType ETHER_TYPE */
// if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) {
// perror("listener: socket");
// return -1;
// }
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE));
if (sockfd == -1) {
perror("listener: socket");
return -1;
}
/* Set interface to promiscuous mode - do we need to do this every time? */
strncpy(ifopts.ifr_name, ifName, IFNAMSIZ-1);
ioctl(sockfd, SIOCGIFFLAGS, &ifopts);
ifopts.ifr_flags |= IFF_PROMISC;
ioctl(sockfd, SIOCSIFFLAGS, &ifopts);
/* Allow the socket to be reused - incase connection is closed prematurely */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
perror("setsockopt");
close(sockfd);
exit(EXIT_FAILURE);
}
/* Bind to device */
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, IFNAMSIZ-1) == -1) {
perror("SO_BINDTODEVICE");
close(sockfd);
exit(EXIT_FAILURE);
}
repeat: printf("listener: Waiting to recvfrom...\n");
numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL);
printf("listener: got packet %lu bytes\n Frame = {",(unsigned long int) numbytes);
for( counter = 0; counter < numbytes; counter++)
printf( "%02X ", buf[counter]);
printf( "}");
/* Check the packet is for me */
if (eh->ether_dhost[0] == DEST_MAC0 &&
eh->ether_dhost[1] == DEST_MAC1 &&
eh->ether_dhost[2] == DEST_MAC2 &&
eh->ether_dhost[3] == DEST_MAC3 &&
eh->ether_dhost[4] == DEST_MAC4 &&
eh->ether_dhost[5] == DEST_MAC5) {
printf("Correct destination MAC address\n");
} else {
printf("Wrong destination MAC: %x:%x:%x:%x:%x:%x\n",
eh->ether_dhost[0],
eh->ether_dhost[1],
eh->ether_dhost[2],
eh->ether_dhost[3],
eh->ether_dhost[4],
eh->ether_dhost[5]);
ret = -1;
goto done;
}
/* Get source IP */
((struct sockaddr_in *)&their_addr)->sin_addr.s_addr = iph->saddr;
inet_ntop(AF_INET, &((struct sockaddr_in*)&their_addr)->sin_addr, sender, sizeof sender);
/* Look up my device IP addr if possible */
strncpy(if_ip.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFADDR, &if_ip) >= 0) { /* if we can't check then don't */
printf("Source IP: %s\n My IP: %s\n", sender,
inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr));
/* ignore if I sent it */
if (strcmp(sender, inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr)) == 0) {
printf("but I sent it :(\n");
ret = -1;
goto done;
}
}
/* UDP payload length */
ret = ntohs(udph->len) - sizeof(struct udphdr);
/* Print packet */
printf("\tData:");
for (i=0; i<numbytes; i++) printf("%02x:", buf[i]);
printf("\n");
done: goto repeat;
close(sockfd);
return ret;
}
Please note that the address mac that I'm initializing is the address that I get from IGMP frame on wireshark. this code actually allows me to detect only ICMP frames.
When using:
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
instead of:
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE);
I don't get nothing !
On wireshark I'm getting all the frames that I want including IGMP and ICMP!!

send() socket operation on non-socket

While trying to implement a server and client, I noticed that the client was writing to stdout instead
of through the network. I figured out that the file descriptor being returned by connect() is always zero, which explains why it was writing to stdout. But I can not figure out why connect() always returns zero instead of a valid socket. All the articles on the web I found with the same problem were due to precedence issues with wrapping if() around the connect() call. But I haven't done that, any help would be appreciated.
server code
int setUpServer(struct fuzzerObj *ptr, int *firstClient)
{
/* Declarations */
int hostSocket, yes = 1, rtrn, clientfd;
union
{
struct sockaddr_in in;
}address;
/* Create Socket */
hostSocket = socket(AF_INET, SOCK_STREAM, 0);
if(hostSocket < 0)
{
errorHandler("Could not create socket\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* Reuse Address */
rtrn = setsockopt(hostSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
if(rtrn < 0)
{
errorHandler("Couldn't Reuse Address\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* Set Up Struct */
address.in.sin_len = sizeof(address.in);
address.in.sin_family = AF_INET;
address.in.sin_port = htons(BBPORT_NUMBER);
address.in.sin_addr.s_addr = htonl(INADDR_ANY);
memset(address.in.sin_zero, 0, sizeof(address.in.sin_zero));
/* Bind Address to Socket */
rtrn = bind(hostSocket, (struct sockaddr*) &address, address.in.sin_len);
if(rtrn < 0)
{
errorHandler("Can't Bind Address to Socket\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
/* listen */
rtrn = listen(hostSocket, ptr->numberOfClients);
if(rtrn < 0)
{
errorHandler("Can't Listen\n", FUNCTION_ID_SET_UP_SERVER);
return -1;
}
while(1)
{
rtrn = acceptClient(hostSocket, &clientfd);
if(rtrn < 0)
{
printf("Can't Accept Client\n");
return -1;
}
break;
}
*firstClient = clientfd;
return 0;
}
client code
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#define BLACKBOX_PORT 9696
int main(int argc, char *argv[])
{
/* Check To See If an argument was passed */
if(argc < 2)
{
printf("No enough Arguments\n");
return -1;
}
/* Declaration's */
const char *ip = argv[1];
int sockfd, fd, rtrn;
char *outBuf;
struct sockaddr_in servaddr;
/* Get Socket to Connect to Fuzz Server */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("Can't Create Socket");
return -1;
}
/* Fill Out Struct */
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(BLACKBOX_PORT);
inet_pton(AF_INET, ip, &servaddr.sin_addr);
/* Attempt Connection */
fd = connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
if(fd < 0)
{
perror("Can not connect to BlackBox Fuzz server");
return -1;
}
/* Allocate Space in Memory for Outgoing Connection */
rtrn = asprintf(&outBuf, "Mac OSX 10.9\n");
if(rtrn < 0)
{
perror("Copy Error");
return -1;
}
/* Send Data to Fuzzer via Socket */
rtrn = send(fd, outBuf, strlen(outBuf), 0);
if(rtrn < 0)
{
perror("Can't write Data to BlackBox Server");
return -1;
}
free(outBuf);
return 0;
}
Upon successfully calling connect(), the sockfd is connected. The 0 return value indicates that the call is successful. If the value was not 0, it would have indicated an error, and that the connection attempt has failed or is not yet completed (if the connect is non-blocking).
After determining that connect() has succeeded, call send() on the sockfd, not on the return value of the connect() call.
rtrn = send(sockfd, outBuf, strlen(outBuf), 0);

Resources