[gssdp/wip/ipv6: 6/7] wip: Add pktinfo handling for ipv6



commit 48af1f1378283c015342d43713c261bf74a64ade
Author: Jens Georg <mail jensge org>
Date:   Thu Feb 18 10:47:36 2016 +0100

    wip: Add pktinfo handling for ipv6
    
    Signed-off-by: Jens Georg <mail jensge org>

 libgssdp/Makefile.am              |    5 +-
 libgssdp/gssdp-pktinfo6-message.c |  219 +++++++++++++++++++++++++++++++++++++
 libgssdp/gssdp-pktinfo6-message.h |   74 +++++++++++++
 libgssdp/gssdp-socket-functions.c |    9 ++
 4 files changed, 306 insertions(+), 1 deletions(-)
---
diff --git a/libgssdp/Makefile.am b/libgssdp/Makefile.am
index 7674d42..77f2f99 100644
--- a/libgssdp/Makefile.am
+++ b/libgssdp/Makefile.am
@@ -49,8 +49,11 @@ libgssdp_1_0_la_SOURCES = $(introspection_sources)   \
                          $(BUILT_SOURCES)
 
 if HAVE_PKTINFO
+AM_CFLAGS += "-D_GNU_SOURCE"
 libgssdp_1_0_la_SOURCES += gssdp-pktinfo-message.c \
-                                                  gssdp-pktinfo-message.h
+                          gssdp-pktinfo-message.h \
+                          gssdp-pktinfo6-message.c \
+                          gssdp-pktinfo6-message.h
 endif
 
 libgssdp_1_0_la_LIBADD = $(LIBGSSDP_LIBS)
