]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
dnstap io, move control frame ready, accept and log to dnstap_fstrm code.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 18 Feb 2020 16:04:08 +0000 (17:04 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Tue, 18 Feb 2020 16:04:08 +0000 (17:04 +0100)
dnstap/dnstap_fstrm.c
dnstap/dnstap_fstrm.h
dnstap/unbound-dnstap-socket.c

index be4acace8e488d1ca8082699a6aa7b1e733183a3..aac98e567103bf186d5b4a8b21a4110979dc45af 100644 (file)
@@ -43,6 +43,7 @@
 
 #include "config.h"
 #include "dnstap/dnstap_fstrm.h"
+#include "sldns/sbuffer.h"
 
 void* fstrm_create_control_frame_start(char* contenttype, size_t* len)
 {
@@ -89,3 +90,114 @@ void* fstrm_create_control_frame_stop(size_t* len)
        *len = n;
        return control;
 }
+
+void* fstrm_create_control_frame_accept(char* contenttype, size_t* len)
+{
+       uint32_t* control;
+       size_t n;
+       /* control frame on reply:
+        * 4 bytes 0 escape
+        * 4 bytes bigendian length of frame
+        * 4 bytes bigendian type ACCEPT
+        * 4 bytes bigendian frame option content type
+        * 4 bytes bigendian length of string
+        * string of content type.
+        */
+       /* len includes the escape and framelength */
+       n = 4+4+4+4+4+strlen(contenttype);
+       control = malloc(n);
+       if(!control) {
+               return NULL;
+       }
+       control[0] = 0;
+       control[1] = htonl(4+4+4+strlen(contenttype));
+       control[2] = htonl(FSTRM_CONTROL_FRAME_ACCEPT);
+       control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE);
+       control[4] = htonl(strlen(contenttype));
+       memmove(&control[5], contenttype, strlen(contenttype));
+       *len = n;
+       return control;
+}
+
+void* fstrm_create_control_frame_finish(size_t* len)
+{
+       uint32_t* control;
+       size_t n;
+       /* control frame on reply:
+        * 4 bytes 0 escape
+        * 4 bytes bigendian length of frame
+        * 4 bytes bigendian type FINISH
+        */
+       /* len includes the escape and framelength */
+       n = 4+4+4;
+       control = malloc(n);
+       if(!control) {
+               return NULL;
+       }
+       control[0] = 0;
+       control[1] = htonl(4);
+       control[2] = htonl(FSTRM_CONTROL_FRAME_FINISH);
+       *len = n;
+       return control;
+}
+
+char* fstrm_describe_control(void* pkt, size_t len)
+{
+       uint32_t frametype = 0;
+       char buf[512];
+       size_t at = 0, remain;
+       uint8_t* pos;
+
+       buf[0]=0;
+       if(len < 4) {
+               snprintf(buf, sizeof(buf), "malformed control frame, "
+                       "too short, len=%u", (unsigned int)len);
+               return strdup(buf);
+       }
+       frametype = sldns_read_uint32(pkt);
+       if(frametype == FSTRM_CONTROL_FRAME_ACCEPT) {
+               at+=snprintf(buf+at, sizeof(buf)-at, "accept");
+       } else if(frametype == FSTRM_CONTROL_FRAME_START) {
+               at+=snprintf(buf+at, sizeof(buf)-at, "start");
+       } else if(frametype == FSTRM_CONTROL_FRAME_STOP) {
+               at+=snprintf(buf+at, sizeof(buf)-at, "stop");
+       } else if(frametype == FSTRM_CONTROL_FRAME_READY) {
+               at+=snprintf(buf+at, sizeof(buf)-at, "ready");
+       } else if(frametype == FSTRM_CONTROL_FRAME_FINISH) {
+               at+=snprintf(buf+at, sizeof(buf)-at, "finish");
+       } else {
+               at+=snprintf(buf+at, sizeof(buf)-at, "type%d",
+                       (int)frametype);
+       }
+
+       /* show the content type options */
+       pos = pkt + 4;
+       remain = len - 4;
+       while(remain >= 8) {
+               uint32_t field_type = sldns_read_uint32(pos);
+               uint32_t field_len = sldns_read_uint32(pos+4);
+               if(remain < field_len) {
+                       at+=snprintf(buf+at, sizeof(buf)-at, "malformed_field");
+                       break;
+               }
+               if(field_type == FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE) {
+                       at+=snprintf(buf+at, sizeof(buf)-at, " content-type(");
+                       if(at+field_len < sizeof(buf)) {
+                               memmove(buf+at, pos+8, field_len);
+                               at += field_len;
+                       }
+                       at+=snprintf(buf+at, sizeof(buf)-at, ")");
+               } else {
+                       at+=snprintf(buf+at, sizeof(buf)-at,
+                               " field(type %u, length %u)",
+                               (unsigned int)field_type,
+                               (unsigned int)field_len);
+               }
+               pos += 8 + field_len;
+               remain -= (8 + field_len);
+       }
+       if(remain > 0)
+               at+=snprintf(buf+at, sizeof(buf)-at, " trailing-bytes"
+                       "(length %u)", (unsigned int)remain);
+       return strdup(buf);
+}
index 3b70547f1de899a76e045ae6631943faa036a31f..f0cf936284ce385907a7c370122d36fd54c476b9 100644 (file)
@@ -139,4 +139,41 @@ void* fstrm_create_control_frame_start(char* contenttype, size_t* len);
  */
 void* fstrm_create_control_frame_stop(size_t* len);
 
