Re: recv list
From: Kurt Van Dijck <hidden>
Date: 2012-01-05 12:09:33
On Thu, Jan 05, 2012 at 10:55:19AM +0000, Wolfgang wrote:
OK, I hope I understood it right now, 'recvfrom' returns me more information than 'recv', I thought I can filter with it. But I have to do this before with struct 'j1939_filter' and 'setsockopt' to choose which frames from the bus are cared about.
right!
So if I unterstand it right this should bridge from can0 to can1 and if the sender is 0x30 it prints the first data byte?
pretty good. I did point a few minor remarks.
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <linux/can/j1939.h>
#include <linux/can.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/types.h>
int main (void)
{
int s;
s = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
struct sockaddr_can addr;
memset(&addr, 0, sizeof(addr));
addr.can_ifindex = if_nametoindex("can0");
addr.can_addr.j1939.name = J1939_NO_NAME;
addr.can_addr.j1939.addr = 0x00;
addr.can_addr.j1939.pgn = J1939_NO_PGN;
addr.can_family = AF_CAN;
if (bind(s, (void *)&addr, sizeof(addr))<0)
{
perror ("bind failed");
}
int s2;
s2 = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
struct sockaddr_can addr2;
memset(&addr2, 0, sizeof(addr2));
addr2.can_ifindex = if_nametoindex("can1");
addr2.can_addr.j1939.name = J1939_NO_NAME;
addr2.can_addr.j1939.addr = 0x3D;
addr2.can_addr.j1939.pgn = J1939_NO_PGN;
addr2.can_family = AF_CAN;
if (bind(s2, (void *)&addr2, sizeof(addr2))<0)
{
perror ("bind2 failed");
}
int ret;
socklen_t len;
struct sockaddr_can src_addr;
char buf[128];
src_addr.can_family = AF_CAN;This assignment is useless...
while (1) {
len = sizeof(src_addr);
ret = recvfrom(s, buf, sizeof(buf), 0, (void *)&src_addr, &len);
if (ret < 0)
perror ("recvfrom failed");
/*if the frame is sent by 0x30 do this*/
if (src_addr.can_addr.j1939.addr == 0x30)
{you could test if 'ret' > 0, since 'ret' may be 0. Altough sending frames without data is rare in j1939...
printf("%x\n", buf[0]);
In this example, the remainder of the 'if' is equal as the 'else' ...
if (sendto(s2, buf, ret, 0, (void *)&src_addr, len) < 0)
perror("sendto failed");
}
/*else just bridge it*/
else
{
if (sendto(s2, buf, ret, 0, (void *)&src_addr, len) < 0)
perror("sendto failed");
}
}
return 0;
}
Thanks so far!Note that this bridge puts the originating source address as bridged destination address. This does not matter for PDU2 type of PGN's (== PDU-specific is not the destination address), it may not be completely right. I'd expect to 'empty' (== put J1939_NO_ADDR) the src_addr.can_addr.j1939.addr member before sendto(), resulting in a broadcasted PGN. In a later iteration, You could (if necessary, since I have no clue what kind of traffic you will bridge): * make the receiving socket (s) 'promiscuous', i.e. receiving all traffic. * fetch the original destination by using recvmsg() as illustrated in jspy. I think you're bridge will work. great job! Kurt
-- To unsubscribe from this list: send the line "unsubscribe linux-can" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html