Exemplo n.º 1
0
/*
 *  Return the next character from `buffer'.
 */
char buffer_peek(buffer_t *buffer)
{
	char c;


	buffer_seek(buffer, 1);
	c = buffer_get_next(buffer);
	buffer_seek(buffer, -2);

	return c;
}
Exemplo n.º 2
0
int
send_file_fd (int out_fd, int in_fd, uint64 offset, uint64 size, uint64 *sent)
{
  char data_in[BUFFER_INSIZE];
  char data_out[BUFFER_OUTSIZE];
  struct buffer buf_in;
  struct buffer buf_out;
  int64 r;
  int64 w;
  uint64 r_sent = 0;
  char *x;

  buffer_init (&buf_in, (buffer_op) read, in_fd, data_in, sizeof (data_in));
  buffer_init (&buf_out, (buffer_op) write, out_fd, data_out, sizeof (data_out));

  for (;;) {
    r = buffer_feed (&buf_in);
    if (r == 0) break;
    if (r == -1) goto FAIL;
    x = buffer_peek (&buf_in);
    w = buffer_put (&buf_out, x, r);
    if (w == -1) goto FAIL;
    buffer_seek (&buf_in, r);
    r_sent += w;
  }
  *sent = r_sent;
  return 0;

  FAIL:
  *sent = r_sent;
  return -1;
}
Exemplo n.º 3
0
static void
elf_phdr(struct buffer *pinput, Elf64_Phdr *phdr,
	 int entsize, struct xdr *xdr, int bit64)
{
	/*
	 * The entsize need not be sizeof(*phdr).
	 * Hence, it is easier to keep a copy of the input,
	 * as the xdr functions may not advance the input
	 * pointer the full entsize; rather than get tricky
	 * we just advance it below.
	 */
	struct buffer input;
	buffer_clone(&input, pinput);
	if (bit64){
		phdr->p_type = xdr->get32(&input);
		phdr->p_flags = xdr->get32(&input);
		phdr->p_offset = xdr->get64(&input);
		phdr->p_vaddr = xdr->get64(&input);
		phdr->p_paddr = xdr->get64(&input);
		phdr->p_filesz = xdr->get64(&input);
		phdr->p_memsz = xdr->get64(&input);
		phdr->p_align = xdr->get64(&input);
	} else {
		phdr->p_type = xdr->get32(&input);
		phdr->p_offset = xdr->get32(&input);
		phdr->p_vaddr = xdr->get32(&input);
		phdr->p_paddr = xdr->get32(&input);
		phdr->p_filesz = xdr->get32(&input);
		phdr->p_memsz = xdr->get32(&input);
		phdr->p_flags = xdr->get32(&input);
		phdr->p_align = xdr->get32(&input);
	}
	buffer_seek(pinput, entsize);
}
Exemplo n.º 4
0
void
http_header_parse(htbl_t *h, buffer_t *b) {
	int eoh = 0;
	char l=0, c = ' ', *t;
	bool kv = false;
	http_header_field_t e = {0};

	if(b == NULL || h == NULL) {
		libnet_error_set(LIBNET_E_INV_ARG);
		return;
	}

	t = &e.key;

	buffer_seek(b, 0);

	while(eoh < 4 && c != 0) {
		int len = buffer_read(b, &c, 1);

		if(c == ':' && kv == false) {
			kv = true;
			t = &e.value;
		} else if(/*iscntrl(c)*/c == '\r' || c == '\n') {
			if(l != '\r' && l != '\n') {
				eoh = 0;
			}

			eoh++;

			if(l == '\r' && c == '\n') {
				if(kv == true) {
					//printf("setting: %s -> %s\n", e.key, e.value);
					htbl_insert_copy(h, e.key, (void *)&e, sizeof(http_header_field_t));
				}

				memset(&e, 0, sizeof(http_header_field_t));
				t = &e.key;

				kv = false;
			}
		} else {
			if(isspace(c) && kv == true && strlen(e.value) == 0) {
				
			} else {
				*t++ = tolower(c);
			}
		}

		l = c;
	}
}
Exemplo n.º 5
0
static void
elf_shdr(struct buffer *pinput, Elf64_Shdr *shdr,
	 int entsize, struct xdr *xdr, int bit64)
{
	/*
	 * The entsize need not be sizeof(*shdr).
	 * Hence, it is easier to keep a copy of the input,
	 * as the xdr functions may not advance the input
	 * pointer the full entsize; rather than get tricky
	 * we just advance it below.
	 */
	struct buffer input = *pinput;
	if (bit64){
		shdr->sh_name = xdr->get32(&input);
		shdr->sh_type = xdr->get32(&input);
		shdr->sh_flags = xdr->get64(&input);
		shdr->sh_addr = xdr->get64(&input);
		shdr->sh_offset = xdr->get64(&input);
		shdr->sh_size= xdr->get64(&input);
		shdr->sh_link = xdr->get32(&input);
		shdr->sh_info = xdr->get32(&input);
		shdr->sh_addralign = xdr->get64(&input);
		shdr->sh_entsize = xdr->get64(&input);
	} else {
		shdr->sh_name = xdr->get32(&input);
		shdr->sh_type = xdr->get32(&input);
		shdr->sh_flags = xdr->get32(&input);
		shdr->sh_addr = xdr->get32(&input);
		shdr->sh_offset = xdr->get32(&input);
		shdr->sh_size = xdr->get32(&input);
		shdr->sh_link = xdr->get32(&input);
		shdr->sh_info = xdr->get32(&input);
		shdr->sh_addralign = xdr->get32(&input);
		shdr->sh_entsize = xdr->get32(&input);
	}
	buffer_seek(pinput, entsize);
}
Exemplo n.º 6
0
static zip_int64_t
read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
{
    struct read_data *ctx = (struct read_data *)state;

    switch (cmd) {
        case ZIP_SOURCE_BEGIN_WRITE:
	    if ((ctx->out = buffer_new_write(WRITE_FRAGMENT_SIZE)) == NULL) {
		zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
		return -1;
	    }
	    return 0;

        case ZIP_SOURCE_CLOSE:
            return 0;
            
        case ZIP_SOURCE_COMMIT_WRITE:
	    buffer_free(ctx->in);
	    ctx->in = ctx->out;
	    ctx->out = NULL;
	    return 0;

        case ZIP_SOURCE_ERROR:
            return zip_error_to_data(&ctx->error, data, len);
            
        case ZIP_SOURCE_FREE:
	    buffer_free(ctx->in);
	    buffer_free(ctx->out);
            free(ctx);
            return 0;
            
        case ZIP_SOURCE_OPEN:
	    ctx->in->offset = 0;
            return 0;
	
        case ZIP_SOURCE_READ:
	    if (len > ZIP_INT64_MAX) {
		zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
		return -1;
	    }
            return buffer_read(ctx->in, data, len);
	
        case ZIP_SOURCE_REMOVE:
	{
	    buffer_t *empty = buffer_new_read(NULL, 0, 0);
	    if (empty == 0) {
		zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
		return -1;
	    }
	
	    buffer_free(ctx->in);
	    ctx->in = empty;
	    return 0;
	}

        case ZIP_SOURCE_ROLLBACK_WRITE:
	    buffer_free(ctx->out);
	    ctx->out = NULL;
	    return 0;

        case ZIP_SOURCE_SEEK:
	    return buffer_seek(ctx->in, data, len, &ctx->error);

        case ZIP_SOURCE_SEEK_WRITE:
	    return buffer_seek(ctx->out, data, len, &ctx->error);
       
        case ZIP_SOURCE_STAT:
        {
            zip_stat_t *st;
	    
	    if (len < sizeof(*st)) {
                zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
		return -1;
	    }

	    st = (zip_stat_t *)data;

	    zip_stat_init(st);
	    st->mtime = ctx->mtime;
	    st->size = ctx->in->size;
	    st->comp_size = st->size;
	    st->comp_method = ZIP_CM_STORE;
	    st->encryption_method = ZIP_EM_NONE;
	    st->valid = ZIP_STAT_MTIME|ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;
	    
	    return sizeof(*st);
	}

        case ZIP_SOURCE_SUPPORTS:
	    return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);
            
        case ZIP_SOURCE_TELL:
            if (ctx->in->offset > ZIP_INT64_MAX) {
		zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
		return -1;
	    }
	    return (zip_int64_t)ctx->in->offset;
		
            
        case ZIP_SOURCE_TELL_WRITE:
            if (ctx->out->offset > ZIP_INT64_MAX) {
		zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
		return -1;
	    }
	    return (zip_int64_t)ctx->out->offset;

        case ZIP_SOURCE_WRITE:
	    if (len > ZIP_INT64_MAX) {
		zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
		return -1;
	    }
	    return buffer_write(ctx->out, data, len, &ctx->error);

        default:
	    zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
            return -1;
    }
}
Exemplo n.º 7
0
static zip_int64_t
source_hole_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t command)
{
    hole_t *ctx = (hole_t *)ud;

    switch (command) {
    case ZIP_SOURCE_BEGIN_WRITE:
        ctx->out = buffer_new();
        return 0;

    case ZIP_SOURCE_CLOSE:
        return 0;

    case ZIP_SOURCE_COMMIT_WRITE:
        if (buffer_to_file(ctx->out, ctx->fname, &ctx->error) < 0) {
            return -1;
        }
        buffer_free(ctx->in);
        ctx->in = ctx->out;
        ctx->out = NULL;
        return 0;

    case ZIP_SOURCE_ERROR:
        return zip_error_to_data(&ctx->error, data, length);

    case ZIP_SOURCE_FREE:
        hole_free(ctx);
        return 0;

    case ZIP_SOURCE_OPEN:
        ctx->in->offset = 0;
        return 0;

    case ZIP_SOURCE_READ:
        return buffer_read(ctx->in, data, length, &ctx->error);

    case ZIP_SOURCE_REMOVE:
        buffer_free(ctx->in);
        ctx->in = buffer_new();
        buffer_free(ctx->out);
        ctx->out = NULL;
        (void)remove(ctx->fname);
        return 0;

    case ZIP_SOURCE_ROLLBACK_WRITE:
        buffer_free(ctx->out);
        ctx->out = NULL;
        return 0;

    case ZIP_SOURCE_SEEK:
        return buffer_seek(ctx->in, data, length, &ctx->error);

    case ZIP_SOURCE_SEEK_WRITE:
        return buffer_seek(ctx->out, data, length, &ctx->error);

    case ZIP_SOURCE_STAT: {
        zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error);

        if (st == NULL) {
            return -1;
        }

        /* TODO: return ENOENT if fname doesn't exist */

        st->valid |= ZIP_STAT_SIZE;
        st->size = ctx->in->size;
        return 0;
    }

    case ZIP_SOURCE_TELL:
        return (zip_int64_t)ctx->in->offset;

    case ZIP_SOURCE_TELL_WRITE:
        return (zip_int64_t)ctx->out->offset;

    case ZIP_SOURCE_WRITE:
        return buffer_write(ctx->out, data, length, &ctx->error);

    case ZIP_SOURCE_SUPPORTS:
        return zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_STAT, ZIP_SOURCE_TELL, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);

    default:
        zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
        return -1;
    }
}
Exemplo n.º 8
0
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *   Write all new alarms to the diskloop.
 */
void alarm_archive( alarm_context_t* alarm_list, buffer_t* url_str,
                    st_info_t* st_info )
{
    time_t   start_time = 0;
    time_t   end_time   = 0;
    uint8_t  buf_byte   = 0;
    uint16_t buf_word   = 0;
    uint32_t buf_dword  = 0L;
    //uint64_t buf_qword  = 0LL;

    uint16_t  version_type = 0x8000 | FALCON_VERSION;
    uint16_t  alarm_count  = 0;
    char*     retmsg     = NULL;
    buffer_t* alarm_data = NULL;
    alarm_line_t* alarm  = NULL;

    alarm_data = buffer_init();

    if (!alarm_data) {
        if (gDebug)
            fprintf(stderr, "falcon: unable to allocate space for alarm data\n");
        else
            syslog(LOG_ERR, "falcon: unable to allocate space for alarm data\n");
        return;
    }

    // Print each line in the filtered list
    list_iterator_stop(alarm_list);
    list_iterator_start(alarm_list);
    while (list_iterator_hasnext(alarm_list)) 
    {
        alarm = (alarm_line_t*)list_iterator_next(alarm_list);
        if (alarm->sent)
            continue;

        if (!start_time)
          start_time = alarm->timestamp;
        if (!end_time)
          end_time = alarm->timestamp;

        if (gDebug)
            fprintf(stdout, "DEBUG %s, line %d, date %s: %s\n", 
                    __FILE__, __LINE__, __DATE__, alarm->text);

        if ((retmsg = q330LogMsg(alarm->text, st_info->station,
                                 st_info->network, "LOG",
                                 st_info->location)) != NULL)
        { // error trying to log the message
            if (gDebug)
                fprintf(stderr, "falcon: failed to write alarms to log: %s\n", retmsg);
            else
                syslog(LOG_ERR, "falcon: failed to write alarms to log: %s\n", retmsg);
            exit(1);
        }

        if (gDebug)
        {
            fprintf(stdout, "Alarm '%s':\n", alarm->description);
            fprintf(stdout, "    Channel    : %02x\n", (alarm->channel));
            fprintf(stdout, "    Timestamp  : %li\n", (long)(alarm->timestamp));
            fprintf(stdout, "    Event Code : 0x%02x\n", (alarm->event));
            fprintf(stdout, "    Sent       : %s\n", alarm->sent ? "Yes" : "No");
            fprintf(stdout, "    Hash       : 0x%08lx\n", (unsigned long)(alarm->hash));
            fprintf(stdout, "    Text       : %s\n", alarm->text);
        }

        if (start_time > alarm->timestamp)
            start_time = alarm->timestamp;
        if (end_time < alarm->timestamp)
            end_time = alarm->timestamp;

        if (!alarm->description[0])
        {
            if (gDebug)
                fprintf(stderr, "falcon: description code not found\n");
            else
                syslog(LOG_ERR, "falcon: description code not found\n");
            continue;
        }

        // There must be at least enough space for one more alarm.
        // If there isn't, queue this buffer's contents, and reset it.
        // This should prevent us from ever fragmenting alarm data
        // across opaque blockettes.
        if (alarm_count && (alarm_data->length > 400))
        {
            buffer_seek(alarm_data, 2);
            buf_dword = htonl(start_time);
            buffer_write(alarm_data, (uint8_t*)(&buf_dword), sizeof(buf_dword));
            buf_dword = htonl(end_time);
            buffer_write(alarm_data, (uint8_t*)(&buf_dword), sizeof(buf_dword));
            buf_word = htons(alarm_count);
            buffer_write(alarm_data, (uint8_t*)(&buf_word), sizeof(buf_word));

            if (gDebug) {
                fprintf(stdout, "falcon: [MID] alarms were found\n");
                fprintf(stdout, "[MID] raw buffer:\n");
                format_data(alarm_data->content, alarm_data->length, 0, 0);
            }

            QueueOpaque(alarm_data->content, (int)alarm_data->length,
                        st_info->station, st_info->network,
                        st_info->alarm_chan, st_info->location,
                        FALCON_IDSTRING);
            alarm_data  = buffer_destroy(alarm_data);
            alarm_count = 0;
            start_time  = alarm->timestamp;
            end_time    = alarm->timestamp;
            alarm_data  = buffer_init();
            if (!alarm_data) {
                if (gDebug)
                    fprintf(stderr, "falcon: unable to allocate space for alarm data\n");
                else
                    syslog(LOG_ERR, "falcon: unable to allocate space for alarm data\n");
                return;
            }
        } // If we've built up a records worth of alarm data

        if (!alarm_count)
        {
            // Write alarm header info
            if (gDebug)
            {
                fprintf(stderr, "falcon: Writing alarm header info.\n");
            }
            buf_word = htons(version_type);
            buffer_write(alarm_data, (uint8_t*)(&buf_word), sizeof(buf_word));
            // Reserve space for elements that will be assigned just 
            // prior to queueing data
            buf_dword = htonl(start_time);
            buffer_write(alarm_data, (uint8_t*)(&buf_dword), sizeof(buf_dword));
            buf_dword = htonl(end_time);
            buffer_write(alarm_data, (uint8_t*)(&buf_dword), sizeof(buf_dword));
            buf_word = htons(alarm_count);
            buffer_write(alarm_data, (uint8_t*)(&buf_word), sizeof(buf_word));
        }

        // Add an alarm
        buf_word = htons(alarm->channel);
        buffer_write(alarm_data, (uint8_t*)(&buf_word), sizeof(buf_word));
        buf_dword = htonl(alarm->timestamp);
        buffer_write(alarm_data, (uint8_t*)(&buf_dword), sizeof(buf_dword));
        buffer_write(alarm_data, &(alarm->event), sizeof(alarm->event));
        buf_byte = (uint8_t)strlen(alarm->description);
        buffer_write(alarm_data, &buf_byte, sizeof(buf_byte));
        buffer_write(alarm_data, (uint8_t*)(alarm->description), (size_t)buf_byte);
        buffer_terminate(alarm_data);

        alarm_count++;
        alarm->sent = 1;
    }
    list_iterator_stop(alarm_list);

    if (alarm_count && alarm_data && alarm_data->content && alarm_data->length)
    {
        buffer_seek(alarm_data, 2);
        buf_dword = htonl(start_time);
        buffer_write(alarm_data, (uint8_t*)(&buf_dword), sizeof(buf_dword));
        buf_dword = htonl(end_time);
        buffer_write(alarm_data, (uint8_t*)(&buf_dword), sizeof(buf_dword));
        buf_word = htons(alarm_count);
        buffer_write(alarm_data, (uint8_t*)(&buf_word), sizeof(buf_word));

        if (gDebug) {
            fprintf(stderr, "falcon: [END] alarms were found\n");
            fprintf(stderr, "[END] raw buffer:\n");
            format_data(alarm_data->content, alarm_data->length, 0, 0);
        }

        QueueOpaque(alarm_data->content, (int)alarm_data->length,
                    st_info->station, st_info->network,
                    st_info->alarm_chan, st_info->location,
                    FALCON_IDSTRING);
    }
    alarm_data = buffer_destroy(alarm_data);

    // Make sure we limit the accumulation of alarm messages
    while (list_size(alarm_list) > MAX_CONTEXT_ALARMS)
    {
        alarm = list_fetch(alarm_list);
        alarm = alarm_line_destroy(alarm);
    }
}
Exemplo n.º 9
0
static int
write_elf(const struct rmod_context *ctx, const struct buffer *in,
          struct buffer *out)
{
	int ret;
	int bit64;
	size_t loc;
	size_t rmod_data_size;
	struct elf_writer *ew;
	struct buffer rmod_data;
	struct buffer rmod_header;
	struct buffer program;
	struct buffer relocs;
	Elf64_Xword total_size;
	Elf64_Addr addr;
	Elf64_Ehdr ehdr;

