From: Radek Matejka Date: Sat, 28 Jul 2012 17:54:01 +0000 (+0200) Subject: switch to rtmsg, cegw --flush implemented X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-eth-gw.git/commitdiff_plain/b4cc9d051cafe859b023bae6252b14bbc2bf425e switch to rtmsg, cegw --flush implemented --- diff --git a/kernel/canethgw.c b/kernel/canethgw.c index 88f2614..02aa60a 100644 --- a/kernel/canethgw.c +++ b/kernel/canethgw.c @@ -197,28 +197,33 @@ inline static void gw_can_send( struct can_frame* cf, int ifidx ) 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; @@ -260,23 +265,48 @@ static int cegw_create_job( struct sk_buff* skb, struct nlmsghdr* nlh, void* arg 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; } @@ -376,7 +406,8 @@ static void __exit cangw_exit( void ) /* ToDo: stop threads */ } - /* ToDo: unregister netlink */ + /* ToDo: unregister netlink + * free jobs */ printk( "cangw: exit\n" ); //kthread_stop( ts ); } diff --git a/kernel/canethgw.h b/kernel/canethgw.h index cfcd1b6..d8743d6 100644 --- a/kernel/canethgw.h +++ b/kernel/canethgw.h @@ -18,15 +18,14 @@ enum { CGW_TYPE_ETH_CAN_UDP, /* ETH->CAN udp */ CGW_TYPE_CAN_ETH_TCP, CGW_TYPE_CONFIG, + CEGW_FLUSH, + CEGW_LISTEN, __CGW_TYPE_MAX }; -enum { - CEGW_FLUSH -}; - #define CGW_TYPE_MAX (__CGW_TYPE_MAX - 1) +/* rtnetlink attributes */ enum { CGW_UNSPEC, CGW_MOD_AND, /* CAN frame modification binary AND */ @@ -40,6 +39,7 @@ enum { CGW_CAN_IF, /* ifindex of source network interface */ CGW_LISTEN_IP, CGW_LISTEN_PORT, + CGW_CMD_INFO, CGW_ETH_IP, CGW_ETH_PORT, CGW_ETH_PROTO, /* ifindex of destination network interface */ diff --git a/utils/cegw/cegw.c b/utils/cegw/cegw.c index efbe2c7..f47418b 100644 --- a/utils/cegw/cegw.c +++ b/utils/cegw/cegw.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "canethgw.h" /** @@ -49,8 +50,8 @@ struct cegw_data 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; @@ -182,6 +183,8 @@ int read_if( char* in, int* iftype, struct cegw_data* d ) 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) ) { @@ -195,9 +198,10 @@ inline static int cegw_add( struct cegw_nlmsg* req, struct cegw_data* d ) 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) ); @@ -209,15 +213,17 @@ inline static int cegw_add( struct cegw_nlmsg* req, struct cegw_data* d ) 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; @@ -230,9 +236,13 @@ inline static int cegw_list( struct cegw_nlmsg* req, struct cegw_data* d ) 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; } @@ -247,11 +257,13 @@ int main( int argc, char* argv[] ) 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[] = @@ -322,14 +334,17 @@ int main( int argc, char* argv[] ) } /* 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 ) { @@ -362,12 +377,13 @@ int main( int argc, char* argv[] ) 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; @@ -383,13 +399,13 @@ int main( int argc, char* argv[] ) 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: