f



sys/queue.h

I am looking for some documentation on using #include <sys/queue.h>
Has anybody ever used it?  I would like to integrate a linked list
using it.

I am writing a packet sniffer and am using a packetCache structure to
hold captured packets for exporting purposes and data collection.

well here is the code

<code>
/*
 *      Copyright (c) 2007 HydraResearch. All rights reserved.
 *
 *      This program is free software: you can redistribute it and/or
modify
 *      it under the terms of the GNU General Public License as
published by
 *      the Free Software Foundation, either version 3 of the License,
or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be
useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public
License
 *      along with this program.  If not, see <http://www.gnu.org/
licenses
 *
 *      Author: Matt Westerburg <mwesterburg@hydraresearch.com>
 */

#include "config.h"
#include "sll.h"
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h> /*includes the ethernet.h*/
#include <pcap.h>

#define VERSION "0.1"

/*implement booleans*/
#define TRUE 1
#define FALSE 0
typedef int bool;

/*
 * function prototypes
 */
void print_help();
void signal_capture_cntrlc(int sig);

/*node*/
struct packetCache
{
        struct packetCache *next;
        ssize_t len;
        unsigned char data[0];
};

/*status variables*/
unsigned long long total_captured_packets = 0;
Sll *head = NULL;
Sll *new = NULL;

/*configuration options*/
char *interface = NULL;
bool promiscuous_mode = FALSE;
bool cache_packets = FALSE;
bool debug = FALSE;
bool display = FALSE;
int wait_time = 0;
int max_packets = -1;

/*pcap_loop callback routine*/
void capture_callback(u_char *buffer, const struct pcap_pkthdr*
packet_header, u_char* data)
{
        total_captured_packets++;
        if (display == TRUE)
        {
                fprintf(stdout, "Received packet %d\n");
        }
        if (cache_packets == TRUE)
        {
                struct packetCache *pc;
                if ((pc = (struct packetCache *) malloc (sizeof
(struct packetCache) + packet_header->len)) == NULL)
                {
                        fprintf(stderr, "Memory Allocation Error!\n");
                        fprintf(stderr, "Turning off caching\n");
                        cache_packets = FALSE;
                }
                else
                {
                        if (debug == TRUE)
                        {
                                fprintf(stderr, "Packet Cached\n");
                        }
                        pc->len = packet_header->len;
                        memcpy (pc->data, data, packet_header->len);
                        pc->next = NULL;
                        pcache_last = pc;
                }
        }
}

