Hi,

with your comments, I have produceds a second version of the patch,
which includes the following changes:

On Sun, 11.04.2010 at 20:47:38 +0200, Toni Mueller <openbsd-t...@oeko.net> 
wrote:
> * No IPv6 support (I have no clue).

* tried to add IPv6 support

* Logging is still not very useful, but at least it does now use
  syslog's log() instead of stdio's printf().

The patch applies to /usr/src/sys/net. I have it running on one of my
machines, and intend to deploy it on others as well.

Comments and improvements are MUCH appreciated!

-- 
Kind regards,
--Toni++


Index: pfkeyv2.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.c,v
retrieving revision 1.119
diff -u -r1.119 pfkeyv2.c
--- pfkeyv2.c   9 May 2008 15:48:15 -0000       1.119
+++ pfkeyv2.c   12 Apr 2010 11:40:59 -0000
@@ -78,6 +78,7 @@
 #include <sys/kernel.h>
 #include <sys/proc.h>
 #include <sys/pool.h>
+#include <sys/syslog.h>
 #include <net/route.h>
 #include <netinet/ip_ipsp.h>
 #include <net/pfkeyv2.h>
@@ -131,6 +132,148 @@
 
 extern struct pool ipsec_policy_pool;
 
+
+/*
+ * DEBUGGING FUNCTIONS
+ */
+
+#define ON_PFKEY_DEBUG 1
+
+#ifdef ON_PFKEY_DEBUG
+
+/* Here are the prototypes for these purely internal functions: */
+
+int on_pfkey_check_tdb(struct tdb *, const char *);
+void on_pfkey_print_sadb_msg(struct sadb_msg *, const char *);
+
+int on_pfkey_check_flow(struct sockaddr_encap *, struct sockaddr_encap *);
+void on_pfkey_log_errors(struct sadb_msg *);
+
+
+/*
+ * on_pfkey_check_flow()
+ *
+ * Checks for the flows for occurrences of "0/0 -> 0/0".
+ *
+ * Return values:
+ * 0: ok
+ * 1: illegal flow detected
+ *
+ * Should be "bool" instead of "int" if we had it...
+ */
+
+int
+on_pfkey_check_flow(struct sockaddr_encap *flow, struct sockaddr_encap 
*flowmask)
+{
+       int rval = 0;
+
+       switch (flow->sen_type) {
+       case SENT_IP6:
+               if (IN6_IS_ADDR_UNSPECIFIED(&(flow->Sen.Sip6.Src))
+                   && IN6_IS_ADDR_UNSPECIFIED(&(flow->Sen.Sip6.Src))
+                   && IN6_IS_ADDR_UNSPECIFIED(&(flowmask->Sen.Sip6.Src))
+                   && IN6_IS_ADDR_UNSPECIFIED(&(flowmask->Sen.Sip6.Src)))
+                       rval = 1;
+               break;
+       case SENT_IP4:
+               if (   flow->Sen.Sip4.Src.s_addr == INADDR_ANY
+                   && flow->Sen.Sip4.Src.s_addr == INADDR_ANY
+                   && flowmask->Sen.Sip4.Src.s_addr == INADDR_ANY
+                   && flowmask->Sen.Sip4.Src.s_addr == INADDR_ANY)
+                       rval = 1;
+
+               break;
+       }
+       return rval;
+}
+
+void on_pfkey_log_errors(struct sadb_msg *smsg)
+{
+       /* Improve on that ASAP: */
+       log(LOG_WARNING, "Illegal flow detected in message %016lx\n", smsg);
+}
+
+
+/*
+ * int on_pfkey_check_tdb(tdb *newsa, const char *f)
+ *
+ * This function is intended to check for source and destination
+ * addresses of flows being zero. This leaves to complete loss of
+ * connectivity.
+ *
+ * The function generates log entries for things it deems dubious.
+ *
+ * Input parameters:
+ * newsa - the to-be new SA
+ * f - a label, may be NULL, used for log entries
+ *
+ * Return value:
+ * 0: newsa is ok
+ * 1: otherwise
+ */
+
+
+int
+on_pfkey_check_tdb(struct tdb *newsa, const char *f) {
+       char *label = "on_pfkey_check_tdb";
+       union sockaddr_union *src, *dst, *proxy;
+
+       char s_addr[INET6_ADDRSTRLEN];
+       char d_addr[INET6_ADDRSTRLEN];
+       char p_addr[INET6_ADDRSTRLEN];
+
+       if (f && *f)    /* label passed */
+           label = (char *)f;
+
+       /* So far, only print all stuff, do nothing: */
+       src = &newsa->tdb_src;
+       dst = &newsa->tdb_dst;
+       proxy = &newsa->tdb_proxy;
+
+       log(LOG_DEBUG, "on_pfkey_check_tdb(tdb at %0lx) families: src=%d, 
dst=%d, proxy=%d\n", 
+               newsa,
+               src->sa.sa_family,
+               dst->sa.sa_family,
+               proxy->sa.sa_family);
+
+       strncpy(s_addr, inet_ntoa(src->sin.sin_addr), INET6_ADDRSTRLEN);
+       strncpy(d_addr, inet_ntoa(dst->sin.sin_addr), INET6_ADDRSTRLEN);
+       strncpy(p_addr, inet_ntoa(proxy->sin.sin_addr), INET6_ADDRSTRLEN);
+
+       log(LOG_DEBUG,
+           "on_pfkey_check_tdb(tdb at %016lx) addresses: src=%s (%08lx), 
dst=%s (%08lx), proxy=%s (%08lx)\n", 
+           newsa,
+           s_addr, src->sin.sin_addr,
+           d_addr, dst->sin.sin_addr,
+           p_addr, proxy->sin.sin_addr);
+
+       return on_pfkey_check_flow(&newsa->tdb_filter, &newsa->tdb_filtermask);
+}
+
+
+
+void
+on_pfkey_print_sadb_msg(struct sadb_msg *m, const char *f) {
+       char *label = "on_pfkey_print_sadb_msg";
+
+       if (f && *f)    /* label passed */
+           label = (char *)f;
+
+       log(LOG_DEBUG,
+           "%s(): received message: sadb_msg { version: %u, type: %u, errno: 
%u, satype: %u, len: %u, reserved: %u, seq: %u, pid: %u }\n",
+           label,
+           m->sadb_msg_version,
+           m->sadb_msg_type,
+           m->sadb_msg_errno,
+           m->sadb_msg_satype,
+           m->sadb_msg_len,
+           m->sadb_msg_reserved,
+           m->sadb_msg_seq,
+           m->sadb_msg_pid);
+}
+
+#endif
+
 /*
  * Wrapper around m_devget(); copy data from contiguous buffer to mbuf
  * chain.
@@ -855,9 +998,10 @@
        bzero(headers, sizeof(headers));
 
        for (pfkeyv2_socket = pfkeyv2_sockets; pfkeyv2_socket;
-           pfkeyv2_socket = pfkeyv2_socket->next)
+           pfkeyv2_socket = pfkeyv2_socket->next) {
                if (pfkeyv2_socket->socket == socket)
                        break;
+       }
 
        if (!pfkeyv2_socket) {
                rval = EINVAL;
@@ -910,6 +1054,17 @@
                goto ret;
 
        smsg = (struct sadb_msg *) headers[0];
+
+       /*
+        * At this point, we can check the addresses passed in this message, and
+        * bail out if they are both zero. We do it after parsing the message to
+        * be sure to not access invalid data.
+        */
+
+#ifdef ON_PFKEY_DEBUG
+       on_pfkey_print_sadb_msg(smsg, "pfkeyv2.c:pfkeyv2_send");
+#endif
+
        switch (smsg->sadb_msg_type) {
        case SADB_GETSPI:  /* Reserve an SPI */
                bzero(&sa, sizeof(struct tdb));
@@ -1055,6 +1210,16 @@
                        import_tag(newsa, headers[SADB_X_EXT_TAG]);
 #endif
 
+#ifdef ON_PFKEY_DEBUG
+                       /* Check for illegal parameters and conditionally 
generate an error message: */
+                       rval = on_pfkey_check_tdb(newsa, 
"pfkeyv2.c:pfkeyv2_send SADB_UPDATE");
+                       if (rval) {
+                               rval = EINVAL;
+                               freeme = NULL;
+                               goto splxret;
+                       }
+#endif
+
                        headers[SADB_EXT_KEY_AUTH] = NULL;
                        headers[SADB_EXT_KEY_ENCRYPT] = NULL;
                        headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
@@ -1220,6 +1385,15 @@
 #if NPF > 0
                        import_tag(newsa, headers[SADB_X_EXT_TAG]);
 #endif
+#ifdef ON_PFKEY_DEBUG
+                       /* Check for illegal parameters and conditionally 
generate an error message: */
+                       rval = on_pfkey_check_tdb(newsa, 
"pfkeyv2.c:pfkeyv2_send SADB_UPDATE");
+                       if (rval) {
+                               rval = EINVAL;
+                               freeme = NULL;
+                               goto splxret;
+                       }
+#endif
 
                        headers[SADB_EXT_KEY_AUTH] = NULL;
                        headers[SADB_EXT_KEY_ENCRYPT] = NULL;
@@ -1521,11 +1695,28 @@
                else
                        ssrc = NULL;
 
+
+
                import_flow(&encapdst, &encapnetmask,
                    headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
                    headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
                    headers[SADB_X_EXT_PROTOCOL], 
headers[SADB_X_EXT_FLOW_TYPE]);
 
+#ifdef ON_PFKEY_DEBUG
+               /*
+                * Now check for illegal flows, containing zero source and 
destination
+                * addresses.
+                *
+                * Where is the information to generate useful log messages, 
ie, who
+                * actually tried to create the illegal flow, so we can go 
after him?
+                */
+
+               if (on_pfkey_check_flow(&encapdst, &encapnetmask)) {
+                       on_pfkey_log_errors(smsg);
+                       rval = EINVAL;
+                       break;
+               }
+#endif
                /* Determine whether the exact same SPD entry already exists. */
                bzero(&encapgw, sizeof(struct sockaddr_encap));
                bzero(&re, sizeof(struct route_enc));
Index: pfkeyv2_convert.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2_convert.c,v
retrieving revision 1.31
diff -u -r1.31 pfkeyv2_convert.c
--- pfkeyv2_convert.c   22 Oct 2008 23:04:45 -0000      1.31
+++ pfkeyv2_convert.c   12 Apr 2010 11:40:59 -0000
@@ -99,6 +99,7 @@
 #include <sys/mbuf.h>
 #include <sys/kernel.h>
 #include <sys/socket.h>
+#include <sys/syslog.h>
 #include <net/route.h>
 #include <net/if.h>
 
@@ -459,8 +460,16 @@
         */
        if ((src->sa.sa_family != dst->sa.sa_family) ||
            (src->sa.sa_family != srcmask->sa.sa_family) ||
-           (src->sa.sa_family != dstmask->sa.sa_family))
+           (src->sa.sa_family != dstmask->sa.sa_family)) {
+               /*
+                * Be sure to *really* bail out and generate a better error
+                * message in pfkeyv2_send()!
+                */
+               log(LOG_ERR, "import_flow: mixed address families %d %d %d 
%d!\n",
+                       src->sa.sa_family, srcmask->sa.sa_family,
+                       dst->sa.sa_family, dstmask->sa.sa_family);
                return;
+       }
 
        /*
         * We set these as an indication that tdb_filter/tdb_filtermask are

Reply via email to