+/**
+ * This creates an FSTRM control frame of type ACCEPT.
+ * @param contenttype: a zero delimited string with the content type.
+ *     for dnstap streams use DNSTAP_CONTENT_TYPE.
+ * @param len: if a buffer is returned this is the length of that buffer.
+ * @return NULL on malloc failure.  Returns a malloced buffer with the
+ * protocol message.  The buffer starts with the 4 bytes of 0 that indicate
+ * a control frame.  The buffer should be sent without preceding it with
+ * the 'len' variable (like data frames are), but straight the content of the
+ * buffer, because the lengths are included in the buffer.  This is so that
+ * the zero control indicator can be included before the control frame length.
+ */
+void* fstrm_create_control_frame_accept(char* contenttype, size_t* len);
+
+/**
+ * This creates an FSTRM control frame of type FINISH.
+ * @param len: if a buffer is returned this is the length of that buffer.
+ * @return NULL on malloc failure.  Returns a malloced buffer with the
+ * protocol message.  The buffer starts with the 4 bytes of 0 that indicate
+ * a control frame.  The buffer should be sent without preceding it with
+ * the 'len' variable (like data frames are), but straight the content of the
+ * buffer, because the lengths are included in the buffer.  This is so that
+ * the zero control indicator can be included before the control frame length.
+ */
+void* fstrm_create_control_frame_finish(size_t* len);
+
+/**
+ * Return string that describes a control packet.  For debug, logs.
+ * Like 'start content-type(protobuf:dnstap.Dnstap)' or 'stop'.
+ * @param pkt: the packet data, that is the data after the 4 zero start
+ * bytes and 4 length bytes.
+ * @param len: the length of the control packet data, in pkt.  This is the
+ * ntohl of the 4 bytes length preceding the data.
+ * @return zero delimited string, malloced.  Or NULL on malloc failure.
+ */
+char* fstrm_describe_control(void* pkt, size_t len);
+
 #endif /* DNSTAP_FSTRM_H */
