static int cegw_create_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg )
{
struct nlattr* tb[ CGW_MAX+1 ];
- struct rtcanmsg *r;
+ struct rtmsg *r;
struct can_eth_gw* cethgw = NULL;
struct eth_can_gw* ecangw = NULL;
int err = 0;
+ int type = 0;
+ /* ToDo: size check
if (nlmsg_len(nlh) < sizeof(*r))
return -EINVAL;
+ */
- r = nlmsg_data(nlh);
- if (r->can_family != AF_CAN)
- return -EPFNOSUPPORT;
-
- err = nlmsg_parse( nlh, sizeof( struct rtcanmsg ), tb, CGW_MAX, NULL );
+ err = nlmsg_parse( nlh, sizeof( struct rtmsg ), tb, CGW_MAX, NULL );
if( err < 0 )
{
printk( KERN_ERR "error: nlmsg_parse\n" );
return err;
}
- switch( r->gwtype )
+ if( tb[CGW_CMD_INFO] == NULL )
+ {
+ printk( "error: bad cmd\n" );
+ return -EINVAL;
+ }
+
+ switch( *(int*)nla_data( tb[CGW_CMD_INFO] ) )
{
- case CGW_TYPE_CONFIG:
+ case CEGW_LISTEN:
listen( 0, *(struct in_addr*)nla_data( tb[CGW_LISTEN_IP] ),
*(u16*)nla_data( tb[CGW_LISTEN_PORT] ) );
break;
static int cegw_remove_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg )
{
- struct rtcanmsg* r;
+ struct rtmsg* r;
struct nlattr* tb[ CGW_MAX+1 ];
+ struct hlist_node* pos,* n;
+ struct can_eth_gw* ceth;
+ struct eth_can_gw* ecan;
+
+ int err = 0;
if( nlmsg_len(nlh) < sizeof(*r) )
return -EINVAL;
r = nlmsg_data( nlh );
- if( r->can_family != AF_CAN )
+ if( r->rtm_family != AF_CAN )
return -EPFNOSUPPORT;
+ /*
if( r->gwtype != CGW_TYPE_CAN_ETH_UDP )
return -EINVAL;
+ */
+ printk( "attrsize=%d\n", nlmsg_attrlen(nlh, sizeof(struct rtmsg)) );
- printk( "flags:%x",r->flags );
- //nlmsg_parse( nlh, sizeof(*r), tb, CGW_MAX, NULL );
+ err = nlmsg_parse( nlh, sizeof(struct rtmsg), tb, CGW_MAX, NULL );
+ if( err != 0 )
+ return -EINVAL;
+ if( tb[CGW_CMD_INFO] == NULL )
+ return -EINVAL;
+
+ if( *(int*)nla_data( tb[CGW_CMD_INFO] ) == CEGW_FLUSH )
+ {
+ hlist_for_each_entry_safe( ceth, pos, n, &can_eth_job, list )
+ {
+ hlist_del( &ceth->list );
+ kfree( ceth );
+ }
+ hlist_for_each_entry_safe( ecan, pos, n, ð_can_job, list )
+ {
+ hlist_del( &ecan->list );
+ kfree( ecan );
+ }
+ }
// tb[]
return 0;
}
/* ToDo: stop threads */
}
- /* ToDo: unregister netlink */
+ /* ToDo: unregister netlink
+ * free jobs */
printk( "cangw: exit\n" );
//kthread_stop( ts );
}
#include <arpa/inet.h>
#include <linux/can.h>
#include <linux/types.h>
+#include <unistd.h>
#include "canethgw.h"
/**
struct cegw_nlmsg
{
struct nlmsghdr nh;
- struct rtcanmsg rtcan;
- char buf[600]; /* enough? */
+ struct rtmsg rt;
+ char buf[768]; /* enough? */
};
unsigned int cegw_errno = 0;
inline static int cegw_add( struct cegw_nlmsg* req, struct cegw_data* d )
{
+ int gwtype = 0;
+
req->nh.nlmsg_type = RTM_NEWROUTE;
if( (d->src_if == 0 || d->dst_if == 0) )
{
return -cegw_errno;
}
- req->rtcan.gwtype = (d->src_if == IF_CAN) ? CGW_TYPE_CAN_ETH_UDP : CGW_TYPE_ETH_CAN_UDP;
+ gwtype = (d->src_if == IF_CAN) ? CGW_TYPE_CAN_ETH_UDP : CGW_TYPE_ETH_CAN_UDP;
addattr_l( &req->nh, sizeof(*req), CGW_CAN_IF, &d->can_ifidx, sizeof(d->can_ifidx) );
- switch( req->rtcan.gwtype )
+
+ switch( gwtype )
{
case CGW_TYPE_CAN_ETH_UDP:
addattr_l( &req->nh, sizeof(*req), CGW_ETH_IP, &d->eth_addr, sizeof(d->eth_addr) );
break;
}
+ addattr32( &req->nh, sizeof(*req), CGW_CMD_INFO, gwtype );
+
return 0;
}
inline static int cegw_listen( struct cegw_nlmsg* req, struct cegw_data* d )
{
req->nh.nlmsg_type = RTM_NEWROUTE;
- req->rtcan.gwtype = CGW_TYPE_CONFIG;
- addattr_l( &req->nh, sizeof(req), CGW_LISTEN_IP, &d->eth_listen_addr, sizeof(d->eth_listen_addr) );
- addattr_l( &req->nh, sizeof(req), CGW_LISTEN_PORT, &d->eth_listen_port, sizeof(d->eth_listen_port) );
+ addattr32( &req->nh, sizeof(*req), CGW_CMD_INFO, CEGW_LISTEN );
+ addattr_l( &req->nh, sizeof(*req), CGW_LISTEN_IP, &d->eth_listen_addr, sizeof(d->eth_listen_addr) );
+ addattr_l( &req->nh, sizeof(*req), CGW_LISTEN_PORT, &d->eth_listen_port, sizeof(d->eth_listen_port) );
printf( "start listen: %x, %hu\n", d->eth_listen_addr, d->eth_listen_port );
return 0;
inline static int cegw_flush( struct cegw_nlmsg* req, struct cegw_data* d )
{
+// char foo[2];
+ addattr32( &req->nh, sizeof(*req), CGW_CMD_INFO, CEGW_FLUSH );
req->nh.nlmsg_type = RTM_DELROUTE;
- req->rtcan.gwtype = CGW_TYPE_CAN_ETH_UDP;
- req->rtcan.flags = CEGW_FLUSH;
+// addattr_l( &req->nh, sizeof(*req), 0, &foo, sizeof(foo) );
+ //addattr_l( &req->nh, sizeof(*req), CGW_CAN_IF, &d->can_ifidx, sizeof(d->can_ifidx) );
+// req->rtcan.gwtype = CGW_TYPE_CAN_ETH_UDP;
+// req->rtcan.flags = 5;//CEGW_FLUSH;
return 0;
}
int err = 0;
struct cegw_nlmsg req;
struct cegw_data d;
- char rxbuf[256];
+ char rxbuf[256]; /* 8129+ ? */
int rsize = 0;
struct nlmsghdr* nlh;
struct nlmsgerr* rte;
+ printf( "size=%d\n", NLMSG_LENGTH(sizeof(struct rtmsg)) );
+
memset( &d, 0, sizeof(d) );
struct option long_opt[] =
}
/* prepare netlink message */
- req.nh.nlmsg_len = NLMSG_LENGTH( sizeof(struct rtcanmsg) );
- req.nh.nlmsg_type = RTM_NEWROUTE;
+ req.nh.nlmsg_len = NLMSG_LENGTH( sizeof(struct rtmsg) );
+ req.nh.nlmsg_type = RTM_DELROUTE;
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
req.nh.nlmsg_seq = 0;
req.nh.nlmsg_pid = 0; /* ? */
-
- req.rtcan.can_family = AF_CAN;
- req.rtcan.flags = 0;
+
+ memset( &req.rt, 0, sizeof(req.rt) );
+ req.rt.rtm_family = AF_CAN;
+
+ //req.rt.gwtype = CGW_TYPE_CAN_CAN;
+ //req.rt.flags = 0;
switch( cmd )
{
memset( &nladdr, 0, sizeof(nladdr) );
nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = 0;
+ nladdr.nl_pad = 0;
+ nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
err = sendto( s, &req, req.nh.nlmsg_len, 0,
- (struct sockaddr*)&nladdr, sizeof(nladdr));
- if (err < 0)
+ (struct sockaddr*)&nladdr, sizeof(nladdr) );
+ if( err < 0 )
{
perror( "netlink sendto" );
return err;
nlh = (struct nlmsghdr*)rxbuf;
if( nlh->nlmsg_type != NLMSG_ERROR )
{
- fprintf( stderr, "error: unexpected netlink answer\n" );
+ fprintf( stderr, "error: unexpected netlink answer=%d\n", nlh->nlmsg_type );
return -1;
}
rte = (struct nlmsgerr*)NLMSG_DATA( nlh );
err = rte->error;
if( err < 0 )
- fprintf( stderr, "error: netlink; %s\n", strerror(abs(err)) );
+ fprintf( stderr, "error: netlink(%d); %s\n", err, strerror(abs(err)) );
return 0;
syntax_error: