Ejemplo n.º 1
0
/**
 * Configure the user supplied buffer.
 */
static ag_bool
fmem_config_user_buf(fmem_cookie_t * pFMC, void * buf, ssize_t len)
{
    /*
     *  User allocated buffer.  User responsible for disposal.
     */
    if (len == 0) {
        free(pFMC);
        errno = EINVAL;
        return AG_FALSE;
    }

    pFMC->buffer = (buf_bytes_t*)buf;

    /*  Figure out where our "next byte" and EOF are.
     *  Truncated files start at the beginning.
     */
    if (pFMC->mode & FLAG_BIT(truncate)) {
        /*
         *  "write" mode
         */
        pFMC->eof = \
            pFMC->next_ix = 0;
    }

    else if (pFMC->mode & FLAG_BIT(binary)) {
        pFMC->eof = len;
        pFMC->next_ix    = (pFMC->mode & FLAG_BIT(append)) ? len : 0;

    } else {
        /*
         * append or read text mode -- find the end of the buffer
         * (the first NUL character)
         */
        buf_bytes_t *p = (buf_bytes_t*)buf;

        pFMC->eof = 0;
        while ((*p != NUL) && (++(pFMC->eof) < len))  p++;
        pFMC->next_ix =
            (pFMC->mode & FLAG_BIT(append)) ? pFMC->eof : 0;
    }

    /*
     *  text mode - NUL terminate buffer, if it fits.
     */
    if (  ((pFMC->mode & FLAG_BIT(binary)) == 0)
       && (pFMC->next_ix < len)) {
        pFMC->buffer[pFMC->next_ix] = NUL;
    }

    pFMC->buf_size = len;
    return AG_TRUE;
}
Ejemplo n.º 2
0
/**
 * Convert a mode string into mode bits.
 */
static int
fmem_getmode(char const * mode, mode_bits_t * pRes)
{
    if (mode == NULL)
        return 1;

    switch (*mode) {
    case 'a': *pRes = FLAG_BIT(write) | FLAG_BIT(append);
              break;
    case 'w': *pRes = FLAG_BIT(write) | FLAG_BIT(truncate);
              break;
    case 'r': *pRes = FLAG_BIT(read);
              break;
    default:  return EINVAL;
    }

    /*
     *  If someone wants to supply a "wxxbxbbxbb+" mode string, I don't care.
     */
    for (;;) {
        switch (*++mode) {
        case '+': *pRes |= FLAG_BIT(read) | FLAG_BIT(write);
                  if (mode[1] != NUL)
                      return EINVAL;
                  break;
        case NUL: break;
        case 'b': *pRes |= FLAG_BIT(binary); continue;
        case 'x': continue;
        default:  return EINVAL;
        }
        break;
    }

    return 0;
}
Ejemplo n.º 3
0
/**
 * Allocate an initial buffer for fmem.
 */
static ag_bool
fmem_alloc_buf(fmem_cookie_t * pFMC, ssize_t len)
{
    /*
     *  We must allocate the buffer.  If "len" is zero, set it to page size.
     */
    pFMC->mode |= FLAG_BIT(allocated);
    if (len == 0)
        len = pFMC->pg_size;

    /*
     *  Unallocated file space is set to NULs.  Emulate that.
     */
    pFMC->buffer = calloc((size_t)1, (size_t)len);
    if (pFMC->buffer == NULL) {
        errno = ENOMEM;
        free(pFMC);
        return AG_FALSE;
    }

    /*
     *  We've allocated the buffer.  The end of file and next entry
     *  are both zero.
     */
    pFMC->next_ix  = 0;
    pFMC->eof      = 0;
    pFMC->buf_size = len;
    return AG_TRUE;
}
Ejemplo n.º 4
0
int
main(int argc, char **argv)
{
    int             flags = 0;
    int             c = 0;
    extern char    *optarg;
    char           *filter = NULL;

    while ((c = getopt(argc, argv, "pf:")) != -1) {
        switch (c) {
        case 'p':
            flags |= FLAG_BIT(FLAG_PROMISC);
            break;
        case 'f':
            filter = strdup(optarg);
            break;
        default:
            usage(argv[0]);
            exit(-1);
            break;	/* not reached */
        }
    }

    if (filter == NULL) {
        filter = "ip";
    }
    process(flags, filter);
    return (0);
}
Ejemplo n.º 5
0
/**
 * Extend the space associated with an fmem file.
 */
static int
fmem_extend(fmem_cookie_t *pFMC, size_t new_size)
{
    size_t ns = (new_size + (pFMC->pg_size - 1)) & (~(pFMC->pg_size - 1));

    /*
     *  We can expand the buffer only if we are in append mode.
     */
    if (pFMC->mode & FLAG_BIT(fixed_size))
        goto no_space;

    if ((pFMC->mode & FLAG_BIT(allocated)) == 0) {
        /*
         *  Previously, this was a user supplied buffer.  We now move to one
         *  of our own.  The user is responsible for the earlier memory.
         */
        void* bf = malloc(ns);
        if (bf == NULL)
            goto no_space;

        memcpy(bf, pFMC->buffer, pFMC->buf_size);
        pFMC->buffer = bf;
        pFMC->mode  |= FLAG_BIT(allocated);
    }
    else {
        void* bf = realloc(pFMC->buffer, ns);
        if (bf == NULL)
            goto no_space;

        pFMC->buffer = bf;
    }

    /*
     *  Unallocated file space is set to zeros.  Emulate that.
     */
    memset(pFMC->buffer + pFMC->buf_size, 0, ns - pFMC->buf_size);
    pFMC->buf_size = ns;
    return 0;

 no_space:
    errno = ENOSPC;
    return -1;
}
Ejemplo n.º 6
0
/**
 * Free up the memory associated with an fmem file.
 * If the user is managing the space, then the allocated bit is set.
 */
static int
fmem_close(void * cookie)
{
    fmem_cookie_t   * pFMC = cookie;
    cookie_fp_map_t * pmap = (void *)map;
    unsigned int      mct  = map_ct;

    while (mct-- != 0) {
        if (pmap->cookie == cookie) {
            *pmap = map[--map_ct];
            break;
        }
        pmap++;
    }

    if (mct > map_ct)
        errno = EINVAL;

    if (pFMC->mode & FLAG_BIT(allocated))
        free(pFMC->buffer);
    free(pFMC);

    return 0;
}
Ejemplo n.º 7
0
/*=export_func ag_fmemopen
 *
 *  what:  Open a stream to a string
 *
 *  arg: + void*   + buf  + buffer to use for i/o +
 *  arg: + ssize_t + len  + size of the buffer +
 *  arg: + char*   + mode + mode string, a la fopen(3C) +
 *
 *  ret-type:  FILE*
 *  ret-desc:  a stdio FILE* pointer
 *
 *  err:  NULL is returned and errno is set to @code{EINVAL} or @code{ENOSPC}.
 *
 *  doc:
 *
 *  This function requires underlying @var{libc} functionality:
 *  either @code{fopencookie(3GNU)} or @code{funopen(3BSD)}.
 *
 *  If @var{buf} is @code{NULL}, then a buffer is allocated.  The initial
 *  allocation is @var{len} bytes.  If @var{len} is less than zero, then the
 *  buffer will be reallocated as more space is needed.  Any allocated
 *  memory is @code{free()}-ed when @code{fclose(3C)} is called.
 *
 *  If @code{buf} is not @code{NULL}, then @code{len} must not be zero.
 *  It may still be less than zero to indicate that the buffer may
 *  be reallocated.
 *
 *  The mode string is interpreted as follows.  If the first character of
 *  the mode is:
 *
 *  @table @code
 *  @item a
 *  Then the string is opened in "append" mode.  In binary mode, "appending"
 *  will begin from the end of the initial buffer.  Otherwise, appending will
 *  start at the first NUL character in the initial buffer (or the end of the
 *  buffer if there is no NUL character).  Do not use fixed size buffers
 *  (negative @var{len} lengths) in append mode.
 *
 *  @item w
 *  Then the string is opened in "write" mode.  Any initial buffer is presumed
 *  to be empty.
 *
 *  @item r
 *  Then the string is opened in "read" mode.
 *  @end table
 *
 *  @noindent
 *  If it is not one of these three, the open fails and @code{errno} is
 *  set to @code{EINVAL}.  These initial characters may be followed by:
 *
 *  @table @code
 *  @item +
 *  The buffer is marked as updatable and both reading and writing is enabled.
 *
 *  @item b
 *  The I/O is marked as "binary" and a trailing NUL will not be inserted
 *  into the buffer.  Without this mode flag, one will be inserted after the
 *  @code{EOF}, if it fits.  It will fit if the buffer is extensible (the
 *  provided @var{len} was negative).  This mode flag has no effect if
 *  the buffer is opened in read-only mode.
 *
 *  @item x
 *  This is ignored.
 *  @end table
 *
 *  @noindent
 *  Any other letters following the inital 'a', 'w' or 'r' will cause an error.
=*/
FILE *
ag_fmemopen(void * buf, ssize_t len, char const * mode)
{
    fmem_cookie_t *pFMC;

    {
        mode_bits_t bits;

        if (fmem_getmode(mode, &bits) != 0) {
            return NULL;
        }

        pFMC = malloc(sizeof(fmem_cookie_t));
        if (pFMC == NULL) {
            errno = ENOMEM;
            return NULL;
        }

        pFMC->mode = bits;
    }

    /*
     *  Two more mode bits that do not come from the mode string:
     *  a negative size implies fixed size buffer and a NULL
     *  buffer pointer means we must allocate (and free) it.
     */
    if (len <= 0) {
        /*
         *  We only need page size if we might extend an allocation.
         */
        len = -len;
        pFMC->pg_size = getpagesize();
    }

    else {
        pFMC->mode |= FLAG_BIT(fixed_size);
    }

    if (buf != NULL) {
        if (! fmem_config_user_buf(pFMC, buf, len))
            return NULL;

    } else if ((pFMC->mode & (FLAG_BIT(append) | FLAG_BIT(truncate))) == 0) {
        /*
         *  Not appending and not truncating.  We must be reading.
         *  We also have no user supplied buffer.  Nonsense.
         */
        errno = EINVAL;
        free(pFMC);
        return NULL;
    }

    else if (! fmem_alloc_buf(pFMC, len))
        return NULL;

#ifdef TEST_FMEMOPEN
    saved_cookie = pFMC;
#endif

    {
        FILE * res;

        cookie_read_function_t* pRd = (pFMC->mode & FLAG_BIT(read))
            ?  (cookie_read_function_t*)fmem_read  : NULL;
        cookie_write_function_t* pWr = (pFMC->mode & FLAG_BIT(write))
            ? (cookie_write_function_t*)fmem_write : NULL;

#ifdef HAVE_FOPENCOOKIE
        cookie_io_functions_t iof;
        iof.read  = pRd;
        iof.write = pWr;
        iof.seek  = fmem_seek;
        iof.close = fmem_close;

        res = fopencookie(pFMC, mode, iof);
#else
        res = funopen(pFMC, pRd, pWr, fmem_seek, fmem_close);
#endif
        if (res == NULL)
            return res;

        if (++map_ct >= map_alloc_ct) {
            void * p = (map_alloc_ct > 0)
                ? realloc((void *)map, (map_alloc_ct += 4) * sizeof(*map))
                : malloc((map_alloc_ct = 4) * sizeof(*map));

            if (p == NULL) {
                fclose(res);
                errno = ENOMEM; /* "fclose" set it to "EINVAL". */
                return NULL;
            }

            map = p;
        }

        {
            cookie_fp_map_t * p = (void *)(map + map_ct - 1);
            p->fp = res;
            p->cookie = pFMC;
        }

        return res;
    }
}
Ejemplo n.º 8
0
/**
 * Handle file system callback to write data to our string
 */
