]> rtime.felk.cvut.cz Git - can-eth-gw.git/commitdiff
switch to rtmsg, cegw --flush implemented
authorRadek Matejka <radek.matejka@gmail.com>
Sat, 28 Jul 2012 17:54:01 +0000 (19:54 +0200)
committerRadek Matejka <radek.matejka@gmail.com>
Sat, 28 Jul 2012 17:54:01 +0000 (19:54 +0200)
kernel/canethgw.c
kernel/canethgw.h
utils/cegw/cegw.c

index 88f2614e935f251fc2669c20f45e5c147ee61f17..02aa60afe6cea7b0abce0a15f4d641b749a47494 100644 (file)
@@ -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, &eth_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 );
 }
index cfcd1b69770b17bdd7fcfcb89550988332cf6d5f..d8743d67b09efb86c26e16e3928bae5500a58ac1 100644 (file)
@@ -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 */
index efbe2c775bcc4e1dd711d6535199a1fa1a4a14fc..f47418b559f80e33a1c0b91bcf1d533dc4e6fc5c 100644 (file)
@@ -12,6 +12,7 @@
 #include <arpa/inet.h>
 #include <linux/can.h>
 #include <linux/types.h>
+#include <unistd.h>
 #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: