Thread (55 messages) 55 messages, 2 authors, 2012-01-09

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help