int main(int argc, char **argv)
{
        /*setup the signals*/
        (void) signal(SIGINT, signal_capture_cntrlc);
        int i;
        char errbuf[PCAP_ERRBUF_SIZE]; /*error buffer for pcap
operations*/
        pcap_t* descr;
        const u_char *packet;
        struct pcap_pkthdr hdr;
        struct ether_header *eptr;
        u_char *ptr;

        /*command line options parsing*/
        int option;
        while ((option = getopt(argc, argv, "i:pdw:Dm:ch")) != -1)
        {
                switch (option)
                {

                        case 'i':
                                interface = optarg;
                                break;
                        case 'h':
                                print_help();
                                return 0;
                        case 'd':
                                debug = TRUE;
                                break;
                        case 'p':
                                promiscuous_mode = TRUE;
                                break;
                        case 'w':
                                wait_time = (int)optarg;
                                break;
                        case 'c':
                                cache_packets = TRUE;
                                break;
                        case 'D':
                                display = TRUE;
                                break;
                        case 'm':
                                max_packets = (int)optarg;
                                break;
                        case '?':
                                if (isprint(optopt))
                                {
                                        fprintf(stderr, "Unknown
option '-%c'.\n", optopt);
                                }
                                else
                                {
                                        fprintf(stderr, "Unknown
option character '\\x%x'.\n", optopt);
                                }
                                print_help();
                                return 1;
                        default:
                                print_help();
                                abort();
                }
        }

        /*display option values*/
        if (debug == TRUE)
        {
                fprintf(stdout, "Interface: %s\n", interface);
                fprintf(stdout, "Promiscuous_mode: %d\n",
promiscuous_mode);
                fprintf(stdout, "Debug: %d\n", debug);
                fprintf(stdout, "Display: %d\n", display);
                fprintf(stdout, "Wait_time: %d\n", wait_time);
                fprintf(stdout, "Max_packets: %d\n", max_packets);
                fprintf(stdout, "Cache_packets: %d\n", cache_packets);
        }

        /*latch onto an interface*/
        if (interface == NULL)
        {
                /*set interface if one was not given by the user*/
                interface = pcap_lookupdev(errbuf);
        }
        descr = pcap_open_live(interface, BUFSIZ, promiscuous_mode,
wait_time, errbuf);
        if (descr == NULL)
        {
                fprintf(stderr, "Couldn't open device %s: %s\n",
interface, errbuf);
                return 2;
        }
        if (debug == TRUE)
        {
                fprintf(stderr, "Opened device: %s\n", interface);
        }


        /*packet capture loop*/
        int status = pcap_loop(descr, max_packets, (pcap_handler)
capture_callback, NULL);
        switch (status)
        {
                case -1:
                        fprintf(stderr, "Error: %s\n", errbuf);
                        break;
                case -2:
                        if (debug == TRUE)
                        {
                                fprintf(stderr, "Exiting Loop status:
%d\n", status);
                        }
                        break;
                case '0':
                        if (debug == TRUE)
                        {
                                fprintf(stderr, "Capture loop exited
successfully\n");
                        }
                default:
                        if (debug == TRUE)
                        {
                                fprintf(stderr, "Unknown exit code: %d
\n", status);
                        }
        }

        return 0;
}

void print_help()
{

        fprintf(stderr, "/*********************/\n");
        fprintf(stderr, "Packman v%s\n", VERSION);
        fprintf(stderr, "command line switches\n");
        fprintf(stderr, "-i interface (example ./pk -i eth0)\n");
        fprintf(stderr, "-p (enables promiscuous mode)\n");
        fprintf(stderr, "-d (enables debugging)\n");
        fprintf(stderr, "-w wait_time ms (wait time in ms between
packet captures) (example -w 10)\n");
        fprintf(stderr, "-h help\n");
        fprintf(stderr, "-m max_packets (maximum number of packets to
capture) (example -m 1000)\n");
        fprintf(stderr, "-D turns display mode on\n");
        fprintf(stderr, "-c turns on caching\n");
}

void signal_capture_cntrlc(int sig)
{
        fprintf(stderr, "Caught a INT signal\n");
        fprintf(stderr, "Shutting Down\n");
        exit(0);
}
</code>

I am getting back into C so I would like some serious criticism.

0
westymatt
7/15/2007 7:14:53 PM
comp.linux.development.system 5436 articles. 0 followers. zixenus (12) is leader. Post Follow

8 Replies
759 Views

Similar Articles

[PageSpeed] 44

On Jul 15, 8:14 pm, westymatt <westym...@gmail.com> wrote:
> I am looking for some documentation on using #include <sys/queue.h>
> Has anybody ever used it?  I would like to integrate a linked list
> using it.

The best documentation is in /usr/include/sys/queue.h  :)
A few remarks on the code below...

> I am writing a packet sniffer and am using a packetCache structure to
> hold captured packets for exporting purposes and data collection.
>
> well here is the code
>
> <code>

> #define TRUE 1
> #define FALSE 0
> typedef int bool;

You can get these from stdbool.h.

>         {
>                 struct packetCache *pc;
>                 if ((pc = (struct packetCache *) malloc (sizeof
> (struct packetCache) + packet_header->len)) == NULL)

Many people will argue that the assignemt is better written:
pc = malloc( sizeof *pc + packet_header->len)
(no cast and take the size of the object rather than a type.)
I have a slight preference that there be no cast, since
failure to include a prototype will cause a compiler
warning, and I strongly encourage sizeof object instead
of sizeof(type), since it can be verified by local inspection
of the code (ie, I don't have to look for the declaration
of pc to confirm that it is a struct packetCache *.
And, the line stays correct when pc's type is changed
to be a struct newpacketCache *)


>        /*command line options parsing*/
>         int option;
>         while ((option = getopt(argc, argv, "i:pdw:Dm:ch")) != -1)
>         {

IMO, this should not be in main, but moved to a seperate
function.

>                                 print_help();
>                                 return 1;

return EXIT_FAILURE is more portable, but this
is okay on linux.

>                         default:
>                                 print_help();
>                                 abort();

Hmmm.  I'm not sure I want a program to
dump core due to erroneous command line
args.

>
> void signal_capture_cntrlc(int sig)
> {
>         fprintf(stderr, "Caught a INT signal\n");
>         fprintf(stderr, "Shutting Down\n");
>         exit(0);}

You really should not call fprintf
from within the signal handler, as it is not
re-entrant.  Especially since you registered with
signal() instead of sigaction, you may receive
a SIGINT during one of the calls to fprintf and
your program will lock up.



0
William
7/15/2007 8:16:56 PM
The structure
<code>
struct packetCache
{
    struct packetCache *next;
    ssize_t len;
    unsigned char data[0];
};

The unsigned char data[0] is this essentially making a single char?

0
westymatt
7/16/2007 4:05:55 AM
In article <1184558755.459343.104170@o61g2000hsh.googlegroups.com>,
westymatt  <westymatt@gmail.com> wrote:

>The unsigned char data[0] is this essentially making a single char?

No



0
ellis
7/16/2007 7:58:28 AM
Out of curiousity what does it create?  Unregulated array growth

0
westymatt
7/16/2007 3:39:35 PM
In article <1184600375.603213.254750@g4g2000hsf.googlegroups.com>,
westymatt  <westymatt@gmail.com> wrote:

>Out of curiousity what does it create?  Unregulated array growth

It creates a way to access data beyond what's defined in the struct.

0
ellis
7/16/2007 8:29:00 PM
On Mon, 16 Jul 2007 20:29:00 -0000 ellis@no.spam wrote:

| In article <1184600375.603213.254750@g4g2000hsf.googlegroups.com>,
| westymatt  <westymatt@gmail.com> wrote:
| 
|>Out of curiousity what does it create?  Unregulated array growth
| 
| It creates a way to access data beyond what's defined in the struct.

Variable length structs, assuming the length information is in, or can be
derived from, what is in the fixed part of the struct, and the [0] member
is the last member.

-- 
|---------------------------------------/----------------------------------|
| Phil Howard KA9WGN (ka9wgn.ham.org)  /  Do not send to the address below |
| first name lower case at ipal.net   /  spamtrap-2007-07-16-1608@ipal.net |
|------------------------------------/-------------------------------------|
0
phil
7/16/2007 9:09:51 PM
I am sorry I follow what your saying, I just don't understand how it
does.

0
westymatt
7/16/2007 10:44:59 PM
In article <1184625899.920399.62260@o61g2000hsh.googlegroups.com>,
westymatt  <westymatt@gmail.com> wrote:

>I am sorry I follow what your saying, I just don't understand how it
>does.

Then you need to go to comp.lang.c and ask. This is a linux kernel
issue. (Or you can read the code in the kernel and see how the
struct is being used.)

--
http://www.spinics.net/lists/kernel/

0
ellis
7/17/2007 6:58:56 AM
Reply: