]> rtime.felk.cvut.cz Git - can-eth-gw.git/blobdiff - kernel/canethgw.c
Sending socket fd over netlink
[can-eth-gw.git] / kernel / canethgw.c
index 36c38be89f4e5e66db19c2b83345614c2736707a..601ea7771bd77a46e9477756c1d85d163c71743e 100644 (file)
@@ -31,6 +31,9 @@ static void cegw_can_send(struct socket *can_sock, struct can_frame *cf,
 static int cegw_thread_start(void *data);
 static int cegw_thread_stop(void);
 
+static int cegw_thread_recv_udp(void *data);
+static int cegw_thread_recv_can(void *data);
+
 enum __cegw_state {
        CEGW_RUN,
        CEGW_STOP,
@@ -52,6 +55,7 @@ struct cegw_setting {
 
 static int cegw_state = CEGW_STOP;
 static struct socket *can_sock = NULL, *udp_sock = NULL;
+static struct socket *s_can = NULL, *s_eth = NULL; 
 static struct task_struct *eth_to_can = NULL, *can_to_eth = NULL;
 static struct notifier_block notifier;
 
@@ -205,6 +209,7 @@ static int cegw_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        unsigned short port;
        struct cegw_setting* set;
        int err = 0;
+       int fd_eth, fd_can;
 
        if (nlmsg_len(nlh) < sizeof(*r))
                return -EINVAL;
@@ -220,11 +225,36 @@ static int cegw_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                return err;
        }
 
+       fd_eth = *(int*)nla_data(tb[CEGW_ETH_SOCK]);
+       fd_can = *(int*)nla_data(tb[CEGW_CAN_SOCK]);
+
+       printk( "cegw: sock=%i,%i\n", fd_eth, fd_can );
+
+       s_can = sockfd_lookup( fd_can, &err );
+       s_eth = sockfd_lookup( fd_eth, &err );
+
+       if( s_can == NULL || s_eth == NULL )
+       {
+               printk( "error: socket look-up failed\n" );
+               return 0;
+       }
+
+       struct can_frame greet;
+       greet.can_id = 0;
+       greet.can_dlc = 4;
+       greet.data[0] = 7;
+
+       //cegw_can_send( s_can, &greet, *(int*)nla_data(tb[CEGW_CAN_IFINDEX]) );
+       kthread_run(cegw_thread_recv_udp, NULL, "canethgw");
+       kthread_run(cegw_thread_recv_can, NULL, "canethgw");
+       /*
        if (tb[CEGW_CMD_INFO] == NULL) {
                pr_devel("canethgw: CEGW_CMD_INFO is missing in rtmsg\n");
                return -EINVAL;
        }
+       */
 
+       return 0;
        switch (*(int*)nla_data(tb[CEGW_CMD_INFO])) {
        case CEGW_LISTEN:
                if (!tb[CEGW_ETH_IP] || !tb[CEGW_ETH_PORT]) {
@@ -466,97 +496,68 @@ static int cegw_notifier(struct notifier_block *nb, unsigned long msg, void *dat
        return NOTIFY_DONE;
 }
 
-/**
- * cegw_thread_start - start working threads
- * @data: (struct cegw_setting *) with new listening address
- *
- * Two threads are started. One is serving udp->can routing and the other
- * can->udp.
- */
-static int cegw_thread_start(void *data)
+static int cegw_thread_recv_udp(void *data)
 {
-       struct sockaddr_in udp_addr;
-       struct sockaddr_can can_addr;
-       struct cegw_setting *set;
-
-       set = (struct cegw_setting *)data;
-
-       can_addr.can_family = AF_CAN;
-       can_addr.can_ifindex = 0;
+       struct can_frame cf;
+       struct kvec vec;
+       struct msghdr mh;
+       struct sockaddr_in sa;
+       struct hlist_node* pos;
+       int can_ifidx;
+       int recv_size;
 
-       udp_addr.sin_family = AF_INET;
-       udp_addr.sin_port = htons(set->eth_port);
-       udp_addr.sin_addr = set->eth_ip;
+       memset(&mh, 0, sizeof(mh));
+       mh.msg_name = &sa;
+       mh.msg_namelen = sizeof(sa);
+       mh.msg_control = NULL;
+       mh.msg_controllen = 0;
+       mh.msg_flags = 0;
 
-       kfree(data);
-       mutex_lock(&cegw_mutex);
-       if (cegw_state == CEGW_EXIT)
-               goto out_err;
+       printk( "udp receiving\n" );
 
-       /* stops threads if exist */
-       cegw_thread_stop();
+       while( 1 )
+       {
+               vec.iov_base = &cf;
+               vec.iov_len = sizeof(cf);
 
-       /* create and bind sockets */
-       if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &udp_sock)
-           != 0) {
-               printk(KERN_ERR "canethgw: udp socket creation failed\n");
-               goto out_err;
+               recv_size = kernel_recvmsg(s_eth, &mh, &vec, 1,
+                               sizeof(cf), 0);
+               printk("udp status=%i\n", recv_size);
        }
 
-       if (sock_create_kern(PF_CAN, SOCK_RAW, CAN_RAW, &can_sock) != 0) {
-               printk(KERN_ERR "canethgw: can socket creation failed\n");
-               sock_release(udp_sock);
-               goto out_err;
-       }
+       return 0;
+}
 
-       if (kernel_bind(udp_sock, (struct sockaddr*)&udp_addr,
-                       sizeof(udp_addr)) != 0) {
-               printk(KERN_ERR "canethgw: udp socket binding failed\n");
-               sock_release(udp_sock);
-               sock_release(can_sock);
-               goto out_err;
-       }
+static int cegw_thread_recv_can(void *data)
+{
+       struct can_frame cf;
+       struct kvec vec;
+       struct msghdr mh;
+       struct sockaddr_can ca;
+       struct hlist_node* pos;
+       int can_ifidx;
+       int recv_size;
 
-       if (kernel_bind(can_sock, (struct sockaddr*) &can_addr,
-                       sizeof(can_addr)) != 0) {
-               printk(KERN_ERR "canethgw: can socket binding failed\n");
-               kernel_sock_shutdown(udp_sock, SHUT_RDWR);
-               sock_release(udp_sock);
-               sock_release(can_sock);
-               goto out_err;
-       }
+       memset(&mh, 0, sizeof(mh));
+       mh.msg_name = &ca;
+       mh.msg_namelen = sizeof(ca);
+       mh.msg_control = NULL;
+       mh.msg_controllen = 0;
+       mh.msg_flags = 0;
 
-       /* start threads */
-       cegw_state = CEGW_RUN;
+       printk( "can receiving\n" );
 
-       eth_to_can = kthread_create(cegw_udp2can, NULL, "canethgw");
-       if (IS_ERR(eth_to_can)) {
-               cegw_state = CEGW_STOP;
-               sock_release(udp_sock);
-               sock_release(can_sock);
-               goto out_err;
-       }
-       get_task_struct(eth_to_can);
-       wake_up_process(eth_to_can);
-
-       can_to_eth = kthread_create(cegw_can2udp, NULL, "canethgw");
-       if (IS_ERR(can_to_eth)) {
-               cegw_state = CEGW_STOP;
-               kernel_sock_shutdown(udp_sock, SHUT_RDWR);
-               kthread_stop(eth_to_can);
-               sock_release(udp_sock);
-               sock_release(can_sock);
-               goto out_err;
+       while( 1 )
+       {
+               vec.iov_base = &cf;
+               vec.iov_len = sizeof(cf);
+
+               recv_size = kernel_recvmsg(s_can, &mh, &vec, 1,
+                               sizeof(cf), 0);
+               printk("can status=%i\n", recv_size);
        }
-       get_task_struct(can_to_eth);
-       wake_up_process(can_to_eth);
 
-       mutex_unlock(&cegw_mutex);
-       pr_devel("threads are running\n");
        return 0;
-out_err:
-       mutex_unlock(&cegw_mutex);
-       return -1;
 }
 
 /**