1 /* 2 * Copyright (c) 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * pcap-common.c - common code for pcap and pcapng files 22 */ 23 24 #ifdef HAVE_CONFIG_H 25 #include <config.h> 26 #endif 27 28 #include <pcap-types.h> 29 30 #include "pcap-int.h" 31 #include "extract.h" 32 #include "pcap-usb-linux-common.h" 33 34 #include "pcap-util.h" 35 36 #include "pflog.h" 37 #include "pcap/can_socketcan.h" 38 #include "pcap/sll.h" 39 #include "pcap/usb.h" 40 #include "pcap/nflog.h" 41 42 /* 43 * Most versions of the DLT_PFLOG pseudo-header have UID and PID fields 44 * that are saved in host byte order. 45 * 46 * When reading a DLT_PFLOG packet, we need to convert those fields from 47 * the byte order of the host that wrote the file to this host's byte 48 * order. 49 */ 50 static void 51 swap_pflog_header(const struct pcap_pkthdr *hdr, u_char *buf) 52 { 53 u_int caplen = hdr->caplen; 54 u_int length = hdr->len; 55 u_int pfloghdr_length; 56 struct pfloghdr *pflhdr = (struct pfloghdr *)buf; 57 58 if (caplen < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid) || 59 length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) { 60 /* Not enough data to have the uid field */ 61 return; 62 } 63 64 pfloghdr_length = pflhdr->length; 65 66 if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, uid) + sizeof pflhdr->uid)) { 67 /* Header doesn't include uid field */ 68 return; 69 } 70 pflhdr->uid = SWAPLONG(pflhdr->uid); 71 72 if (caplen < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid) || 73 length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) { 74 /* Not enough data to have the pid field */ 75 return; 76 } 77 if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, pid) + sizeof pflhdr->pid)) { 78 /* Header doesn't include pid field */ 79 return; 80 } 81 pflhdr->pid = SWAPLONG(pflhdr->pid); 82 83 if (caplen < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid) || 84 length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) { 85 /* Not enough data to have the rule_uid field */ 86 return; 87 } 88 if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_uid) + sizeof pflhdr->rule_uid)) { 89 /* Header doesn't include rule_uid field */ 90 return; 91 } 92 pflhdr->rule_uid = SWAPLONG(pflhdr->rule_uid); 93 94 if (caplen < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid) || 95 length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) { 96 /* Not enough data to have the rule_pid field */ 97 return; 98 } 99 if (pfloghdr_length < (u_int) (offsetof(struct pfloghdr, rule_pid) + sizeof pflhdr->rule_pid)) { 100 /* Header doesn't include rule_pid field */ 101 return; 102 } 103 pflhdr->rule_pid = SWAPLONG(pflhdr->rule_pid); 104 } 105 106 /* 107 * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or 108 * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload, 109 * with the CAN ID being in host byte order. 110 * 111 * When reading a DLT_LINUX_SLL packet, we need to check for those 112 * packets and convert the CAN ID from the byte order of the host that 113 * wrote the file to this host's byte order. 114 */ 115 static void 116 swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf) 117 { 118 u_int caplen = hdr->caplen; 119 u_int length = hdr->len; 120 struct sll_header *shdr = (struct sll_header *)buf; 121 uint16_t protocol; 122 pcap_can_socketcan_hdr *chdr; 123 124 if (caplen < (u_int) sizeof(struct sll_header) || 125 length < (u_int) sizeof(struct sll_header)) { 126 /* Not enough data to have the protocol field */ 127 return; 128 } 129 130 protocol = EXTRACT_BE_U_2(&shdr->sll_protocol); 131 if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD) 132 return; 133 134 /* 135 * SocketCAN packet; fix up the packet's header. 136 */ 137 chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header)); 138 if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) || 139 length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) { 140 /* Not enough data to have the CAN ID */ 141 return; 142 } 143 chdr->can_id = SWAPLONG(chdr->can_id); 144 } 145 146 /* 147 * The same applies for DLT_LINUX_SLL2. 148 */ 149 static void 150 swap_linux_sll2_header(const struct pcap_pkthdr *hdr, u_char *buf) 151 { 152 u_int caplen = hdr->caplen; 153 u_int length = hdr->len; 154 struct sll2_header *shdr = (struct sll2_header *)buf; 155 uint16_t protocol; 156 pcap_can_socketcan_hdr *chdr; 157 158 if (caplen < (u_int) sizeof(struct sll2_header) || 159 length < (u_int) sizeof(struct sll2_header)) { 160 /* Not enough data to have the protocol field */ 161 return; 162 } 163 164 protocol = EXTRACT_BE_U_2(&shdr->sll2_protocol); 165 if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD) 166 return; 167 168 /* 169 * SocketCAN packet; fix up the packet's header. 170 */ 171 chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll2_header)); 172 if (caplen < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id) || 173 length < (u_int) sizeof(struct sll2_header) + sizeof(chdr->can_id)) { 174 /* Not enough data to have the CAN ID */ 175 return; 176 } 177 chdr->can_id = SWAPLONG(chdr->can_id); 178 } 179 180 /* 181 * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host 182 * byte order when capturing (it's supplied directly from a 183 * memory-mapped buffer shared by the kernel). 184 * 185 * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED packet, we 186 * need to convert it from the byte order of the host that wrote the 187 * file to this host's byte order. 188 */ 189 static void 190 swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, 191 int header_len_64_bytes) 192 { 193 pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf; 194 bpf_u_int32 offset = 0; 195 196 /* 197 * "offset" is the offset *past* the field we're swapping; 198 * we skip the field *before* checking to make sure 199 * the captured data length includes the entire field. 200 */ 201 202 /* 203 * The URB id is a totally opaque value; do we really need to 204 * convert it to the reading host's byte order??? 205 */ 206 offset += 8; /* skip past id */ 207 if (hdr->caplen < offset) 208 return; 209 uhdr->id = SWAPLL(uhdr->id); 210 211 offset += 4; /* skip past various 1-byte fields */ 212 213 offset += 2; /* skip past bus_id */ 214 if (hdr->caplen < offset) 215 return; 216 uhdr->bus_id = SWAPSHORT(uhdr->bus_id); 217 218 offset += 2; /* skip past various 1-byte fields */ 219 220 offset += 8; /* skip past ts_sec */ 221 if (hdr->caplen < offset) 222 return; 223 uhdr->ts_sec = SWAPLL(uhdr->ts_sec); 224 225 offset += 4; /* skip past ts_usec */ 226 if (hdr->caplen < offset) 227 return; 228 uhdr->ts_usec = SWAPLONG(uhdr->ts_usec); 229 230 offset += 4; /* skip past status */ 231 if (hdr->caplen < offset) 232 return; 233 uhdr->status = SWAPLONG(uhdr->status); 234 235 offset += 4; /* skip past urb_len */ 236 if (hdr->caplen < offset) 237 return; 238 uhdr->urb_len = SWAPLONG(uhdr->urb_len); 239 240 offset += 4; /* skip past data_len */ 241 if (hdr->caplen < offset) 242 return; 243 uhdr->data_len = SWAPLONG(uhdr->data_len); 244 245 if (uhdr->transfer_type == URB_ISOCHRONOUS) { 246 offset += 4; /* skip past s.iso.error_count */ 247 if (hdr->caplen < offset) 248 return; 249 uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count); 250 251 offset += 4; /* skip past s.iso.numdesc */ 252 if (hdr->caplen < offset) 253 return; 254 uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc); 255 } else 256 offset += 8; /* skip USB setup header */ 257 258 /* 259 * With the old header, there are no isochronous descriptors 260 * after the header. 261 * 262 * With the new header, the actual number of descriptors in 263 * the header is not s.iso.numdesc, it's ndesc - only the 264 * first N descriptors, for some value of N, are put into 265 * the header, and ndesc is set to the actual number copied. 266 * In addition, if s.iso.numdesc is negative, no descriptors 267 * are captured, and ndesc is set to 0. 268 */ 269 if (header_len_64_bytes) { 270 /* 271 * This is either the "version 1" header, with 272 * 16 bytes of additional fields at the end, or 273 * a "version 0" header from a memory-mapped 274 * capture, with 16 bytes of zeroed-out padding 275 * at the end. Byte swap them as if this were 276 * a "version 1" header. 277 */ 278 offset += 4; /* skip past interval */ 279 if (hdr->caplen < offset) 280 return; 281 uhdr->interval = SWAPLONG(uhdr->interval); 282 283 offset += 4; /* skip past start_frame */ 284 if (hdr->caplen < offset) 285 return; 286 uhdr->start_frame = SWAPLONG(uhdr->start_frame); 287 288 offset += 4; /* skip past xfer_flags */ 289 if (hdr->caplen < offset) 290 return; 291 uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags); 292 293 offset += 4; /* skip past ndesc */ 294 if (hdr->caplen < offset) 295 return; 296 uhdr->ndesc = SWAPLONG(uhdr->ndesc); 297 298 if (uhdr->transfer_type == URB_ISOCHRONOUS) { 299 /* swap the values in struct linux_usb_isodesc */ 300 usb_isodesc *pisodesc; 301 uint32_t i; 302 303 pisodesc = (usb_isodesc *)(void *)(buf+offset); 304 for (i = 0; i < uhdr->ndesc; i++) { 305 offset += 4; /* skip past status */ 306 if (hdr->caplen < offset) 307 return; 308 pisodesc->status = SWAPLONG(pisodesc->status); 309 310 offset += 4; /* skip past offset */ 311 if (hdr->caplen < offset) 312 return; 313 pisodesc->offset = SWAPLONG(pisodesc->offset); 314 315 offset += 4; /* skip past len */ 316 if (hdr->caplen < offset) 317 return; 318 pisodesc->len = SWAPLONG(pisodesc->len); 319 320 offset += 4; /* skip past padding */ 321 322 pisodesc++; 323 } 324 } 325 } 326 } 327 328 /* 329 * The DLT_NFLOG "packets" have a mixture of big-endian and host-byte-order 330 * data. They begin with a fixed-length header with big-endian fields, 331 * followed by a set of TLVs, where the type and length are in host 332 * byte order but the values are either big-endian or are a raw byte 333 * sequence that's the same regardless of the host's byte order. 334 * 335 * When reading a DLT_NFLOG packet, we need to convert the type and 336 * length values from the byte order of the host that wrote the file 337 * to the byte order of this host. 338 */ 339 static void 340 swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf) 341 { 342 u_char *p = buf; 343 nflog_hdr_t *nfhdr = (nflog_hdr_t *)buf; 344 nflog_tlv_t *tlv; 345 u_int caplen = hdr->caplen; 346 u_int length = hdr->len; 347 uint16_t size; 348 349 if (caplen < (u_int) sizeof(nflog_hdr_t) || 350 length < (u_int) sizeof(nflog_hdr_t)) { 351 /* Not enough data to have any TLVs. */ 352 return; 353 } 354 355 if (nfhdr->nflog_version != 0) { 356 /* Unknown NFLOG version */ 357 return; 358 } 359 360 length -= sizeof(nflog_hdr_t); 361 caplen -= sizeof(nflog_hdr_t); 362 p += sizeof(nflog_hdr_t); 363 364 while (caplen >= sizeof(nflog_tlv_t)) { 365 tlv = (nflog_tlv_t *) p; 366 367 /* Swap the type and length. */ 368 tlv->tlv_type = SWAPSHORT(tlv->tlv_type); 369 tlv->tlv_length = SWAPSHORT(tlv->tlv_length); 370 371 /* Get the length of the TLV. */ 372 size = tlv->tlv_length; 373 if (size % 4 != 0) 374 size += 4 - size % 4; 375 376 /* Is the TLV's length less than the minimum? */ 377 if (size < sizeof(nflog_tlv_t)) { 378 /* Yes. Give up now. */ 379 return; 380 } 381 382 /* Do we have enough data for the full TLV? */ 383 if (caplen < size || length < size) { 384 /* No. */ 385 return; 386 } 387 388 /* Skip over the TLV. */ 389 length -= size; 390 caplen -= size; 391 p += size; 392 } 393 } 394 395 static void 396 swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data) 397 { 398 /* 399 * Convert pseudo-headers from the byte order of 400 * the host on which the file was saved to our 401 * byte order, as necessary. 402 */ 403 switch (linktype) { 404 405 case DLT_PFLOG: 406 swap_pflog_header(hdr, data); 407 break; 408 409 case DLT_LINUX_SLL: 410 swap_linux_sll_header(hdr, data); 411 break; 412 413 case DLT_LINUX_SLL2: 414 swap_linux_sll2_header(hdr, data); 415 break; 416 417 case DLT_USB_LINUX: 418 swap_linux_usb_header(hdr, data, 0); 419 break; 420 421 case DLT_USB_LINUX_MMAPPED: 422 swap_linux_usb_header(hdr, data, 1); 423 break; 424 425 case DLT_NFLOG: 426 swap_nflog_header(hdr, data); 427 break; 428 } 429 } 430 431 void 432 pcap_post_process(int linktype, int swapped, struct pcap_pkthdr *hdr, 433 u_char *data) 434 { 435 if (swapped) 436 swap_pseudo_headers(linktype, hdr, data); 437 438 fixup_pcap_pkthdr(linktype, hdr, data); 439 } 440 441 void 442 fixup_pcap_pkthdr(int linktype, struct pcap_pkthdr *hdr, const u_char *data) 443 { 444 const pcap_usb_header_mmapped *usb_hdr; 445 446 usb_hdr = (const pcap_usb_header_mmapped *) data; 447 if (linktype == DLT_USB_LINUX_MMAPPED && 448 hdr->caplen >= sizeof (pcap_usb_header_mmapped)) { 449 /* 450 * In older versions of libpcap, in memory-mapped captures, 451 * the "on-the-bus length" for completion events for 452 * incoming isochronous transfers was miscalculated; it 453 * needed to be calculated based on the* offsets and lengths 454 * in the descriptors, not on the raw URB length, but it 455 * wasn't. 456 * 457 * If this packet contains transferred data (yes, data_flag 458 * is 0 if we *do* have data), and the total on-the-network 459 * length is equal to the value calculated from the raw URB 460 * length, then it might be one of those transfers. 461 * 462 * We only do this if we have the full USB pseudo-header. 463 */ 464 if (!usb_hdr->data_flag && 465 hdr->len == sizeof(pcap_usb_header_mmapped) + 466 (usb_hdr->ndesc * sizeof (usb_isodesc)) + usb_hdr->urb_len) { 467 /* 468 * It might need fixing; fix it if it's a completion 469 * event for an incoming isochronous transfer. 470 */ 471 fix_linux_usb_mmapped_length(hdr, data); 472 } 473 } 474 } 475