/*! \brief Validates struct uses. * * \param ip_table * the interprocedural symbol table. * * Pointers to structs with the same name but different definitions have been * merged into unions containing pointers to each struct type. We now need * to search for OP_arrow and OP_dot expressions that reference these unions * and add an OP_dot so they get the correct pointer out of the union. */ void Plink_ValidateTypes (SymbolTable ip_table) { SymTabEntry e; Key k; for (k = PST_GetTableEntryByType (ip_table, ET_FUNC | ET_VAR); P_ValidKey (k); k = PST_GetTableEntryByTypeNext (ip_table, k, ET_FUNC | ET_VAR)) { e = PST_GetSymTabEntry (ip_table, k); if (P_GetSymTabEntryType (e) == ET_FUNC) { FuncDcl f = P_GetSymTabEntryFuncDcl (e); P_StmtApplyPost (P_GetFuncDclStmt (f), NULL, fix_multi_ref, ip_table); } else { VarDcl v = P_GetSymTabEntryVarDcl (e); validate_init (ip_table, P_GetVarDclInit (v), P_GetVarDclType (v)); } } return; }
int CMEM_exit(void) { int result = 0; __D("exit: entered - ref_count %d, cmem_fd %d\n", ref_count, cmem_fd); if (!validate_init()) { return -1; } __D("exit: decrementing ref_count\n"); ref_count--; if (ref_count == 0) { result = close(cmem_fd); __D("exit: ref_count == 0, closed /dev/cmem (%s)\n", result == -1 ? strerror(errno) : "succeeded"); /* setting -3 allows to distinguish CMEM exit from CMEM failed */ cmem_fd = -3; } __D("exit: exiting, returning %d\n", result); return result; }
static int getBlock(int blockid, unsigned long *pphys_base, size_t *psize) { union CMEM_AllocUnion block; int rv; __D("getBlock: entered\n"); if (!validate_init()) { return -1; } block.blockid = blockid; rv = ioctl(cmem_fd, CMEM_IOCGETBLOCK | CMEM_IOCMAGIC, &block); if (rv != 0) { __E("getBlock: Failed to retrieve memory block bounds for block %d " "from driver: %d.\n", blockid, rv); return -1; } *pphys_base = block.get_block_outparams.physp; *psize = block.get_block_outparams.size; __D("getBlock: exiting, ioctl CMEM_IOCGETBLOCK succeeded, " "returning *pphys_base=0x%lx, *psize=0x%x\n", *pphys_base, *psize); return 0; }
/*! \brief Validates a variable initializer. * * \param ip_table * the interprocedural symbol table. * \param init * the Init to validate. * \param type * the Type of the variable being initialized. * * If a variable used to be declared: * * struct *s = (struct *)0; * * it is now declared * * union s = (struct *)0; * * And should be declared * * union s = { (struct *)0 }; * * This function does this transformation. It recurses into aggregate * initializers to find multi unions hidden inside. */ static void validate_init (SymbolTable ip_table, Init init, Type type) { Init i; StructDcl s; UnionDcl u; Field f; if (init) { if (is_multi_type (ip_table, type)) { /* Copy init's fields to i and set i as init->set. */ i = P_NewInit (); P_SetInitExpr (i, P_GetInitExpr (init)); P_SetInitNext (i, P_GetInitNext (init)); P_SetInitSet (i, P_GetInitSet (init)); P_SetInitExpr (init, NULL); P_SetInitNext (init, NULL); P_SetInitSet (init, i); } else if (PST_IsStructureType (ip_table, type)) { if (PST_GetTypeBasicType (ip_table, type) & BT_STRUCT) { s = PST_GetTypeStructDcl (ip_table, type); for (f = P_GetStructDclFields (s), i = P_GetInitSet (init); f && i; f = P_GetFieldNext (f), i = P_GetInitNext (i)) validate_init (ip_table, i, P_GetFieldType (f)); } else { u = PST_GetTypeUnionDcl (ip_table, type); /* Only the first field in the union can be initialized. */ validate_init (ip_table, P_GetInitSet (init), P_GetFieldType (P_GetUnionDclFields (u))); } } } return; }
static void *allocPool(int blockid, int poolid, CMEM_AllocParams *params) { if (params == NULL) { params = &CMEM_DEFAULTPARAMS; } __D("allocPool: entered w/ poolid %d, params - flags %s%s\n", poolid, params->flags & CMEM_CACHED ? "CACHED" : "NONCACHED", params == &CMEM_DEFAULTPARAMS ? " (default)" : ""); if (!validate_init()) { return NULL; } return allocFromPool(blockid, poolid, params); }
static int getPoolFromBlock(int blockid, size_t size) { union CMEM_AllocUnion poolDesc; if (!validate_init()) { return -1; } poolDesc.get_pool_inparams.size = size; poolDesc.get_pool_inparams.blockid = blockid; if (ioctl(cmem_fd, CMEM_IOCGETPOOL | CMEM_IOCMAGIC, &poolDesc) == -1) { __E("getPool: Failed to get a pool fitting a size %d\n", size); return -1; } __D("getPool: exiting, ioctl CMEM_IOCGETPOOL succeeded, returning %d\n", poolDesc.poolid); return poolDesc.poolid; }
int CMEM_cacheInv(void *ptr, size_t size) { struct block_struct block; __D("cacheInv: entered w/ addr %p, size %#x\n", ptr, size); if (!validate_init()) { return -1; } block.addr = (unsigned long)ptr; block.size = size; if (ioctl(cmem_fd, CMEM_IOCCACHEINV | CMEM_IOCMAGIC, &block) == -1) { __E("cacheInv: Failed to invalidate %#x\n", (unsigned int) ptr); return -1; } __D("cacheInv: exiting, ioctl CMEM_IOCCACHEINV succeeded, returning 0\n"); return 0; }
unsigned long CMEM_getPhys(void *ptr) { union CMEM_AllocUnion getDesc; __D("getPhys: entered w/ addr %p\n", ptr); if (!validate_init()) { return 0; } getDesc.virtp = (unsigned long)ptr; if (ioctl(cmem_fd, CMEM_IOCGETPHYS | CMEM_IOCMAGIC, &getDesc) == -1) { __E("getPhys: Failed to get physical address of %#x\n", (unsigned int) ptr); return 0; } __D("getPhys: exiting, ioctl CMEM_IOCGETPHYS succeeded, returning %#lx\n", getDesc.physp); return getDesc.physp; }
int CMEM_free(void *ptr, CMEM_AllocParams *params) { union CMEM_AllocUnion freeDesc; unsigned int cmd; size_t size; if (params == NULL) { params = &CMEM_DEFAULTPARAMS; } __D("free: entered w/ ptr %p, params - type %s%s\n", ptr, params->type == CMEM_POOL ? "POOL" : "HEAP", params == &CMEM_DEFAULTPARAMS ? " (default)" : ""); if (!validate_init()) { return -1; } freeDesc.virtp = (int)ptr; cmd = CMEM_IOCFREE | params->type; if (ioctl(cmem_fd, cmd | CMEM_IOCMAGIC, &freeDesc) == -1) { __E("free: failed to free %#x\n", (unsigned int) ptr); return -1; } size = freeDesc.free_outparams.size; __D("free: ioctl CMEM_IOCFREE%s succeeded, size %#x\n", params->type == CMEM_POOL ? "POOL" : "HEAP", size); if (munmap(ptr, size) == -1) { __E("free: failed to munmap %#x\n", (unsigned int) ptr); return -1; } __D("free: munmap succeeded, returning 0\n"); return 0; }
int CMEM_getNumBlocks(int *pnblocks) { int rv; __D("getNumBlocks: entered\n"); if (!validate_init()) { return -1; } rv = ioctl(cmem_fd, CMEM_IOCGETNUMBLOCKS | CMEM_IOCMAGIC, pnblocks); if (rv != 0) { __E("getBlock: Failed to retrieve number of blocks " "from driver: %d.\n", rv); return -1; } __D("getNumBlocks: exiting, ioctl CMEM_IOCGETNUMBLOCKS succeeded, " "returning *pnblocks=%d\n", *pnblocks); return 0; }
int CMEM_getVersion(void) { unsigned int version; int rv; __D("getVersion: entered\n"); if (!validate_init()) { return -1; } rv = ioctl(cmem_fd, CMEM_IOCGETVERSION | CMEM_IOCMAGIC, &version); if (rv != 0) { __E("getVersion: Failed to retrieve version from driver: %d.\n", rv); return -1; } __D("getVersion: exiting, ioctl CMEM_IOCGETVERSION returned %#x\n", version); return version; }
/* * Single interface into all flavors of alloc. * Need to support: * - cached vs. noncached * - heap vs. pool * - alignment w/ heap allocs */ static void *alloc(int blockid, size_t size, CMEM_AllocParams *params) { if (params == NULL) { params = &CMEM_DEFAULTPARAMS; } __D("alloc: entered w/ size %#x, params - type %s, flags %s, align %#x%s\n", size, params->type == CMEM_POOL ? "POOL" : "HEAP", params->flags & CMEM_CACHED ? "CACHED" : "NONCACHED", params->alignment, params == &CMEM_DEFAULTPARAMS ? " (default)" : ""); if (!validate_init()) { return NULL; } if (params->type == CMEM_POOL) { return getAndAllocFromPool(blockid, size, params); } else { return allocFromHeap(blockid, size, params); } }
// global sender initialize (not thread specific) iterator_t* send_init(void) { // generate a new primitive root and starting position iterator_t *it; it = iterator_init(zconf.senders, zconf.shard_num, zconf.total_shards); // process the dotted-notation addresses passed to ZMAP and determine // the source addresses from which we'll send packets; srcip_first = inet_addr(zconf.source_ip_first); if (srcip_first == INADDR_NONE) { log_fatal("send", "invalid begin source ip address: `%s'", zconf.source_ip_first); } srcip_last = inet_addr(zconf.source_ip_last); if (srcip_last == INADDR_NONE) { log_fatal("send", "invalid end source ip address: `%s'", zconf.source_ip_last); } log_debug("send", "srcip_first: %u", srcip_first); log_debug("send", "srcip_last: %u", srcip_last); if (srcip_first == srcip_last) { srcip_offset = 0; num_src_addrs = 1; } else { uint32_t ip_first = ntohl(srcip_first); uint32_t ip_last = ntohl(srcip_last); assert(ip_first && ip_last); assert(ip_last > ip_first); uint32_t offset = (uint32_t) (aesrand_getword(zconf.aes) & 0xFFFFFFFF); srcip_offset = offset % (srcip_last - srcip_first); num_src_addrs = ip_last - ip_first + 1; } // process the source port range that ZMap is allowed to use num_src_ports = zconf.source_port_last - zconf.source_port_first + 1; log_debug("send", "will send from %i address%s on %u source ports", num_src_addrs, ((num_src_addrs ==1 ) ? "":"es"), num_src_ports); // global initialization for send module assert(zconf.probe_module); if (zconf.probe_module->global_initialize) { zconf.probe_module->global_initialize(&zconf); } // concert specified bandwidth to packet rate if (zconf.bandwidth > 0) { int pkt_len = zconf.probe_module->packet_length; pkt_len *= 8; pkt_len += 8*24; // 7 byte MAC preamble, 1 byte Start frame, // 4 byte CRC, 12 byte inter-frame gap if (pkt_len < 84*8) { pkt_len = 84*8; } if (zconf.bandwidth / pkt_len > 0xFFFFFFFF) { zconf.rate = 0; } else { zconf.rate = zconf.bandwidth / pkt_len; if (zconf.rate == 0) { log_warn("send", "bandwidth %lu bit/s is slower than 1 pkt/s, " "setting rate to 1 pkt/s", zconf.bandwidth); zconf.rate = 1; } } log_debug("send", "using bandwidth %lu bits/s, rate set to %d pkt/s", zconf.bandwidth, zconf.rate); } // Get the source hardware address, and give it to the probe // module if (!zconf.hw_mac_set) { if (get_iface_hw_addr(zconf.iface, zconf.hw_mac)) { log_fatal("send", "could not retrieve hardware address for " "interface: %s", zconf.iface); return NULL; } log_debug("send", "no source MAC provided. " "automatically detected %02x:%02x:%02x:%02x:%02x:%02x as hw " "interface for %s", zconf.hw_mac[0], zconf.hw_mac[1], zconf.hw_mac[2], zconf.hw_mac[3], zconf.hw_mac[4], zconf.hw_mac[5], zconf.iface); } log_debug("send", "source MAC address %02x:%02x:%02x:%02x:%02x:%02x", zconf.hw_mac[0], zconf.hw_mac[1], zconf.hw_mac[2], zconf.hw_mac[3], zconf.hw_mac[4], zconf.hw_mac[5]); if (zconf.dryrun) { log_info("send", "dryrun mode -- won't actually send packets"); } // initialize random validation key validate_init(); zsend.start = now(); return it; }
// global sender initialize (not thread specific) int send_init(void) { // generate a new primitive root and starting position cyclic_init(0, 0); zsend.first_scanned = cyclic_get_curr_ip(); // compute number of targets uint64_t allowed = blacklist_count_allowed(); if (allowed == (1LL << 32)) { zsend.targets = 0xFFFFFFFF; } else { zsend.targets = allowed; } if (zsend.targets > zconf.max_targets) { zsend.targets = zconf.max_targets; } // process the dotted-notation addresses passed to ZMAP and determine // the source addresses from which we'll send packets; srcip_first = inet_addr(zconf.source_ip_first); if (srcip_first == INADDR_NONE) { log_fatal("send", "invalid begin source ip address: `%s'", zconf.source_ip_first); } srcip_last = inet_addr(zconf.source_ip_last); if (srcip_last == INADDR_NONE) { log_fatal("send", "invalid end source ip address: `%s'", zconf.source_ip_last); } if (srcip_first == srcip_last) { srcip_offset = 0; num_addrs = 1; } else { srcip_offset = rand() % (srcip_last - srcip_first); num_addrs = ntohl(srcip_last) - ntohl(srcip_first) + 1; } // process the source port range that ZMap is allowed to use num_src_ports = zconf.source_port_last - zconf.source_port_first + 1; log_debug("send", "will send from %i address%s on %u source ports", num_addrs, ((num_addrs==1)?"":"es"), num_src_ports); // global initialization for send module assert(zconf.probe_module); if (zconf.probe_module->global_initialize) { zconf.probe_module->global_initialize(&zconf); } // concert specified bandwidth to packet rate if (zconf.bandwidth > 0) { int pkt_len = zconf.probe_module->packet_length; pkt_len *= 8; pkt_len += 8*24; // 7 byte MAC preamble, 1 byte Start frame, // 4 byte CRC, 12 byte inter-frame gap if (pkt_len < 84*8) { pkt_len = 84*8; } if (zconf.bandwidth / pkt_len > 0xFFFFFFFF) { zconf.rate = 0; } else { zconf.rate = zconf.bandwidth / pkt_len; if (zconf.rate == 0) { log_warn("send", "bandwidth %lu bit/s is slower than 1 pkt/s, " "setting rate to 1 pkt/s", zconf.bandwidth); zconf.rate = 1; } } log_debug("send", "using bandwidth %lu bits/s, rate set to %d pkt/s", zconf.bandwidth, zconf.rate); } if (zconf.dryrun) { log_info("send", "dryrun mode -- won't actually send packets"); } // initialize random validation key validate_init(); zsend.start = now(); return EXIT_SUCCESS; }