Module: xenomai-head
Branch: master
Commit: f8d1a994d59736dcc941843dbebf9b2e36b61eb1
URL:    
http://git.xenomai.org/?p=xenomai-head.git;a=commit;h=f8d1a994d59736dcc941843dbebf9b2e36b61eb1

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Sep  8 15:17:35 2009 +0200

rtipc/iddp: introduce IDDP_SETLABEL

---

 examples/rtdm/profiles/ipc/Makefile        |    2 +-
 examples/rtdm/profiles/ipc/iddp-label.c    |  240 ++++++++++++++++++++++++++++
 examples/rtdm/profiles/ipc/iddp-sendrecv.c |    2 +-
 examples/rtdm/profiles/ipc/xddp-label.c    |   34 ++--
 include/rtdm/rtipc.h                       |    3 +
 ksrc/drivers/ipc/iddp.c                    |  182 ++++++++++++++++++----
 ksrc/drivers/ipc/internal.h                |    3 +
 ksrc/drivers/ipc/rtipc.c                   |    9 +
 ksrc/drivers/ipc/xddp.c                    |   13 +--
 9 files changed, 430 insertions(+), 58 deletions(-)

diff --git a/examples/rtdm/profiles/ipc/Makefile 
b/examples/rtdm/profiles/ipc/Makefile
index 3905229..a44959c 100644
--- a/examples/rtdm/profiles/ipc/Makefile
+++ b/examples/rtdm/profiles/ipc/Makefile
@@ -1,7 +1,7 @@
 ###### CONFIGURATION ######
 
 ### List of applications to be built
-APPLICATIONS = xddp-echo xddp-label xddp-stream iddp-sendrecv
+APPLICATIONS = xddp-echo xddp-label xddp-stream iddp-sendrecv iddp-label
 
 ### Note: to override the search path for the xeno-config script, use "make 
XENO=..."
 
