static int handle_number(void * ctx, const char *val, unsigned int len) { struct ctx *_ctx = (struct ctx *) ctx; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("handle_number, val = %s, enter state '%s'", buf, parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_CONSUMED_CAPACITY_KEY: { if (aws_dynamo_json_get_double(val, len, &(_ctx->r->consumed_capacity_units)) == -1) { Warnx("handle_number: failed to get capacity int."); return 0; } _ctx->parser_state = PARSER_STATE_ROOT_MAP; break; } default: { Warnx("handle_number - unexpected state '%s'", parser_state_string(_ctx->parser_state)); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_number exit state '%s'", parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ return 1; }
struct aws_dynamo_create_table_response *aws_dynamo_create_table(struct aws_handle *aws, const char *request) { const char *response; int response_len; struct aws_dynamo_create_table_response *r; if (aws_dynamo_request(aws, AWS_DYNAMO_CREATE_TABLE, request) == -1) { return NULL; } response = http_get_data(aws->http, &response_len); if (response == NULL) { Warnx("aws_dynamo_create_table: Failed to get response."); return NULL; } if ((r = aws_dynamo_parse_create_table_response(response, response_len)) == NULL) { Warnx("aws_dynamo_create_table: Failed to parse response: '%s'", response); return NULL; } return r; }
struct aws_dynamo_delete_item_response *aws_dynamo_delete_item(struct aws_handle *aws, const char *request, struct aws_dynamo_attribute *attributes, int num_attributes) { const char *response; int response_len; struct aws_dynamo_delete_item_response *r; if (aws_dynamo_request(aws, AWS_DYNAMO_DELETE_ITEM, request) == -1) { return NULL; } response = http_get_data(aws->http, &response_len); if (response == NULL) { Warnx("aws_dynamo_delete_item: Failed to get response."); return NULL; } if ((r = aws_dynamo_parse_delete_item_response(response, response_len, attributes, num_attributes)) == NULL) { Warnx("aws_dynamo_delete_item: Failed to parse response: '%s'", response); return NULL; } return r; }
/************************************************************************************************** READ_TCP_LENGTH The first two octets of a TCP question are the length. Read them. Returns 0 on success, -1 on failure. **************************************************************************************************/ static int read_tcp_length(TASK *t) { int rv; char len[2]; if ((rv = recv(t->fd, len, 2, 0)) != 2) { if (rv < 0) { if (errno == EAGAIN) return (0); if (errno != ECONNRESET) Warn("%s: %s", clientaddr(t), _("recv (length) (TCP)")); return (-1); } if (rv == 0) return (-1); return Warnx("%s: %s", clientaddr(t), _("TCP message length invalid")); } if ((t->len = ((len[0] << 8) | (len[1]))) < DNS_HEADERSIZE) return Warnx("%s: %s (%d octet%s)", clientaddr(t), _("TCP message too short"), t->len, S(t->len)); if (t->len > DNS_MAXPACKETLEN_TCP) return Warnx("%s: %s (%d octet%s)", clientaddr(t), _("TCP message too long"), t->len, S(t->len)); if (!(t->query = calloc(1, t->len + 1))) Err(_("out of memory")); t->offset = 0; return (0); }
static int handle_end_array(void *ctx) { struct ctx *_ctx = (struct ctx *)ctx; #ifdef DEBUG_PARSER Debug("handle_end_array enter state '%s'", parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ATTRIBUTE_VALUE_ARRAY: { _ctx->parser_state = PARSER_STATE_ATTRIBUTE_MAP; break; } default:{ Warnx("handle_end_array - unexpected state '%s'", parser_state_string(_ctx->parser_state)); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_end_array exit state '%s'", parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ return 1; }
static int handle_end_map(void *ctx) { struct ctx *_ctx = (struct ctx *) ctx; #ifdef DEBUG_PARSER Debug("handle_end_map enter state '%s'", parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ATTRIBUTE_MAP: { _ctx->parser_state = PARSER_STATE_ATTRIBUTES_MAP; break; } case PARSER_STATE_ATTRIBUTES_MAP: { _ctx->parser_state = PARSER_STATE_ROOT_MAP; break; } case PARSER_STATE_ROOT_MAP: { _ctx->parser_state = PARSER_STATE_NONE; break; } default: { Warnx("handle_end_map - unexpected state: %s", parser_state_string(_ctx->parser_state)); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_end_map exit state '%s'", parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ return 1; }
/************************************************************************************************** READ_TCP_QUERY Returns 0 on success, -1 on failure. **************************************************************************************************/ int read_tcp_query(TASK *t) { unsigned char *end; int rv; /* Read packet length if we haven't already */ if (!t->len) return read_tcp_length(t); end = t->query + t->len; /* Read whatever data is ready */ if ((rv = recv(t->fd, t->query + t->offset, t->len - t->offset, 0)) < 0) return Warn("%s: %s", clientaddr(t), _("recv (TCP)")); if (!rv) return (-1); /* Client closed connection */ #if DEBUG_ENABLED && DEBUG_TCP Debug("%s: 2+%d TCP octets in", clientaddr(t), rv); #endif t->offset += rv; if (t->offset > t->len) return Warnx("%s: %s", clientaddr(t), _("TCP message data too long")); if (t->offset < t->len) return 0; /* Not finished reading */ t->offset = 0; /* Reset offset for writing reply */ return new_task(t, t->query, t->len); }
static int put_item_end_array(void *ctx) { struct put_item_ctx *_ctx = (struct put_item_ctx *)ctx; #ifdef DEBUG_PARSER Debug("put_item_end_array enter %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ATTRIBUTE_VALUE:{ /* A String Set or a Number Set, no need for a state change. */ break; } default:{ Warnx("put_item_end_array - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("put_item_end_array exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
static int put_item_end_map(void *ctx) { struct put_item_ctx *_ctx = (struct put_item_ctx *)ctx; #ifdef DEBUG_PARSER Debug("put_item_end_map enter %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ATTRIBUTE_VALUE:{ _ctx->parser_state = PARSER_STATE_ATTRIBUTES_MAP; break; } case PARSER_STATE_ATTRIBUTES_MAP:{ _ctx->parser_state = PARSER_STATE_ROOT_MAP; break; } case PARSER_STATE_ROOT_MAP:{ _ctx->parser_state = PARSER_STATE_NONE; break; } default:{ Warnx("put_item_end_map - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("put_item_end_map exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
static int handle_string(void *ctx, const unsigned char *val, unsigned int len) { struct ctx *_ctx = (struct ctx *) ctx; struct aws_dynamo_item *item; struct aws_dynamo_attribute *attribute; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("handle_string, val = %s, enter state '%s'", buf, parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ item = &(_ctx->r->item); attribute = &(item->attributes[_ctx->attribute_index]); switch (_ctx->parser_state) { case PARSER_STATE_ATTRIBUTE_TYPE_KEY: { if (aws_dynamo_parse_attribute_value(attribute, val, len) != 1) { Warnx("handle_string - attribute parse failed, attribute %d", _ctx->attribute_index); return 0; } _ctx->parser_state = PARSER_STATE_ATTRIBUTE_MAP; break; } case PARSER_STATE_ATTRIBUTE_VALUE_ARRAY: { if (aws_dynamo_parse_attribute_value(attribute, val, len) != 1) { Warnx("handle_string - attribute parse failed, attribute %d", _ctx->attribute_index); return 0; } break; } default: { Warnx("handle_string - unexpected state '%s'", parser_state_string(_ctx->parser_state)); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_string exit state '%s'", parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ return 1; }
struct aws_dynamo_put_item_response * aws_dynamo_parse_put_item_response(const char *response, int response_len, struct aws_dynamo_attribute *attributes, int num_attributes) { yajl_handle hand; yajl_status stat; struct put_item_ctx _ctx = { 0 }; _ctx.r = calloc(sizeof(*(_ctx.r)), 1); if (_ctx.r == NULL) { Warnx("aws_dynamo_parse_put_item_response: response alloc failed."); return NULL; } if (num_attributes > 0) { _ctx.r->attributes = malloc(sizeof(*(_ctx.r->attributes)) * num_attributes); if (_ctx.r->attributes == NULL) { Warnx("aws_dynamo_parse_put_item_response: attribute alloc failed."); free(_ctx.r); return NULL; } memcpy(_ctx.r->attributes, attributes, sizeof(*(attributes)) * num_attributes); _ctx.r->num_attributes = num_attributes; } #if YAJL_MAJOR == 2 hand = yajl_alloc(&put_item_callbacks, NULL, &_ctx); yajl_parse(hand, response, response_len); stat = yajl_complete_parse(hand); #else hand = yajl_alloc(&put_item_callbacks, NULL, NULL, &_ctx); yajl_parse(hand, response, response_len); stat = yajl_parse_complete(hand); #endif if (stat != yajl_status_ok) { unsigned char *str = yajl_get_error(hand, 1, response, response_len); Warnx("aws_dynamo_parse_put_item_response: json parse failed, '%s'", (const char *)str); yajl_free_error(hand, str); yajl_free(hand); aws_dynamo_free_put_item_response(_ctx.r); return NULL; } yajl_free(hand); return _ctx.r; }
/************************************************************************************************** CHECK_CONFIG_FILE_PERMS **************************************************************************************************/ void check_config_file_perms(void) { FILE *fp; if ((fp = fopen(opt_conf, "r"))) { Warnx("%s: %s", opt_conf, _("WARNING: config file is readable by unprivileged user")); fclose(fp); } }
static int put_item_string(void *ctx, const unsigned char *val, unsigned int len) { struct put_item_ctx *_ctx = (struct put_item_ctx *)ctx; struct aws_dynamo_attribute *attribute; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("put_item_string, val = %s, enter state %d", buf, _ctx->parser_state); #endif /* DEBUG_PARSER */ attribute = &(_ctx->r->attributes[_ctx->attribute_index]); switch (_ctx->parser_state) { case PARSER_STATE_ATTRIBUTE_VALUE:{ if (aws_dynamo_parse_attribute_value(attribute, val, len) != 1) { Warnx("get_item_string - attribute parse failed, attribute %d", _ctx->attribute_index); return 0; } break; } default:{ Warnx("put_item_string - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("put_item_string exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
static char *aws_dynamo_get_canonicalized_headers(struct http_headers *headers) { int i; int canonical_headers_len = 0; char *canonical_headers; char *ptr; /* Assume all header .name fields are lowercase. */ /* Assume no duplicate headers (that is, all header names are distinct.) */ /* Assume headers are already sorted alphabetically by header name. */ for (i = 0; i < headers->count; i++) { canonical_headers_len += strlen(headers->entries[i].name); canonical_headers_len += strlen(headers->entries[i].value); canonical_headers_len += 2; /* ':' and '\n' */ } canonical_headers_len++; /* \0 terminator */ ptr = canonical_headers = calloc(sizeof(char), canonical_headers_len); if (ptr == NULL) { Err("aws_dynamo_get_canonicalized_headers: Failed to allocate."); return NULL; } for (i = 0; i < headers->count; i++) { int n; int remaining; remaining = canonical_headers_len - (ptr - canonical_headers); n = snprintf(ptr, remaining, "%s:%s\n", headers->entries[i].name, headers->entries[i].value); if (n == -1 || n >= remaining) { Warnx("aws_dynamo_get_canonicalized_headers: string buffer not large enough."); free(canonical_headers); return NULL; } ptr += n; } return canonical_headers; }
static int handle_end_map(void *ctx) { struct ctx *_ctx = (struct ctx *)ctx; #ifdef DEBUG_PARSER Debug("handle_end_map enter %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ROOT_MAP:{ _ctx->parser_state = PARSER_STATE_NONE; break; } case PARSER_STATE_TABLE_DESCRIPTION_MAP:{ _ctx->parser_state = PARSER_STATE_ROOT_MAP; break; } case PARSER_STATE_PROVISIONED_THROUGHPUT_MAP:{ _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_MAP; break; } case PARSER_STATE_HASH_KEY_ELEMENT_MAP:{ _ctx->parser_state = PARSER_STATE_KEY_SCHEMA_MAP; break; } case PARSER_STATE_RANGE_KEY_ELEMENT_MAP:{ _ctx->parser_state = PARSER_STATE_KEY_SCHEMA_MAP; break; } case PARSER_STATE_KEY_SCHEMA_MAP:{ _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_MAP; break; } default:{ Warnx("handle_end_map - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_end_map exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
static int handle_end_array(void *ctx) { struct ctx *_ctx = (struct ctx *)ctx; #ifdef DEBUG_PARSER Debug("handle_end_array enter %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { default:{ Warnx("handle_end_array - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_end_array exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
/* static void axfr_error(TASK *, const char *, ...) __attribute__ ((__noreturn__)); */ static void axfr_error(TASK *t, const char *fmt, ...) { va_list ap; char *msg = NULL; if (t) { task_output_info(t, NULL); } else { va_start(ap, fmt); VASPRINTF(&msg, fmt, ap); va_end(ap); Warnx("%s", msg); RELEASE(msg); } sockclose(t->fd); _exit(EXIT_FAILURE); /* NOTREACHED */ }
/* each map is a case, compare key with all valid keys for that map * and set state accordingly. */ static int handle_map_key(void *ctx, const unsigned char *val, unsigned int len) { struct ctx *_ctx = (struct ctx *)ctx; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("handle_map_key, val = %s, enter state %d", buf, _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ROOT_MAP:{ if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_TABLE_DESCRIPTION, val, len)) { _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_KEY; } else { char key[len + 1]; snprintf(key, len + 1, "%s", val); Warnx("handle_map_key: Unknown root key '%s'.", key); return 0; } break; } case PARSER_STATE_TABLE_DESCRIPTION_MAP:{ if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_CREATION_DATE_TIME, val, len)) { _ctx->parser_state = PARSER_STATE_CREATION_DATE_TIME_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_KEY_SCHEMA, val, len)) { _ctx->parser_state = PARSER_STATE_KEY_SCHEMA_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_PROVISIONED_THROUGHPUT, val, len)) { _ctx->parser_state = PARSER_STATE_PROVISIONED_THROUGHPUT_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_TABLE_NAME, val, len)) { _ctx->parser_state = PARSER_STATE_TABLE_NAME_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_TABLE_STATUS, val, len)) { _ctx->parser_state = PARSER_STATE_TABLE_STATUS_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_ITEM_COUNT, val, len)) { _ctx->parser_state = PARSER_STATE_ITEM_COUNT_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_TABLE_SIZE_BYTES, val, len)) { _ctx->parser_state = PARSER_STATE_TABLE_SIZE_BYTES_KEY; } else { char key[len + 1]; snprintf(key, len + 1, "%s", val); Warnx("handle_map_key: Unknown table description key '%s'.", key); return 0; } break; } case PARSER_STATE_PROVISIONED_THROUGHPUT_MAP:{ if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_READ_CAPACITY_UNITS, val, len)) { _ctx->parser_state = PARSER_STATE_READ_CAPACITY_UNITS_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_WRITE_CAPACITY_UNITS, val, len)) { _ctx->parser_state = PARSER_STATE_WRITE_CAPACITY_UNITS_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_NUMBER_OF_DECREASES_TODAY, val, len)) { _ctx->parser_state = PARSER_STATE_NUMBER_OF_DECREASES_TODAY_KEY; } else { char key[len + 1]; snprintf(key, len + 1, "%s", val); Warnx("handle_map_key: Unknown provisioned throughput key '%s'.", key); return 0; } break; } case PARSER_STATE_KEY_SCHEMA_MAP:{ if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_HASH_KEY_ELEMENT, val, len)) { _ctx->parser_state = PARSER_STATE_HASH_KEY_ELEMENT_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_RANGE_KEY_ELEMENT, val, len)) { _ctx->parser_state = PARSER_STATE_RANGE_KEY_ELEMENT_KEY; } else { char key[len + 1]; snprintf(key, len + 1, "%s", val); Warnx("handle_map_key: Unknown key schema key '%s'.", key); return 0; } break; } case PARSER_STATE_HASH_KEY_ELEMENT_MAP:{ if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_ATTRIBUTE_NAME, val, len)) { _ctx->parser_state = PARSER_STATE_HASH_KEY_ATTRIBUTE_NAME_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_ATTRIBUTE_TYPE, val, len)) { _ctx->parser_state = PARSER_STATE_HASH_KEY_ATTRIBUTE_TYPE_KEY; } else { char key[len + 1]; snprintf(key, len + 1, "%s", val); Warnx("handle_map_key: Unknown hash key element key '%s'.", key); return 0; } break; } case PARSER_STATE_RANGE_KEY_ELEMENT_MAP:{ if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_ATTRIBUTE_NAME, val, len)) { _ctx->parser_state = PARSER_STATE_RANGE_KEY_ATTRIBUTE_NAME_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_ATTRIBUTE_TYPE, val, len)) { _ctx->parser_state = PARSER_STATE_RANGE_KEY_ATTRIBUTE_TYPE_KEY; } else { char key[len + 1]; snprintf(key, len + 1, "%s", val); Warnx("handle_map_key: Unknown range key element key '%s'.", key); return 0; } break; } default:{ Warnx("handle_map_key - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_map_key exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
static taskexec_t ixfr_purge_all_soas(TASK *t, void *data) { /* * Retrieve all zone id's that have deleted records. * * For each zone get the expire field and delete any records that have expired. * */ SQL_RES *res = NULL; SQL_ROW row = NULL; size_t querylen; const char *QUERY0 = "SELECT DISTINCT zone FROM %s WHERE active='%s'"; const char *QUERY1 = "SELECT origin FROM %s " "WHERE id=%u;"; const char *QUERY2 = "DELETE FROM %s WHERE zone=%u AND active='%s' " " AND stamp < DATE_SUB(NOW(),INTERVAL %u SECOND);"; char *query = NULL; /* * Reset task timeout clock to some suitable value in the future */ t->timeout = current_time + ixfr_gc_interval; /* Try again e.g. tomorrow */ querylen = sql_build_query(&query, QUERY0, mydns_rr_table_name, mydns_rr_active_types[2]); if (!(res = sql_query(sql, query, querylen))) ErrSQL(sql, "%s: %s", desctask(t), _("error loading zone id's for DELETED records")); RELEASE(query); while((row = sql_getrow(res, NULL))) { unsigned int id = atou(row[0]); char *origin = NULL; MYDNS_SOA *soa = NULL; SQL_RES *sres = NULL; querylen = sql_build_query(&query, QUERY1, mydns_soa_table_name, id); if (!(res = sql_query(sql, query, querylen))) ErrSQL(sql, "%s: %s", desctask(t), _("error loading zone from DELETED record zone id")); RELEASE(query); if (!(row = sql_getrow(res, NULL))) { Warnx(_("%s: no soa found for soa id %u"), desctask(t), id); continue; } origin = row[0]; if (mydns_soa_load(sql, &soa, origin) == 0) { querylen = sql_build_query(&query, QUERY2, mydns_rr_table_name, soa->id, mydns_rr_active_types[2], soa->expire); if (sql_nrquery(sql, query, querylen) != 0) WarnSQL(sql, "%s: %s %s", desctask(t), _("error deleting expired records for zone "), soa->origin); RELEASE(query); sql_free(sres); } } sql_free(res); RELEASE(query); return (TASK_CONTINUE); }
static int handle_map_key(void *ctx, const unsigned char *val, unsigned int len) { struct ctx *_ctx = (struct ctx *) ctx; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("handle_map_key, val = %s, enter state '%s'", buf, parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ROOT_MAP: { if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_CONSUMED_CAPACITY, val, len)) { _ctx->parser_state = PARSER_STATE_CONSUMED_CAPACITY_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_ATTRIBUTES, val, len)) { _ctx->parser_state = PARSER_STATE_ATTRIBUTES_KEY; _ctx->r->item.attributes = malloc(sizeof(*(_ctx->attributes)) * _ctx->num_attributes); if (_ctx->r->item.attributes == NULL) { Warnx("handle_map_key: attribute alloc failed."); return 0; } /* Set expected types for attributes. */ memcpy(_ctx->r->item.attributes, _ctx->attributes, sizeof(*(_ctx->attributes)) * _ctx->num_attributes); _ctx->r->item.num_attributes = _ctx->num_attributes; } else { Warnx("handle_map_key: Unknown key."); return 0; } break; } case PARSER_STATE_ATTRIBUTES_MAP: { /* Set the attribute index based on the name. */ int attribute; for (attribute = 0; attribute < _ctx->num_attributes; attribute++) { struct aws_dynamo_attribute *a = &(_ctx->attributes[attribute]); if (len == a->name_len && strncmp(val, a->name, len) == 0) { _ctx->attribute_index = attribute; break; } } if (attribute == _ctx->num_attributes) { Warnx("handle_map_key: Unknown attribute."); return 0; } _ctx->parser_state = PARSER_STATE_ATTRIBUTE_KEY; break; } case PARSER_STATE_ATTRIBUTE_MAP: { struct aws_dynamo_attribute *a = &(_ctx->attributes[_ctx->attribute_index]); const char *expected_type = aws_dynamo_attribute_types[a->type]; if (len != strlen(expected_type) || strncmp(val, expected_type, len) != 0) { Warnx("handle_map_key: Unexpected attribute type."); return 0; } _ctx->parser_state = PARSER_STATE_ATTRIBUTE_TYPE_KEY; break; } default: { Warnx("handle_map_key - unexpected state: %s", parser_state_string(_ctx->parser_state)); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_map_key exit state '%s'", parser_state_string(_ctx->parser_state)); #endif /* DEBUG_PARSER */ return 1; }
/************************************************************************************************** LOAD_CONFIG Load the configuration file. **************************************************************************************************/ void load_config(void) { int n; struct passwd *pwd = NULL; struct group *grp = NULL; /* Load config */ conf_load(&Conf, opt_conf); /* Set defaults */ for (n = 0; defConfig[n].name; n++) { if (defConfig[n].name[0] == '-' || !defConfig[n].value) continue; if (!conf_get(&Conf, defConfig[n].name, NULL)) conf_set(&Conf, defConfig[n].name, defConfig[n].value, 1); } /* Support "mysql-user" etc. for backwards compatibility */ if (conf_get(&Conf, "mysql-host", NULL)) conf_set(&Conf, "db-host", conf_get(&Conf, "mysql-host", NULL), 0); if (conf_get(&Conf, "mysql-user", NULL)) conf_set(&Conf, "db-user", conf_get(&Conf, "mysql-user", NULL), 0); if (conf_get(&Conf, "mysql-pass", NULL)) conf_set(&Conf, "db-password", conf_get(&Conf, "mysql-pass", NULL), 0); if (conf_get(&Conf, "mysql-password", NULL)) conf_set(&Conf, "db-password", conf_get(&Conf, "mysql-password", NULL), 0); #if HAVE_GETPWUID /* Set default for database username to real username if none was provided */ if (!conf_get(&Conf, "db-user", NULL)) { struct passwd *pwd2; if ((pwd2 = getpwuid(getuid())) && pwd2->pw_name) { conf_set(&Conf, "db-user", pwd2->pw_name, 0); memset(pwd2, 0, sizeof(struct passwd)); } } #endif /* Load user/group perms */ if (!(pwd = getpwnam(conf_get(&Conf, "user", NULL)))) Err(_("error loading uid for user `%s'"), conf_get(&Conf, "user", NULL)); perms_uid = pwd->pw_uid; perms_gid = pwd->pw_gid; memset(pwd, 0, sizeof(struct passwd)); if (!(grp = getgrnam(conf_get(&Conf, "group", NULL))) && !(grp = getgrnam("nobody"))) { Warnx(_("error loading gid for group `%s'"), conf_get(&Conf, "group", NULL)); Warnx(_("using gid %lu from user `%s'"), (unsigned long)perms_gid, conf_get(&Conf, "user", NULL)); } else { perms_gid = grp->gr_gid; memset(grp, 0, sizeof(struct group)); } /* We call conf_set_logging() again after moving into background, but it's called here to report on errors. */ conf_set_logging(); /* Set global options */ task_timeout = atou(conf_get(&Conf, "timeout", NULL)); axfr_enabled = GETBOOL(conf_get(&Conf, "allow-axfr", NULL)); Verbose(_("AXFR is %senabled"), (axfr_enabled)?"":_("not ")); tcp_enabled = GETBOOL(conf_get(&Conf, "allow-tcp", NULL)); Verbose(_("TCP ports are %senabled"), (tcp_enabled)?"":_("not ")); dns_update_enabled = GETBOOL(conf_get(&Conf, "allow-update", NULL)); Verbose(_("DNS UPDATE is %senabled"), (dns_update_enabled)?"":_("not ")); mydns_soa_use_active = GETBOOL(conf_get(&Conf, "use-soa-active", NULL)); mydns_rr_use_active = GETBOOL(conf_get(&Conf, "use-rr-active", NULL)); dns_notify_enabled = dns_update_enabled && GETBOOL(conf_get(&Conf, "notify-enabled", NULL)); Verbose(_("DNS NOTIFY is %senabled"), (dns_notify_enabled)?"":_("not ")); notify_timeout = atou(conf_get(&Conf, "notify-timeout", NULL)); notify_retries = atou(conf_get(&Conf, "notify-retries", NULL)); notify_algorithm = conf_get(&Conf, "notify-algorithm", NULL); dns_ixfr_enabled = GETBOOL(conf_get(&Conf, "ixfr-enabled", NULL)); Verbose(_("DNS IXFR is %senabled"), (dns_ixfr_enabled)?"":_("not ")); ixfr_gc_enabled = GETBOOL(conf_get(&Conf, "ixfr-gc-enabled", NULL)); ixfr_gc_interval = atou(conf_get(&Conf, "ixfr-gc-interval", NULL)); ixfr_gc_delay = atou(conf_get(&Conf, "ixfr-gc-delay", NULL)); mydns_rr_extended_data = GETBOOL(conf_get(&Conf, "extended-data-support", NULL)); mydns_dbengine = conf_get(&Conf, "dbengine", NULL); wildcard_recursion = atoi(conf_get(&Conf, "wildcard-recursion", NULL)); ignore_minimum = GETBOOL(conf_get(&Conf, "ignore-minimum", NULL)); /* Set table names if provided */ mydns_set_soa_table_name(conf_get(&Conf, "soa-table", NULL)); mydns_set_rr_table_name(conf_get(&Conf, "rr-table", NULL)); /* Set additional where clauses if provided */ mydns_set_soa_where_clause(conf_get(&Conf, "soa-where", NULL)); mydns_set_rr_where_clause(conf_get(&Conf, "rr-where", NULL)); /* Set recursive server if specified */ conf_set_recursive(); #ifdef DN_COLUMN_NAMES dn_default_ns = conf_get(&Conf, "default-ns", NULL); #endif }
int main(int argc, char **argv) { char buffer[MAXLENGTH]; char file[MAXLENGTH]; char filename[MAXLENGTH]; char filename_path[MAXLENGTH]; char filetype[MAXLENGTH]; char server_adresa[32]; char klijent_adresa[32]; char *char_p, znak; FILE *datoteka; int ch; int sockfd, newfd; int msglen, status; int should_be_daemon = 0; int should_be_binary = 1; int zadnji_znak_oznaka_novog_reda; int oznaka_kraja_datoteke; int retransmission_count; uint16_t kod_poruke, broj_bloka, tip_zahtjeva, brojac_blokova; pid_t pid; socklen_t server_l; struct sockaddr server; socklen_t client_l; struct sockaddr client; struct sockaddr_in dijete; struct timeval timeout; fd_set readfs; char* port = (char *)malloc(sizeof(char) * 8); strcpy(port, S_PORT); while ((ch = getopt(argc, argv, "d")) != -1) { switch(ch) { case 'd': should_be_daemon = 1; break; default: errx(1, "Usage: ./tftpserver [-d] port_name_or_number"); break; } } if (argc - optind != 1) { errx(1, "Usage: ./tcpserver [-d] port_name_or_number"); } else { strcpy(port, argv[optind]); /* * provjeri ispravnost danog porta * da li je ok staviti NULL ili bas moram navesti ime protokola */ if (sscanf(port, "%d", &status) == 0 && getservbyname(port, NULL) == NULL) { errx(1, "Invalid port name given"); } } /* * ako treba napravi ga demonom */ if (should_be_daemon) { if (daemon_init("MrePro tftpserver", LOG_FTP) < 0) { errx(1, "daemon failed to initialize!"); } } else { daemon_proc = 0; } /* * NOTE: dalje se sva upozorenja/pogreske pisu sa * Errx(status, format, ...) * koja radi errx ili syslog ovisno o varijabli daemon_proc */ sockfd = noviSocket(NULL, port, &server, &server_l); while (1) { // primi prvi datagram od klijenta koji opisuje njegove zelje // forkaj // neka child posluzi klijenta // mi nastavljamo u petlju memset(buffer, 0, sizeof buffer); client_l = sizeof(client); msglen = recvfrom(sockfd, buffer, sizeof(buffer), 0, &client, &client_l); if ((pid = fork()) < 0) { Errx(daemon_proc ? LOG_ALERT : 1, "TFTP ERROR 0 ms45889: fork error"); } else if (pid == 0) { /* * dijete */ Close(sockfd); // clear buffers memset(file, 0, sizeof file); memset(filename, 0, sizeof filename); memset(filetype, 0, sizeof filetype); // spremi klijentovu adresu inet_ntop( client.sa_family, &((struct sockaddr_in *)&client)->sin_addr, klijent_adresa, sizeof(klijent_adresa) ); // spremi moju adresu inet_ntop( server.sa_family, &((struct sockaddr_in *)&server)->sin_addr, server_adresa, sizeof(server_adresa) ); // napravi novi socket newfd = Socket(AF_INET, SOCK_DGRAM, 0); memset(&dijete, 0, sizeof(dijete)); dijete.sin_family = AF_INET; dijete.sin_port = htons(0); dijete.sin_addr.s_addr = INADDR_ANY; Bind(newfd, (struct sockaddr *)&dijete, sizeof (struct sockaddr)); /* * prvi zahtjev dolazi na dogovoreni port * odgovor saljemo klijentu s nekog drugog porta i na tom portu * nastavljamo priamti klijentove poruke */ // read = 1 // write = 2 // data = 3 // ack = 4 // error = 5 // 1) izdvoji tip zahtjeva memcpy(&tip_zahtjeva, buffer, 2); tip_zahtjeva = ntohs(tip_zahtjeva); // 2) izdvoji naziv datoteke u filename strcpy(filename, buffer + 2); // 3) izdvoji nacin prijenosa u filetype strcpy(filetype, buffer + 2 + strlen(filename) + 1); for (char_p = filetype; *char_p; ++char_p) { *char_p = tolower(*char_p); } if (tip_zahtjeva == 1) { // ovisno o filetype napuni file buffer // za netascii treba svaki \n pretvoriti u \r\n // za binary samo trpaj // velicina datagrama je 4 + 512 // radi najvise 3 retransmisije, 3 sekunde izmedju svake // jedini dozvoljeni direktorij je /tftpboot if (strstr(filename, "/tftpboot/") == NULL) { strcpy(filename_path, "/tftpboot/"); } strcat(filename_path, filename); if (strstr(filetype, "netascii")) { should_be_binary = 0; datoteka = fopen(filename_path, "r"); } else { should_be_binary = 1; datoteka = fopen(filename_path, "rb"); } // ako datoteka ne postoji ili nemamo prava otvaranja iste if (datoteka == NULL) { status = errno; kod_poruke = htons(5); memcpy(file, &kod_poruke, 2); broj_bloka = htons(3 - status); memcpy(file + 2, &broj_bloka, 2); strcpy(file + 4, strerror(status)); sendto(newfd, file, 516, 0, &client, client_l); Close(newfd); Errx(daemon_proc ? LOG_ALERT : 1, "TFTP ERROR %d ms45889 %s", 3 - status , strerror(status)); } // kreni s citanjem datoteke ovisno o should_be_binary zastavici // te svaki paket posalji najvise 3 puta dok ne dobis potvrdu ili // odustani // spremi podatke u datagram oznaka_kraja_datoteke = 0; brojac_blokova = 1; while (oznaka_kraja_datoteke == 0) { memset(file, 0, sizeof(file)); memset(buffer, 0, sizeof(buffer)); kod_poruke = htons(3); memcpy(file, &kod_poruke, 2); broj_bloka = htons(brojac_blokova); memcpy(file + 2, &broj_bloka, 2); ch = 0; char_p = file + 4; zadnji_znak_oznaka_novog_reda = 0; while (ch < 512) { if (zadnji_znak_oznaka_novog_reda == 0) { znak = fgetc(datoteka); } zadnji_znak_oznaka_novog_reda = 0; if (feof(datoteka)) { oznaka_kraja_datoteke = 1; break; } if (should_be_binary == 0 && zadnji_znak_oznaka_novog_reda == 0 && znak == '\n') { *char_p = '\r'; ++ch; ++char_p; if (ch == 512) { zadnji_znak_oznaka_novog_reda = 1; break; } } *char_p = znak; ++ch; ++char_p; } retransmission_count = 0; // postavimo timeout na 3 sekunde timeout.tv_usec = 0; timeout.tv_sec = 3; while (retransmission_count < 3) { sendto(newfd, file, 4 + ch, 0, &client, client_l); FD_ZERO(&readfs); FD_SET(newfd, &readfs); // tu sad ide timeout status = select(newfd + 1, &readfs, NULL, NULL, &timeout); if (FD_ISSET(newfd, &readfs) == 0) { ++ retransmission_count; continue; } else { msglen = recvfrom(newfd, buffer, sizeof(buffer), 0, &client, &client_l); retransmission_count = 5; } memcpy(&tip_zahtjeva, buffer, 2); tip_zahtjeva = ntohs(tip_zahtjeva); memcpy(&broj_bloka, buffer + 2, 2); broj_bloka = ntohs(broj_bloka); // ako je ack i ne podudaraju se brojevi posalji ponovno if (tip_zahtjeva == 4 && broj_bloka != brojac_blokova) { retransmission_count = -1; } } // 3 puta smo timeoutali if (retransmission_count == 3) { memset(file, 0, sizeof file); // pogreska kod_poruke = htons(5); memcpy(file, &kod_poruke, 2); // illegal TFTP option broj_bloka = htons(0); memcpy(file + 2, &broj_bloka, 2); strcpy(file + 4, "TFTP timeout nad istim blokom 3 puta\0"); sendto(newfd, file, 516, 0, &client, client_l); Errx(daemon_proc ? LOG_ALERT : 1, "TFTP ERROR %d ms45889: timeout 3 puta"); } // pogledaj sta je klijent poslao ako nije ack (mozda error) // tip zahtjeva if (tip_zahtjeva == 5 ) { Close(newfd); Errx(daemon_proc ? LOG_ALERT : 1, "TFTP ERROR %d ms45889: klijent", broj_bloka); } ++ brojac_blokova; } fclose(datoteka); if (daemon_proc) { syslog(LOG_INFO, "%s->%s", klijent_adresa, filename); } else { printf("%s->%s\n", klijent_adresa, filename); } } else { // pogreska kod_poruke = htons(5); memcpy(file, &kod_poruke, 2); // illegal TFTP option broj_bloka = htons(4); memcpy(file + 2, &broj_bloka, 2); strcpy(file + 4, "TFTP server podrzava samo GET request\0"); sendto(newfd, file, 516, 0, &client, client_l); Warnx("TFTP ERROR 4 ms45889: podrzano samo citanje"); } /* * ubij proces dijeteta */ Close(newfd); _exit(0); } } Close(sockfd); free(port); return 0; }
/************************************************************************************************** CONF_SET_RECURSIVE If the 'recursive' configuration option was specified, set the recursive server. **************************************************************************************************/ static void conf_set_recursive(void) { char *c; const char *address = conf_get(&Conf, "recursive", NULL); char addr[512]; int port = 53; if (!address || !address[0]) return; strncpy(addr, address, sizeof(addr)-1); #if HAVE_IPV6 if (is_ipv6(addr)) { /* IPv6 - treat '+' as port separator */ recursive_family = AF_INET6; if ((c = strchr(addr, '+'))) { *c++ = '\0'; if (!(port = atoi(c))) port = 53; } if (inet_pton(AF_INET6, addr, &recursive_sa6.sin6_addr) <= 0) { Warnx("%s: %s", address, _("invalid network address for recursive server")); return; } recursive_sa6.sin6_family = AF_INET6; recursive_sa6.sin6_port = htons(port); forward_recursive = 1; #if DEBUG_ENABLED && DEBUG_CONF DebugX("conf", 1,_("recursive forwarding service through %s:%u"), ipaddr(AF_INET6, &recursive_sa6.sin6_addr), port); #endif recursive_fwd_server = STRDUP(address); } else { /* IPv4 - treat '+' or ':' as port separator */ #endif recursive_family = AF_INET; if ((c = strchr(addr, '+')) || (c = strchr(addr, ':'))) { *c++ = '\0'; if (!(port = atoi(c))) port = 53; } if (inet_pton(AF_INET, addr, &recursive_sa.sin_addr) <= 0) { Warnx("%s: %s", address, _("invalid network address for recursive server")); return; } recursive_sa.sin_family = AF_INET; recursive_sa.sin_port = htons(port); #if DEBUG_ENABLED &&DEBUG_CONF DebugX("conf", 1,_("recursive forwarding service through %s:%u"), ipaddr(AF_INET, &recursive_sa.sin_addr), port); #endif forward_recursive = 1; recursive_fwd_server = STRDUP(address); #if HAVE_IPV6 } #endif if (!forward_recursive) return; recursion_timeout = atou(conf_get(&Conf, "recursive-timeout", NULL)); recursion_connect_timeout = atou(conf_get(&Conf, "recursive-connect-timeout", NULL)); recursion_retries = atou(conf_get(&Conf, "recursive-retries", NULL)); recursion_algorithm = conf_get(&Conf, "recursive-algorithm", NULL); }
static int handle_string(void *ctx, const unsigned char *val, unsigned int len) { struct ctx *_ctx = (struct ctx *)ctx; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("handle_string, val = %s, enter state %d", buf, _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_TABLE_STATUS_KEY:{ if (aws_dynamo_json_get_table_status(val, len, &(_ctx->r->status))) { Warnx("handle_string - failed to get table status"); return 0; } _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_MAP; break; } case PARSER_STATE_TABLE_NAME_KEY:{ _ctx->r->table_name = strndup(val, len); _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_MAP; break; } case PARSER_STATE_HASH_KEY_ATTRIBUTE_NAME_KEY:{ _ctx->r->hash_key_name = strndup(val, len); _ctx->parser_state = PARSER_STATE_HASH_KEY_ELEMENT_MAP; break; } case PARSER_STATE_RANGE_KEY_ATTRIBUTE_NAME_KEY:{ _ctx->r->range_key_name = strndup(val, len); _ctx->parser_state = PARSER_STATE_HASH_KEY_ELEMENT_MAP; break; } case PARSER_STATE_HASH_KEY_ATTRIBUTE_TYPE_KEY:{ if (aws_dynamo_json_get_type(val, len, &(_ctx->r->hash_key_type))) { Warnx("handle_string - failed to get hash key type"); return 0; } _ctx->parser_state = PARSER_STATE_HASH_KEY_ELEMENT_MAP; break; } case PARSER_STATE_RANGE_KEY_ATTRIBUTE_TYPE_KEY:{ if (aws_dynamo_json_get_type(val, len, &(_ctx->r->range_key_type))) { Warnx("handle_string - failed to get hash key type"); return 0; } _ctx->parser_state = PARSER_STATE_HASH_KEY_ELEMENT_MAP; break; } default:{ Warnx("handle_string - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_string exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
static int put_item_map_key(void *ctx, const unsigned char *val, unsigned int len) { struct put_item_ctx *_ctx = (struct put_item_ctx *)ctx; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("put_item_map_key, val = %s, enter state %d", buf, _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_ROOT_MAP:{ if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_ATTRIBUTES, val, len)) { _ctx->parser_state = PARSER_STATE_ATTRIBUTES_KEY; } else if (AWS_DYNAMO_VALCMP(AWS_DYNAMO_JSON_CONSUMED_CAPACITY, val, len)) { _ctx->parser_state = PARSER_STATE_CAPACITY_KEY; } else { char key[len + 1]; snprintf(key, len + 1, "%s", val); Warnx("put_item_map_key: Unknown root key '%s'.", key); return 0; } break; } case PARSER_STATE_ATTRIBUTES_MAP:{ /* Set the attribute index based on the name. */ int attribute; for (attribute = 0; attribute < _ctx->r->num_attributes; attribute++) { struct aws_dynamo_attribute *a = &(_ctx->r->attributes[attribute]); if (len == a->name_len && strncmp(val, a->name, len) == 0) { _ctx->attribute_index = attribute; break; } } if (attribute == _ctx->r->num_attributes) { char attr[len + 1]; snprintf(attr, len + 1, "%s", val); Warnx("put_item_map_key: Unknown attribute '%s'.", attr); return 0; } _ctx->parser_state = PARSER_STATE_ATTRIBUTE_KEY; break; } case PARSER_STATE_ATTRIBUTE_MAP:{ /* verify the attribute is of the expected type. */ struct aws_dynamo_attribute *a; const char *expected_type; a = &(_ctx->r->attributes[_ctx->attribute_index]); expected_type = aws_dynamo_attribute_types[a->type]; if (len != strlen(expected_type) || strncmp(val, expected_type, len) != 0) { char type[len + 1]; snprintf(type, len + 1, "%s", val); Warnx("put_item_map_key: Unexpected type for attribute %s. Got %s, expected %s.", a->name, type, expected_type); return 0; } _ctx->parser_state = PARSER_STATE_ATTRIBUTE_VALUE; break; } default:{ Warnx("put_item_map_key - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("put_item_map_key exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
static int handle_number(void *ctx, const char *val, unsigned int len) { struct ctx *_ctx = (struct ctx *)ctx; #ifdef DEBUG_PARSER char buf[len + 1]; snprintf(buf, len + 1, "%s", val); Debug("handle_number, val = %s, enter state %d", buf, _ctx->parser_state); #endif /* DEBUG_PARSER */ switch (_ctx->parser_state) { case PARSER_STATE_CREATION_DATE_TIME_KEY:{ double date_time; if (aws_dynamo_json_get_double(val, len, &date_time) == -1) { Warnx("handle_number: failed to get creation date time."); return 0; } _ctx->r->creation_date_time = (int)date_time; _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_MAP; break; } case PARSER_STATE_READ_CAPACITY_UNITS_KEY:{ if (aws_dynamo_json_get_int(val, len, &(_ctx->r->read_units)) == -1) { Warnx("handle_number: failed to get read units."); return 0; } _ctx->parser_state = PARSER_STATE_PROVISIONED_THROUGHPUT_MAP; break; } case PARSER_STATE_WRITE_CAPACITY_UNITS_KEY:{ if (aws_dynamo_json_get_int(val, len, &(_ctx->r->write_units)) == -1) { Warnx("handle_number: failed to get write units."); return 0; } _ctx->parser_state = PARSER_STATE_PROVISIONED_THROUGHPUT_MAP; break; } case PARSER_STATE_NUMBER_OF_DECREASES_TODAY_KEY:{ if (aws_dynamo_json_get_int(val, len, &(_ctx->r->number_decreases_today)) == -1) { Warnx("handle_number: failed to get number of decreases today."); return 0; } _ctx->parser_state = PARSER_STATE_PROVISIONED_THROUGHPUT_MAP; break; } case PARSER_STATE_ITEM_COUNT_KEY:{ if (aws_dynamo_json_get_int(val, len, &(_ctx->r->item_count)) == -1) { Warnx("handle_number: failed to get item count."); return 0; } _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_MAP; break; } case PARSER_STATE_TABLE_SIZE_BYTES_KEY:{ if (aws_dynamo_json_get_int(val, len, &(_ctx->r->table_size_bytes)) == -1) { Warnx("handle_number: failed to get table size bytes."); return 0; } _ctx->parser_state = PARSER_STATE_TABLE_DESCRIPTION_MAP; break; } default:{ Warnx("handle_number - unexpected state %d", _ctx->parser_state); return 0; break; } } #ifdef DEBUG_PARSER Debug("handle_number exit %d", _ctx->parser_state); #endif /* DEBUG_PARSER */ return 1; }
struct aws_dynamo_create_table_response *aws_dynamo_parse_create_table_response(const char *response, int response_len) { yajl_handle hand; yajl_status stat; struct ctx _ctx = { 0 }; _ctx.r = calloc(sizeof(*(_ctx.r)), 1); if (_ctx.r == NULL) { Warnx("aws_dynamo_parse_create_table_response: response alloc failed."); return NULL; } #if YAJL_MAJOR == 2 hand = yajl_alloc(&handle_callbacks, NULL, &_ctx); yajl_parse(hand, response, response_len); stat = yajl_complete_parse(hand); #else hand = yajl_alloc(&handle_callbacks, NULL, NULL, &_ctx); yajl_parse(hand, response, response_len); stat = yajl_parse_complete(hand); #endif if (stat != yajl_status_ok) { unsigned char *str = yajl_get_error(hand, 1, response, response_len); Warnx("aws_dynamo_parse_create_table_response: json parse failed, '%s'", (const char *)str); yajl_free_error(hand, str); yajl_free(hand); aws_dynamo_free_create_table_response(_ctx.r); return NULL; } yajl_free(hand); return _ctx.r; }