	bit64 = ctx->pelf.ehdr.e_ident[EI_CLASS] == ELFCLASS64;

	/*
	 * 3 sections will be added  to the ELF file.
	 * +------------------+
	 * |  rmodule header  |
	 * +------------------+
	 * |     program      |
	 * +------------------+
	 * |   relocations    |
	 * +------------------+
	 */

	/* Create buffer for header and relocations. */
	rmod_data_size = sizeof(struct rmodule_header);
	if (bit64)
		rmod_data_size += ctx->nrelocs * sizeof(Elf64_Addr);
	else
		rmod_data_size += ctx->nrelocs * sizeof(Elf32_Addr);

	if (buffer_create(&rmod_data, rmod_data_size, "rmod"))
		return -1;

	buffer_splice(&rmod_header, &rmod_data,
	              0, sizeof(struct rmodule_header));
	buffer_clone(&relocs, &rmod_data);
	buffer_seek(&relocs, sizeof(struct rmodule_header));

	/* Reset current location. */
	buffer_set_size(&rmod_header, 0);
	buffer_set_size(&relocs, 0);

	/* Program contents. */
	buffer_splice(&program, in, ctx->phdr->p_offset, ctx->phdr->p_filesz);

	/* Create ELF writer with modified entry point. */
	memcpy(&ehdr, &ctx->pelf.ehdr, sizeof(ehdr));
	ew = elf_writer_init(&ehdr);