static ssize_t
fmem_write(void *cookie, const void *pBuf, size_t sz)
{
    fmem_cookie_t *pFMC = cookie;
    int add_nul_char;

    /*
     *  In append mode, always seek to the end before writing.
     */
    if (pFMC->mode & FLAG_BIT(append))
        pFMC->next_ix = pFMC->eof;

    /*
     *  Only add a NUL character if:
     *
     *  * we are not in binary mode
     *  * there are data to write
     *  * the last character to write is not already NUL
     */
    add_nul_char =
           ((pFMC->mode & FLAG_BIT(binary)) != 0)
        && (sz > 0)
        && (((char*)pBuf)[sz - 1] != NUL);

    {
        size_t next_pos = pFMC->next_ix + sz + add_nul_char;
        if (next_pos > pFMC->buf_size) {
            if (fmem_extend(pFMC, next_pos) != 0) {
                /*
                 *  We could not extend the memory.  Try to write some data.
                 *  Fail if we are either at the end or not writing data.
                 */
                if ((pFMC->next_ix >= pFMC->buf_size) || (sz == 0))
                    return -1; /* no space at all.  errno is set. */

                /*
                 *  Never add the NUL for a truncated write.  "sz" may be
                 *  unchanged or limited here.
                 */
                add_nul_char = 0;
                sz = pFMC->buf_size - pFMC->next_ix;
            }
        }
    }

    memcpy(pFMC->buffer + pFMC->next_ix, pBuf, sz);

    pFMC->next_ix += sz;

    /*
     *  Check for new high water mark and remember it.  Add a NUL if
     *  we do that and if we have a new high water mark.
     */
    if (pFMC->next_ix > pFMC->eof) {
        pFMC->eof = pFMC->next_ix;
        if (add_nul_char)
            /*
             *  There is space for this NUL.  The "add_nul_char" is not part of
             *  the "sz" that was added to "next_ix".
             */
            pFMC->buffer[ pFMC->eof ] = NUL;
    }

    return sz;
}
Ejemplo n.º 9
0
void process(int flags)
{
    char *interface=NULL;
	char errbuf[PCAP_ERRBUF_SIZE];
	struct bpf_program prog;
	bpf_u_int32 network, netmask;
	char *filter=NULL;
	int flagdef;

	filter="tcp";

	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, signal_handler);
	signal(SIGQUIT, signal_handler);
	signal(SIGTERM, signal_handler);

	/* Attempt to find the interface */
	interface=pcap_lookupdev(errbuf);
	if(interface==NULL) {
	    fprintf(stderr, "pcap_lookupdev: %s\n", errbuf);
		exit(-1);
	}

	if(pcap_lookupnet(interface, &network, &netmask, errbuf) < 0) {
	    fprintf(stderr, "pcap_lookupnet: %s\n", errbuf);
		exit(-1);
	}

	if(flags&FLAG_BIT(FLAG_PROMISC)) /* find out if we want to be promisc */
		flagdef=1;
	else
	    flagdef=0;

	pcap_socket=pcap_open_live(interface, 1024, flagdef, 1024, errbuf);

	if(pcap_socket==NULL) {
	    fprintf(stderr, "pcap_open_live: %s\n", errbuf);
		exit(-1);
	}

	switch(pcap_datalink(pcap_socket)) {
	    case DLT_EN10MB:
		    dlt_len=14;
			break;
	    case DLT_SLIP:
		    dlt_len=16;
			break;
		case DLT_PPP:
			dlt_len=4;
		    break;
		case DLT_FDDI:
			fprintf(stderr, "Sorry, can't do FDDI\n");
			signal_handler(-1);
			break;
	    default:
			dlt_len=4;
	}

	if(pcap_compile(pcap_socket, &prog, filter, 1, netmask) < 0) {
	    fprintf(stderr, "pcap_compile: %s\n", errbuf);
		signal_handler(-1);
	}

	if(pcap_setfilter(pcap_socket, &prog) < 0) {
	    fprintf(stderr, "pcap_setfilter: %s\n", errbuf);
		signal_handler(-1);
	}

	fprintf(stderr, "interface: %s, filter: %s, promiscuous: %s\n",
	        interface, filter, (flags&FLAG_BIT(FLAG_PROMISC))?"yes":"no");

	for(;;)
	    pcap_loop(pcap_socket, -1, (pcap_handler)filter_packet, NULL);
}