Author Archives: te-bachi

Wireshark

Filter

Capture Filter (tshark -f): BPF syntax
Display Filter (tshark -Y): Wireshark syntax

Wireshark Wiki: Capture Filters
Ask Wireshark: what is the difference between capture filter and display filter?
Ask Wireshark: Changing Display Filter to Capture Filter

TShark

Tshark column fields
Bug 10201 – col.Protocol missing from tshark 1.11.3 and 1.12.0-rc2

# tshark -i re0 -T fields -e frame.number -e ip.addr -e udp -e _ws.col.info
Capturing on 're0'
[...]
44      172.21.5.130,224.0.0.252        User Datagram Protocol, Src Port: 55317 (55317), Dst Port: 5355 (5355)
45      172.21.5.69,239.255.255.250     User Datagram Protocol, Src Port: 1900 (1900), Dst Port: 1900 (1900)

Video

Troubleshooting with Wireshark – Virtual Tour

ICMP Echo

opensource.apple.com: ping.c

/*
 * pinger --
 *	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
 * will be added on by the kernel.  The ID field is our UNIX process ID,
 * and the sequence number is an ascending integer.  The first TIMEVAL_LEN
 * bytes of the data portion are used to hold a UNIX "timeval" struct in
 * host byte-order, to compute the round-trip time.
 */
static void
pinger(void)
{
    [...]
    if ((options & F_TIME) || timing) {
        (void)gettimeofday(&now, NULL);

        if (options & F_TIME)
            icp->icmp_otime = htonl((now.tv_sec % (24*60*60)) * 1000 + now.tv_usec / 1000);
        if (timing)
            bcopy((void *)&now, (void *)&outpack[ICMP_MINLEN + phdr_len], sizeof(struct timeval));
    }
    [...]
}
typedef u_int32_t n_time;       /* ms since 00:00 GMT, byte rev */
#define icmp_otime      icmp_dun.id_ts.its_otime
#define icmp_rtime      icmp_dun.id_ts.its_rtime
#define icmp_ttime      icmp_dun.id_ts.its_ttime

struct icmp {
        u_char  icmp_type;              /* type of message, see below */
        u_char  icmp_code;              /* type sub code */
        u_short icmp_cksum;             /* ones complement cksum of struct */
        union {
                u_char ih_pptr;                 /* ICMP_PARAMPROB */
                struct in_addr ih_gwaddr;       /* ICMP_REDIRECT */
                struct ih_idseq {
                        n_short icd_id;
                        n_short icd_seq;
                } ih_idseq;
                int ih_void;

                /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
                struct ih_pmtu {
                        n_short ipm_void;
                        n_short ipm_nextmtu;
                } ih_pmtu;

                struct ih_rtradv {
                        u_char irt_num_addrs;
                        u_char irt_wpa;
                        u_int16_t irt_lifetime;
                } ih_rtradv;
        } icmp_hun;
        union {
                struct id_ts {                  /* ICMP Timestamp */
                        n_time its_otime;       /* Originate */
                        n_time its_rtime;       /* Receive */
                        n_time its_ttime;       /* Transmit */
                } id_ts;
                struct id_ip  {
                        struct ip idi_ip;
                        /* options and then 64 bits of data */
                } id_ip;
                struct icmp_ra_addr id_radv;
                u_int32_t id_mask;
                char    id_data[1];
        } icmp_dun;
};

Wireshark-bugs: For ICMP Time Response, In detail pane, Timestamp is incorrectly decoded for MS Windows

Reference (1):
http://tools.ietf.org/html/rfc778

“The timestamp values are in milliseconds from midnight
UT and are stored right-justified in the 32-bit fields shown
above. Ordinarily, all time calculations are performed
modulo-24 hours in milliseconds.”


/* Converts a little-endian byte order unsigned long to host byte order. */
uint32 LETOHL(uint32 ul);

/*
 * RFC 792 for basic ICMP.
 * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
 * RFC 1256 for router discovery messages.
 * RFC 2002 and 3012 for Mobile IP stuff.
 */
static void
dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
    [...]

    /* Decode the second 4 bytes of the packet. */
    switch (icmp_type) {
    
    [...]
    
    case ICMP_ECHOREPLY:
    case ICMP_ECHO:
        
        [...]
        
        /* Interpret the first 8 bytes of the icmp data as a timestamp
         * But only if it does look like it's a timestamp.
         *
         * FIXME:
         *    Timestamps could be in different formats depending on the OS
         */
        ts.secs  = tvb_get_ntohl(tvb, 8);
        ts.nsecs = tvb_get_ntohl(tvb, 8 + 4);   /* Leave at microsec resolution for now */
        
        if (abs((guint32) (ts.secs - pinfo->fd->abs_ts.secs)) >=
            3600 * 24 || ts.nsecs >= 1000000) {
            /* Timestamp does not look right in BE, try LE representation */
            ts.secs  = tvb_get_letohl(tvb, 8);
            ts.nsecs = tvb_get_letohl(tvb, 8 + 4);  /* Leave at microsec resolution for now */
        }
        if (abs((guint32) (ts.secs - pinfo->fd->abs_ts.secs)) < 3600 * 24 && ts.nsecs < 1000000) {
            ts.nsecs *= 1000;   /* Convert to nanosec resolution */
            proto_tree_add_time(icmp_tree, hf_icmp_data_time,
                                tvb, 8, 8, &ts);
            nstime_delta(&time_relative, &pinfo->fd->abs_ts,
                         &ts);
            ti = proto_tree_add_time(icmp_tree,
                                     hf_icmp_data_time_relative,
                                     tvb, 8, 8,
                                     &time_relative);
            PROTO_ITEM_SET_GENERATED(ti);
            call_dissector(data_handle,
                       tvb_new_subset_remaining(tvb,
                                8 + 8),
                       pinfo, icmp_tree);
        } else {
            call_dissector(data_handle,
                       tvb_new_subset_remaining(tvb, 8),
                       pinfo, icmp_tree);
        }
        break;
        
        [...]
    }
    
    [...]
}

Packet Filter (PF) + ALTQ

Presentation

PF, The OpenBSD Packet Filter: Building The Network You Need, EuroBSDCon 2015, Stockholm, Sweden, October 1st 2015

Tutorials & HowTos

Pf Firewall “how to” – FreeBSD and OpenBSD ( pf.conf )
Paket Filter (PF) von OpenBSD und ALTQ
Getting AltQ working in pf.conf (limiting inbound Tor traffic)
PF Firewall Quick Guide
FreeBSD Tuning and Optimization – performance modifications for 1gig and 10gig networks

Statistics

pfstat
ALTQ statistics?

ntop (Official)
ntopng – High-Speed Web-based Traffic Analysis and Flow Collection (Official)
ntop (Wikipedia)
NTop
Network Monitoring Using Free Linux Tools
Unveiling Application Visibility in ntop and nProbe (both in NetFlow v9 and IPFIX)

FAQ

Table not found

Couldn't manipulate device /dev/pf: No such process
table <hacker> persist {
}

$ pfctl -n -f /etc/pf.conf       # Parse the configuration file, do not actually load rules
$ pfctl -T load -f /etc/pf.conf  # Load only the table definitions
$ pfctl -t hacker -T show        # Show the content of a table

RRDTool

RRDTool – tutorial and graph examples (OpenBSD with pf)
rrd-beginners

Network usage

Network Traffic Monitoring with RRDTool
Monitoring network traffic with iptraf and rrdtool
Monitorix Project by Jordi Sanfeliu
RRDtool with pfctl and spamd
Setting up traffic monitoring using rrdtool (and snmp)
Using SNMP and RRD to monitor your LEAF system

Alternatives

Alternatives to rrdtool?
Java RRD library
rrd4j, RRD4J 3.1 (released 2017-01-01)

BIND9 Reject DNS Root Queries

bind: blackhole for invalid recursive queries?
Disabling Root DNS Server queries on Redhat linux
Ubuntu server 12.04 bind9 dns query rejected

Using FreeBSD’s BPF device with C/C++

Socket Compiler Error

Compile Error in using /usr/include/net/if.h
compile problems on freebsd

SVNWEB

sys/pf
sbin/pfctl

[root@gateway ~]# pfctl -t hacker -T add 192.168.0.2 192.168.0.3 192.168.0.4
1 table created.
3/3 addresses added.

[root@gateway ~]# pfctl -f /etc/pf.conf

[root@gateway ~]# pfctl -t hacker -T show
   192.168.1.1

[root@gateway ~]# pfctl -t hacker -T add 192.168.0.2 192.168.0.3 192.168.0.4
3/3 addresses added.

[root@gateway ~]# pfctl -t hacker -T show
   192.168.0.2
   192.168.0.3
   192.168.0.4
   192.168.1.1
     DIOCRADDADDRS struct pfioc_table *io
	     Add one or	more addresses to a table.  On entry, pfrio_table con-
	     tains the table ID	and pfrio_buffer must point to an array	of
	     struct pfr_addr containing	at least pfrio_size elements to	add to
	     the table.	 pfrio_esize must be the size of struct	pfr_addr.  On
	     exit, pfrio_nadd contains the number of addresses effectively
	     added.

	     struct pfr_addr {
		     union {
			     struct in_addr   _pfra_ip4addr;
			     struct in6_addr  _pfra_ip6addr;
		     }		      pfra_u;
		     u_int8_t	      pfra_af;
		     u_int8_t	      pfra_net;
		     u_int8_t	      pfra_not;
		     u_int8_t	      pfra_fback;
	     };
	     #define pfra_ip4addr    pfra_u._pfra_ip4addr
	     #define pfra_ip6addr    pfra_u._pfra_ip6addr
