/* * Insert an additional listener in to the sorted list of listeners */ void add_listener(struct Listener_head *listeners, struct Listener *listener) { assert(listeners != NULL); assert(listener != NULL); assert(listener->address != NULL); listener_ref_get(listener); if (SLIST_FIRST(listeners) == NULL || address_compare(listener->address, SLIST_FIRST(listeners)->address) < 0) { SLIST_INSERT_HEAD(listeners, listener, entries); return; } struct Listener *iter; SLIST_FOREACH(iter, listeners, entries) { if (SLIST_NEXT(iter, entries) == NULL || address_compare(listener->address, SLIST_NEXT(iter, entries)->address) < 0) { SLIST_INSERT_AFTER(iter, listener, entries); return; } } }
void ngram(const char *word, size_t len, size_t gramsize) { char *c = 0; size_t i = 0; struct gram *prevgram = NULL; SLIST_INIT(&grams_head); c = (char *) word; while (iscntrl(*c) == 0) { struct gram *newgram = init_gram(gramsize); i = 0; while (i < gramsize && iscntrl(*c) == 0) newgram ->buf[++i] = *c++; newgram->buf[i] = '\0'; if (prevgram == NULL) SLIST_INSERT_HEAD(&grams_head, newgram, grams); else SLIST_INSERT_AFTER(prevgram, newgram, grams); prevgram = newgram; } }
/* Read and parse a configuration file */ void read_config(const char *filename) { char buf[5000], plugin_name[50], plugin_path[100]; char plugin_data_name[100]; FILE *f, *fs; char *p; int line = 0; void *handle; enum sections { Servers, Options, Plugin } section = Servers; struct plugins_data *plugins_data; struct plugin_options *popt, *last_popt = NULL; if ((f = fopen(filename, "r")) == NULL) errx(1, "Can't open: %s", filename); while (fgets(buf, sizeof(buf), f) != NULL) { line++; /* Ignore empty lines and comments */ if (buf[0] == '\n' || buf[0] == '#') continue; /* strip \n */ if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; /* A new section starts */ if (buf[0] == '[') { p = strchr(buf, ']'); if (p == NULL || *(p + 1) != '\0') errx(1, "Config file syntax error. Line: %d", line); *p = '\0'; if (strcasecmp(buf + 1, "servers") == 0) { section = Servers; continue; } if (strcasecmp(buf + 1, "options") == 0) { section = Options; continue; } if ((p = strcasestr(buf, "-plugin")) != NULL) { if (plugins_number > MAX_PLUGINS - 1) errx(1, "Too many plugins. Line: %d", line); section = Plugin; *p = '\0'; strlcpy(plugin_name, buf + 1, sizeof(plugin_name)); strlcpy(plugin_data_name, plugin_name, sizeof(plugin_data_name)); strlcat(plugin_data_name, "_plugin", sizeof(plugin_data_name)); strlcpy(plugin_path, plugin_base, sizeof(plugin_path)); strlcat(plugin_path, "dhcprelya_", sizeof(plugin_path)); strlcat(plugin_path, plugin_name, sizeof(plugin_path)); strlcat(plugin_path, "_plugin.so", sizeof(plugin_path)); handle = dlopen(plugin_path, RTLD_LAZY); if (handle == NULL) { printf("dlerror(): %s\n", dlerror()); errx(1, "Can't open plugin: %s", plugin_path); } plugins_data = dlsym(handle, plugin_data_name); if (plugins_data == NULL) errx(1, "Can't load symbol %s", plugin_data_name); plugins[plugins_number] = malloc(sizeof(struct plugin_data)); if (plugins[plugins_number] == NULL) process_error(EX_MEM, "malloc"); memcpy(plugins[plugins_number], plugins_data, sizeof(struct plugin_data)); /* head for options list for this plugin */ options_heads[plugins_number] = malloc(sizeof(plugin_options_head_t)); if (options_heads[plugins_number] == NULL) process_error(EX_MEM, "malloc"); SLIST_INIT(options_heads[plugins_number]); plugins_number++; logd(LOG_DEBUG, "Plugin #%d (%s) loaded", plugins_number, plugin_name); continue; } errx(1, "Section name error. Line: %d", line); } if (section == Servers) { if ((p = strchr(buf, '=')) == NULL) parse_servers_line(buf); else { *p = '\0'; p++; if (strcasecmp(buf, "file") != 0) errx(1, "Unknown option in Server section. Line: %d", line); if ((fs = fopen(p, "r")) == NULL) errx(1, "Can't open servers config file: %s", p); while (fgets(buf, sizeof(buf), fs) != NULL) { /* Ignore empty lines and comments */ if (buf[0] == '\n' || buf[0] == '#') continue; /* strip \n */ if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; parse_servers_line(buf); } fclose(fs); } } if (section == Options) { p = strchr(buf, '='); if (p == NULL) errx(1, "Option error. Line: %d", line); *p = '\0'; p++; if (strcasecmp(buf, "max_packet_size") == 0) { max_packet_size = strtol(p, NULL, 10); if (max_packet_size < 300 || max_packet_size > DHCP_MTU_MAX) errx(1, "Wrong packet size. Line: %d", line); logd(LOG_DEBUG, "Option max_packet_size set to: %d", max_packet_size); continue; } if (strcasecmp(buf, "max_hops") == 0) { max_hops = strtol(p, NULL, 10); if (max_hops < 1 || max_hops > 16) errx(1, "Wrong hops number. Line: %d", line); logd(LOG_DEBUG, "Option max_hops set to: %d", max_hops); continue; } if (strcasecmp(buf, "rps_limit") == 0) { errno = 0; rps_limit = strtol(p, NULL, 10); if (errno != 0) errx(1, "rps_limit number error"); logd(LOG_DEBUG, "Option rps_limit set to: %d", rps_limit); continue; } if (strcasecmp(buf, "plugin_path") == 0) { strlcpy(plugin_base, p, sizeof(plugin_base)); if (plugin_base[strlen(plugin_base) - 1] != '/') strlcat(plugin_base, "/", sizeof(plugin_base)); logd(LOG_DEBUG, "Option plugin_base set to: %s", plugin_base); continue; } errx(1, "Unknown option. Line: %d", line); } if (section == Plugin) { popt = malloc(sizeof(struct plugin_options)); if (popt == NULL) process_error(EX_MEM, "malloc"); popt->option_line = malloc(strlen(buf) + 1); if (popt->option_line == NULL) process_error(EX_MEM, "malloc"); strcpy(popt->option_line, buf); if (SLIST_EMPTY(options_heads[plugins_number - 1])) { SLIST_INSERT_HEAD(options_heads[plugins_number - 1], popt, next); last_popt = popt; } else { SLIST_INSERT_AFTER(last_popt, popt, next); last_popt = popt; } } } fclose(f); if (if_num == 0) errx(1, "No interfaces found to listen. Exiting."); }
void symtable_dump(FILE *ofile) { /* * Sort the registers by address with a simple insertion sort. * Put bitmasks next to the first register that defines them. * Put constants at the end. */ symlist_t registers; symlist_t masks; symlist_t constants; symlist_t download_constants; symlist_t aliases; symlist_t exported_labels; u_int i; SLIST_INIT(®isters); SLIST_INIT(&masks); SLIST_INIT(&constants); SLIST_INIT(&download_constants); SLIST_INIT(&aliases); SLIST_INIT(&exported_labels); if (symtable != NULL) { DBT key; DBT data; int flag = R_FIRST; while (symtable->seq(symtable, &key, &data, flag) == 0) { symbol_t *cursym; memcpy(&cursym, data.data, sizeof(cursym)); switch(cursym->type) { case REGISTER: case SCBLOC: case SRAMLOC: symlist_add(®isters, cursym, SYMLIST_SORT); break; case MASK: case BIT: symlist_add(&masks, cursym, SYMLIST_SORT); break; case CONST: symlist_add(&constants, cursym, SYMLIST_INSERT_HEAD); break; case DOWNLOAD_CONST: symlist_add(&download_constants, cursym, SYMLIST_INSERT_HEAD); break; case ALIAS: symlist_add(&aliases, cursym, SYMLIST_INSERT_HEAD); break; case LABEL: if (cursym->info.linfo->exported == 0) break; symlist_add(&exported_labels, cursym, SYMLIST_INSERT_HEAD); break; default: break; } flag = R_NEXT; } /* Put in the masks and bits */ while (SLIST_FIRST(&masks) != NULL) { symbol_node_t *curnode; symbol_node_t *regnode; char *regname; curnode = SLIST_FIRST(&masks); SLIST_REMOVE_HEAD(&masks, links); regnode = SLIST_FIRST(&curnode->symbol->info.minfo->symrefs); regname = regnode->symbol->name; regnode = symlist_search(®isters, regname); SLIST_INSERT_AFTER(regnode, curnode, links); } /* Add the aliases */ while (SLIST_FIRST(&aliases) != NULL) { symbol_node_t *curnode; symbol_node_t *regnode; char *regname; curnode = SLIST_FIRST(&aliases); SLIST_REMOVE_HEAD(&aliases, links); regname = curnode->symbol->info.ainfo->parent->name; regnode = symlist_search(®isters, regname); SLIST_INSERT_AFTER(regnode, curnode, links); } /* Output what we have */ fprintf(ofile, "/* * DO NOT EDIT - This file is automatically generated * from the following source files: * %s */\n", versions); while (SLIST_FIRST(®isters) != NULL) { symbol_node_t *curnode; u_int value; char *tab_str; char *tab_str2; curnode = SLIST_FIRST(®isters); SLIST_REMOVE_HEAD(®isters, links); switch(curnode->symbol->type) { case REGISTER: case SCBLOC: case SRAMLOC: fprintf(ofile, "\n"); value = curnode->symbol->info.rinfo->address; tab_str = "\t"; tab_str2 = "\t\t"; break; case ALIAS: { symbol_t *parent; parent = curnode->symbol->info.ainfo->parent; value = parent->info.rinfo->address; tab_str = "\t"; tab_str2 = "\t\t"; break; } case MASK: case BIT: value = curnode->symbol->info.minfo->mask; tab_str = "\t\t"; tab_str2 = "\t"; break; default: value = 0; /* Quiet compiler */ tab_str = NULL; tab_str2 = NULL; stop("symtable_dump: Invalid symbol type " "encountered", EX_SOFTWARE); break; } fprintf(ofile, "#define%s%-16s%s0x%02x\n", tab_str, curnode->symbol->name, tab_str2, value); free(curnode); } fprintf(ofile, "\n\n"); while (SLIST_FIRST(&constants) != NULL) { symbol_node_t *curnode; curnode = SLIST_FIRST(&constants); SLIST_REMOVE_HEAD(&constants, links); fprintf(ofile, "#define\t%-8s\t0x%02x\n", curnode->symbol->name, curnode->symbol->info.cinfo->value); free(curnode); } fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n"); for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) { symbol_node_t *curnode; curnode = SLIST_FIRST(&download_constants); SLIST_REMOVE_HEAD(&download_constants, links); fprintf(ofile, "#define\t%-8s\t0x%02x\n", curnode->symbol->name, curnode->symbol->info.cinfo->value); free(curnode); } fprintf(ofile, "#define\tDOWNLOAD_CONST_COUNT\t0x%02x\n", i); fprintf(ofile, "\n\n/* Exported Labels */\n"); while (SLIST_FIRST(&exported_labels) != NULL) { symbol_node_t *curnode; curnode = SLIST_FIRST(&exported_labels); SLIST_REMOVE_HEAD(&exported_labels, links); fprintf(ofile, "#define\tLABEL_%-8s\t0x%02x\n", curnode->symbol->name, curnode->symbol->info.linfo->address); free(curnode); } }
void symlist_add(symlist_t *symlist, symbol_t *symbol, int how) { symbol_node_t *newnode; newnode = (symbol_node_t *)malloc(sizeof(symbol_node_t)); if (newnode == NULL) { stop("symlist_add: Unable to malloc symbol_node", EX_SOFTWARE); /* NOTREACHED */ } newnode->symbol = symbol; if (how == SYMLIST_SORT) { symbol_node_t *curnode; int mask; mask = FALSE; switch(symbol->type) { case REGISTER: case SCBLOC: case SRAMLOC: break; case BIT: case MASK: mask = TRUE; break; default: stop("symlist_add: Invalid symbol type for sorting", EX_SOFTWARE); /* NOTREACHED */ } curnode = SLIST_FIRST(symlist); if (curnode == NULL || (mask && (curnode->symbol->info.minfo->mask > newnode->symbol->info.minfo->mask)) || (!mask && (curnode->symbol->info.rinfo->address > newnode->symbol->info.rinfo->address))) { SLIST_INSERT_HEAD(symlist, newnode, links); return; } while (1) { if (SLIST_NEXT(curnode, links) == NULL) { SLIST_INSERT_AFTER(curnode, newnode, links); break; } else { symbol_t *cursymbol; cursymbol = SLIST_NEXT(curnode, links)->symbol; if ((mask && (cursymbol->info.minfo->mask > symbol->info.minfo->mask)) || (!mask &&(cursymbol->info.rinfo->address > symbol->info.rinfo->address))){ SLIST_INSERT_AFTER(curnode, newnode, links); break; } } curnode = SLIST_NEXT(curnode, links); } } else { SLIST_INSERT_HEAD(symlist, newnode, links); } }
/* * Load new table/tables to device. * Call apropriate target init routine open all physical pdev's and * link them to device. For other targets mirror, strip, snapshot * etc. also add dependency devices to upcalls list. * * Load table to inactive slot table are switched in dm_device_resume_ioctl. * This simulates Linux behaviour better there should not be any difference. * */ int dm_table_load_ioctl(prop_dictionary_t dm_dict) { dm_dev_t *dmv; dm_table_entry_t *table_en, *last_table; dm_table_t *tbl; dm_target_t *target; prop_object_iterator_t iter; prop_array_t cmd_array; prop_dictionary_t target_dict; const char *name, *uuid, *type; uint32_t flags, ret, minor; char *str; ret = 0; flags = 0; name = NULL; uuid = NULL; dmv = NULL; last_table = NULL; str = NULL; /* * char *xml; xml = prop_dictionary_externalize(dm_dict); * printf("%s\n",xml); */ prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_NAME, &name); prop_dictionary_get_cstring_nocopy(dm_dict, DM_IOCTL_UUID, &uuid); prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags); prop_dictionary_get_uint32(dm_dict, DM_IOCTL_MINOR, &minor); cmd_array = prop_dictionary_get(dm_dict, DM_IOCTL_CMD_DATA); iter = prop_array_iterator(cmd_array); dm_dbg_print_flags(flags); if ((dmv = dm_dev_lookup(name, uuid, minor)) == NULL) { DM_REMOVE_FLAG(flags, DM_EXISTS_FLAG); return ENOENT; } aprint_debug("Loading table to device: %s--%d\n", name, dmv->table_head.cur_active_table); /* * I have to check if this table slot is not used by another table list. * if it is used I should free them. */ if (dmv->flags & DM_INACTIVE_PRESENT_FLAG) dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE); dm_dbg_print_flags(dmv->flags); tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_INACTIVE); aprint_debug("dmv->name = %s\n", dmv->name); prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor); while ((target_dict = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(target_dict, DM_TABLE_TYPE, &type); /* * If we want to deny table with 2 or more different * target we should do it here */ if (((target = dm_target_lookup(type)) == NULL) && ((target = dm_target_autoload(type)) == NULL)) { dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE); dm_dev_unbusy(dmv); return ENOENT; } if ((table_en = kmalloc(sizeof(dm_table_entry_t), M_DM, M_WAITOK)) == NULL) { dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE); dm_dev_unbusy(dmv); dm_target_unbusy(target); return ENOMEM; } prop_dictionary_get_uint64(target_dict, DM_TABLE_START, &table_en->start); prop_dictionary_get_uint64(target_dict, DM_TABLE_LENGTH, &table_en->length); aprint_debug("dm_ioctl.c... table_en->start = %ju, " "table_en->length = %ju\n", (uintmax_t)table_en->start, (uintmax_t)table_en->length); table_en->target = target; table_en->dm_dev = dmv; table_en->target_config = NULL; /* * There is a parameter string after dm_target_spec * structure which points to /dev/wd0a 284 part of * table. String str points to this text. This can be * null and therefore it should be checked before we try to * use it. */ prop_dictionary_get_cstring(target_dict, DM_TABLE_PARAMS, &str); if (SLIST_EMPTY(tbl)) /* insert this table to head */ SLIST_INSERT_HEAD(tbl, table_en, next); else SLIST_INSERT_AFTER(last_table, table_en, next); /* * Params string is different for every target, * therfore I have to pass it to target init * routine and parse parameters there. */ aprint_debug("DM: str passed in is: %s", str); if ((ret = target->init(dmv, &table_en->target_config, str)) != 0) { dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE); dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE); kfree(str, M_TEMP); dm_dev_unbusy(dmv); dm_target_unbusy(target); return ret; } last_table = table_en; kfree(str, M_TEMP); } prop_object_iterator_release(iter); DM_ADD_FLAG(flags, DM_INACTIVE_PRESENT_FLAG); atomic_set_int(&dmv->flags, DM_INACTIVE_PRESENT_FLAG); dm_table_release(&dmv->table_head, DM_TABLE_INACTIVE); dm_dev_unbusy(dmv); #if 0 dmsetdiskinfo(dmv->diskp, &dmv->table_head); #endif return 0; }
void emulate_constructor(dmp_ctx_t *ctx, uint64_t constructor_address, struct hierarchy_entry_head *head) { if (!ctx) return; if (!ctx->kimage_mh || !ctx->map || !ctx->reg_map) return; uint64_t kimage_base = find_kimage_base(ctx->kimage_mh); uint64_t kimage_os_metaclass_constructor = find_kimage_os_metaclass_constructor(ctx->kimage_mh, kimage_base); csh handle; cs_insn *insn; size_t count; cs_regs regs_read = {0}, regs_write = {0}; uint8_t read_count, write_count; if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &handle) != CS_ERR_OK) return; cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); uint8_t *constructor_code = (uint8_t *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, constructor_address); uint64_t constructor_size = get_constructor_size(ctx->kimage_mh, constructor_address, kimage_base); count = cs_disasm(handle, constructor_code, constructor_size, constructor_address, 0, &insn); if (count > 0) { size_t j; for (j = 0; j < count; j++) { if (cs_regs_access(handle, &insn[j], regs_read, &read_count, regs_write, &write_count) == 0) { switch (insn[j].id) { case ARM64_INS_ADR: { uint64_t adr_addr = 0; int is_adrp = 0; uint32_t rd = 0; int32_t off = 0; if (aarch64_decode_adr(*(uint32_t *)(&insn[j].bytes), &is_adrp, &rd, &off)) { adr_addr = insn[j].address + off; } get_ctx_reg_map_reg(ctx, regs_write[0]) = adr_addr; break; } case ARM64_INS_ADRP: { uint64_t adr_addr = 0; int is_adrp = 0; uint32_t rd = 0; int32_t off = 0; if (aarch64_decode_adr(*(uint32_t *)(&insn[j].bytes), &is_adrp, &rd, &off)) { adr_addr = ((insn[j].address + off) >> 12) << 12; } get_ctx_reg_map_reg(ctx, regs_write[0]) = adr_addr; break; } case ARM64_INS_LDR: { uint64_t ldr_addr = 0; int is_w = 0; int is64 = 0; uint32_t rt = 0; int32_t s_off = 0; uint32_t u_off = 0; if (aarch64_decode_ldr_literal(*(uint32_t *)(&insn[j].bytes), &is_w, &is64, &rt, &s_off)) { ldr_addr = insn[j].address + s_off; uint64_t ldr_deref = *(uint64_t *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, ldr_addr); get_ctx_reg_map_reg(ctx, regs_write[0]) = ldr_deref; } else if (aarch64_decode_ldr_immediate(*(uint32_t *)(&insn[j].bytes), &u_off)) { uint64_t op1 = get_ctx_reg_map_reg(ctx, regs_read[0]); op1 += u_off; uint64_t ldr_addr = *(uint64_t *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, op1); get_ctx_reg_map_reg(ctx, regs_write[0]) = ldr_addr; } break; } case ARM64_INS_ADD: { uint32_t off = 0; if (aarch64_decode_add(*(uint32_t *)(&insn[j].bytes), &off)) { uint64_t op1 = get_ctx_reg_map_reg(ctx, regs_read[0]); op1 += off; get_ctx_reg_map_reg(ctx, regs_write[0]) = op1; } break; } case ARM64_INS_MOV: { uint64_t op1 = get_ctx_reg_map_reg(ctx, regs_read[0]); get_ctx_reg_map_reg(ctx, regs_write[0]) = op1; break; } /* ugly. libdump should be independent of iokitdumper, but I was lazy and this was the quickest way to map constructors lmao */ case ARM64_INS_BL: { int is_bl = 0; int32_t off = 0; if (aarch64_decode_b(*(uint32_t *)(&insn[j].bytes), &is_bl, &off)) { if (insn[j].address + off == kimage_os_metaclass_constructor) { const char *kext_name = get_kext_name(ctx->map, ctx->kimage_mh); struct hierarchy_entry *entry = malloc(sizeof(struct hierarchy_entry)); strncpy(entry->class_name, (char *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, get_ctx_reg_map_reg(ctx, REG_X1)), sizeof(entry->class_name)); if (kext_name) strncpy(entry->kext_name, kext_name, sizeof(entry->kext_name)); else { if (((void *)ctx->map->map_data == (void *)ctx->kimage_mh)) { strncpy(entry->kext_name, "kernel", sizeof(entry->kext_name)); } else { strncpy(entry->kext_name, "unknown", sizeof(entry->kext_name)); } } struct hierarchy_regs_set set = {0}; set.reg_x0 = get_ctx_reg_map_reg(ctx, REG_X0); set.reg_x1 = get_ctx_reg_map_reg(ctx, REG_X1); set.reg_x2 = get_ctx_reg_map_reg(ctx, REG_X2); entry->set = set; if (head) { if (SLIST_EMPTY(head)) { SLIST_INSERT_HEAD(head, entry, entries); prev = entry; } else { SLIST_INSERT_AFTER(prev, entry, entries); prev = entry; } } else { free(entry); } } } break; } } } }