diff --git a/examples/rtdm/profiles/ipc/iddp-label.c 
b/examples/rtdm/profiles/ipc/iddp-label.c
new file mode 100644
index 0000000..e11f450
--- /dev/null
+++ b/examples/rtdm/profiles/ipc/iddp-label.c
@@ -0,0 +1,240 @@
+/*
+ * IDDP-based client/server demo, using the write(2)/recvfrom(2)
+ * system calls to exchange data.
+ *
+ * In this example, two sockets are created.  A server thread (reader)
+ * is bound to a labeled real-time port and receives datagrams sent to
+ * this port from a client thread (writer). The client thread attaches
+ * to the port opened by the server using a labeled connection
+ * request. The client socket is bound to a different port, only to
+ * provide a valid peer name; this is optional.
+ *
+ * ASCII labels can be attached to bound ports, in order to connect
+ * sockets to them in a more descriptive way than using plain numeric
+ * port values.
+ *
+ * See Makefile in this directory for build directives.
+ */
+#include <sys/mman.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <pthread.h>
+#include <errno.h>
+#include <rtdk.h>
+#include <rtdm/rtipc.h>
+
+pthread_t svtid, cltid;
+
+#define IDDP_SVPORT 12
+#define IDDP_CLPORT 13
+
+#define IDDP_PORT_LABEL  "iddp-demo"
+
+static const char *msg[] = {
+    "Surfing With The Alien",
+    "Lords of Karma",
+    "Banana Mango",
+    "Psycho Monkey",
+    "Luminous Flesh Giants",
+    "Moroccan Sunset",
+    "Satch Boogie",
+    "Flying In A Blue Dream",
+    "Ride",
+    "Summer Song",
+    "Speed Of Light",
+    "Crystal Planet",
+    "Raspberry Jam Delta-V",
+    "Champagne?",
+    "Clouds Race Across The Sky",
+    "Engines Of Creation"
+};
+
+static void fail(const char *reason)
+{
+       perror(reason);
+       exit(EXIT_FAILURE);
+}
+
+void *server(void *arg)
+{
+       struct sockaddr_ipc saddr, claddr;
+       char label[IDDP_LABEL_LEN];
+       socklen_t addrlen;
+       char buf[128];
+       int ret, s;
+
+       s = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_IDDP);
+       if (s < 0)
+               fail("socket");
+
+       /*
+        * We will use Xenomai's system heap for datagram, so no
+        * IDDP_SETLOCALPOOL required here.
+        */
+
+       /*
+        * Set a port label. This name will be registered when
+        * binding, in addition to the port number (if given).
+        */
+       strcpy(label, IDDP_PORT_LABEL);
+       ret = setsockopt(s, SOL_RTIPC, IDDP_SETLABEL,
+                        label, sizeof(label));
+       if (ret)
+               fail("setsockopt");
+
+       /*
+        * Bind the socket to the port. Assign that port a label, so
+        * that peers may use a descriptive information to locate
+        * it. Labeled ports will appear in the
+        * /proc/xenomai/registry/rtipc/iddp directory once the socket
+        * is bound.
+        */
+       saddr.sipc_family = AF_RTIPC;
+       saddr.sipc_port = IDDP_SVPORT;
+       ret = bind(s, (struct sockaddr *)&saddr, sizeof(saddr));
+       if (ret)
+               fail("bind");
+
+       for (;;) {
+               addrlen = sizeof(saddr);
+               ret = recvfrom(s, buf, sizeof(buf), 0,
+                              (struct sockaddr *)&claddr, &addrlen);
+               if (ret < 0) {
+                       close(s);
+                       fail("recvfrom");
+               }
+               rt_printf("%s: received %d bytes, \"%.*s\" from port %d\n",
+                         __FUNCTION__, ret, ret, buf, claddr.sipc_port);
+       }
+
+       return NULL;
+}
+
+void *client(void *arg)
+{
+       struct sockaddr_ipc svsaddr, clsaddr;
+       char label[IDDP_LABEL_LEN];
+       int ret, s, n = 0, len;
+       struct timespec ts;
+       char buf[128];
+
+       s = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_IDDP);
+       if (s < 0)
+               fail("socket");
+
+       /*
+        * Set a name on the client socket. This is strictly optional,
+        * and only done here for the purpose of getting back a
+        * different port number in recvfrom().
+        */
+       clsaddr.sipc_family = AF_RTIPC;
+       clsaddr.sipc_port = IDDP_CLPORT;
+       ret = bind(s, (struct sockaddr *)&clsaddr, sizeof(clsaddr));
+       if (ret)
+               fail("bind");
+
+       /*
+        * Set the port label. This name will be used to find the peer
+        * when connecting, instead of the port number. The label must
+        * be set _after_ the socket is bound to the port, so that
+        * IDDP does not try to register this label for the client
+        * port as well (like the server thread did).
+        */
+       strcpy(label, IDDP_PORT_LABEL);
+       ret = setsockopt(s, SOL_RTIPC, IDDP_SETLABEL,
+                        label, sizeof(label));
+       if (ret)
+               fail("setsockopt");
+
+       memset(&svsaddr, 0, sizeof(svsaddr));
+       svsaddr.sipc_family = AF_RTIPC;
+       svsaddr.sipc_port = -1; /* Tell IDDP to search by label. */
+       ret = connect(s, (struct sockaddr *)&svsaddr, sizeof(svsaddr));
+       if (ret)
+               fail("connect");
+
+       for (;;) {
+               len = strlen(msg[n]);
+               /* Send to default destination we connected to. */
+               ret = write(s, msg[n], len);
+               if (ret < 0) {
+                       close(s);
+                       fail("sendto");
+               }
+               rt_printf("%s: sent %d bytes, \"%.*s\"\n",
+                         __FUNCTION__, ret, ret, msg[n]);
+               n = (n + 1) % (sizeof(msg) / sizeof(msg[0]));
+               /*
+                * We run in full real-time mode (i.e. primary mode),
+                * so we have to let the system breathe between two
+                * iterations.
+                */
+               ts.tv_sec = 0;
+               ts.tv_nsec = 500000000; /* 500 ms */
+               clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL);
+       }
+
+       return NULL;
+}
+
+void cleanup_upon_sig(int sig)
+{
+       pthread_cancel(svtid);
+       pthread_cancel(cltid);
+       signal(sig, SIG_DFL);
+       pthread_join(svtid, NULL);
+       pthread_join(cltid, NULL);
+}
+
+int main(int argc, char **argv)
+{
+       struct sched_param svparam = {.sched_priority = 71 };
+       struct sched_param clparam = {.sched_priority = 70 };
+       pthread_attr_t svattr, clattr;
+       sigset_t mask, oldmask;
+
+       mlockall(MCL_CURRENT | MCL_FUTURE);
+
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGINT);
+       signal(SIGINT, cleanup_upon_sig);
+       sigaddset(&mask, SIGTERM);
+       signal(SIGTERM, cleanup_upon_sig);
+       sigaddset(&mask, SIGHUP);
+       signal(SIGHUP, cleanup_upon_sig);
+       pthread_sigmask(SIG_BLOCK, &mask, &oldmask);
+
+       /*
+        * This is a real-time compatible printf() package from
+        * Xenomai's RT Development Kit (RTDK), that does NOT cause
+        * any transition to secondary mode.
+        */
+       rt_print_auto_init(1);
+
+       pthread_attr_init(&svattr);
+       pthread_attr_setdetachstate(&svattr, PTHREAD_CREATE_JOINABLE);
+       pthread_attr_setinheritsched(&svattr, PTHREAD_EXPLICIT_SCHED);
+       pthread_attr_setschedpolicy(&svattr, SCHED_FIFO);
+       pthread_attr_setschedparam(&svattr, &svparam);
+
+       errno = pthread_create(&svtid, &svattr, &server, NULL);
+       if (errno)
+               fail("pthread_create");
+
+       pthread_attr_init(&clattr);
+       pthread_attr_setdetachstate(&clattr, PTHREAD_CREATE_JOINABLE);
+       pthread_attr_setinheritsched(&clattr, PTHREAD_EXPLICIT_SCHED);
+       pthread_attr_setschedpolicy(&clattr, SCHED_FIFO);
+       pthread_attr_setschedparam(&clattr, &clparam);
+
+       errno = pthread_create(&cltid, &clattr, &client, NULL);
+       if (errno)
+               fail("pthread_create");
+
+       sigsuspend(&oldmask);
+
+       return 0;
+}
diff --git a/examples/rtdm/profiles/ipc/iddp-sendrecv.c 
b/examples/rtdm/profiles/ipc/iddp-sendrecv.c
index 78ae564..00c8dbb 100644
--- a/examples/rtdm/profiles/ipc/iddp-sendrecv.c
+++ b/examples/rtdm/profiles/ipc/iddp-sendrecv.c
@@ -110,7 +110,7 @@ void *client(void *arg)
        clsaddr.sipc_port = IDDP_CLPORT;
        ret = bind(s, (struct sockaddr *)&clsaddr, sizeof(clsaddr));
        if (ret)