diff --git a/libgssdp/gssdp-pktinfo6-message.c b/libgssdp/gssdp-pktinfo6-message.c
new file mode 100644
index 0000000..fefd267
--- /dev/null
+++ b/libgssdp/gssdp-pktinfo6-message.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2014 Jens Georg.
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <sys/socket.h>
+#include <netinet/ip.h>
+
+#include "gssdp-pktinfo6-message.h"
+
+G_DEFINE_TYPE (GSSDPPktinfo6Message,
+               gssdp_pktinfo6_message,
+               G_TYPE_SOCKET_CONTROL_MESSAGE)
+
+struct _GSSDPPktinfo6MessagePrivate
+{
+        GInetAddress *iface_addr;
+        gint          index;
+};
+
+enum {
+        PROP_0,
+        PROP_IFACE_ADDR,
+        PROP_INDEX
+};
+
+static gsize
+gssdp_pktinfo6_message_get_size (GSocketControlMessage *msg)
+{
+    return sizeof (struct in6_pktinfo);
+}
+
+static int
+gssdp_pktinfo6_message_get_level (GSocketControlMessage *msg)
+{
+        return IPPROTO_IPV6;
+}
+
+static int
+gssdp_pktinfo6_message_get_msg_type (GSocketControlMessage *msg)
+{
+        return IPV6_PKTINFO;
+}
+
+static void
+gssdp_pktinfo6_message_get_property (GObject    *object,
+                                    guint       property_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+        GSSDPPktinfo6Message *self;
+
+        self = GSSDP_PKTINFO6_MESSAGE (object);
+        switch (property_id)
+        {
+        case PROP_IFACE_ADDR:
+                g_value_set_object (value, self->priv->iface_addr);
+                break;
+        case PROP_INDEX:
+                g_value_set_int (value, self->priv->index);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+                break;
+        }
+}
+
+static void
+gssdp_pktinfo6_message_set_property (GObject      *object,
+                                    guint         property_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+        GSSDPPktinfo6Message *self;
+
+        self = GSSDP_PKTINFO6_MESSAGE (object);
+        switch (property_id)
+        {
+        case PROP_IFACE_ADDR:
+                self->priv->iface_addr = g_value_get_object (value);
+                break;
+        case PROP_INDEX:
+                self->priv->index = g_value_get_int (value);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+                break;
+        }
+}
+
+static void
+gssdp_pktinfo6_dispose (GObject *object)
+{
+        GSSDPPktinfo6Message *self = GSSDP_PKTINFO6_MESSAGE (object);
+
+        g_clear_object (&self->priv->iface_addr);
+}
+
+static GSocketControlMessage *
+gssdp_pktinfo6_message_deserialize (int      level,
+                                   int      type,
+                                   gsize    size,
+                                   gpointer data)
+{
+        GSocketControlMessage *message;
+        GInetAddress *addr;
+        struct in6_pktinfo *info = (struct in6_pktinfo *) data;
+        const guint8 *bytes;
+
+        if (level != IPPROTO_IPV6 || type != IPV6_PKTINFO)
+                return NULL;
+
+        bytes = (const guint8 *)&(info->ipi6_addr);
+        addr = g_inet_address_new_from_bytes (bytes, G_SOCKET_FAMILY_IPV6);
+
+        message = gssdp_pktinfo6_message_new (addr, info->ipi6_ifindex);
+
+        return message;
+}
+
+static void
+gssdp_pktinfo6_message_init (GSSDPPktinfo6Message *self)
+{
+        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                                  GSSDP_TYPE_PKTINFO6_MESSAGE,
+                                                  GSSDPPktinfo6MessagePrivate);
+}
+
+static void
+gssdp_pktinfo6_message_class_init (GSSDPPktinfo6MessageClass *klass)
+{
+        GSocketControlMessageClass *scm_class =
+                G_SOCKET_CONTROL_MESSAGE_CLASS (klass);
+
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        g_type_class_add_private (klass, sizeof (GSSDPPktinfo6MessagePrivate));
+
+        scm_class->get_size = gssdp_pktinfo6_message_get_size;
+        scm_class->get_level = gssdp_pktinfo6_message_get_level;
+        scm_class->get_type = gssdp_pktinfo6_message_get_msg_type;
+        scm_class->deserialize = gssdp_pktinfo6_message_deserialize;
+
+        object_class->get_property = gssdp_pktinfo6_message_get_property;
+        object_class->set_property = gssdp_pktinfo6_message_set_property;
+        object_class->dispose = gssdp_pktinfo6_dispose;
+
+        g_object_class_install_property
+                (object_class,
+                 PROP_IFACE_ADDR,
+                 g_param_spec_object ("iface-address",
+                                      "iface-address",
+                                      "IP v4 Address of the interface this packet was received on",
+                                      G_TYPE_INET_ADDRESS,
+                                      G_PARAM_READWRITE |
+                                      G_PARAM_CONSTRUCT |
+                                      G_PARAM_STATIC_STRINGS));
+
+        g_object_class_install_property
+                (object_class,
+                 PROP_INDEX,
+                 g_param_spec_int ("index",
+                                    "index",
+                                    "Network interface index",
+                                    0,
+                                    G_MAXINT,
+                                    0,
+                                    G_PARAM_READWRITE |
+                                    G_PARAM_CONSTRUCT |
+                                    G_PARAM_STATIC_STRINGS));
+
+}
+
+GSocketControlMessage *
+gssdp_pktinfo6_message_new (GInetAddress *addr, gint ifindex)
+{
+        GSSDPPktinfo6Message *msg;
+
+        msg = GSSDP_PKTINFO6_MESSAGE (
+                g_object_new (GSSDP_TYPE_PKTINFO6_MESSAGE,
+                              "iface-address", addr,
+                              "index", ifindex,
+                              NULL));
+
+        return G_SOCKET_CONTROL_MESSAGE (msg);
+}
+
+gint
+gssdp_pktinfo6_message_get_ifindex (GSSDPPktinfo6Message *message)
+{
+        g_return_val_if_fail (GSSDP_IS_PKTINFO6_MESSAGE (message), -1);
+
+        return message->priv->index;
+}
+
+GInetAddress *
+gssdp_pktinfo6_message_get_local_addr (GSSDPPktinfo6Message *message)
+{
+        g_return_val_if_fail (GSSDP_IS_PKTINFO6_MESSAGE (message), NULL);
+
+        return message->priv->iface_addr;
+}
+
diff --git a/libgssdp/gssdp-pktinfo6-message.h b/libgssdp/gssdp-pktinfo6-message.h
new file mode 100644
index 0000000..50ab0f2
--- /dev/null
+++ b/libgssdp/gssdp-pktinfo6-message.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 Jens Georg <mail jensge org>
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GSSDP_PKTINFO6_MESSAGE_H__
+#define __GSSDP_PKTINFO6_MESSAGE_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL GType
+gssdp_pktinfo6_message_get_type (void) G_GNUC_CONST;
+
+#define GSSDP_TYPE_PKTINFO6_MESSAGE (gssdp_pktinfo6_message_get_type())
+#define GSSDP_PKTINFO6_MESSAGE(obj) \
+                            (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                             GSSDP_TYPE_PKTINFO6_MESSAGE, \
+                             GSSDPPktinfo6Message))
+#define GSSDP_PKTINFO6_MESAGE_CLASS(klass) \
+                            (G_TYPE_CHECK_CLASS_CAST ((klass), \
+                             GSSDP_TYPE_PKTINFO6_MESSAGE, \
+                             GSSDPPktinfo6Class))
+#define GSSDP_IS_PKTINFO6_MESSAGE(obj) \
+                            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                             GSSDP_TYPE_PKTINFO6_MESSAGE))
+#define GSSDP_IS_PKTINFO6_MESSAGE_CLASS(klass) \
+                            (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+                             GSSDP_TYPE_PKTINFO6_MESSAGE))
+#define GSSDP_PKTINFO6_MESSAGE_GET_CLASS(obj) \
+                            (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                             GSSDP_TYPE_PKTINFO6_MESSAGE, \
+                             GSSDPPktinfo6MessageClass))
+
+typedef struct _GSSDPPktinfo6MessagePrivate GSSDPPktinfo6MessagePrivate;
+typedef struct _GSSDPPktInfo6Message GSSDPPktinfo6Message;
+typedef struct _GSSDPPktinfo6MessageClass GSSDPPktinfo6MessageClass;
+
+struct _GSSDPPktInfo6Message {
+        GSocketControlMessage parent;
+        GSSDPPktinfo6MessagePrivate *priv;
+};
+
+struct _GSSDPPktinfo6MessageClass {
+        GSocketControlMessageClass parent_class;
+};
+
+G_GNUC_INTERNAL GSocketControlMessage *
+gssdp_pktinfo6_message_new (GInetAddress *addr, gint ifindex);
+
+G_GNUC_INTERNAL gint
+gssdp_pktinfo6_message_get_ifindex (GSSDPPktinfo6Message *message);
+
+G_GNUC_INTERNAL GInetAddress *
+gssdp_pktinfo6_message_get_local_addr (GSSDPPktinfo6Message *message);
+
+#endif /* __GSSDP_PKTINFO6_MESSAGE_H__ */
diff --git a/libgssdp/gssdp-socket-functions.c b/libgssdp/gssdp-socket-functions.c
index 70b3566..f93dd5b 100644
--- a/libgssdp/gssdp-socket-functions.c
+++ b/libgssdp/gssdp-socket-functions.c
@@ -39,6 +39,7 @@
 #include "gssdp-error.h"
 #include "gssdp-socket-functions.h"
 #include "gssdp-pktinfo-message.h"
+#include "gssdp-pktinfo6-message.h"
 
 static char*
 gssdp_socket_error_message (int error) {
@@ -154,6 +155,14 @@ gssdp_socket_enable_info         (GSocket *socket,
         /* Register the type so g_socket_control_message_deserialize() will
          * find it */
         g_object_unref (g_object_new (GSSDP_TYPE_PKTINFO_MESSAGE, NULL));
+        g_object_unref (g_object_new (GSSDP_TYPE_PKTINFO6_MESSAGE, NULL));
+
+        gssdp_socket_option_set (socket,
+                                 IPPROTO_IPV6,
+                                 IPV6_RECVPKTINFO,
+                                 (char *)&enable,
+                                 sizeof (enable),
+                                 error);
 
         return gssdp_socket_option_set (socket,
                                         IPPROTO_IP,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]