static void set_encoding(struct encoding **encoding_ref, const char *arg, bool priority) { if (!strcasecmp(arg, "utf-8") || !strcasecmp(arg, "utf8")) return; if (parse_encoding(encoding_ref, arg, priority) == SUCCESS) encoding_arg[0] = 0; }
static void parse_cmdline(int *argcp, char ***argvp) { cfg_load_global_config_file(); w_getopt(opts, argcp, argvp, &daemon_argv); if (show_help) { usage(opts, stdout); } if (show_version) { printf("%s\n", PACKAGE_VERSION); exit(0); } setup_sock_name(); parse_encoding(server_encoding, &server_pdu); parse_encoding(output_encoding, &output_pdu); if (!output_encoding) { output_pdu = no_pretty ? is_json_compact : is_json_pretty; } }
static void set_encoding(struct encoding **encoding_ref, const char *arg, bool priority) { if (parse_encoding(encoding_ref, arg, priority) == SUCCESS) encoding_arg[0] = 0; }
static void parse_cff_bytecode(cff_File *cff, const otfcc_Options *options) { uint32_t pos; int32_t offset; /* Header */ cff->head.major = gu1(cff->raw_data, 0); cff->head.minor = gu1(cff->raw_data, 1); cff->head.hdrSize = gu1(cff->raw_data, 2); cff->head.offSize = gu1(cff->raw_data, 3); /* Name INDEX */ pos = cff->head.hdrSize; cff_iIndex.parse(cff->raw_data, pos, &cff->name); /* Top Dict INDEX */ pos = 4 + cff_iIndex.getLength(&cff->name); cff_iIndex.parse(cff->raw_data, pos, &cff->top_dict); /** LINT CFF FONTSET **/ if (cff->name.count != cff->top_dict.count) logWarning("[libcff] Bad CFF font: (%d, name), (%d, top_dict).\n", cff->name.count, cff->top_dict.count); /* String INDEX */ pos = 4 + cff_iIndex.getLength(&cff->name) + cff_iIndex.getLength(&cff->top_dict); cff_iIndex.parse(cff->raw_data, pos, &cff->string); /* Global Subr INDEX */ pos = 4 + cff_iIndex.getLength(&cff->name) + cff_iIndex.getLength(&cff->top_dict) + cff_iIndex.getLength(&cff->string); cff_iIndex.parse(cff->raw_data, pos, &cff->global_subr); if (cff->top_dict.data != NULL) { int32_t offset; // cff->topdict.dict = calloc(1, sizeof(cff_Dict)); // cff->topdict.dict = cff_extract_Dict(cff->top_dict.data, cff->top_dict.offset[1] - // cff->top_dict.offset[0]); /* CharStrings INDEX */ offset = cff_iDict .parseDictKey(cff->top_dict.data, cff->top_dict.offset[1] - cff->top_dict.offset[0], op_CharStrings, 0) .i; if (offset != -1) { cff_iIndex.parse(cff->raw_data, offset, &cff->char_strings); cff->cnt_glyph = cff->char_strings.count; } else { cff_iIndex.empty(&cff->char_strings); logWarning("[libcff] Bad CFF font: no any glyph data.\n"); } /* Encodings */ offset = cff_iDict .parseDictKey(cff->top_dict.data, cff->top_dict.offset[1] - cff->top_dict.offset[0], op_Encoding, 0) .i; if (offset != -1) { parse_encoding(cff, offset, &cff->encodings); } else { cff->encodings.t = cff_ENC_UNSPECED; } /* Charsets */ offset = cff_iDict.parseDictKey(cff->top_dict.data, cff->top_dict.offset[1] - cff->top_dict.offset[0], op_charset, 0) .i; if (offset != -1) { cff_extract_Charset(cff->raw_data, offset, cff->char_strings.count, &cff->charsets); } else { cff->charsets.t = cff_CHARSET_UNSPECED; } /* FDSelect */ offset = cff_iDict .parseDictKey(cff->top_dict.data, cff->top_dict.offset[1] - cff->top_dict.offset[0], op_FDSelect, 0) .i; if (cff->char_strings.count && offset != -1) { cff_extract_FDSelect(cff->raw_data, offset, cff->char_strings.count, &cff->fdselect); } else { cff->fdselect.t = cff_FDSELECT_UNSPECED; } /* Font Dict INDEX */ offset = cff_iDict.parseDictKey(cff->top_dict.data, cff->top_dict.offset[1] - cff->top_dict.offset[0], op_FDArray, 0) .i; if (offset != -1) { cff_iIndex.parse(cff->raw_data, offset, &cff->font_dict); } else { cff_iIndex.empty(&cff->font_dict); } } /* Private and Local Subr */ { int32_t private_len = -1; int32_t private_off = -1; if (cff->top_dict.data != NULL) { private_len = cff_iDict .parseDictKey(cff->top_dict.data, cff->top_dict.offset[1] - cff->top_dict.offset[0], op_Private, 0) .i; private_off = cff_iDict .parseDictKey(cff->top_dict.data, cff->top_dict.offset[1] - cff->top_dict.offset[0], op_Private, 1) .i; } if (private_off != -1 && private_len != -1) { offset = cff_iDict.parseDictKey(cff->raw_data + private_off, private_len, op_Subrs, 0).i; if (offset != -1) cff_iIndex.parse(cff->raw_data, private_off + offset, &cff->local_subr); else cff_iIndex.empty(&cff->local_subr); } else { cff_iIndex.empty(&cff->local_subr); } } }
int main(int argc, char **argv) { char *errormsg = NULL; #ifndef WINDOWS32 struct passwd *pw = NULL; #endif int choice = -1; int retval = 0; char *username = NULL; char *newroot = NULL; char *context = NULL; char *device = NULL; char *pidfile = NULL; int remote_forward_port = 0; char *nameserv_host = NULL; struct sockaddr_storage nameservaddr; int nameservaddr_len = 0; int nameserv_family = AF_UNSPEC; #ifdef WINDOWS32 WSAStartup(req_version, &wsa_data); #endif #if !defined(BSD) && !defined(__GLIBC__) __progname = strrchr(argv[0], '/'); if (__progname == NULL) __progname = argv[0]; else __progname++; #endif #define OPT_RDOMAIN 0x80 #define OPT_NODROP 0x81 /* each option has format: * char *name, int has_arg, int *flag, int val */ static struct option iodine_args[] = { {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"stats", optional_argument, 0, 'V'}, {"context", required_argument, 0, 'z'}, {"rdomain", required_argument, 0, OPT_RDOMAIN}, {"chrootdir", required_argument, 0, 't'}, {"preset", required_argument, 0, 'Y'}, {"proxycommand", no_argument, 0, 'R'}, // {"nodrop", no_argument, 0, OPT_NODROP}, {"remote", required_argument, 0, 'R'}, {NULL, 0, 0, 0} }; /* Pre-parse command line to get preset * This is so that all options override preset values regardless of order in command line */ int optind_orig = optind, preset_id = -1; static char *iodine_args_short = "46vfDhrY:s:V:c:C:i:j:u:t:d:R:P:w:W:m:M:F:T:O:L:I:"; while ((choice = getopt_long(argc, argv, iodine_args_short, iodine_args, NULL))) { /* Check if preset has been found yet so we don't process any other options */ if (preset_id < 0) { if (choice == -1) { /* reached end of command line and no preset specified - use default */ preset_id = 0; } else if (choice == 'Y') { /* find index of preset */ if (optarg) { for (int i = 0; i < NUM_CLIENT_PRESETS; i++) { if (toupper(optarg[0]) == client_presets[i].short_name) { preset_id = i; break; } } } } else if (choice == '?') { usage(); /* Not reached */ } else { /* skip all other options until we find preset */ continue; } if (preset_id < 0) { /* invalid preset or none specified */ fprintf(stderr, "Invalid preset or none specified with -Y or --preset!\n"); print_presets(2); usage(); /* not reached */ } memcpy(&this, client_presets[preset_id].preset_data, sizeof(struct client_instance)); /* Reset optind to reparse command line */ optind = optind_orig; continue; } else if (choice == -1) { break; } /* Once a preset is used, it is copied into memory. This way other * options can override preset values regardless of order in command line */ switch (choice) { case '4': nameserv_family = AF_INET; break; case '6': nameserv_family = AF_INET6; break; case 'v': version(); /* NOTREACHED */ break; case 'V': this.stats = atoi(optarg); if (this.stats < 0) this.stats = 0; break; case 'f': this.foreground = 1; break; case 'D': this.debug++; break; case 'h': help(); /* NOTREACHED */ break; case 'r': this.raw_mode = 0; break; case 'u': username = optarg; break; case 't': newroot = optarg; break; case 'd': device = optarg; break; #ifdef OPENBSD case OPT_RDOMAIN: rtable = atoi(optarg); break; #endif case 'R': /* Argument format: [host:]port */ if (!optarg) break; this.use_remote_forward = 1; remote_forward_port = parse_tcp_forward_option(optarg); break; case OPT_NODROP: // TODO implement TCP-over-tun optimisations break; case 'P': strncpy(this.password, optarg, sizeof(this.password)); this.password[sizeof(this.password)-1] = 0; /* XXX: find better way of cleaning up ps(1) */ memset(optarg, 0, strlen(optarg)); break; case 'm': this.autodetect_frag_size = 0; this.max_downstream_frag_size = atoi(optarg); break; case 'M': this.hostname_maxlen = atoi(optarg); if (this.hostname_maxlen > 255) this.hostname_maxlen = 255; if (this.hostname_maxlen < 10) this.hostname_maxlen = 10; break; case 'z': context = optarg; break; case 'F': pidfile = optarg; break; case 'T': if (client_set_qtype(optarg)) errx(5, "Invalid query type '%s'", optarg); break; case 'O': if ((this.downenc = parse_encoding(optarg)) == 0) errx(6, "Invalid encoding type '%s'", optarg); break; case 'L': this.lazymode = atoi(optarg); if (this.lazymode > 1) this.lazymode = 1; if (this.lazymode < 0) this.lazymode = 0; break; case 'I': this.max_timeout_ms = strtod(optarg, NULL) * 1000; if (this.autodetect_server_timeout) { this.server_timeout_ms = this.max_timeout_ms / 2; } break; case 'i': this.server_timeout_ms = strtod(optarg, NULL) * 1000; this.autodetect_server_timeout = 0; break; case 'j': this.downstream_timeout_ms = strtod(optarg, NULL) * 1000; if (this.autodetect_server_timeout) { this.autodetect_server_timeout = 0; this.server_timeout_ms = 4000; } break; case 's': this.send_interval_ms = atoi(optarg); if (this.send_interval_ms < 0) this.send_interval_ms = 0; case 'w': this.windowsize_down = atoi(optarg); break; case 'W': this.windowsize_up = atoi(optarg); break; case 'c': this.compression_down = atoi(optarg) & 1; break; case 'C': this.compression_up = atoi(optarg) & 1; break; case 'Y': /* Already processed preset: ignore */ continue; default: usage(); /* NOTREACHED */ } } srand((unsigned) time(NULL)); this.rand_seed = (uint16_t) rand(); this.chunkid = (uint16_t) rand(); this.running = 1; check_superuser(usage); argc -= optind; argv += optind; if (this.debug) { fprintf(stderr, "Debug level %d enabled, will stay in foreground.\n", this.debug); fprintf(stderr, "Add more -D switches to set higher debug level.\n"); this.foreground = 1; } this.nameserv_hosts_len = argc - 1; if (this.nameserv_hosts_len <= 0) /* if no hosts specified, use resolv.conf */ this.nameserv_hosts_len = 1; // Preallocate memory with expected number of hosts this.nameserv_hosts = malloc(sizeof(char *) * this.nameserv_hosts_len); this.nameserv_addrs = malloc(sizeof(struct sockaddr_storage) * this.nameserv_hosts_len); if (argc == 0) { usage(); /* NOT REACHED */ } else if (argc == 1) { this.nameserv_hosts[0] = get_resolvconf_addr(); } else if (argc > 1) for (int h = 0; h < this.nameserv_hosts_len; h++) this.nameserv_hosts[h] = strdup(argv[h + 1]); this.topdomain = strdup(argv[0]); for (int n = 0; n < this.nameserv_hosts_len; n++) { nameserv_host = this.nameserv_hosts[n]; if (!nameserv_host) { errx(1, "Error processing nameserver hostnames!"); } nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr); if (nameservaddr_len < 0) { errx(1, "Cannot lookup nameserver '%s': %s ", nameserv_host, gai_strerror(nameservaddr_len)); } memcpy(&this.nameserv_addrs[n], &nameservaddr, sizeof(struct sockaddr_storage)); this.nameserv_addrs_len ++; nameserv_host = NULL; } if (this.nameserv_addrs_len <= 0 || !this.nameserv_hosts[0]) { warnx("No nameservers found - not connected to any network?"); usage(); } if (this.max_downstream_frag_size < 10 || this.max_downstream_frag_size > MAX_FRAGSIZE) { warnx("Use a max frag size between 10 and %d bytes.", MAX_FRAGSIZE); usage(); /* NOTREACHED */ } if(check_topdomain(this.topdomain, &errormsg)) { warnx("Invalid topdomain: %s", errormsg); usage(); /* NOTREACHED */ } int max_ws = MAX_SEQ_ID / 2; if (this.windowsize_up < 1 || this.windowsize_down < 1 || this.windowsize_up > max_ws || this.windowsize_down > max_ws) { warnx("Window sizes (-w or -W) must be between 0 and %d!", max_ws); usage(); } if (this.max_timeout_ms < 100) { warnx("Target interval (-I) must be greater than 0.1 seconds!"); usage(); } if ((this.server_timeout_ms < 100 || this.server_timeout_ms >= this.max_timeout_ms) && !this.autodetect_server_timeout) { warnx("Server timeout (-i) must be greater than 0.1 sec and less than target interval!"); usage(); } if (this.downstream_timeout_ms < 100) { warnx("Downstream fragment timeout must be more than 0.1 sec to prevent excessive retransmits."); usage(); } if (!this.lazymode && this.max_timeout_ms > 1000) { fprintf(stderr, "Warning: Target interval of >1 second in immediate mode will cause high latency.\n"); } if (username != NULL) { #ifndef WINDOWS32 if ((pw = getpwnam(username)) == NULL) { warnx("User %s does not exist!", username); usage(); /* NOTREACHED */ } #else warnx("Warning: Cannot switch user on Windows systems."); #endif } if (strlen(this.password) == 0) { if (NULL != getenv(PASSWORD_ENV_VAR)) snprintf(this.password, sizeof(this.password), "%s", getenv(PASSWORD_ENV_VAR)); else read_password(this.password, sizeof(this.password)); } if (!this.use_remote_forward) { if ((this.tun_fd = open_tun(device)) == -1) { retval = 1; goto cleanup; } } if ((this.dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) { retval = 1; goto cleanup; } #ifdef OPENBSD if (rtable > 0) socket_setrtable(dns_fd, rtable); #endif signal(SIGINT, sighandler); signal(SIGTERM, sighandler); fprintf(stderr, "Sending DNS queries for %s to ", this.topdomain); for (int a = 0; a < this.nameserv_addrs_len; a++) fprintf(stderr, "%s%s", format_addr(&this.nameserv_addrs[a], sizeof(struct sockaddr_storage)), (a != this.nameserv_addrs_len - 1) ? ", " : ""); fprintf(stderr, "\n"); if (this.remote_forward_addr.ss_family != AF_UNSPEC) fprintf(stderr, "Requesting TCP data forwarding from server to %s:%d\n", format_addr(&this.remote_forward_addr, sizeof(struct sockaddr_storage)), remote_forward_port); if (client_handshake()) { retval = 1; goto cleanup; } if (this.conn == CONN_RAW_UDP) { fprintf(stderr, "Sending raw UDP traffic directly to %s\n", client_get_raw_addr()); } fprintf(stderr, "Connection setup complete, transmitting data.\n"); if (this.foreground == 0) do_detach(); if (pidfile != NULL) do_pidfile(pidfile); if (newroot != NULL) do_chroot(newroot); if (username != NULL) { #ifndef WINDOWS32 gid_t gids[1]; gids[0] = pw->pw_gid; if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) { warnx("Could not switch to user %s!\n", username); usage(); /* NOTREACHED */ } #endif } if (context != NULL) do_setcon(context); client_tunnel(); cleanup: if (this.use_remote_forward) close(STDOUT_FILENO); close_socket(this.dns_fd); close_socket(this.tun_fd); #ifdef WINDOWS32 WSACleanup(); #endif return retval; }
SendingMessage::SendingMessage(scenario *msg_scenario, const char *src, bool skip_sanity, int dialog_number, bool use_txn) : ack(false),cancel(false), response(false) { // should we parse out the _n portion of call here or later? Here would be faster and more // in keepin with the existing style, I suppose... const char *osrc = src; char * literal; int literalLen; char * dest; char * key; char current_line[MAX_HEADER_LEN]; const char * line_mark = NULL; int num_cr = get_cr_number(src); this->msg_scenario = msg_scenario; this->dialog_number = dialog_number; dest = literal = (char *)malloc(strlen(src) + num_cr + 1); literalLen = 0; current_line[0] = '\0'; *dest = 0; while(*src) { /* If start of new line, copy through next \n into current_line */ if (current_line[0] == '\0') { line_mark = strchr(src, '\n'); if (line_mark) { int header_len = line_mark - src; if (header_len > MAX_HEADER_LEN-1) header_len = MAX_HEADER_LEN-1; memcpy(current_line, src, header_len); current_line[header_len] = '\0'; } } /* This hex encoding could be done in XML parsing, allowing us to skip * these conditionals and branches. */ if ((*src == '\\') && (*(src+1) == 'x')) { /* Allows any hex coded char like '\x5B' ([) */ src += 2; if (isxdigit(*src)) { int val = get_decimal_from_hex(*src); src++; if (isxdigit(*src)) { val = (val << 4) + get_decimal_from_hex(*src); } *dest++ = val & 0xff; } src++; } else if (*src == '\n') { *dest++ = '\r'; *dest++ = *src++; current_line[0] = '\0'; } else if (*src != '[') { *dest++ = *src++; } else { /* We have found a keyword, store the literal that we have been generating. */ literalLen = dest - literal; if (literalLen) { *dest = '\0'; literal = (char *)realloc(literal, literalLen + 1); if (!literal) { REPORT_ERROR("Out of memory!"); } MessageComponent *newcomp = (MessageComponent *)calloc(1, sizeof(MessageComponent)); if (!newcomp) { REPORT_ERROR("Out of memory!"); } newcomp->type = E_Message_Literal; newcomp->literal = literal; newcomp->literalLen = literalLen; // length without the terminator newcomp->dialog_number = dialog_number; messageComponents.push_back(newcomp); } else { free(literal); } dest = literal = (char *)malloc(strlen(src) + num_cr + 1); literalLen = 0; *dest = '\0'; /* Now lets determine which keyword we have. */ MessageComponent *newcomp = (MessageComponent *)calloc(1, sizeof(MessageComponent)); if (!newcomp) { REPORT_ERROR("Out of memory!"); } newcomp->dialog_number = dialog_number; char keyword [KEYWORD_SIZE+1]; src++; /* Like strchr, but don't count things in quotes. */ // cast away const of src [*UGLY*] for(key = (char *) src; *key && *key != '\n'; key++) { if (*key == '\"') { do { key++; } while(*key && *key != '\"' && *key != '\n'); } if (*key == ']') break; } if (*key == '\n') REPORT_ERROR("Cannot have end of line characters in the middle of keywords. Possibly a missing ']' or a duplicate 'CDATA[' section in scenario while parsing '%s'.", current_line); if (*key != ']') { key = NULL; } if((!key) || ((key - src) > KEYWORD_SIZE) || (!(key - src))) { REPORT_ERROR("Syntax error or invalid [keyword] in scenario while parsing '%s'", current_line); } memcpy(keyword, src, key - src); keyword[key - src] = 0; src = key + 1; // allow +/-n for numeric variables newcomp->offset = 0; if ((strncmp(keyword, "authentication", strlen("authentication")) && strncmp(keyword, "tdmmap", strlen("tdmmap")))) { newcomp->offset = parseOffset(keyword); /* end the string before the +/- sign so that the parser doesn't read it as an unrecognized keyword */ if(((key = strchr(keyword,'+')) || (key = strchr(keyword,'-'))) && isdigit(*(key+1))) *key = 0; } char *spc = NULL; char ospc; if ((spc = strchr(keyword, ' '))) { ospc = *spc; *spc = '\0'; } kw_map::iterator it = keyword_map.find(keyword); if (spc) { *spc = ospc; } if (it != keyword_map.end()) { newcomp->type = E_Message_Custom; newcomp->comp_param.fxn = it->second; messageComponents.push_back(newcomp); continue; } bool simple_keyword = false; for (unsigned int i = 0; i < sizeof(SimpleKeywords)/sizeof(SimpleKeywords[0]); i++) { if (!strcmp(keyword, SimpleKeywords[i].keyword)) { newcomp->type = SimpleKeywords[i].type; simple_keyword = true; break; } } // check ip addresses for optional specifier for ipv6 esc bool ip_keyword = false; if (!simple_keyword) { for (unsigned int i = 0; i< sizeof(IP_Keywords)/sizeof(IP_Keywords[0]); i++) { //exact match or contains full keyword and a space if ( !strcmp(keyword, IP_Keywords[i].keyword) || ( !strncmp(keyword, IP_Keywords[i].keyword, strlen(IP_Keywords[i].keyword) ) && ( strlen(keyword)> strlen(IP_Keywords[i].keyword )) && ( keyword[strlen(IP_Keywords[i].keyword)] == ' ') ) ) { newcomp->type = IP_Keywords[i].type; if ((IP_Keywords[i].type == E_Message_Local_IP2)&&(strlen(local_ip2)==0)) REPORT_ERROR("Scenario uses [local_ip2], requires use of -i2 command line argument"); if( strstr(keyword, "no_square_bracket") ) { // want the no escape version of the ip address switch (IP_Keywords[i].type) { case (E_Message_Remote_IP): newcomp->type = E_Message_Remote_IP_noesc; break; case (E_Message_Local_IP): newcomp->type = E_Message_Local_IP_noesc; break; case (E_Message_Local_IP2): newcomp->type = E_Message_Local_IP2_noesc; break; case (E_Message_Server_IP): newcomp->type = E_Message_Server_IP_noesc; break; case(E_Message_Media_IP): newcomp->type = E_Message_Media_IP_noesc; break; default: REPORT_ERROR("Unknown ip address specifier type %d while building message to send", IP_Keywords[i].keyword); break; } } ip_keyword = true; break; } }//for } bool dialog_keyword = false; for (unsigned int i = 0; i < sizeof(DialogSpecificKeywords)/sizeof(DialogSpecificKeywords[0]); i++) { if (strstr(keyword, DialogSpecificKeywords[i].keyword) == keyword) { newcomp->type = DialogSpecificKeywords[i].type; parse_dialog_number(keyword, newcomp); if ((use_txn) && (i <= HighestTransactionSpecificKeywordsIndex) && (newcomp->dialog_number != dialog_number)) { REPORT_ERROR("Cannot use 'dialog=' attribute in [%s] keyword when also specifying 'use_txn' for the message.\n", keyword); } parse_encoding(keyword, newcomp); dialog_keyword = true; break; } } if (newcomp->type == E_Message_Peer_Tag_Param || newcomp->type == E_Message_Remote_Tag_Param || newcomp->type == E_Message_Remote_Tag ) { parse_generated(keyword, newcomp); } if (simple_keyword || dialog_keyword || ip_keyword) { messageComponents.push_back(newcomp); continue; } /* Now handle all the keywords which are neither simple nor determined solely by dialog */ if(!strncmp(keyword, "field", strlen("field"))) { newcomp->type = E_Message_Injection; /* Parse out the interesting things like file and number. */ newcomp->comp_param.field_param.field = atoi(keyword + strlen("field")); char fileName[KEYWORD_SIZE]; getKeywordParam(keyword, "file=", fileName); if (fileName[0] == '\0') { if (!default_file) { REPORT_ERROR("No injection file was specified!\n"); } newcomp->comp_param.field_param.filename = strdup(default_file); } else { newcomp->comp_param.field_param.filename = strdup(fileName); } if (inFiles.find(newcomp->comp_param.field_param.filename) == inFiles.end()) { REPORT_ERROR("Invalid injection file: %s\n", fileName); } char line[KEYWORD_SIZE]; getKeywordParam(keyword, "line=", line); if (line[0]) { /* Turn this into a new message component. */ newcomp->comp_param.field_param.line = new SendingMessage(msg_scenario, line, true, dialog_number); } } else if(!strncmp(keyword, "file", strlen("file"))) { newcomp->type = E_Message_File; /* Parse out the interesting things like file and number. */ char fileName[KEYWORD_SIZE]; getKeywordParam(keyword, "name=", fileName); if (fileName[0] == '\0') { REPORT_ERROR("No name specified for 'file' keyword!\n"); } /* Turn this into a new message component. */ newcomp->comp_param.filename = new SendingMessage(msg_scenario, fileName, true, dialog_number); } else if(*keyword == '$') { newcomp->type = E_Message_Variable; if (!msg_scenario) { REPORT_ERROR("SendingMessage with variable usage outside of scenario!"); } newcomp->varId = msg_scenario->get_var(keyword + 1, "Variable keyword"); } else if(!strncmp(keyword, "fill", strlen("fill"))) { newcomp->type = E_Message_Fill; char filltext[KEYWORD_SIZE]; char varName[KEYWORD_SIZE]; getKeywordParam(keyword, "text=", filltext); if (filltext[0] == '\0') { strcpy(filltext, "X"); } getKeywordParam(keyword, "variable=", varName); newcomp->literal = strdup(filltext); newcomp->literalLen = strlen(newcomp->literal); if (!msg_scenario) { REPORT_ERROR("SendingMessage with variable usage outside of scenario!"); } newcomp->varId = msg_scenario->get_var(varName, "Fill Variable"); } else if(!strncmp(keyword, "last_", strlen("last_"))) { newcomp->type = E_Message_Last_Header; // parse optional dialog/value only parameter bool is_dialog_number = parse_dialog_number(keyword, newcomp); bool is_value_only = parse_value_only(keyword, newcomp); if (is_dialog_number || is_value_only) { // if dialog= specified, only copy header portion if (use_txn && strstr(keyword, "dialog=")) { REPORT_ERROR("Cannot use 'dialog=' attribute in [last_] keyword when also specifying 'use_txn' for the message.\n"); } const char *diagptr = strstr(keyword, "dialog="); const char *valueptr = strstr(keyword, "value_only="); const char *index; if(diagptr) { // if both pointers exist start from the one closer to the beginning if(valueptr) index = (diagptr < valueptr) ? diagptr : valueptr; else index = diagptr; } else if (valueptr) { index = valueptr; } else REPORT_ERROR("Incorrect formatting of options in \"last_\" header"); //Back up the pointer to the end of the last_* so we can extract * correctly while ((index > keyword) && (*(index-1) == ' ')) index--; newcomp->literal = strndup(keyword + strlen("last_"), index - keyword - strlen("last_")); } else newcomp->literal = strdup(keyword + strlen("last_")); newcomp->literalLen = strlen(newcomp->literal); } else if(!strncmp(keyword, "authentication", strlen("authentication"))) { parseAuthenticationKeyword(msg_scenario, newcomp, keyword); } #ifndef PCAPPLAY else if(!strcmp(keyword, "auto_media_port") || !strcmp(keyword, "media_port") || !strcmp(keyword, "media_ip") || !strcmp(keyword, "media_ip_type")) { REPORT_ERROR("The %s keyword requires PCAPPLAY.\n", keyword); } #endif #ifndef _USE_OPENSSL else if(!strcmp(keyword, "authentication")) { REPORT_ERROR("The %s keyword requires OpenSSL.\n", keyword); } #endif else { // scan for the generic parameters - must be last test int i = 0; while (generic[i]) { char *msg1 = *generic[i]; char *msg2 = *(generic[i] + 1); if(!strcmp(keyword, msg1)) { newcomp->type = E_Message_Literal; newcomp->literal = strdup(msg2); newcomp->literalLen = strlen(newcomp->literal); break; } ++i; } if (!generic[i]) { REPORT_ERROR("Unsupported keyword '%s' in xml scenario file", keyword); } } messageComponents.push_back(newcomp); } } if (literal[0]) { *dest++ = '\0'; literalLen = dest - literal; literal = (char *)realloc(literal, literalLen); if (!literal) { REPORT_ERROR("Out of memory!"); } MessageComponent *newcomp = (MessageComponent *)calloc(1, sizeof(MessageComponent)); if (!newcomp) { REPORT_ERROR("Out of memory!"); } newcomp->type = E_Message_Literal; newcomp->literal = literal; newcomp->literalLen = literalLen-1; messageComponents.push_back(newcomp); } else { free(literal); } if (skip_sanity) { cancel = response = ack = false; method = NULL; return; } if (numComponents() < 1) { REPORT_ERROR("Can not create a message that is empty!"); } if (getComponent(0)->type != E_Message_Literal) { REPORT_ERROR("You can not use a keyword for the METHOD or to generate \"SIP/2.0\" to ensure proper [cseq] operation!\n%s\n", osrc); } char *p = method = strdup(getComponent(0)->literal); char *q; while (isspace(*p)) { p++; } if (!(q = strchr(method, ' '))) { REPORT_ERROR("You can not use a keyword for the METHOD or to generate \"SIP/2.0\" to ensure proper [cseq] operation!%s\n", osrc); } *q++ = '\0'; while (isspace(*q)) { q++; } if (!strcmp(method, "SIP/2.0")) { char *endptr; code = strtol(q, &endptr, 10); if (*endptr && !isspace(*endptr)) { REPORT_ERROR("Invalid reply code: %s\n", q); } if (code < 100 || code >= 700) { REPORT_ERROR("Response codes must be in the range of 100-700"); } response = true; ack = false; cancel = false; free(method); method = NULL; } else { if (p != method) { memmove(method, p, strlen(p) + 1); } method = (char *)realloc(method, strlen(method) + 1); if (!method) { REPORT_ERROR("Out of memory"); } ack = (!strcmp(method, "ACK")); cancel = (!strcmp(method, "CANCEL")); response = false; } }