-               fail("connect");
+               fail("bind");
 
        svsaddr.sipc_family = AF_RTIPC;
        svsaddr.sipc_port = IDDP_SVPORT;
diff --git a/examples/rtdm/profiles/ipc/xddp-label.c 
b/examples/rtdm/profiles/ipc/xddp-label.c
index 337566c..859baa0 100644
--- a/examples/rtdm/profiles/ipc/xddp-label.c
+++ b/examples/rtdm/profiles/ipc/xddp-label.c
@@ -31,20 +31,20 @@
  *
  * The example code below illustrates the following process:
  *
- * realtime_thread1----------------------------->-------+
- *   =>  get socket                                     |
- *   =>  bind socket to port "demo"                     |
- *   =>  read traffic from NRT domain via recvfrom() <--+--+
- *                                                      |  |
- * realtime_thread2-------------------------------------+  |
- *   =>  get socket                                     |  |
- *   =>  connect socket to port "demo"                  |  |
- *   =>  write traffic to NRT domain via sendto()       v  |
- *                                                      |  ^
- * regular_thread---------------------------------------+  |
- *   =>  open /proc/xenomai/registry/rtdm/xddp/demo     |  |
- *   =>  read traffic from RT domain via read()         |  |
- *   =>  mirror traffic to RT domain via write()        +--+
+ * realtime_thread1----------------------------->----------+
+ *   =>  get socket                                        |
+ *   =>  bind socket to port "xddp-demo                    |
+ *   =>  read traffic from NRT domain via recvfrom()    <--+--+
+ *                                                         |  |
+ * realtime_thread2----------------------------------------+  |
+ *   =>  get socket                                        |  |
+ *   =>  connect socket to port "xddp-demo"                |  |
+ *   =>  write traffic to NRT domain via sendto()          v  |
+ *                                                         |  ^
+ * regular_thread------------------------------------------+  |
+ *   =>  open /proc/xenomai/registry/rtipc/xddp/xddp-demo  |  |
+ *   =>  read traffic from RT domain via read()            |  |
+ *   =>  mirror traffic to RT domain via write()           +--+
  *
  * See Makefile in this directory for build directives.
  *
