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>