chiark / gitweb /
netlink: Avoid crash with clientless netlink
[secnet.git] / netlink.c
index af6434feb9002c12a938a2d2923d2f92ea8b9c53..6384c02220720721d9f8a123e83d976a0e21c9ac 100644 (file)
--- a/netlink.c
+++ b/netlink.c
@@ -409,6 +409,28 @@ static bool_t netlink_check(struct netlink *st, struct buffer_if *buf,
 #undef BAD
 }
 
+/* Deliver a packet _to_ client; used after we have decided
+ * what to do with it (and just to check that the client has
+ * actually registered a delivery function with us). */
+static void netlink_client_deliver(struct netlink *st,
+                                  struct netlink_client *client,
+                                  uint32_t source, uint32_t dest,
+                                  struct buffer_if *buf)
+{
+    if (!client->deliver) {
+       string_t s,d;
+       s=ipaddr_to_string(source);
+       d=ipaddr_to_string(dest);
+       Message(M_ERR,"%s: dropping %s->%s, client not registered\n",
+               st->name,s,d);
+       free(s); free(d);
+       BUF_FREE(buf);
+       return;
+    }
+    client->deliver(client->dst, buf);
+    client->outcount++;
+}
+
 /* Deliver a packet. "client" is the _origin_ of the packet, not its
    destination, and is NULL for packets from the host and packets
    generated internally in secnet.  */
@@ -521,9 +543,8 @@ static void netlink_packet_deliver(struct netlink *st,
        } else {
            if (best_quality>0) {
                /* XXX Fragment if required */
-               st->routes[best_match]->deliver(
-                   st->routes[best_match]->dst, buf);
-               st->routes[best_match]->outcount++;
+               netlink_client_deliver(st,st->routes[best_match],
+                                      source,dest,buf);
                BUF_ASSERT_FREE(buf);
            } else {
                /* Generate ICMP destination unreachable */
@@ -678,7 +699,7 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client,
        if (client) {
            st->deliver_to_host(st->dst,buf);
        } else {
-           st->clients->deliver(st->clients->dst,buf);
+           netlink_client_deliver(st,st->clients,source,dest,buf);
        }
        BUF_ASSERT_FREE(buf);
        return;