@@ -65,7 +65,7 @@
 
 pthread_t rt1, rt2, nrt;
 
-#define XDDP_PORT_LABEL  "demo"
+#define XDDP_PORT_LABEL  "xddp-demo"
 
 static const char *msg[] = {
     "Surfing With The Alien",
@@ -125,7 +125,7 @@ void *realtime_thread1(void *arg)
         * so that peers may use a descriptive information to locate
         * it. For instance, the pseudo-device matching our RT
         * endpoint will appear as
-        * /proc/xenomai/registry/rtdm/xddp/<XDDP_PORT_LABEL> in the
+        * /proc/xenomai/registry/rtipc/xddp/<XDDP_PORT_LABEL> in the
         * Linux domain, once the socket is bound.
         *
         * saddr.sipc_port specifies the port number to use. If -1 is
@@ -245,7 +245,7 @@ void *regular_thread(void *arg)
        int fd, ret;
 
        if (asprintf(&devname,
-                    "/proc/xenomai/registry/rtdm/xddp/%s",
+                    "/proc/xenomai/registry/rtipc/xddp/%s",
                     XDDP_PORT_LABEL) < 0)
                fail("asprintf");
 
diff --git a/include/rtdm/rtipc.h b/include/rtdm/rtipc.h
index 5be0483..091ea5c 100644
--- a/include/rtdm/rtipc.h
+++ b/include/rtdm/rtipc.h
@@ -85,8 +85,11 @@ enum {
 #define XDDP_GETLABEL          5
 #define IDDP_SETLOCALPOOL      6
 #define IDDP_GETSTALLCOUNT     7
+#define IDDP_SETLABEL          8
+#define IDDP_GETLABEL          9
 
 #define XDDP_LABEL_LEN         XNOBJECT_NAME_LEN
+#define IDDP_LABEL_LEN         XNOBJECT_NAME_LEN
 
  /*
   * Valid port ranges:
diff --git a/ksrc/drivers/ipc/iddp.c b/ksrc/drivers/ipc/iddp.c
index 8e547fc..b37872e 100644
--- a/ksrc/drivers/ipc/iddp.c
+++ b/ksrc/drivers/ipc/iddp.c
@@ -28,6 +28,8 @@
 
 #define trace(m,a...) printk(KERN_WARNING "%s: " m "\n", __FUNCTION__, ##a)
 
+#define IDDP_SOCKET_MAGIC 0xa37a37a8
+
 struct iddp_message {
        struct list_head next;
        int from;
@@ -37,6 +39,7 @@ struct iddp_message {
 };
 
 struct iddp_socket {
+       int magic;
        struct sockaddr_ipc name;
        struct sockaddr_ipc peer;
 
@@ -50,6 +53,8 @@ struct iddp_socket {
        rtdm_sem_t insem;
        struct list_head inq;
        u_long status;
+       xnhandle_t handle;
+       char label[IDDP_LABEL_LEN];
 
        nanosecs_rel_t rx_timeout;
        nanosecs_rel_t tx_timeout;
@@ -72,6 +77,33 @@ static int poolwait;
 #define MAX_IOV_NUMBER  64
 
 #define _IDDP_BINDING  0
+#define _IDDP_BOUND    1
+
+#ifdef CONFIG_PROC_FS
+
+static ssize_t __iddp_link_proc(char *buf, int count, void *data)
+{
+       struct iddp_socket *sk = data;
+       return snprintf(buf, count, "%d", sk->name.sipc_port);
+}
+
+static struct xnpnode __iddp_pnode = {
+
+       .dir = NULL,
+       .type = "iddp",
+       .entries = 0,
+       .link_proc = &__iddp_link_proc,
+       .root = &rtipc_ptree,
+};
+
+#else /* !CONFIG_PROC_FS */
+
+static struct xnpnode __iddp_pnode = {
+
+       .type = "iddp"
+};
+
+#endif /* !CONFIG_PROC_FS */
 
 static inline void __iddp_init_mbuf(struct iddp_message *mbuf, size_t len)
 {
@@ -152,7 +184,7 @@ static int iddp_socket(struct rtipc_private *priv,
 {
        struct iddp_socket *sk = priv->state;
 
-       rtdm_sem_init(&sk->insem, 0);
+       sk->magic = IDDP_SOCKET_MAGIC;
        sk->name = nullsa;      /* Unbound */
        sk->peer = nullsa;
        sk->bufpool = &kheap;
@@ -163,7 +195,9 @@ static int iddp_socket(struct rtipc_private *priv,
        sk->rx_timeout = RTDM_TIMEOUT_INFINITE;
        sk->tx_timeout = RTDM_TIMEOUT_INFINITE;
        sk->stalls = 0;
+       *sk->label = 0;
        INIT_LIST_HEAD(&sk->inq);
+       rtdm_sem_init(&sk->insem, 0);
        sk->priv = priv;
 
        return 0;
@@ -183,6 +217,9 @@ static int iddp_close(struct rtipc_private *priv,
 
        rtdm_sem_destroy(&sk->insem);
 
+       if (sk->handle)
+               xnregistry_remove(sk->handle);
+
        if (sk->bufpool != &kheap) {
                xnheap_destroy(&sk->privpool, __iddp_flush_pool, NULL);
                return 0;
@@ -210,6 +247,9 @@ static ssize_t __iddp_recvmsg(struct rtipc_private *priv,
        struct iddp_message *mbuf;
        nanosecs_rel_t timeout;
 
+       if (!test_bit(_IDDP_BOUND, &sk->status))
+               return -EAGAIN;
+
        /* Compute available iovec space to maxlen. */
        for (maxlen = 0, nvec = 0; nvec < iovlen; nvec++) {
                ssize_t l = iov[nvec].iov_len;
@@ -486,20 +526,20 @@ static int __iddp_bind_socket(struct iddp_socket *sk,
        size_t poolsz;
        int ret = 0;
 
-       if (sa == NULL) {
-               sa = &nullsa;
-               goto set_binding;
-       }
-
        if (sa->sipc_family != AF_RTIPC)
                return -EINVAL;
 
-       if (sa->sipc_port < -1 ||
+       if (sa->sipc_port < 0 ||
            sa->sipc_port >= CONFIG_XENO_OPT_IDDP_NRPORT)
                return -EINVAL;
 
-       if (test_and_set_bit(_IDDP_BINDING, &sk->status))
-               return -EINPROGRESS;
+       RTDM_EXECUTE_ATOMICALLY(
+               if (test_bit(_IDDP_BOUND, &sk->status) ||
+                   __test_and_set_bit(_IDDP_BINDING, &sk->status))
+                       ret = -EADDRINUSE;
+       );
+       if (ret)
+               return ret;
 
        /*
         * Allocate a local buffer pool if we were told to do so via
@@ -511,41 +551,55 @@ static int __iddp_bind_socket(struct iddp_socket *sk,
                poolmem = xnarch_alloc_host_mem(poolsz);
                if (poolmem == NULL) {
                        ret = -ENOMEM;
-                       goto out;
+                       goto fail;
                }
 
                ret = xnheap_init(&sk->privpool,
                                  poolmem, poolsz, XNHEAP_PAGE_SIZE);
                if (ret) {
                        xnarch_free_host_mem(poolmem, poolsz);
-                       goto out;
+                       goto fail;
                }
 
-               RTDM_EXECUTE_ATOMICALLY(
-                       sk->poolevt = &sk->privevt;
-                       sk->poolwait = &sk->privwait;
-                       sk->bufpool = &sk->privpool;
-               );
+               sk->poolevt = &sk->privevt;
+               sk->poolwait = &sk->privwait;
+               sk->bufpool = &sk->privpool;
+       }
+
+       sk->name = *sa;
+       /* Set default destination if unset at binding time. */
+       if (sk->peer.sipc_port < 0)
+               sk->peer = *sa;
+
+       if (*sk->label) {
+               ret = xnregistry_enter(sk->label, sk,
+                                      &sk->handle, &__iddp_pnode);
+               if (ret) {
+                       if (poolsz > 0)
+                               xnheap_destroy(&sk->privpool,
+                                              __iddp_flush_pool, NULL);
+                       return ret;
+               }
        }
 
- set_binding:
        RTDM_EXECUTE_ATOMICALLY(
-               if (sk->name.sipc_port >= 0) /* Clear previous binding. */
-                       portmap[sk->name.sipc_port] = NULL;
-               if (sa->sipc_port >= 0) /* Set next binding. */
-                       portmap[sa->sipc_port] = sk;
-               sk->name = *sa;
+               portmap[sa->sipc_port] = sk;
+               __clear_bit(_IDDP_BINDING, &sk->status);
+               __set_bit(_IDDP_BOUND, &sk->status);
        );
 
-out:
+       return 0;
+fail:
        clear_bit(_IDDP_BINDING, &sk->status);
-
+       
        return ret;
 }
 
 static int __iddp_connect_socket(struct iddp_socket *sk,
                                 struct sockaddr_ipc *sa)
 {
+       struct iddp_socket *rsk;
+       xnhandle_t h;
        int ret;
 
        if (sa == NULL) {
@@ -559,12 +613,48 @@ static int __iddp_connect_socket(struct iddp_socket *sk,
        if (sa->sipc_port < -1 ||
            sa->sipc_port >= CONFIG_XENO_OPT_IDDP_NRPORT)
                return -EINVAL;
+       /*
+        * - If a valid sipc_port is passed in the [0..NRPORT-1] range,
+        * it is used verbatim and the connection succeeds
+        * immediately, regardless of whether the destination is
+        * bound at the time of the call.
+        *
+        * - If sipc_port is -1 and a label was set via IDDP_SETLABEL,
+        * connect() blocks for the requested amount of time until a
+        * socket is bound to the same label, unless the internal
+        * timeout (see SO_RCVTIMEO) specifies a non-blocking
+        * operation (RTDM_TIMEOUT_NONE).
+        *
+        * - If sipc_port is -1 and no label is given, the default
+        * destination address is cleared, meaning that any subsequent
+        * write() to the socket will return -EDESTADDRREQ, until a
+        * valid destination address is set via connect() or bind().
+        *
+        * - In all other cases, -EINVAL is returned.
+        */
+       if (sa->sipc_port < 0 && *sk->label) {
+               ret = xnregistry_bind(sk->label,
+                                     sk->rx_timeout, XN_RELATIVE, &h);
+               if (ret)
+                       return ret;
+
+               RTDM_EXECUTE_ATOMICALLY(
+                       rsk = xnregistry_fetch(h);
+                       if (rsk == NULL || rsk->magic != IDDP_SOCKET_MAGIC)
+                               ret = -EINVAL;
+                       else
+                               /* Fetch labeled port number. */
+                               sa->sipc_port = rsk->name.sipc_port;
+               );
+               if (ret)
+                       return ret;
+       }
 
 set_assoc:
-       ret = __iddp_bind_socket(sk, sa); /* Set listening port. */
-       if (ret)
-               return ret;
        RTDM_EXECUTE_ATOMICALLY(
+               if (!test_bit(_IDDP_BOUND, &sk->status))
+                       /* Set default name. */
+                       sk->name = *sa;
                /* Set default destination. */
                sk->peer = *sa;
        );
@@ -631,6 +721,7 @@ static int __iddp_setsockopt(struct iddp_socket *sk,
                             void *arg)
 {
        struct _rtdm_setsockopt_args sopt;
+       char label[IDDP_LABEL_LEN];
        struct timeval tv;
        int ret = 0;
        size_t len;
@@ -684,8 +775,8 @@ static int __iddp_setsockopt(struct iddp_socket *sk,
                         * We may not do this more than once, and we
                         * have to do this before the first binding.
                         */
-                       if (test_bit(_IDDP_BINDING, &sk->status) ||
-                           sk->bufpool != &kheap)
+                       if (test_bit(_IDDP_BOUND, &sk->status) ||
+                           test_bit(_IDDP_BINDING, &sk->status))
                                ret = -EALREADY;
                        else
                                sk->poolsz = len;
@@ -698,6 +789,26 @@ static int __iddp_setsockopt(struct iddp_socket *sk,
                        return -EFAULT;
                break;
 
+       case IDDP_SETLABEL:
+               if (sopt.optlen < sizeof(label))
+                       return -EINVAL;
+               if (rtipc_get_arg(user_info, label,
+                                 sopt.optval, sizeof(label) - 1))
+                       return -EFAULT;
+               RTDM_EXECUTE_ATOMICALLY(
+                       /*
+                        * We may attach a label to a client socket
+                        * which was previously bound in IDDP.
+                        */
+                       if (test_bit(_IDDP_BINDING, &sk->status))
+                               ret = -EALREADY;
+                       else {
+                               strcpy(sk->label, label);
+                               sk->label[IDDP_LABEL_LEN-1] = 0;
+                       }
+               );
+               break;
+
        default:
                ret = -EINVAL;
        }
@@ -710,6 +821,7 @@ static int __iddp_getsockopt(struct iddp_socket *sk,
                             void *arg)
 {
        struct _rtdm_getsockopt_args sopt;
+       char label[IDDP_LABEL_LEN];
        struct timeval tv;
        socklen_t len;
        int ret = 0;
@@ -761,6 +873,16 @@ static int __iddp_getsockopt(struct iddp_socket *sk,
                        return -EFAULT;
                break;
 
+       case IDDP_GETLABEL:
+               if (len < sizeof(label))
+                       return -EINVAL;
+               RTDM_EXECUTE_ATOMICALLY(
+                       strcpy(label, sk->label);
+               );
+               if (rtipc_put_arg(user_info, sopt.optval,
+                                 label, sizeof(label)))
+                       return -EFAULT;
+               break;
 
        default:
                ret = -EINVAL;
@@ -835,6 +957,8 @@ static int iddp_ioctl(struct rtipc_private *priv,
        ret = __iddp_getuser_address(user_info, arg, &saddrp);
        if (ret)
                return ret;
+       if (saddrp == NULL)
+               return -EFAULT;
 
        return __iddp_bind_socket(sk, saddrp);
 }
diff --git a/ksrc/drivers/ipc/internal.h b/ksrc/drivers/ipc/internal.h
index 732501c..a30f5b9 100644
--- a/ksrc/drivers/ipc/internal.h
+++ b/ksrc/drivers/ipc/internal.h
@@ -21,6 +21,7 @@
 #ifndef _RTIPC_INTERNAL_H
 #define _RTIPC_INTERNAL_H
 
+#include <nucleus/registry.h>
 #include <rtdm/rtdm.h>
 #include <rtdm/rtdm_driver.h>
 
@@ -81,6 +82,8 @@ extern struct rtipc_protocol xddp_proto_driver;
 
 extern struct rtipc_protocol iddp_proto_driver;
 
+extern struct xnptree rtipc_ptree;
+
 int rtipc_get_arg(rtdm_user_info_t *user_info,
                  void *dst, const void *src, size_t len);
 
diff --git a/ksrc/drivers/ipc/rtipc.c b/ksrc/drivers/ipc/rtipc.c
index e2de49d..ea1d6ea 100644
--- a/ksrc/drivers/ipc/rtipc.c
+++ b/ksrc/drivers/ipc/rtipc.c
@@ -32,6 +32,15 @@ static struct rtipc_protocol *protocols[IPCPROTO_MAX] = {
 #endif
 };
 
+#ifdef CONFIG_PROC_FS
+struct xnptree rtipc_ptree = {
+
+       .dir = NULL,
+       .name = "rtipc",
+       .entries = 0,
+};
+#endif /* CONFIG_PROC_FS */
+
 int rtipc_get_arg(rtdm_user_info_t *user_info,
                  void *dst, const void *src, size_t len)
 {
diff --git a/ksrc/drivers/ipc/xddp.c b/ksrc/drivers/ipc/xddp.c
index 494d823..26170e0 100644
--- a/ksrc/drivers/ipc/xddp.c
+++ b/ksrc/drivers/ipc/xddp.c
@@ -23,7 +23,6 @@
 #include <nucleus/heap.h>
 #include <nucleus/bufd.h>
 #include <nucleus/pipe.h>
-#include <nucleus/registry.h>
 #include <rtdm/rtipc.h>
 #include "internal.h"
 
@@ -76,30 +75,24 @@ static struct xddp_socket 
*portmap[CONFIG_XENO_OPT_PIPE_NRDEV];
 
 #ifdef CONFIG_PROC_FS
 
-static xnptree_t __xddp_ptree = {
-       .dir = NULL,
-       .name = "rtdm",
-       .entries = 0,
-};
-
 static ssize_t __xddp_link_proc(char *buf, int count, void *data)
 {
        struct xddp_socket *sk = data;
        return snprintf(buf, count, "/dev/rtp%d", sk->minor);
 }
 
-static xnpnode_t __xddp_pnode = {
+static struct xnpnode __xddp_pnode = {
 
        .dir = NULL,
        .type = "xddp",
        .entries = 0,
        .link_proc = &__xddp_link_proc,
-       .root = &__xddp_ptree,
+       .root = &rtipc_ptree,
 };
 
 #else /* !CONFIG_PROC_FS */
 
-static xnpnode_t __xddp_pnode = {
+static struct xnpnode __xddp_pnode = {
 
        .type = "xddp"
 };


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to