	if (ew == NULL) {
		ERROR("Failed to create ELF writer.\n");
		buffer_delete(&rmod_data);
		return -1;
	}

	/* Write out rmodule_header. */
	ctx->xdr->put16(&rmod_header, RMODULE_MAGIC);
	ctx->xdr->put8(&rmod_header, RMODULE_VERSION_1);
	ctx->xdr->put8(&rmod_header, 0);
	/* payload_begin_offset */
	loc = sizeof(struct rmodule_header);
	ctx->xdr->put32(&rmod_header, loc);
	/* payload_end_offset */
	loc += ctx->phdr->p_filesz;
	ctx->xdr->put32(&rmod_header, loc);
	/* relocations_begin_offset */
	ctx->xdr->put32(&rmod_header, loc);
	/* relocations_end_offset */
	if (bit64)
		loc += ctx->nrelocs * sizeof(Elf64_Addr);
	else
		loc += ctx->nrelocs * sizeof(Elf32_Addr);
	ctx->xdr->put32(&rmod_header, loc);
	/* module_link_start_address */
	ctx->xdr->put32(&rmod_header, ctx->phdr->p_vaddr);
	/* module_program_size */
	ctx->xdr->put32(&rmod_header, ctx->phdr->p_memsz);
	/* module_entry_point */
	ctx->xdr->put32(&rmod_header, ctx->pelf.ehdr.e_entry);
	/* parameters_begin */
	ctx->xdr->put32(&rmod_header, ctx->parameters_begin);
	/* parameters_end */
	ctx->xdr->put32(&rmod_header, ctx->parameters_end);
	/* bss_begin */
	ctx->xdr->put32(&rmod_header, ctx->bss_begin);
	/* bss_end */
	ctx->xdr->put32(&rmod_header, ctx->bss_end);
	/* padding[4] */
	ctx->xdr->put32(&rmod_header, 0);
	ctx->xdr->put32(&rmod_header, 0);
	ctx->xdr->put32(&rmod_header, 0);
	ctx->xdr->put32(&rmod_header, 0);

