Tweak packet dump code to make port numbers more accurate.
authorSimon Kelley <simon@thekelleys.org.uk>
Mon, 5 Sep 2022 17:04:35 +0000 (18:04 +0100)
committerSimon Kelley <simon@thekelleys.org.uk>
Mon, 5 Sep 2022 17:04:35 +0000 (18:04 +0100)
Also add query-ids with log-queries=extra.

src/dhcp.c
src/dhcp6.c
src/dnsmasq.h
src/dump.c
src/forward.c
src/radv.c
src/rfc3315.c
src/tftp.c

index 8e9c606..42d819f 100644 (file)
@@ -177,8 +177,7 @@ void dhcp_packet(time_t now, int pxe_fd)
     return;
   
 #ifdef HAVE_DUMPFILE
-  dump_packet(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, NULL,
-             pxe_fd ? PXE_PORT : daemon->dhcp_server_port);
+  dump_packet_udp(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, NULL, fd);
 #endif
   
 #if defined (HAVE_LINUX_NETWORK)
@@ -464,8 +463,8 @@ void dhcp_packet(time_t now, int pxe_fd)
         dest.sin_addr = mess->yiaddr;
       dest.sin_port = htons(daemon->dhcp_client_port);
       
-      dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
-                 (union mysockaddr *)&dest, daemon->dhcp_server_port);
+      dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
+                     (union mysockaddr *)&dest, fd);
 #endif
       
       send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
@@ -478,8 +477,8 @@ void dhcp_packet(time_t now, int pxe_fd)
 #endif
 
 #ifdef HAVE_DUMPFILE
-  dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
-             (union mysockaddr *)&dest, daemon->dhcp_server_port);
+  dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
+                 (union mysockaddr *)&dest, fd);
 #endif
   
   while(retry_send(sendmsg(fd, &msg, 0)));
@@ -1147,8 +1146,8 @@ static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
          fromsock.in.sin_port = htons(daemon->dhcp_server_port);
          fromsock.in.sin_addr = from.addr4;
          fromsock.sa.sa_family = AF_INET;
-         
-         dump_packet(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, 0);
+
+         dump_packet_udp(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, -1);
        }
 #endif
        
index edb87a4..1c8c679 100644 (file)
@@ -119,8 +119,8 @@ void dhcp6_packet(time_t now)
     return;
   
 #ifdef HAVE_DUMPFILE
-  dump_packet(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
-             (union mysockaddr *)&from, NULL, DHCPV6_SERVER_PORT);
+  dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
+                 (union mysockaddr *)&from, NULL, daemon->dhcp6fd);
 #endif
   
   for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
@@ -142,8 +142,8 @@ void dhcp6_packet(time_t now)
   if (relay_reply6(&from, sz, ifr.ifr_name))
     {
 #ifdef HAVE_DUMPFILE
-      dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL,
-                 (union mysockaddr *)&from, DHCPV6_SERVER_PORT);
+      dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL,
+                     (union mysockaddr *)&from, daemon->dhcp6fd);
 #endif
       
       while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, 
@@ -254,8 +254,8 @@ void dhcp6_packet(time_t now)
          from.sin6_port = htons(port);
          
 #ifdef HAVE_DUMPFILE
-         dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
-                     NULL, (union mysockaddr *)&from, DHCPV6_SERVER_PORT);
+         dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
+                         NULL, (union mysockaddr *)&from, daemon->dhcp6fd);
 #endif 
          
          while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
index 990d27f..36d17fe 100644 (file)
@@ -1803,8 +1803,10 @@ int do_arp_script_run(void);
 /* dump.c */
 #ifdef HAVE_DUMPFILE
 void dump_init(void);
-void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src,
-                union mysockaddr *dst, int port);
+void dump_packet_udp(int mask, void *packet, size_t len, union mysockaddr *src,
+                    union mysockaddr *dst, int fd);
+void dump_packet_icmp(int mask, void *packet, size_t len, union mysockaddr *src,
+                     union mysockaddr *dst);
 #endif
 
 /* domain-match.c */
index 7b15945..57352a9 100644 (file)
@@ -21,6 +21,8 @@
 #include <netinet/icmp6.h>
 
 static u32 packet_count;
+static void do_dump_packet(int mask, void *packet, size_t len,
+                          union mysockaddr *src, union mysockaddr *dst, int port, int proto);
 
 /* https://wiki.wireshark.org/Development/LibpcapFileFormat */
 struct pcap_hdr_s {
@@ -81,9 +83,45 @@ void dump_init(void)
     }
 }
 