/usr/include/sys/ioctl.h: ioctl                (dev, DIOCRADDADDRS, &io)
sbin/pfctl/pfctl_radix.c: pfr_add_addrs        (tbl=0xbfbfd198, addr=0x28826100, size=3, nadd=0xbfbfd16c, flags=0)
sbin/pfctl/pfctl_table.c: pfctl_table          (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
sbin/pfctl/pfctl_table.c: pfctl_command_tables (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
sbin/pfctl/pfctl.c:       main                 (argc=3, argv=0xbfbfdc90)


tbl:
$1 = (struct pfr_table *) 0xbfbfd198
$2 = { pfrt_anchor = '\0' 
       pfrt_name   = "hacker", 
       pfrt_flags  = 0,
       pfrt_fback  = 0 '\0'}

addr:
$3 = (struct pfr_addr *) 0x28826100
$4 = { pfra_u = { _pfra_ip4addr = { s_addr = 33597632 },
                  _pfra_ip6addr = { [...] }
                },
       pfra_af = 2 '\002',
       pfra_net = 32 ' ', 
       pfra_not = 0 '\0',
       pfra_fback = 0 '\0'}

pfctl_radix.c:418    pfr_buf_add          (b=0xbfbfd188, e=0xbfbfcfb0)
pfctl_parser.c:1704  append_addr_host     (b=0xbfbfd188, n=0x28814460, test=0, not=0)
pfctl_parser.c:1659  append_addr          (b=0xbfbfd188, s=0xbfbfddf9 "192.168.0.4", test=0)
pfctl_table.c:418    load_addr            (b=0xbfbfd188, argc=0, argv=0xbfbfdc9c, file=0x0, nonetwork=0)
pfctl_table.c:201    pfctl_table          (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
pfctl_table.c:124    pfctl_command_tables (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
pfctl.c:2328         main                 (argc=3, argv=0xbfbfdc90)
typedef char *          caddr_t;        /* core address */
typedef const char *    c_caddr_t;      /* core address, pointer to const */
/*
 * Internet address (a structure for historical reasons)
 */
struct in_addr {
	in_addr_t s_addr;
};

Essential Socket Functions

int
main(int argc, char *argv[])
{
    [...]
    while ((ch = getopt(argc, argv,
        "a:AdD:eqf:F:ghi:k:K:mnNOo::Pp:rRs:t:T:vx:z")) != -1) {
        switch (ch) {
        [...]
        case 't':
            tableopt = optarg;
            break;
        case 'T':
            tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
            if (tblcmdopt == NULL) {
                warnx("Unknown table command '%s'", optarg);
                usage();
            }
            break;
        [...]
        }
    }
    [...]
    if (tblcmdopt != NULL) {
        error = pfctl_command_tables(argc, argv, tableopt,
            tblcmdopt, rulesopt, anchorname, opts);
        rulesopt = NULL;
    }
    [...]
}
enum {
    PFRB_TABLES = 1,
    PFRB_TSTATS,
    PFRB_ADDRS,
    PFRB_ASTATS,
    PFRB_IFACES,
    PFRB_TRANS,
    PFRB_MAX
};

struct pfr_buffer {
    int                 pfrb_type;      /* type of content, see enum above */
    int                 pfrb_size;      /* number of objects in buffer */
    int                 pfrb_msize;     /* maximum number of objects in buffer */
    void               *pfrb_caddr;     /* malloc'ated memory area */
};

/*  int            int            int              void *                */
   {pfrb_type = 3, pfrb_size = 0, pfrb_msize = 0,  pfrb_caddr = 0x0}
   {pfrb_type = 3, pfrb_size = 1, pfrb_msize = 64, pfrb_caddr = 0x28826100}
   {pfrb_type = 3, pfrb_size = 2, pfrb_msize = 64, pfrb_caddr = 0x28826100}


struct pfioc_table {
    struct pfr_table    pfrio_table;
    void               *pfrio_buffer;
    int                 pfrio_esize;
    int                 pfrio_size;
    int                 pfrio_size2;
    int                 pfrio_nadd;
    int                 pfrio_ndel;
    int                 pfrio_nchange;
    int                 pfrio_flags;
    u_int32_t           pfrio_ticket;
};

struct pfr_table {
    char                pfrt_anchor[MAXPATHLEN];
    char                pfrt_name[PF_TABLE_NAME_SIZE];
    u_int32_t           pfrt_flags;
    u_int8_t            pfrt_fback;
};

/*  char *              char *                       u_int32_t       u_int8_t          */
   {pfrt_anchor = '\0', pfrt_name = "hacker", '\0' , pfrt_flags = 0, pfrt_fback = 0 '\0'}

pfrt_flags:
#define PFR_TFLAG_PERSIST       0x00000001
#define PFR_TFLAG_CONST         0x00000002
#define PFR_TFLAG_ACTIVE        0x00000004
#define PFR_TFLAG_INACTIVE      0x00000008
#define PFR_TFLAG_REFERENCED    0x00000010
#define PFR_TFLAG_REFDANCHOR    0x00000020
#define PFR_TFLAG_USRMASK       0x00000003
#define PFR_TFLAG_SETMASK       0x0000003C
#define PFR_TFLAG_ALLMASK       0x0000003F

struct pfr_table.pfrt_fback:
struct pfr_addr.pfra_fback:
enum {
    PFR_FB_NONE,
    PFR_FB_MATCH,
    PFR_FB_ADDED,
    PFR_FB_DELETED,
    PFR_FB_CHANGED,
    PFR_FB_CLEARED,
    PFR_FB_DUPLICATE,
    PFR_FB_NOTMATCH,
    PFR_FB_CONFLICT,
    PFR_FB_MAX
};

struct pfr_addr {
    union {
        struct in_addr   _pfra_ip4addr;
        struct in6_addr  _pfra_ip6addr;
    }                pfra_u;
    u_int8_t         pfra_af;        /**< AF_INET or AF_INET6 */
    u_int8_t         pfra_net;
    u_int8_t         pfra_not;
    u_int8_t         pfra_fback;
};
#define pfra_ip4addr    pfra_u._pfra_ip4addr
#define pfra_ip6addr    pfra_u._pfra_ip6addr

/* union                                                           */
   { pfra_u = { _pfra_ip4addr = { s_addr = 33597632 },
                _pfra_ip6addr = {__u6_addr = { __u6_addr8  = { ... },
                                               __u6_addr16 = { ... },
                                               __u6_addr32 = { ... }
                                             }
                                }
              },
/*   u_int8_t      u_int8_t        u_int8_t       u_int8_t         */
     pfra_af = 2 , pfra_net = 32 , pfra_not = 0 , pfra_fback = 0   }

/***************************************************************/

#define v4      pfa.v4
#define v6      pfa.v6
#define addr8   pfa.addr8
#define addr16  pfa.addr16
#define addr32  pfa.addr32

struct pf_addr {
    union {
        struct in_addr          v4;
        struct in6_addr         v6;
        u_int8_t                addr8[16];
        u_int16_t               addr16[8];
        u_int32_t               addr32[4];
    }                           pfa;           /* 128-bit address */
};

struct pf_addr_wrap {
    union {
        struct {
            struct pf_addr      addr;
            struct pf_addr      mask;
        }                       a;
        char                    ifname[IFNAMSIZ];
        char                    tblname[PF_TABLE_NAME_SIZE];
    }                           v;
    union {
        struct pfi_dynaddr     *dyn;
        struct pfr_ktable      *tbl;
        int                     dyncnt;
        int                     tblcnt;
    }                           p;
    u_int8_t                    type;          /* PF_ADDR_* */
    u_int8_t                    iflags;        /* PFI_AFLAG_* */
};

#define CREATE_TABLE do {                                   \
    table.pfrt_flags |= PFR_TFLAG_PERSIST;                  \
    if ((!(opts & PF_OPT_NOACTION) ||                       \
        (opts & PF_OPT_DUMMYACTION)) &&                     \
        (pfr_add_tables(&table, 1, &nadd, flags)) &&        \
        (errno != EPERM)) {                                 \
            radix_perror();                                 \
            goto _error;                                    \
    }                                                       \
    if (nadd) {                                             \
        warn_namespace_collision(table.pfrt_name);          \
        xprintf(opts, "%d table created", nadd);            \
        if (opts & PF_OPT_NOACTION)                         \
            return (0);                                     \
    }                                                       \
    table.pfrt_flags &= ~PFR_TFLAG_PERSIST;                 \
} while(0)                           

int
pfctl_command_tables(int argc, char *argv[], char *tname,
    const char *command, char *file, const char *anchor, int opts)
{
	if (tname == NULL || command == NULL)
		usage();
	return pfctl_table(argc, argv, tname, command, file, anchor, opts);
}

int
pfctl_table(int argc, char *argv[], char *tname, const char *command,
    char *file, const char *anchor, int opts)
{
    struct pfr_table    table;
    struct pfr_buffer   b, b2;
    struct pfr_addr    *a, *a2;
    int                 nadd = 0;

    [...]

    strlcpy(table.pfrt_name, tname, sizeof(table.pfrt_name);      /**< copy table name */

    [...]
    } else if (!strcmp(command, "add")) {
        b.pfrb_type = PFRB_ADDRS;                                 /**< set type to ADDR */
        if (load_addr(&b, argc, argv, file, 0))                   /**< load_addr(): parse arguments and pass it to struct pfr_buffer */
            goto _error;
        CREATE_TABLE;
        if (opts & PF_OPT_VERBOSE)
            flags |= PFR_FLAG_FEEDBACK;
        RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size, &nadd, flags));    /**< pfr_add_addrs(): 
        xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size);
        if (opts & PF_OPT_VERBOSE)
            PFRB_FOREACH(a, &b)
                if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
                    print_addrx(a, NULL, opts & PF_OPT_USEDNS);
    }
    [...]
}

int
load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file,
    int nonetwork)
{
    while (argc--)
        if (append_addr(b, *argv++, nonetwork)) {
            if (errno)
                warn("cannot decode %s", argv[-1]);
            return (-1);
        }
    if (pfr_buf_load(b, file, nonetwork, append_addr)) {
        warn("cannot load %s", file);
        return (-1);
    }
    return (0);
}
struct node_host {
    struct pf_addr_wrap  addr;
    struct pf_addr       bcast;
    struct pf_addr       peer;
    sa_family_t          af;
    u_int8_t             not;
    u_int32_t            ifindex;   /* link-local IPv6 addrs */
    char                *ifname;
    u_int                ifa_flags;
    struct node_host    *next;
    struct node_host    *tail;
};
/*
 * convert a hostname to a list of addresses and put them in the given buffer.
 * test:
 *  if set to 1, only simple addresses are accepted (no netblock, no "!").
 */
int
append_addr(struct pfr_buffer *b, char *s, int test)
{
    char             *r;
    struct node_host    *h, *n;
    int          rv, not = 0;

    for (r = s; *r == '!'; r++)
        not = !not;
    if ((n = host(r)) == NULL) {
        errno = 0;
        return (-1);
    }
    rv = append_addr_host(b, n, test, not);
    do {
        h = n;
        n = n->next;
        free(h);
    } while (n != NULL);
    return (rv);
}

/*
 * same as previous function, but with a pre-parsed input and the ability
 * to "negate" the result. Does not free the node_host list.
 * not:
 *      setting it to 1 is equivalent to adding "!" in front of parameter s.
 */
int
append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
{
    int          bits;
    struct pfr_addr      addr;

    do {
        bzero(&addr, sizeof(addr));
        addr.pfra_not = n->not ^ not;
        addr.pfra_af = n->af;
        addr.pfra_net = unmask(&n->addr.v.a.mask, n->af);            /**< assign netmask, node_host -> pfr_addr */
        switch (n->af) {
        case AF_INET:
            addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0];   /**< assign address, node_host -> pfr_addr */
            bits = 32;
            break;
        case AF_INET6:
            memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6,
                sizeof(struct in6_addr));
            bits = 128;
            break;
        default:
            errno = EINVAL;
            return (-1);
        }
        if ((test && (not || addr.pfra_net != bits)) ||              /**< test = 0, not = 0 => bypass these lines */
            addr.pfra_net > bits) {
            errno = EINVAL;
            return (-1);
        }
        if (pfr_buf_add(b, &addr))
            return (-1);
    } while ((n = n->next) != NULL);

    return (0);
}