	/* Write the relocations. */
	for (unsigned i = 0; i < ctx->nrelocs; i++) {
		if (bit64)
			ctx->xdr->put64(&relocs, ctx->emitted_relocs[i]);
		else
			ctx->xdr->put32(&relocs, ctx->emitted_relocs[i]);
	}

	total_size = 0;
	addr = 0;

	/*
	 * There are 2 cases to deal with. The program has a large NOBITS
	 * section and the relocations can fit entirely within occupied memory
	 * region for the program. The other is that the relocations increase
	 * the memory footprint of the program if it was loaded directly into
	 * the region it would run. The rmdoule header is a fixed cost that
	 * is considered a part of the program.
	 */
	total_size += buffer_size(&rmod_header);
	if (buffer_size(&relocs) + ctx->phdr->p_filesz > ctx->phdr->p_memsz) {
		total_size += buffer_size(&relocs);
		total_size += ctx->phdr->p_filesz;
	} else {
		total_size += ctx->phdr->p_memsz;
	}

	ret = add_section(ew, &rmod_header, ".header", addr,
	                  buffer_size(&rmod_header));
	if (ret < 0)
		goto out;
	addr += buffer_size(&rmod_header);

	ret = add_section(ew, &program, ".program", addr, ctx->phdr->p_filesz);
	if (ret < 0)
		goto out;
	addr += ctx->phdr->p_filesz;

	if (ctx->nrelocs) {
		ret = add_section(ew, &relocs, ".relocs", addr,
				  buffer_size(&relocs));
		if (ret < 0)
			goto out;
		addr += buffer_size(&relocs);
	}

	if (total_size != addr) {
		ret = add_section(ew, NULL, ".empty", addr, total_size - addr);
		if (ret < 0)
			goto out;
	}

	/*
	 * Ensure last section has a memory usage that meets the required
	 * total size of the program in memory.
	 */