index e26e12ede5d59add227357621ed5455d4e23d797..0605d4d7c7606a3b05dfd92f26c6280803b41fd0 100644 (file)
@@ -409,54 +409,15 @@ static int tap_socket_list_addevs(struct tap_socket_list* list,
 /** log control frame contents */
 static void log_control_frame(uint8_t* pkt, size_t len)
 {
-       uint32_t frametype = 0;
-       char buf[256];
-       size_t at = 0, remain;
-       uint8_t* pos;
+       char* desc;
        if(verbosity == 0) return;
-       if(len < 4) {
-               log_err("malformed control frame, too short, len=%d", (int)len);
+       desc = fstrm_describe_control(pkt, len);
+       if(!desc) {
+               log_err("out of memory");
                return;
        }
-       buf[0]=0;
-       frametype = sldns_read_uint32(pkt);
-       if(frametype == FSTRM_CONTROL_FRAME_ACCEPT) {
-               at+=snprintf(buf+at, sizeof(buf)-at, "accept");
-       } else if(frametype == FSTRM_CONTROL_FRAME_START) {
-               at+=snprintf(buf+at, sizeof(buf)-at, "start");
-       } else if(frametype == FSTRM_CONTROL_FRAME_STOP) {
-               at+=snprintf(buf+at, sizeof(buf)-at, "stop");
-       } else if(frametype == FSTRM_CONTROL_FRAME_READY) {
-               at+=snprintf(buf+at, sizeof(buf)-at, "ready");
-       } else if(frametype == FSTRM_CONTROL_FRAME_FINISH) {
-               at+=snprintf(buf+at, sizeof(buf)-at, "finish");
-       } else {
-               at+=snprintf(buf+at, sizeof(buf)-at, "type%d",
-                       (int)frametype);
-       }
-
-       /* show the content type options */
-       pos = pkt + 4;
-       remain = len - 4;
-       while(remain >= 8) {
-               uint32_t field_type = sldns_read_uint32(pos);
-               uint32_t field_len = sldns_read_uint32(pos+4);
-               if(remain < field_len) {
-                       at+=snprintf(buf+at, sizeof(buf)-at, "malformed_field");
-                       break;
-               }
-               if(field_type == FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE) {
-                       at+=snprintf(buf+at, sizeof(buf)-at, " content-type(");
-                       if(at+field_len < sizeof(buf)) {
-                               memmove(buf+at, pos+8, field_len);
-                               at += field_len;
-                       }
-                       at+=snprintf(buf+at, sizeof(buf)-at, ")");
-               }
-               pos += 8 + field_len;
-               remain -= (8 + field_len);
-       }
-       log_info("control frame %s", buf);
+       log_info("control frame %s", desc);
+       free(desc);
 }
 
 /** convert mtype to string */
@@ -804,32 +765,17 @@ void tap_data_free(struct tap_data* data)
  * returns 0 on error */
 static int reply_with_accept(int fd)
 {
-       /* control frame on reply:
-        * 4 bytes 0 escape
-        * 4 bytes bigendian length of frame
-        * 4 bytes bigendian type ACCEPT
-        * 4 bytes bigendian frame option content type
-        * 4 bytes bigendian length of string
-        * string of content type.
-        */
-       uint32_t* acceptframe;
        /* len includes the escape and framelength */
-       size_t len = 4+4+4+4+4+strlen(DNSTAP_CONTENT_TYPE);
-       acceptframe = calloc(1, len);
+       size_t len = 0;
+       void* acceptframe = fstrm_create_control_frame_accept(
+               DNSTAP_CONTENT_TYPE, &len);
        if(!acceptframe) {
                log_err("out of memory");
                return 0;
        }
-       acceptframe[0] = 0;
-       acceptframe[1] = htonl(4+4+4+strlen(DNSTAP_CONTENT_TYPE));
-       acceptframe[2] = htonl(FSTRM_CONTROL_FRAME_ACCEPT);
-       acceptframe[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE);
-       acceptframe[4] = htonl(strlen(DNSTAP_CONTENT_TYPE));
-       memmove(&acceptframe[5], DNSTAP_CONTENT_TYPE,
-               strlen(DNSTAP_CONTENT_TYPE));
 
        fd_set_block(fd);
-       if(send(fd, (void*)acceptframe, len, 0) == -1) {
+       if(send(fd, acceptframe, len, 0) == -1) {
 #ifndef USE_WINSOCK
                log_err("send failed: %s", strerror(errno));
 #else
@@ -851,31 +797,28 @@ static int reply_with_accept(int fd)
  * returns 0 on error */
 static int reply_with_finish(int fd)
 {
-       /* control frame on reply:
-        * 4 bytes 0 escape
-        * 4 bytes bigendian length of frame
-        * 4 bytes bigendian type FINISH
-        */
-       uint32_t finishframe[3];
-       /* len includes the escape and framelength */
-       size_t len = 4+4+4;
-       finishframe[0] = 0;
-       finishframe[1] = htonl(4);
-       finishframe[2] = htonl(FSTRM_CONTROL_FRAME_FINISH);
+       size_t len = 0;
+       void* finishframe = fstrm_create_control_frame_finish(&len);
+       if(!finishframe) {
+               log_err("out of memory");
+               return 0;
+       }
 
        fd_set_block(fd);
-       if(send(fd, (void*)finishframe, len, 0) == -1) {
+       if(send(fd, finishframe, len, 0) == -1) {
 #ifndef USE_WINSOCK
                log_err("send failed: %s", strerror(errno));
 #else
                log_err("send failed: %s", wsa_strerror(WSAGetLastError()));
 #endif
                fd_set_nonblock(fd);
+               free(finishframe);
                return 0;
        }
        if(verbosity) log_info("sent control frame(finish)");
 
        fd_set_nonblock(fd);
+       free(finishframe);
        return 1;
 }