struct node_host *
host(const char *s)
{
    struct node_host    *h = NULL;
    int          mask, v4mask, v6mask, cont = 1;
    char            *p, *q, *ps;

    if ((p = strrchr(s, '/')) != NULL) {
        mask = strtol(p+1, &q, 0);
        if (!q || *q || mask > 128 || q == (p+1)) {
            fprintf(stderr, "invalid netmask '%s'\n", p);
            return (NULL);
        }
        if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
            err(1, "host: malloc");
        strlcpy(ps, s, strlen(s) - strlen(p) + 1);
        v4mask = v6mask = mask;
    } else {
        if ((ps = strdup(s)) == NULL)
            err(1, "host: strdup");
        v4mask = 32;
        v6mask = 128;
        mask = -1;
    }

    /* interface with this name exists? */
    if (cont && (h = host_if(ps, mask)) != NULL)
        cont = 0;

    /* IPv4 address? */
    if (cont && (h = host_v4(s, mask)) != NULL)
        cont = 0;

    /* IPv6 address? */
    if (cont && (h = host_v6(ps, v6mask)) != NULL)
        cont = 0;

    /* dns lookup */
    if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL)
        cont = 0;
    free(ps);

    if (h == NULL || cont == 1) {
        fprintf(stderr, "no IP address found for %s\n", s);
        return (NULL);
    }
    return (h);
}

struct node_host *
host_v4(const char *s, int mask)
{
    struct node_host    *h = NULL;
    struct in_addr       ina;
    int          bits = 32;

    memset(&ina, 0, sizeof(struct in_addr));
    if (strrchr(s, '/') != NULL) {
        if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)     /**< parse string, return netmask bits */
            return (NULL);
    } else {
        if (inet_pton(AF_INET, s, &ina) != 1)
            return (NULL);
    }

    h = calloc(1, sizeof(struct node_host));
    if (h == NULL)
        err(1, "address: calloc");
    h->ifname = NULL;
    h->af = AF_INET;
    h->addr.v.a.addr.addr32[0] = ina.s_addr;
    set_ipmask(h, bits);                                                     /**< set IP mask */
    h->next = NULL;
    h->tail = h;

    return (h);
}

void
set_ipmask(struct node_host *h, u_int8_t b)
{
    struct pf_addr  *m, *n;
    int      i, j = 0;

    m = &h->addr.v.a.mask;
    memset(m, 0, sizeof(*m));

    while (b >= 32) {
        m->addr32[j++] = 0xffffffff;
        b -= 32;
    }
    for (i = 31; i > 31-b; --i)
        m->addr32[j] |= (1 << i);
    if (b)
        m->addr32[j] = htonl(m->addr32[j]);

    /* Mask off bits of the address that will never be used. */
    n = &h->addr.v.a.addr;
    if (h->addr.type == PF_ADDR_ADDRMASK)
        for (i = 0; i < 4; i++)
            n->addr32[i] = n->addr32[i] & m->addr32[i];
}
/* buffer management code */

size_t buf_esize[PFRB_MAX] = { 0,
    sizeof(struct pfr_table), sizeof(struct pfr_tstats),
    sizeof(struct pfr_addr), sizeof(struct pfr_astats),
    sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
};

/*
 * add one element to the buffer
 */
int
pfr_buf_add(struct pfr_buffer *b, const void *e)
{
    size_t bs;

    if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
        e == NULL) {
        errno = EINVAL;
        return (-1);
    }
    bs = buf_esize[b->pfrb_type];           /**< choose buffer size, ex. sizeof(struct pfr_addr) */
    if (b->pfrb_size == b->pfrb_msize)      /**< no space left */
        if (pfr_buf_grow(b, 0))             /**< increase buffer */
            return (-1);
    memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
    b->pfrb_size++;
    return (0);
}

int
pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    int *nadd, int flags)
{
    struct pfioc_table io;

    if (tbl == NULL || size < 0 || (size && addr == NULL)) {
        errno = EINVAL;
        return (-1);
    }
    bzero(&io, sizeof io);
    io.pfrio_flags = flags;
    io.pfrio_table = *tbl;
    io.pfrio_buffer = addr;
    io.pfrio_esize = sizeof(*addr);
    io.pfrio_size = size;
    if (ioctl(dev, DIOCRADDADDRS, &io))
        return (-1);
    if (nadd != NULL)
        *nadd = io.pfrio_nadd;
    return (0);
}

Pointer Handling

Pointer Arithmetic

arr[ i ] == * ( arr + i )

ex.
sizeof(unsigned long) = 64-bit = 8 byte
unsigned long arr[2];
&arr[0] = (arr + 0) = 0x608ea0
&arr[1] = (arr + 1) = 0x608ea8
(gdb) p &entry.allocator[0]         (gdb) p &((ethernet_header_t *) entry.allocator)[0]  
$19 = (header_t *) 0x608e90         $21 = (struct _ethernet_header_t *) 0x608e90


(gdb) p &entry.allocator[1]         (gdb) p &((ethernet_header_t *) entry.allocator)[1]
$20 = (header_t *) 0x608eb8         $22 = (struct _ethernet_header_t *) 0x608ed0
   
            
(gdb) p sizeof(header_t)            (gdb) p sizeof(ethernet_header_t)
$24 = 40 = 0x28                     $23 = 64 = 0x40

  0x608e90                            0x608e90
+ 0x000028                          + 0x000040
----------                          ----------
  0x608eb8                            0x608ed0
===========                         ===========

NXP LPCXpresso

LPC1343 QuickStart Board
LPC1347 LPCXpresso board
LPC1549 LPCXpresso board (aka. LPCXpresso V2 board)
LPC1769 LPCXpresso board
LPC800 / LPC812 MAX Board
LPCXpresso Experiment Kit
LPC-Link 2 board

LPCXpresso V2 Boards (aka. LPC1549 LPCXpresso board)
LPCXpresso11U37H board (aka. Extended LPCXpresso V2 board)
LPC1549 LPCXpresso Motor Control Kit (BLDC)

LPCOpen Software Development Platform for NXP LPC Microcontrollers
LightWeight IP (LWIP) networking stack for NXP LPC Microcontrollers

  • ARM CMSIS DSP Library
  • emWin, a graphics library
  • SWIM, a simple graphics library
  • LWIP, an open-source networking stack
  • LPCUSBLib, an open-source USB device and host stack
  • FreeRTOS, an open-source RTOS
  • The core library – A set of common core and chip specific drivers that are standardized across platforms
  • Examples & Projects