// create a new open packet packet_t crypt_openize_1a(crypt_t self, crypt_t c, packet_t inner) { unsigned char secret[uECC_BYTES], iv[16], hash[32]; packet_t open; int inner_len; crypt_1a_t cs = (crypt_1a_t)c->cs, scs = (crypt_1a_t)self->cs; open = packet_chain(inner); packet_json(open,&(self->csid),1); inner_len = packet_len(inner); if(!packet_body(open,NULL,4+40+inner_len)) return NULL; // copy in the line public key memcpy(open->body+4, cs->line_public, 40); // get the shared secret to create the iv+key for the open aes if(!uECC_shared_secret(cs->id_public, cs->line_private, secret)) return packet_free(open); crypt_hash(secret,uECC_BYTES,hash); fold1(hash,hash); memset(iv,0,16); iv[15] = 1; // encrypt the inner aes_128_ctr(hash,inner_len,iv,packet_raw(inner),open->body+4+40); // generate secret for hmac if(!uECC_shared_secret(cs->id_public, scs->id_private, secret)) return packet_free(open); hmac_256(secret,uECC_BYTES,open->body+4,40+inner_len,hash); fold3(hash,open->body); return open; }
static int packet_process_thread(void *p) { while (1) { using_spinlock(&packet_queue_lock) { kp(KP_NORMAL, "packet-queue awake\n"); while (!list_empty(&packet_queue)) { struct packet *packet = list_take_first(&packet_queue, struct packet, packet_entry); kp(KP_NORMAL, "Recieved packet! len: %d\n", packet_len(packet)); kp(KP_NORMAL, "Packets in queue: %d\n", --packet_queue_length); not_using_spinlock(&packet_queue_lock) packet_linklayer_rx(packet); } sleep { if (list_empty(&packet_queue)) { not_using_spinlock(&packet_queue_lock) scheduler_task_yield(); } } } } return 0; }
packet_t packet_copy(packet_t p) { packet_t np; np = packet_parse(packet_raw(p), packet_len(p)); np->to = p->to; np->from = p->from; np->out = p->out; return np; }
int net_send_packet(int sock, struct packet *packet) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_BROADCAST; addr.sin_port = htons(63322); return sendto(sock, packet_data(packet), packet_len(packet), 0, (struct sockaddr *)&addr, sizeof(addr)); }
packet_t crypt_lineize_1a(crypt_t c, packet_t p) { packet_t line; unsigned char iv[16], hmac[32]; crypt_1a_t cs = (crypt_1a_t)c->cs; line = packet_chain(p); packet_body(line,NULL,16+4+4+packet_len(p)); memcpy(line->body,c->lineIn,16); memcpy(line->body+16+4,&(cs->seq),4); memset(iv,0,16); memcpy(iv+12,&(cs->seq),4); cs->seq++; aes_128_ctr(cs->keyOut,packet_len(p),iv,packet_raw(p),line->body+16+4+4); hmac_256(cs->keyOut,16,line->body+16+4,4+packet_len(p),hmac); fold3(hmac,line->body+16); return line; }
vmxnet3::vmxnet3(hw::PCI_Device& d, const uint16_t mtu) : Link(Link_protocol{{this, &vmxnet3::transmit}, mac()}, bufstore_), m_pcidev(d), m_mtu(mtu), bufstore_{1024, buffer_size_for_mtu(mtu)} { INFO("vmxnet3", "Driver initializing (rev=%#x)", d.rev_id()); assert(d.rev_id() == REVISION_ID); // find and store capabilities d.parse_capabilities(); // find BARs etc. d.probe_resources(); if (d.msix_cap()) { d.init_msix(); uint8_t msix_vectors = d.get_msix_vectors(); INFO2("[x] Device has %u MSI-X vectors", msix_vectors); assert(msix_vectors >= 3); if (msix_vectors > 2 + NUM_RX_QUEUES) msix_vectors = 2 + NUM_RX_QUEUES; for (int i = 0; i < msix_vectors; i++) { auto irq = Events::get().subscribe(nullptr); this->irqs.push_back(irq); d.setup_msix_vector(SMP::cpu_id(), IRQ_BASE + irq); } Events::get().subscribe(irqs[0], {this, &vmxnet3::msix_evt_handler}); Events::get().subscribe(irqs[1], {this, &vmxnet3::msix_xmit_handler}); for (int q = 0; q < NUM_RX_QUEUES; q++) Events::get().subscribe(irqs[2 + q], {this, &vmxnet3::msix_recv_handler}); } else { assert(0 && "This driver does not support legacy IRQs"); } // dma areas this->iobase = d.get_bar(PCI_BAR_VD); assert(this->iobase); this->ptbase = d.get_bar(PCI_BAR_PT); assert(this->ptbase); // verify and select version bool ok = check_version(); assert(ok); // reset device ok = reset(); assert(ok); // get mac address retrieve_hwaddr(); // check link status auto link_spd = check_link(); if (link_spd) { INFO2("Link up at %u Mbps", link_spd); } else { INFO2("LINK DOWN! :("); return; } // set MAC set_hwaddr(this->hw_addr); // initialize DMA areas this->dma = (vmxnet3_dma*) memalign(VMXNET3_DMA_ALIGN, sizeof(vmxnet3_dma)); memset(this->dma, 0, sizeof(vmxnet3_dma)); auto& queues = dma->queues; // setup tx queues queues.tx.cfg.desc_address = (uintptr_t) &dma->tx_desc; queues.tx.cfg.comp_address = (uintptr_t) &dma->tx_comp; queues.tx.cfg.num_desc = vmxnet3::NUM_TX_DESC; queues.tx.cfg.num_comp = VMXNET3_NUM_TX_COMP; queues.tx.cfg.intr_index = 1; // temp rxq buffer storage memset(tx.buffers, 0, sizeof(tx.buffers)); // setup rx queues for (int q = 0; q < NUM_RX_QUEUES; q++) { memset(rx[q].buffers, 0, sizeof(rx[q].buffers)); rx[q].desc0 = &dma->rx0_desc[0]; rx[q].desc1 = &dma->rx1_desc[0]; rx[q].comp = &dma->rx_comp[0]; rx[q].index = q; auto& queue = queues.rx[q]; queue.cfg.desc_address[0] = (uintptr_t) rx[q].desc0; queue.cfg.desc_address[1] = (uintptr_t) rx[q].desc1; queue.cfg.comp_address = (uintptr_t) rx[q].comp; queue.cfg.num_desc[0] = vmxnet3::NUM_RX_DESC; queue.cfg.num_desc[1] = vmxnet3::NUM_RX_DESC; queue.cfg.num_comp = VMXNET3_NUM_RX_COMP; queue.cfg.driver_data_len = sizeof(vmxnet3_rx_desc) + 2 * sizeof(vmxnet3_rx_desc); queue.cfg.intr_index = 2 + q; } auto& shared = dma->shared; // setup shared physical area shared.magic = VMXNET3_REV1_MAGIC; shared.misc.guest_info.arch = (sizeof(void*) == 4) ? GOS_BITS_32_BITS : GOS_BITS_64_BITS; shared.misc.guest_info.type = GOS_TYPE_LINUX; shared.misc.version = VMXNET3_VERSION_MAGIC; shared.misc.version_support = 1; shared.misc.upt_version_support = 1; shared.misc.upt_features = UPT1_F_RXVLAN; shared.misc.driver_data_address = (uintptr_t) &dma; shared.misc.queue_desc_address = (uintptr_t) &dma->queues; shared.misc.driver_data_len = sizeof(vmxnet3_dma); shared.misc.queue_desc_len = sizeof(vmxnet3_queues); shared.misc.mtu = packet_len(); // 60-9000 shared.misc.num_tx_queues = 1; shared.misc.num_rx_queues = NUM_RX_QUEUES; shared.interrupt.mask_mode = VMXNET3_IT_AUTO | (VMXNET3_IMM_AUTO << 2); shared.interrupt.num_intrs = 2 + NUM_RX_QUEUES; shared.interrupt.event_intr_index = 0; memset(shared.interrupt.moderation_level, UPT1_IML_ADAPTIVE, VMXNET3_MAX_INTRS); shared.interrupt.control = 0x1; // disable all shared.rx_filter.mode = VMXNET3_RXM_UCAST | VMXNET3_RXM_BCAST | VMXNET3_RXM_ALL_MULTI; // location of shared area to device uintptr_t shabus = (uintptr_t) &shared; mmio_write32(this->iobase + 0x10, shabus); // shared low mmio_write32(this->iobase + 0x18, 0x0); // shared high // activate device int status = command(VMXNET3_CMD_ACTIVATE_DEV); if (status) { assert(0 && "Failed to activate device"); } // initialize and fill RX queue... for (int q = 0; q < NUM_RX_QUEUES; q++) { refill(rx[q]); } // deferred transmit this->deferred_irq = Events::get().subscribe(handle_deferred); // enable interrupts enable_intr(0); enable_intr(1); for (int q = 0; q < NUM_RX_QUEUES; q++) enable_intr(2 + q); }