Annotation of embedaddon/dnsmasq/src/dump.c, revision 1.1
1.1 ! misho 1: /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
! 2:
! 3: This program is free software; you can redistribute it and/or modify
! 4: it under the terms of the GNU General Public License as published by
! 5: the Free Software Foundation; version 2 dated June, 1991, or
! 6: (at your option) version 3 dated 29 June, 2007.
! 7:
! 8: This program is distributed in the hope that it will be useful,
! 9: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 10: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 11: GNU General Public License for more details.
! 12:
! 13: You should have received a copy of the GNU General Public License
! 14: along with this program. If not, see <http://www.gnu.org/licenses/>.
! 15: */
! 16:
! 17: #include "dnsmasq.h"
! 18:
! 19: #ifdef HAVE_DUMPFILE
! 20:
! 21: static u32 packet_count;
! 22:
! 23: /* https://wiki.wireshark.org/Development/LibpcapFileFormat */
! 24: struct pcap_hdr_s {
! 25: u32 magic_number; /* magic number */
! 26: u16 version_major; /* major version number */
! 27: u16 version_minor; /* minor version number */
! 28: u32 thiszone; /* GMT to local correction */
! 29: u32 sigfigs; /* accuracy of timestamps */
! 30: u32 snaplen; /* max length of captured packets, in octets */
! 31: u32 network; /* data link type */
! 32: };
! 33:
! 34: struct pcaprec_hdr_s {
! 35: u32 ts_sec; /* timestamp seconds */
! 36: u32 ts_usec; /* timestamp microseconds */
! 37: u32 incl_len; /* number of octets of packet saved in file */
! 38: u32 orig_len; /* actual length of packet */
! 39: };
! 40:
! 41:
! 42: void dump_init(void)
! 43: {
! 44: struct stat buf;
! 45: struct pcap_hdr_s header;
! 46: struct pcaprec_hdr_s pcap_header;
! 47:
! 48: packet_count = 0;
! 49:
! 50: if (stat(daemon->dump_file, &buf) == -1)
! 51: {
! 52: /* doesn't exist, create and add header */
! 53: header.magic_number = 0xa1b2c3d4;
! 54: header.version_major = 2;
! 55: header.version_minor = 4;
! 56: header.thiszone = 0;
! 57: header.sigfigs = 0;
! 58: header.snaplen = daemon->edns_pktsz + 200; /* slop for IP/UDP headers */
! 59: header.network = 101; /* DLT_RAW http://www.tcpdump.org/linktypes.html */
! 60:
! 61: if (errno != ENOENT ||
! 62: (daemon->dumpfd = creat(daemon->dump_file, S_IRUSR | S_IWUSR)) == -1 ||
! 63: !read_write(daemon->dumpfd, (void *)&header, sizeof(header), 0))
! 64: die(_("cannot create %s: %s"), daemon->dump_file, EC_FILE);
! 65: }
! 66: else if ((daemon->dumpfd = open(daemon->dump_file, O_APPEND | O_RDWR)) == -1 ||
! 67: !read_write(daemon->dumpfd, (void *)&header, sizeof(header), 1))
! 68: die(_("cannot access %s: %s"), daemon->dump_file, EC_FILE);
! 69: else if (header.magic_number != 0xa1b2c3d4)
! 70: die(_("bad header in %s"), daemon->dump_file, EC_FILE);
! 71: else
! 72: {
! 73: /* count existing records */
! 74: while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 1))
! 75: {
! 76: lseek(daemon->dumpfd, pcap_header.incl_len, SEEK_CUR);
! 77: packet_count++;
! 78: }
! 79: }
! 80: }
! 81:
! 82: void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst)
! 83: {
! 84: struct ip ip;
! 85: struct ip6_hdr ip6;
! 86: int family;
! 87: struct udphdr {
! 88: u16 uh_sport; /* source port */
! 89: u16 uh_dport; /* destination port */
! 90: u16 uh_ulen; /* udp length */
! 91: u16 uh_sum; /* udp checksum */
! 92: } udp;
! 93: struct pcaprec_hdr_s pcap_header;
! 94: struct timeval time;
! 95: u32 i, sum;
! 96: void *iphdr;
! 97: size_t ipsz;
! 98: int rc;
! 99:
! 100: if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
! 101: return;
! 102:
! 103: /* So wireshark can Id the packet. */
! 104: udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT);
! 105:
! 106: if (src)
! 107: family = src->sa.sa_family;
! 108: else
! 109: family = dst->sa.sa_family;
! 110:
! 111: if (family == AF_INET6)
! 112: {
! 113: iphdr = &ip6;
! 114: ipsz = sizeof(ip6);
! 115: memset(&ip6, 0, sizeof(ip6));
! 116:
! 117: ip6.ip6_vfc = 6 << 4;
! 118: ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
! 119: ip6.ip6_nxt = IPPROTO_UDP;
! 120: ip6.ip6_hops = 64;
! 121:
! 122: if (src)
! 123: {
! 124: memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ);
! 125: udp.uh_sport = src->in6.sin6_port;
! 126: }
! 127:
! 128: if (dst)
! 129: {
! 130: memcpy(&ip6.ip6_dst, &dst->in6.sin6_addr, IN6ADDRSZ);
! 131: udp.uh_dport = dst->in6.sin6_port;
! 132: }
! 133:
! 134: /* start UDP checksum */
! 135: for (sum = 0, i = 0; i < IN6ADDRSZ; i+=2)
! 136: {
! 137: sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ;
! 138: sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ;
! 139:
! 140: }
! 141: }
! 142: else
! 143: {
! 144: iphdr = &ip;
! 145: ipsz = sizeof(ip);
! 146: memset(&ip, 0, sizeof(ip));
! 147:
! 148: ip.ip_v = IPVERSION;
! 149: ip.ip_hl = sizeof(struct ip) / 4;
! 150: ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
! 151: ip.ip_ttl = IPDEFTTL;
! 152: ip.ip_p = IPPROTO_UDP;
! 153:
! 154: if (src)
! 155: {
! 156: ip.ip_src = src->in.sin_addr;
! 157: udp.uh_sport = src->in.sin_port;
! 158: }
! 159:
! 160: if (dst)
! 161: {
! 162: ip.ip_dst = dst->in.sin_addr;
! 163: udp.uh_dport = dst->in.sin_port;
! 164: }
! 165:
! 166: ip.ip_sum = 0;
! 167: for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
! 168: sum += ((u16 *)&ip)[i];
! 169: while (sum >> 16)
! 170: sum = (sum & 0xffff) + (sum >> 16);
! 171: ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
! 172:
! 173: /* start UDP checksum */
! 174: sum = ip.ip_src.s_addr & 0xffff;
! 175: sum += (ip.ip_src.s_addr >> 16) & 0xffff;
! 176: sum += ip.ip_dst.s_addr & 0xffff;
! 177: sum += (ip.ip_dst.s_addr >> 16) & 0xffff;
! 178: }
! 179:
! 180: if (len & 1)
! 181: ((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */
! 182:
! 183: udp.uh_sum = 0;
! 184: udp.uh_ulen = htons(sizeof(struct udphdr) + len);
! 185: sum += htons(IPPROTO_UDP);
! 186: sum += htons(sizeof(struct udphdr) + len);
! 187: for (i = 0; i < sizeof(struct udphdr)/2; i++)
! 188: sum += ((u16 *)&udp)[i];
! 189: for (i = 0; i < (len + 1) / 2; i++)
! 190: sum += ((u16 *)packet)[i];
! 191: while (sum >> 16)
! 192: sum = (sum & 0xffff) + (sum >> 16);
! 193: udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
! 194:
! 195: rc = gettimeofday(&time, NULL);
! 196: pcap_header.ts_sec = time.tv_sec;
! 197: pcap_header.ts_usec = time.tv_usec;
! 198: pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
! 199:
! 200: if (rc == -1 ||
! 201: !read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
! 202: !read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
! 203: !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0) ||
! 204: !read_write(daemon->dumpfd, (void *)packet, len, 0))
! 205: my_syslog(LOG_ERR, _("failed to write packet dump"));
! 206: else
! 207: my_syslog(LOG_INFO, _("dumping UDP packet %u mask 0x%04x"), ++packet_count, mask);
! 208:
! 209: }
! 210:
! 211: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>