static void enter_mode_rx_only_or_dump(struct mode *mode) { int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long fcnt = 0; short ifflags = 0; uint8_t *packet; struct ring rx_ring; struct pollfd rx_poll; struct frame_map *hdr; struct sock_fprog bpf_ops; if (!device_up_and_running(mode->device_in)) panic("Device not up and running!\n"); set_memcpy(); sock = pf_socket(); if (mode->dump) { struct stat tmp; memset(&tmp, 0, sizeof(tmp)); ret = stat(mode->device_out, &tmp); if (ret < 0) { mode->dump_dir = 0; goto try_file; } mode->dump_dir = !!S_ISDIR(tmp.st_mode); if (mode->dump_dir) { fd = begin_multi_pcap_file(mode); } else { try_file: fd = begin_single_pcap_file(mode); } } memset(&rx_ring, 0, sizeof(rx_ring)); memset(&rx_poll, 0, sizeof(rx_poll)); memset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(mode->device_in); size = ring_size(mode->device_in, mode->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(mode->filter, &bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); setup_rx_ring_layout(sock, &rx_ring, size, mode->jumbo_support); create_rx_ring(sock, &rx_ring); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_in); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_in, irq, mode->cpu); } if (mode->promiscuous == true) { ifflags = enter_promiscuous_mode(mode->device_in); printf("PROMISC\n"); } printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RX %s\n\n", mode->dump ? pcap_ops[mode->pcap]->name : ""); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { hdr = rx_ring.frames[it].iov_base; packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; fcnt++; if (mode->packet_type != PACKET_ALL) if (mode->packet_type != hdr->s_ll.sll_pkttype) goto next; if (unlikely(rx_ring.layout.tp_frame_size < hdr->tp_h.tp_snaplen)) { fprintf(stderr, "Skipping too large packet! " "No jumbo support selected?\n"); fflush(stderr); goto next; } if (mode->dump) { struct pcap_pkthdr phdr; tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &phdr); ret = pcap_ops[mode->pcap]->write_pcap_pkt(fd, &phdr, packet, phdr.len); if (unlikely(ret != sizeof(phdr) + phdr.len)) panic("Write error to pcap!\n"); } show_frame_hdr(hdr, mode->print_mode, RING_MODE_INGRESS); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, mode->link_type); if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) { sigint = 1; break; } next: kernel_may_pull_from_rx(&hdr->tp_h); next_slot(&it, &rx_ring); if (unlikely(sigint == 1)) break; if (mode->dump && next_dump) { struct tpacket_stats kstats; socklen_t slen = sizeof(kstats); memset(&kstats, 0, sizeof(kstats)); getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen); fd = next_multi_pcap_file(mode, fd); next_dump = false; if (mode->print_mode == FNTTYPE_PRINT_NONE) { printf(".(+%u/-%u)", kstats.tp_packets - kstats.tp_drops, kstats.tp_drops); fflush(stdout); } } } poll(&rx_poll, 1, -1); poll_error_maybe_die(sock, &rx_poll); } if (!(mode->dump_dir && mode->print_mode == FNTTYPE_PRINT_NONE)) sock_print_net_stats(sock); else { printf("\n\n"); fflush(stdout); } dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (mode->promiscuous == true) leave_promiscuous_mode(mode->device_in, ifflags); close(sock); if (mode->dump) { if (mode->dump_dir) finish_multi_pcap_file(mode, fd); else finish_single_pcap_file(mode, fd); } }
static void enter_mode_pcap_to_tx(struct mode *mode) { int irq, ifindex, fd = 0, ret; unsigned int size, it = 0; struct ring tx_ring; struct frame_map *hdr; struct sock_fprog bpf_ops; struct tx_stats stats; uint8_t *out = NULL; if (!device_up_and_running(mode->device_out)) panic("Device not up and running!\n"); set_memcpy(); tx_sock = pf_socket(); if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); ret = pcap_ops[mode->pcap]->pull_file_header(fd); if (ret) panic("error reading pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_reading_pcap) { ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd); if (ret) panic("error prepare reading pcap!\n"); } memset(&tx_ring, 0, sizeof(tx_ring)); memset(&bpf_ops, 0, sizeof(bpf_ops)); memset(&stats, 0, sizeof(stats)); ifindex = device_ifindex(mode->device_out); size = ring_size(mode->device_out, mode->reserve_size); bpf_parse_rules(mode->filter, &bpf_ops); set_packet_loss_discard(tx_sock); setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_out); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq, mode->cpu); } if (mode->kpull) interval = mode->kpull; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: TX %luus %s\n\n", interval, pcap_ops[mode->pcap]->name); while (likely(sigint == 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) { struct pcap_pkthdr phdr; hdr = tx_ring.frames[it].iov_base; /* Kernel assumes: data = ph.raw + po->tp_hdrlen - * sizeof(struct sockaddr_ll); */ out = ((uint8_t *) hdr) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); do { ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr, out, ring_frame_size(&tx_ring)); if (unlikely(ret <= 0)) goto out; } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len)); pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h); stats.tx_bytes += hdr->tp_h.tp_len;; stats.tx_packets++; show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS); dissector_entry_point(out, hdr->tp_h.tp_snaplen, mode->link_type); kernel_may_pull_from_tx(&hdr->tp_h); next_slot(&it, &tx_ring); if (unlikely(sigint == 1)) break; if (frame_cnt_max != 0 && stats.tx_packets >= frame_cnt_max) { sigint = 1; break; } } } out: fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", stats.tx_packets); printf("\r%12lu bytes outgoing\n", stats.tx_bytes); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); close(tx_sock); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ); close(fd); }
/* If netsniff-ngs in device is on a tap, it can efficiently filter out * some interesting packets and give them to the out device for testing * or debugging for instance. */ static void enter_mode_rx_to_tx(struct mode *mode) { int rx_sock, ifindex_in, ifindex_out; unsigned int size_in, size_out, it_in = 0, it_out = 0; unsigned long fcnt = 0; uint8_t *in, *out; short ifflags = 0; struct frame_map *hdr_in, *hdr_out; struct ring tx_ring; struct ring rx_ring; struct pollfd rx_poll; struct sock_fprog bpf_ops; if (!strncmp(mode->device_in, mode->device_out, strlen(mode->device_in))) panic("Ingress/egress devices must be different!\n"); if (!device_up_and_running(mode->device_out)) panic("Egress device not up and running!\n"); if (!device_up_and_running(mode->device_in)) panic("Ingress device not up and running!\n"); set_memcpy(); rx_sock = pf_socket(); tx_sock = pf_socket(); memset(&tx_ring, 0, sizeof(tx_ring)); memset(&rx_ring, 0, sizeof(rx_ring)); memset(&rx_poll, 0, sizeof(rx_poll)); memset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex_in = device_ifindex(mode->device_in); size_in = ring_size(mode->device_in, mode->reserve_size); ifindex_out = device_ifindex(mode->device_out); size_out = ring_size(mode->device_out, mode->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(mode->filter, &bpf_ops); bpf_attach_to_sock(rx_sock, &bpf_ops); setup_rx_ring_layout(rx_sock, &rx_ring, size_in, mode->jumbo_support); create_rx_ring(rx_sock, &rx_ring); mmap_rx_ring(rx_sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(rx_sock, &rx_ring, ifindex_in); prepare_polling(rx_sock, &rx_poll); set_packet_loss_discard(tx_sock); setup_tx_ring_layout(tx_sock, &tx_ring, size_out, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex_out); mt_init_by_seed_time(); dissector_init_all(mode->print_mode); if (mode->promiscuous == true) { ifflags = enter_promiscuous_mode(mode->device_in); printf("PROMISC\n"); } if (mode->kpull) interval = mode->kpull; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RXTX %luus\n\n", interval); printf("Running! Hang up with ^C!\n\n"); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it_in].iov_base)) { hdr_in = rx_ring.frames[it_in].iov_base; in = ((uint8_t *) hdr_in) + hdr_in->tp_h.tp_mac; fcnt++; if (mode->packet_type != PACKET_ALL) if (mode->packet_type != hdr_in->s_ll.sll_pkttype) goto next; hdr_out = tx_ring.frames[it_out].iov_base; out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); /* If we cannot pull, look for a different slot. */ for (; !user_may_pull_from_tx(tx_ring.frames[it_out].iov_base) && likely(!sigint);) { if (mode->randomize) next_rnd_slot(&it_out, &tx_ring); else next_slot(&it_out, &tx_ring); hdr_out = tx_ring.frames[it_out].iov_base; out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); } tpacket_hdr_clone(&hdr_out->tp_h, &hdr_in->tp_h); __memcpy(out, in, hdr_in->tp_h.tp_len); kernel_may_pull_from_tx(&hdr_out->tp_h); if (mode->randomize) next_rnd_slot(&it_out, &tx_ring); else next_slot(&it_out, &tx_ring); /* Should actually be avoided ... */ show_frame_hdr(hdr_in, mode->print_mode, RING_MODE_INGRESS); dissector_entry_point(in, hdr_in->tp_h.tp_snaplen, mode->link_type); if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) { sigint = 1; break; } next: kernel_may_pull_from_rx(&hdr_in->tp_h); next_slot(&it_in, &rx_ring); if (unlikely(sigint == 1)) goto out; } poll(&rx_poll, 1, -1); poll_error_maybe_die(rx_sock, &rx_poll); } out: sock_print_net_stats(rx_sock); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); destroy_rx_ring(rx_sock, &rx_ring); if (mode->promiscuous == true) leave_promiscuous_mode(mode->device_in, ifflags); close(tx_sock); close(rx_sock); }
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); CallConstructors(); EFI_STATUS Status; const char16_t* searchdir = u"\\EFI\\ChaiOS\\"; if (Status = SetWorkingDirectory(searchdir)) printf(u"Error setting working directory: %s\r\n", getError(Status)); CHAIOS_BOOT_FILES* bootfile = nullptr; while (bootfile = iterateBootFiles(bootfile)) { if (bootfile->loadLocation != nullptr) continue; //Support in-memory images EFI_FILE* file = OpenFile(bootfile->fileName, "r"); if (!file) { printf(u"Error: could not open %s: %s\r\n", bootfile->fileName, getError(getErrno())); } UINT64 fileSize = GetFileSize(file); VOID* bootfilebuf = kmalloc(fileSize+1); UINTN read = ReadFile(bootfilebuf, 1, fileSize, file); if (read < fileSize) printf(u"Read %d bytes, failed\r\n", read); else printf(u"Successfully read %d bytes\r\n", read); //Boot file is now loaded into memory CloseFile(file); bootfile->loadLocation = bootfilebuf; bootfile->fileSize = fileSize; if (bootfile->bootType == CHAIOS_BOOT_CONFIGURATION) { //We need to parse this now. INI format ((char*)bootfilebuf)[fileSize] = '\0'; ini_parse_string((const char*)bootfilebuf, &bootini_handler, nullptr); } } //size_t value = GetIntegerInput(u"Enter scrolling lines configuration: "); //set_scrolllines(value); UINT32 AutoMode = IterateGraphicsMode(&match_config_resoultion); EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* info; UINTN SizeOfInfo; if (AutoMode == UINT32_MAX) { if (!EFI_ERROR(GetGraphicsModeInfo(AutoMode, &info, &SizeOfInfo))) { IterateGraphicsMode(&print_graphics_mode); size_t value = GetIntegerInput(u"Enter boot graphics mode: "); SetGraphicsMode(value); AutoMode = value; } } else { SetGraphicsMode(AutoMode); } if (!EFI_ERROR(GetGraphicsModeInfo(AutoMode, &info, &SizeOfInfo))) { printf(u"Graphics mode %d: %dx%d\r\n", AutoMode, info->HorizontalResolution, info->VerticalResolution); } puts(u"ChaiOS 0.09 UEFI Loader\r\n"); int majorver = SystemTable->Hdr.Revision / (1 << 16); int minorver = SystemTable->Hdr.Revision % (1 << 16); printf(u"Firmware Vendor: %s, version: %d (UEFI:%d.%d)\r\n", SystemTable->FirmwareVendor, SystemTable->FirmwareRevision, majorver, minorver); //Read ACPI configuration tables //startup_acpi(SystemTable); //startup_multiprocessor(); const size_t EARLY_PAGE_STACK_SIZE = 1024*1024; EFI_PHYSICAL_ADDRESS earlyPhypageStack = 0; if (EFI_ERROR(SystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, EARLY_PAGE_STACK_SIZE / EFI_PAGE_SIZE, &earlyPhypageStack))) { puts(u"Could not allocate page stack\r\n"); return EFI_OUT_OF_RESOURCES; } SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, nullptr); PrepareExitBootServices(); EfiMemoryMap map; map.MemMapSize = map.MapKey = map.DescriptorSize = map.DescriptorVersion = 0; SystemTable->BootServices->GetMemoryMap(&map.MemMapSize, nullptr, &map.MapKey, &map.DescriptorSize, &map.DescriptorVersion); //Give a nice bit of room to spare (memory map can change) map.MemMapSize += 16 * map.DescriptorSize; map.memmap = (EFI_MEMORY_DESCRIPTOR*)kmalloc(map.MemMapSize); //Allocate a nice buffer SystemTable->BootServices->GetMemoryMap(&map.MemMapSize, map.memmap, &map.MapKey, &map.DescriptorSize, &map.DescriptorVersion); printf(u"EFI Memory Map: Descriptor size %d\n", map.DescriptorSize); #if 0 //Dump the UEFI memory map to a file for testing EFI_FILE* file = OpenFile(u"efimap.dat", "w"); if (!file) { printf(u"Error: could not open %s: %s\r\n", u"efimap.dat", getError(getErrno())); } WriteFile(map.memmap, 1, map.MemMapSize, file); CloseFile(file); #endif if (EFI_ERROR(Status = SystemTable->BootServices->ExitBootServices(ImageHandle, map.MapKey))) { printf(u"Failed to exit boot services: %s\r\n", getError(Status)); UINTN index; SystemTable->BootServices->WaitForEvent(1, &SystemTable->ConIn->WaitForKey, &index); return EFI_SUCCESS; } //We need to take control of the hardware now. Setup basic memory management setLiballocAllocator(nullptr, nullptr); InitializePmmngr(map, (void*)earlyPhypageStack, EARLY_PAGE_STACK_SIZE); puts(u"Physical memory manager intialized\n"); arch_initialize_paging(); puts(u"Paging initialized\n"); setLiballocAllocator(&arch_allocate_pages, &arch_free_pages); //Now load the OS! bootfile = nullptr; kimage_entry kentry = nullptr; KLOAD_HANDLE kernel = NULL; while (bootfile = iterateBootFiles(bootfile)) { printf(u"Boot file: %s @ %x, length %d, type %d\n", bootfile->fileName, bootfile->loadLocation, bootfile->fileSize, bootfile->bootType); if (!bootfile->loadLocation) continue; if (bootfile->bootType == CHAIOS_DLL) { KLOAD_HANDLE dll = LoadImage(bootfile->loadLocation, bootfile->fileName); if (GetProcAddress(dll, "memcpy")) { set_memcpy((memcpy_proc)GetProcAddress(dll, "memcpy")); } } else if (bootfile->bootType == CHAIOS_KERNEL) { kernel = LoadImage(bootfile->loadLocation, bootfile->fileName); kentry = GetEntryPoint(kernel); } } size_t kstacksize = GetStackSize(kernel); if (!paging_map(stackaddr, PADDR_T_MAX, kstacksize, PAGE_ATTRIBUTE_WRITABLE)) { puts(u"Error: could not allocate kernel stack\n"); while (1); } KERNEL_BOOT_INFO bootinfo; fill_pmmngr_info(bootinfo.pmmngr_info); fill_arch_paging_info(bootinfo.paging_info); fill_modloader_info(bootinfo.modloader_info); get_framebuffer_info(bootinfo.fbinfo); populate_kterm_info(bootinfo.kterm_status); bootinfo.efi_system_table = SystemTable; bootinfo.memory_map = ↦ bootinfo.loaded_files = &bootfiles; bootinfo.boottype = CHAIOS_BOOT_TYPE_UEFI; bootinfo.printf_proc = &printf; bootinfo.puts_proc = &puts; printf(u"Success: Kernel entry point at %x, stack at %x, length %x\n", kentry, stackaddr, kstacksize); call_kernel(&bootinfo, kentry, stackaddr, kstacksize); puts(u"Kernel returned"); while (1); }