	ret = elf_writer_serialize(ew, out);
	if (ret < 0)
		ERROR("Failed to serialize ELF to buffer.\n");

out:
	buffer_delete(&rmod_data);
	elf_writer_destroy(ew);

	return ret;
}
//This is the implementation of the UIPAPP that uIP will call when
//something network data related happens.
//The purpose of this app is to move buffer data to and from the network
void uip_socket_app(void)
{
    int i;
    file_handle_t file_handle =  (uip_conn->appstate)[0];
    struct file_t* file = NULL;
    struct buffer_t *rxbuf = NULL;
    struct buffer_t *txbuf = NULL;
    bool may_send = true;

#ifdef __DEBUG
    printf("\r\napp: process conn @ %p", uip_conn);
#endif


    if(uip_connected())
    {
#ifdef __DEBUG
        printf("\r\napp: connected. Ports %hd:%hd", uip_conn->lport, uip_conn->rport);
#endif
        if( file_handle == FILE_INVALID_HANDLE )
        {
            //it's an incoming connection (no assigned handle)
            //find the index of the listening port
            for( i = 0; i < UIP_LISTENPORTS ; i++ )
            {
                if( uip_listenports[i] == uip_conn->lport )
                {
                    file_handle = listenports[i](uip_conn->lport, uip_conn->ripaddr, uip_conn->rport);
                    if( file_handle != FILE_INVALID_HANDLE )
                    {
                        uip_conn->appstate[0] = file_handle;
                    }
                    break;
                }
            }
        }
    }
    if( file_handle == FILE_INVALID_HANDLE)
    {
        goto close_or_abort;
    }

    file =  file_get_by_handle(file_handle);
    rxbuf = file->read_buffer;
    txbuf = file->write_buffer;


    if( file->state == ClosePending )
    {
#ifdef __DEBUG
        printf("\r\napp: freeing handle %hhd",uip_conn->appstate[0]);
#endif
        file_free(uip_conn->appstate[0]);
        uip_conn->appstate[0] = FILE_INVALID_HANDLE;
        goto close_or_abort;
    }


    if( rxbuf == NULL || txbuf == NULL )
    {
        goto close_or_abort;
    }

    if( uip_connected() ) file->state = Open;

    if( uip_acked() ) {
#ifdef __DEBUG
        printf("\r\napp: acked %d bytes", uip_this_ack);
#endif
        buffer_seek( txbuf, uip_this_ack );
    }

    int free = buffer_free( rxbuf );//free to write to
    int available = buffer_available( txbuf );//available to read

    if(uip_rexmit()) {
//#ifdef __DEBUG
        printf("\r\napp: rexmit. Handle: %hhd", file_handle);
//#endif
        buffer_peek( txbuf, (char*)uip_appdata, uip_conn->len);
        uip_send(uip_appdata, uip_conn->len);
        may_send = false;
    }
    else if(uip_newdata())
    {
#ifdef __DEBUG
        printf("\r\napp: newdata. Handle: %hhd. len=%u\n", file_handle, uip_datalen() );
#endif
        if( free >= uip_datalen() )
        {
            free -= buffer_write( rxbuf, (char*)uip_appdata, uip_datalen() );
        }
        else {
            puts("buffer overflow\n");
        }
    }
    else if( uip_closed() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd closed\n", file_handle );
#endif
        file->state = Closed;
        may_send = false;
    }
    else if( uip_aborted() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd aborted\n", file_handle );
#endif
        file->state = Aborted;
        may_send = false;
    }
    else if( uip_timedout() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd timed out\n", file_handle );
#endif
        file->state = TimedOut;
        may_send = false;
    }
//	if( available >  0 && file->state > Open )
//	{
//		buffer_seek( txbuf, available);
//	}
    if( available > 0 && may_send && uip_conn->len == 0) {
        //we can send the smaller of what's available or the connection mss
        int size = available < uip_mss() ? available : uip_mss() ;
        int peek = buffer_peek( txbuf, (char*)uip_appdata, size);
        uip_appdata[peek] = '\0';
#ifdef __DEBUG
        printf("\r\napp: sending %d of %d available bytes: [%s] ", peek,available, (char*)uip_appdata);
#endif
        uip_send(uip_appdata, peek);

    }
    /*
    This code prevents the "silly-window" TCP problem
    The problem is though, that we want to fill our rx buffer entirely
    sometimes before acting on it.
    I've disabled this code in the meantime, until we can
    set the behaviour on a connection basis
    ...Or it becomes apparent that we just don't need it.

    if( free < rxbuf->size / 2 )
    {
    	puts("\napp: stopping rx\n");
    	uip_stop();
    }
    else if( uip_stopped(uip_conn) )
    {
    	puts("\napp: restarting rx\n");
    	uip_restart(); //TODO NEED to be able to set the window size?
    }
    */
    //...instead let's try setting the window size
    uip_receive_window = free;
    return;

close_or_abort:
    if( uip_closed() || uip_aborted() || uip_timedout() )
    {
        puts("\r\napp: abort chosen");
        uip_abort();
    }
    else
    {
        puts("\r\napp: close chosen");
        uip_close();
    }

}
Exemplo n.º 11
0
void
http_response_parse/*_and_read*/(struct http_ctx *c, http_response_t *r, buffer_t *d) {
	char buf[LIBNET_HTTP_SIZE_CHUNK] = {0}, *tok;
	uint32_t len, i = 0, chunk_size = 0;
	bool chunked = false;
	http_header_field_t *hf_e;

	if(c == NULL || r == NULL || d == NULL) {
		libnet_error_set(LIBNET_E_INV_ARG);
		return;
	}

	htbl_create(&r->header, 0);
	buffer_create(&r->body, LIBNET_BM_FILE);

	len = buffer_size(d);
	buffer_seek(d, 0);

	/* read status line */
	while(len > 0) {
		buffer_read(d, buf + i, 1);
		
		if(strstr(buf, LIBNET_HTTP_DEL)) {
			break;
		}

		++i; --len;
	}

	//printf("status line: %s", buf);

	/* do something with the http version */

	/* get status code */
	tok = strstr(buf, " ") + 1;
	sprintf(buf, "%s", tok);
	sscanf(buf, "%3d", &r->code);

	/* get reason */
	i = strcspn(buf+4, LIBNET_HTTP_DEL) + 1;

	if(i > LIBNET_HTTP_SIZE_REASON) {
		i -= LIBNET_HTTP_SIZE_REASON; // LIBNET_HTTP_DEL;
	}

	snprintf(r->reason, i, "%s", buf+4);

	/* now parse header */
	http_header_parse(&r->header, d);

	/* chunked? */
	hf_e = (http_header_field_t *)htbl_get(&r->header, "transfer-encoding");
	chunked = (!strcmp(hf_e->value, "chunked") ? true : false);

	uint32_t get_chunk_size(socket_t *s) {
		uint32_t i = 0, size;
		char buf[LIBNET_HTTP_SIZE_CHUNK] = {0};

		while(!strstr(buf, LIBNET_HTTP_DEL)) {
			if(0 == socket_read(s, buf+i++, 1)) {
				return 0;
			}
		}

		if(i >= 3) {
			buf[i-2] = 0;
		} else {
			return 0;
		}

		sscanf(buf, "%x", &size);
		return size;
	}
Exemplo n.º 12
0
int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output,
				uint32_t *location, const char *ignore_section)
{
	struct xip_context xipctx;
	struct rmod_context *rmodctx;
	struct reloc_filter filter;
	struct parsed_elf *pelf;
	size_t output_sz;
	uint32_t adjustment;
	struct buffer binput;
	struct buffer boutput;
	Elf64_Xword i;
	int ret = -1;

	xipctx.ignored_section_idx = 0;
	rmodctx = &xipctx.rmodctx;
	pelf = &rmodctx->pelf;

	if (rmodule_init(rmodctx, input))
		return -1;

	/* Only support x86 XIP currently. */
	if (rmodctx->pelf.ehdr.e_machine != EM_386) {
		ERROR("Only support XIP stages for x86\n");
		goto out;
	}

	xipctx.ignored_section =
		find_ignored_section_header(pelf, ignore_section);

	if (xipctx.ignored_section != NULL)
		xipctx.ignored_section_idx =
			xipctx.ignored_section - pelf->shdr;

	filter.filter = rmod_filter;
	filter.context = &xipctx;

	if (rmodule_collect_relocations(rmodctx, &filter))
		goto out;

	output_sz = sizeof(struct cbfs_stage) + pelf->phdr->p_filesz;
	if (buffer_create(output, output_sz, input->name) != 0) {
		ERROR("Unable to allocate memory: %m\n");
		goto out;
	}
	buffer_clone(&boutput, output);
	memset(buffer_get(&boutput), 0, output_sz);
	buffer_set_size(&boutput, 0);

	/* Single loadable segment. The entire segment moves to final
	 * location from based on virtual address of loadable segment. */
	adjustment = *location - pelf->phdr->p_vaddr;
	DEBUG("Relocation adjustment: %08x\n", adjustment);

	fill_cbfs_stage(&boutput, CBFS_COMPRESS_NONE,
			(uint32_t)pelf->ehdr.e_entry + adjustment,
			(uint32_t)pelf->phdr->p_vaddr + adjustment,
			pelf->phdr->p_filesz, pelf->phdr->p_memsz);
	/* Need an adjustable buffer. */
	buffer_clone(&binput, input);
	buffer_seek(&binput, pelf->phdr->p_offset);
	bputs(&boutput, buffer_get(&binput), pelf->phdr->p_filesz);

	buffer_clone(&boutput, output);
	buffer_seek(&boutput, sizeof(struct cbfs_stage));

	/* Make adjustments to all the relocations within the program. */
	for (i = 0; i < rmodctx->nrelocs; i++) {
		size_t reloc_offset;
		uint32_t val;
		struct buffer in, out;

		/* The relocations represent in-program addresses of the
		 * linked program. Obtain the offset into the program to do
		 * the adjustment. */
		reloc_offset = rmodctx->emitted_relocs[i] - pelf->phdr->p_vaddr;

		buffer_clone(&out, &boutput);
		buffer_seek(&out, reloc_offset);
		buffer_clone(&in, &out);
		/* Appease around xdr semantics: xdr decrements buffer
		 * size when get()ing and appends to size when put()ing. */
		buffer_set_size(&out, 0);

		val = xdr_le.get32(&in);
		DEBUG("reloc %zx %08x -> %08x\n", reloc_offset, val,
			val + adjustment);
		xdr_le.put32(&out, val + adjustment);
	}

	/* Need to back up the location to include cbfs stage metadata. */
	*location -= sizeof(struct cbfs_stage);
	ret = 0;

out:
	rmodule_cleanup(rmodctx);
	return ret;
}
//The main telnet task
void telnet_task_main(void)
{
/*
	commands[0].command="help";
	commands[0].exec = &telnet_help;

	commands[1].command="echo";
	commands[1].exec = &telnet_echo;

	commands[2].command="time";
	commands[2].exec = &telnet_time;

	commands[3].command="quit";
	commands[3].exec = &telnet_quit;

	commands[4].command="memdump";
	commands[4].exec = &telnet_memdump;
*/
	connection_event.event_mask = ReadableOrException;
	telnet_handle = FILE_INVALID_HANDLE;
	socket_listen(HTONS(23), &telnet_connect_accept );

	unsigned short pos = 0;
	while(1)
	{
restart:
		while( ! file_get_next_event( &telnet_handle, 1, &connection_event) )
		{
			task_yield();
		}
		if( connection_event.event & Exception )
		{
//#ifdef __DEBUG
			puts("\r\nTelnet: Closing connection");
//#endif
			file_close( telnet_handle );
			telnet_handle = FILE_INVALID_HANDLE;
			pos = 0;
			optneg_mode = 0;
			goto restart;
		}

		unsigned short avail = buffer_available(&telnet_receive_buffer);
		char* rd_buf = buffer_read_ptr(&telnet_receive_buffer);
		while( pos < avail)//if avail == 1, rd_buf[0] is the last char we can read
		{
			unsigned char c = rd_buf[pos];
			if( pos == REC_BUF_SIZE-1 )
			{
				//buffer is full, but no CR/LF seen yet... what to do?
				//either discard line, or pretend the last char was \r ??
				c = '\r';
			}

			switch(c)
			{
				case TELNET_IAC:
					if( avail - pos > 2 )
					{
						//buf[pos+1] = will/wont/do/dont
						//buf[pos+2] = option
						switch( (unsigned char) rd_buf[pos+2] )
						{
							case TELNET_ECHO:
								switch( (unsigned char) rd_buf[pos+1] )
								{
									case TELNET_DO:
										//other end wants us to echo
										telnet_mode |= MODE_ECHO;
										break;
									case TELNET_DONT:
										//other end demands we don't echo
										telnet_mode &= ~MODE_ECHO;
										break;
								}
								break;
						}
						//remove 3 chars from buffer
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos], 3 );
						avail -= 3;
					}
					else
					{
						task_yield();
					}
					break;
				case '\r': // could be \r\n , \r\0 or just \r on its own
					pos++;
					if( telnet_mode & MODE_ECHO)
					{
						file_puts(CRLF, telnet_handle);
					}
					//if there's a following character, and it's \n or \0, chomp it too.
					if( pos < avail && (rd_buf[pos+1] == '\n' || rd_buf[pos+1] == '\0')) pos++; 
					exec_line( rd_buf, rd_buf+pos ); //if read rd_buf[0], pos == 1 -> end = (rd_ptr + 1)

					buffer_seek( &telnet_receive_buffer, pos ); //free buffer
					rd_buf = buffer_read_ptr(&telnet_receive_buffer);

					pos = 0;
					avail = buffer_available(&telnet_receive_buffer);
					file_putchar('>', telnet_handle);
					break;
				case '\b':
				case 0x7f:
					puts("\r\ntel:backspace");
					if( pos > 0 ) //not the first character
					{
						if( telnet_mode & MODE_ECHO)
						{
							file_putchar('\b', telnet_handle);
							file_putchar(' ', telnet_handle);
							file_putchar('\b', telnet_handle);
						}
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos-1], 2 );
						avail-=2;
						pos--;
					}
					else
					{
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos], 1 );
						avail--;
					}
					break;
				default:
					if( c >= ' ' && c <='~' )
					{
						if( telnet_mode & MODE_ECHO)
						{
							file_putchar(c, telnet_handle);
							pos++;
						}
					}
					else
					{
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos], 1 );
						avail--;
					}
			}//end switch
		}//end while loop

		task_yield();
	}//end outer while
}