📄 snap_io.c
字号:
/* $Id: snap_io.c,v 1.2 2003/09/17 11:26:10 tmoerlan Exp $ *//*#define iphdr ip#define ihl ip_hl#define tot_len ip_len*/#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>//#include <linux/ip.h>#include "snap.h"#include "config.h"#include "myassert.h"#include "consts.h"#include "bytecode.h"#include "io.h"#include "memalloc.h"#include "packet.h"#include "timers.h"#include "d_printf.h"#include "wassert.h"struct iphdr {#if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int ihl:4; unsigned int version:4;#elif __BYTE_ORDER == __BIG_ENDIAN unsigned int version:4; unsigned int ihl:4;#else# error "Please fix <bits/endian.h>"#endif u_int8_t tos; u_int16_t tot_len; u_int16_t id; u_int16_t frag_off; u_int8_t ttl; u_int8_t protocol; u_int16_t check; u_int32_t saddr; u_int32_t daddr; /*The options start here. */ };static void *scan_value(value_t *v, void *fromh, void *fromhmax, void *fromhalloc, void *fromhallocmax, void *tohmin, void *tohalloc, void *tohmax);static void *copy_heap_obj(heap_obj *hsrc, int sizeb, void *tohmin, void *tohalloc, void *tohmax);static void reset_heap(packet_t *p, void *to_heap, void *to_heap_max);/* used to verify packet integrity */#define VERIFY(e) \ if (e); \ else { \ fprintf(stderr,"%s:%d: packet check failed\n",__FILE__,__LINE__); \ return NULL; \ }/* checks if the given heap_obj ptr is within the heap bounds. side-effects sizeb to contain the object's length (word-aligned) */#define IF_IN_FROM_HEAP(ho,sizeb,hmin,hmax,hmin2,hmax2) \if ((((void *)(ho) >= (void *)(hmin)) && \ ((void *)(ho) < (void *)(hmax)) && \ (((void *)(ho) + \ ((sizeb) = (ho)->len + sizeof(heap_obj))) <= (void *)(hmax))) || \ (((void *)(ho) >= (void *)(hmin2)) && \ ((void *)(ho) < (void *)(hmax2)) && \ (((void *)(ho) + \ ((sizeb) = (ho)->len + sizeof(heap_obj))) <= (void *)(hmax2)))) { \ if (((sizeb) & 0x3) != 0) { \ (sizeb) = ((sizeb) & ~0x3) + 4; \ }#define ELSE_NOT_IN_FROM_HEAP } else#define IN_TOSPACE_HEAP(hdst,sizeb,toh,tohmax) \ (((void *)(hdst) >= (toh)) && (((void *)(hdst) + (sizeb)) <= (tohmax)))/* cache the packet_t struct */static packet_t phandle;/* given a buffer containing a packet, find pointers to the header, code, stack, and heap portions */packet_t *unmarshal_packet(char *buffer, int packet_lenb, int buf_lenb) { packet_t *p; /* packet struct to return */ void *buf_end = buffer + buf_lenb; void *packet_end = buffer + packet_lenb; unsigned short int code_lenb, entry_point, stack_lenb, heap_lenb; assert(sizeof(unsigned long int) == sizeof(unsigned int)); assert(packet_lenb <= buf_lenb); d_printf(100,"%s:%d: unmarshal_packet, buf=0x%x, plen=%d, blen=%d\n", __FILE__,__LINE__,(unsigned int)buffer,packet_lenb,buf_lenb); print_anti_timer(7,"unmarshal_packet"); p = &phandle; p->iph = (struct iphdr *)buffer; /* set up header */ { struct iphdr *iph = (struct iphdr *)buffer; p->hdr = (header_t *)((void *)iph + (iph->ihl << 2)); } code_lenb = ntohs(p->hdr->code_sizeb); stack_lenb = ntohs(p->hdr->stack_sizeb); heap_lenb = ntohs(p->hdr->heap_sizeb); entry_point = ntohs(p->hdr->entry_point); /* set up code */ print_anti_timer(9,"unmarshal_code"); p->code_min = (instr_t *)((void *)p->hdr + sizeof(header_t)); p->code_max = (instr_t *)((void *)p->code_min + code_lenb); p->pc = p->code_min + entry_point; p->handler = p->code_max; /* default exception handler quits */ VERIFY((entry_point * sizeof(instr_t)) <= code_lenb); print_timer(9,"unmarshal_code"); /* set up heap */ print_anti_timer(11,"unmarshal_heap"); p->heap_min = (void *)p->code_max; p->heap_max = p->heap_min + heap_lenb; print_timer(11,"unmarshal_heap"); /* set up stack */ print_anti_timer(10,"unmarshal_stack"); p->stack_min = (value_t *)p->heap_max; p->stack_max = (value_t *)buf_end; p->sp = (value_t *)((void *)p->stack_min + stack_lenb); VERIFY(((void *)(p->sp) <= packet_end)); print_timer(10,"unmarshal_stack"); /* top of buffer */ p->h_alloc_heap_max = (void *)p->stack_max; p->is_contiguous = 1; d_printf(150,"%s:%d: @hdr = %#x\n", __FILE__,__LINE__,(uint32)p->hdr); d_printf(150,"%s:%d: @code_min = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->code_min,(void *)p->code_min - (void *)p->hdr); d_printf(150,"%s:%d: @pc = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->pc, (void *)p->pc - (void *)p->code_min); d_printf(150,"%s:%d: @code_max = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->code_max, (void *)p->code_max - (void *)p->pc); d_printf(150,"%s:%d: @heap_min = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->heap_min, (void *)p->heap_min - (void *)p->code_max); d_printf(150,"%s:%d: @heap_max = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->heap_max, (void *)p->heap_max - (void *)p->heap_min); d_printf(150,"%s:%d: @stack_min = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->stack_min, (void *)p->stack_min - (void *)p->heap_max); d_printf(150,"%s:%d: @sp = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->sp, (void *)p->sp - (void *)p->stack_min); d_printf(150,"%s:%d: @stack_max = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->stack_max, (void *)p->stack_max - (void *)p->sp); d_printf(150,"%s:%d: @h_alloc_heap_max = %#x, delta = %d\n", __FILE__,__LINE__, (uint32)p->h_alloc_heap_max, (void *)p->h_alloc_heap_max - (void *)p->stack_max); print_timer(7,"unmarshal_packet"); return(p);}/* cache a 10k output buffer */static char *io_outbuf = NULL;static int io_outbuf_sizeb = 10 * 1024;/* given a packet and the amount of stack to take, marshal up a packet into a continuous block of bytes. We assume that the packet_t structure is well-formed, but don't assume anything about the contents of the stack and the heap (there may be bogus values), so we require some extra checks. */int marshal_packet(packet_t *p, int stack_amt, buffer_t *bufstr) { int sizeb; /* size in bytes of new buffer */ instr_t *codesrc; /* code pointer in old packet */ instr_t *codedst; /* code pointer in new packet */ value_t *stacksrc; /* stack pointer in old packet */ value_t *stackdst; /* stack pointer in new packet */ void *newhmin; /* bottom of new heap */ void *newhalloc; /* new heap allocation pointer */ void *newhscan; /* new heap scan pointer */ void *newhmax; /* high limit for new heap */ header_t *newhdr; /* header for the new packet */ d_printf(150,"%s:%d: @hdr = %#x\n", __FILE__,__LINE__,(unsigned int)p->hdr); d_printf(150,"%s:%d: @code_min = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->code_min,(void *)p->code_min - (void *)p->hdr); d_printf(150,"%s:%d: @pc = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->pc, (void *)p->pc - (void *)p->code_min); d_printf(150,"%s:%d: @code_max = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->code_max, (void *)p->code_max - (void *)p->pc); d_printf(150,"%s:%d: @heap_min = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->heap_min, (void *)p->heap_min - (void *)p->code_max); d_printf(150,"%s:%d: @heap_max = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->heap_max, (void *)p->heap_max - (void *)p->heap_min); d_printf(150,"%s:%d: @stack_min = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->stack_min, (void *)p->stack_min - (void *)p->heap_max); d_printf(150,"%s:%d: @sp = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->sp, (void *)p->sp - (void *)p->stack_min); d_printf(150,"%s:%d: @stack_max = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->stack_max, (void *)p->stack_max - (void *)p->sp); d_printf(150,"%s:%d: @h_alloc_heap_max = %#x, delta = %d\n", __FILE__,__LINE__, (unsigned int)p->h_alloc_heap_max, (void *)p->h_alloc_heap_max - (void *)p->stack_max); print_anti_timer(8,"marshal_packet"); /* check for valid args */ assert(stack_amt >= 0); assert(p != NULL); assert(bufstr != NULL); /* see if we can reuse this buffer. We can if the entire stack is to be transmitted and if we haven't done any further heap allocation. */ /* XXX this optimization won't work in the kernel case yet unless this send is resulting from a forw or a forwto (as then we won't compute any further). Might be possible to clone the buffer, though. */ if (((p->sp - p->stack_min) == stack_amt) && (p->h_alloc_heap_max == p->stack_max) && (p->is_contiguous)) { d_printf(100,"%s:%d: reusing old buffer during marshalling\n", __FILE__,__LINE__); p->hdr->stack_sizeb = htons(stack_amt * sizeof(value_t)); bufstr->lenb = (void *)p->sp - (void *)p->iph; bufstr->s = (char *)p->iph; print_timer(8,"marshal_packet"); return 0; } /* take a conservative size for the packet-- the actual heap may be smaller than the space we provide */ /* XXX should be statically allocated */ d_printf(100,"%s:%d: sh:%d B,cs:%d B,ss:%d B,hs1:%d B,hs2:%d B\n", __FILE__,__LINE__, sizeof(header_t), ((void *)(p->code_max) - (void *)(p->code_min)), (stack_amt * sizeof(value_t)), ((void *)p->heap_max - (void *)p->heap_min), ((void *)p->h_alloc_heap_max - (void *)p->stack_max)); sizeb = /* IP hdr */ sizeof(struct iphdr) + /* RA option */ 4 + /* header */ sizeof(header_t) + /* code */ ((void *)(p->code_max) - (void *)(p->code_min)) + /* stack */ (stack_amt * sizeof(value_t)) + /* heap1 */ ((void *)p->heap_max - (void *)p->heap_min) + /* heap2 */ ((void *)p->h_alloc_heap_max - (void *)p->stack_max); d_printf(100, "%s:%d: out sizeb = %d bytes\n", __FILE__,__LINE__,sizeb); if (io_outbuf == NULL) { if (sizeb > io_outbuf_sizeb) { io_outbuf_sizeb = sizeb; } memalloc(io_outbuf,char *,io_outbuf_sizeb); } else { if (sizeb > io_outbuf_sizeb) { io_outbuf_sizeb = sizeb; free(io_outbuf); memalloc(io_outbuf,char *,io_outbuf_sizeb); } } /* copy over the IP header from the current packet */ { if (p && p->iph){ unsigned char *where = io_outbuf; d_printf(250,"marshall_packet : where=%p, p->iph=%p, size of header=%u",where,p->iph, sizeof(struct iphdr)); memcpy(where, p->iph, sizeof(struct iphdr)); /* copy over RA option */ memcpy(where + sizeof(struct iphdr),(void *)p->iph + sizeof(struct iphdr),4); } /* the following is only used by snapas (the assembler, can be found in the utils subdir) */ else{ d_printf(250,"creating new IP header"); } } /* set up all the source and destination pointers */ newhdr = (header_t *)(io_outbuf + sizeof(struct iphdr) + 4 ); codesrc = p->code_min; codedst = (instr_t *)(newhdr+1); newhmin = newhscan = newhalloc = (void *)codedst + ((void *)p->code_max - (void *)p->code_min); newhmax = (void *)newhmin + ((void *)p->heap_max - (void *)p->heap_min) + ((void *)p->h_alloc_heap_max - (void *)p->stack_max); stacksrc = p->sp - stack_amt; stackdst = (value_t *)newhmax; /* first copy the header */ memcpy(newhdr,p->hdr,sizeof(header_t)); /* now copy code */ d_printf(150,"%s:%d: scanning code\n",__FILE__,__LINE__); { int sizeb = (int)((void *)p->code_max - (void *)codesrc); instr_t *codemax = (instr_t *)((void *)codedst + sizeb); memcpy(codedst,codesrc,sizeb); /* scan it, forwarding pointers to moved objects */ while (codedst < codemax) {#ifdef SMALL_INSTRS switch (GET_OP(*codedst)) { case SVCV: case CALLS: case PSTR: case EQSTR: case NQSTR: case PTUP: case EQTUP: case NQTUP: case PADDR: case EQADR: case NQADR: case PFLT: case EQFLT: case NQFLT: case FGTI: case FGEQI: case FLEQI: case FLTI: case FADDI: case FSUBI: case FMULI: case FDIVI: case SNETI: case BCASTI: { int hoffs; heap_obj *hsrc; int sizeb; GET_LIT(hoffs,BOGUSV,*codedst); hsrc = (heap_obj *)(p->heap_min + hoffs); IF_IN_FROM_HEAP(hsrc,sizeb,p->heap_min,p->heap_max, p->stack_max,p->h_alloc_heap_max) { newhalloc = copy_heap_obj(hsrc, sizeb, newhmin, newhalloc, newhmax); /* forward it */ /* note that if copy_heap_obj doesn't copy the object because it is bogus (or a previous object was), then this will result in a bogus pointer. This doesn't matter as we check against it later in both the GC and the interpreter. */ SET_LIT(*codedst,BOGUSV,hsrc->flag - 4); /* subtract the extra 4 from the offset */ } /* bogus pointer, leave it XXX */ ELSE_NOT_IN_FROM_HEAP { fprintf (stderr,"%s:%d: warning, pointer @%#x not in heap\n", __FILE__,__LINE__,(unsigned int)hsrc); } break; } default: break; } /* end switch */#else switch (GET_OP(*codedst)) {#ifdef ADDR_IN_HEAP case SNETI: case BCASTI: /* these may contain floating point values */ case GTI: case GEQI: case LTI: case LEQI: case ADDI: case SUBI: case MULTI: case DIVI:#endif case PUSH: case EQI:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -