7 #include <sys/socket.h>
9 #include <libnetlink.h>
10 #include <linux/netlink.h>
11 #include <linux/rtnetlink.h>
12 #include <arpa/inet.h>
17 * - refactor error messages
26 int read_addr_port( char* in, struct in_addr* addr, unsigned short* port )
32 if( (delim = strchr( in, ':' )) == NULL )
34 fprintf( stderr, "error: ':'\n" );
40 memcpy( addrstr, in, addrlen );
41 addrstr[addrlen] = '\0';
42 if( inet_aton( addrstr, addr ) == 0 )
44 fprintf( stderr, "error: aton\n" );
49 if( sscanf( delim, ":%hu", port ) != 1 ) /* todo: handle overflow */
51 fprintf( stderr, "error: port\n" );
58 char* read_iftype( char* in, int* iftype )
62 if( strncmp( "udp@", optarg, 4 ) == 0 )
67 else if( strncmp( "tcp@", optarg, 4 ) == 0 )
71 else if( strncmp( "can@", optarg, 4 ) == 0 )
80 int main( int argc, char* argv[] )
83 int src_if = 0, dst_if = 0;
87 struct in_addr eth_addr;
88 unsigned short eth_port;
89 struct in_addr eth_listen_addr;
90 unsigned short eth_listen_port;
93 struct sockaddr_nl nladdr;
98 struct rtcanmsg rtcan;
99 char buf[600]; /* enough? */
102 while( (opt = getopt( argc, argv, "As:d:l:" )) != -1 )
107 if( (optstr = read_iftype( optarg, &src_if )) == NULL )
109 fprintf( stderr, "error: bad input format\n" );
117 can_ifidx = if_nametoindex( optstr );
120 read_addr_port( optstr, ð_addr, ð_port );
123 fprintf( stderr, "error: unrecognized interface" );
129 if( (optstr = read_iftype( optarg, &dst_if )) == NULL )
131 fprintf( stderr, "error: bad input format\n" );
139 can_ifidx = if_nametoindex( optstr ); /*chk*/
142 read_addr_port( optstr, ð_addr, ð_port ); /*chk*/
145 fprintf( stderr, "error: unrecognized interface" );
150 if( (optstr = read_iftype( optarg, &tmp )) == NULL )
152 fprintf( stderr, "error: -l bad input format\n" );
157 if( tmp != IF_ETH_UDP )
159 fprintf( stderr, "error: -l bad input format\n" );
164 read_addr_port( optstr, ð_listen_addr, ð_listen_port ); /*chk*/
166 fprintf( stderr, "error: unknown option\n" );
171 /* 2. do check on arguments */
172 if( (src_if == 0 || dst_if == 0) || (src_if == dst_if) )
174 fprintf( stderr, "error: source or destination not specified\n" );
178 if( src_if == dst_if )
180 fprintf( stderr, "error: source and destination same interface type\n" );
183 /* 3. prepare netlink message */
184 req.nh.nlmsg_len = NLMSG_LENGTH( sizeof(struct rtcanmsg) );
185 req.nh.nlmsg_type = RTM_NEWROUTE;
186 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
187 req.nh.nlmsg_seq = 0;
188 req.nh.nlmsg_pid = 0; /* ? */
190 req.rtcan.can_family = AF_CAN;
191 req.rtcan.gwtype = (src_if == IF_CAN) ? CGW_TYPE_CAN_ETH_UDP : CGW_TYPE_ETH_CAN_UDP;
194 addattr_l( &req.nh, sizeof(req), CGW_CAN_IF, &can_ifidx, sizeof(can_ifidx) );
195 switch( req.rtcan.gwtype )
197 case CGW_TYPE_CAN_ETH_UDP:
198 addattr_l( &req.nh, sizeof(req), CGW_ETH_IP, ð_addr, sizeof(eth_addr) );
199 addattr_l( &req.nh, sizeof(req), CGW_ETH_PORT, ð_port, sizeof(eth_port) );
201 case CGW_TYPE_ETH_CAN_UDP:
209 addattr_l( &req.nh, sizeof(req), CGW_LISTEN_IP, ð_listen_addr, sizeof(eth_listen_addr) );
210 addattr_l( &req.nh, sizeof(req), CGW_LISTEN_PORT, ð_listen_port, sizeof(eth_listen_port) );
213 /* 4. send over netlink socket */
214 s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); /* chck */
216 memset(&nladdr, 0, sizeof(nladdr));
217 nladdr.nl_family = AF_NETLINK;
219 nladdr.nl_groups = 0;
221 err = sendto( s, &req, req.nh.nlmsg_len, 0,
222 (struct sockaddr*)&nladdr, sizeof(nladdr));
225 perror( "netlink sendto" );