-/* port == -1 ->ICMPv6 */
-void dump_packet(int mask, void *packet, size_t len,
-                union mysockaddr *src, union mysockaddr *dst, int port)
+void dump_packet_udp(int mask, void *packet, size_t len,
+                    union mysockaddr *src, union mysockaddr *dst, int fd)
+{
+  union mysockaddr fd_addr;
+  socklen_t addr_len = sizeof(fd_addr);
+
+  if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
+     {
+       /* if fd is negative it carries a port number (negated) 
+         which we use as a source or destination when not otherwise
+         specified so wireshark can ID the packet. 
+         If both src and dst are specified, set this to -1 to avoid
+         a spurious getsockname() call. */
+       int port = (fd < 0) ? -fd : -1;
+       
+       /* fd >= 0 is a file descriptor and the address of that file descriptor is used
+         in place of a NULL src or dst. */
+       if (fd >= 0 && getsockname(fd, (struct sockaddr *)&fd_addr, &addr_len) != -1)
+        {
+          if (!src)
+            src = &fd_addr;
+          
+          if (!dst)
+            dst = &fd_addr;
+        }
+       
+       do_dump_packet(mask, packet, len, src, dst, port, IPPROTO_UDP);
+     }
+}
+
+void dump_packet_icmp(int mask, void *packet, size_t len,
+                     union mysockaddr *src, union mysockaddr *dst)
+{
+  if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
+    do_dump_packet(mask, packet, len, src, dst, -1, IPPROTO_ICMP);
+}
+
+static void do_dump_packet(int mask, void *packet, size_t len,
+                          union mysockaddr *src, union mysockaddr *dst, int port, int proto)
 {
   struct ip ip;
   struct ip6_hdr ip6;
@@ -100,13 +138,14 @@ void dump_packet(int mask, void *packet, size_t len,
   void *iphdr;
   size_t ipsz;
   int rc;
+     
+  /* if port != -1 it carries a port number 
+     which we use as a source or destination when not otherwise
+     specified so wireshark can ID the packet. 
+     If both src and dst are specified, set this to -1 to avoid
+     a spurious getsockname() call. */
+  udp.uh_sport = udp.uh_dport = htons(port < 0 ? 0 : port);
   
-  if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
-    return;
-  
-  /* So wireshark can Id the packet. */
-  udp.uh_sport = udp.uh_dport = htons(port);
-
   if (src)
     family = src->sa.sa_family;
   else
@@ -121,15 +160,12 @@ void dump_packet(int mask, void *packet, size_t len,
       ip6.ip6_vfc = 6 << 4;
       ip6.ip6_hops = 64;
 
-      if (port == -1)
-       {
-         ip6.ip6_plen = htons(len);
-         ip6.ip6_nxt = IPPROTO_ICMPV6;
-       }
+      if ((ip6.ip6_nxt = proto) == IPPROTO_UDP)
+       ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
       else
        {
-         ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
-         ip6.ip6_nxt = IPPROTO_UDP;
+         proto = ip6.ip6_nxt = IPPROTO_ICMPV6;
+         ip6.ip6_plen = htons(len);
        }
       
       if (src)
@@ -161,15 +197,12 @@ void dump_packet(int mask, void *packet, size_t len,
       ip.ip_hl = sizeof(struct ip) / 4;
       ip.ip_ttl = IPDEFTTL;
 
-      if (port == -1)
-       {
-         ip.ip_len = htons(sizeof(struct ip) + len);
-         ip.ip_p = IPPROTO_ICMP;
-       }
+      if ((ip.ip_p = proto) == IPPROTO_UDP)
+       ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
       else
        {
-         ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len); 
-         ip.ip_p = IPPROTO_UDP;
+         ip.ip_len = htons(sizeof(struct ip) + len);
+         proto = ip.ip_p = IPPROTO_ICMP;
        }
       
       if (src)
@@ -191,7 +224,7 @@ void dump_packet(int mask, void *packet, size_t len,
        sum = (sum & 0xffff) + (sum >> 16);  
       ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
       
-      /* start UDP checksum */
+      /* start UDP/ICMP checksum */
       sum = ip.ip_src.s_addr & 0xffff;
       sum += (ip.ip_src.s_addr >> 16) & 0xffff;
       sum += ip.ip_dst.s_addr & 0xffff;
@@