Commit 0a4176c1 authored by Timothy Stack's avatar Timothy Stack

Various nfstrace changes that have been sitting in my tree for awhile.

	* GNUmakefile.in: Do fs-install in the sensors subdir so the
	nfstracer gets installed.

	* sensors/and/and-emulab.priorities: Add some more daemon uid's to
	be excluded from auto-nicing.

	* sensors/and/and.c: Ignore invalid uids/gids in the config file
	instead of dying.

	* sensors/nfstrace/GNUmakefile: Makefile used to generate
	nfsdb-create.sql.

	* sensors/nfstrace/GNUmakefile.in: Some more installation stuff.

	* sensors/nfstrace/nfsdb-create.sql: SQL used to create the nfsdb
	database.

	* sensors/nfstrace/nfsdump2db: Bunch of bug fixes and cleanup.

	* sensors/nfstrace/nfsdump2db.8, sensors/nfstrace/nfstrace.7,
	sensors/nfstrace/nfstrace.proxy.8: Start at some man pages.

	* sensors/nfstrace/nfstrace.init.in: Try to detect the interface
	to listen on, not perfect though.  Add a restart handler that just
	restarts nfsdump2db.  Some other cleanup.

	* sensors/nfstrace/nfstrace.proxy: Some optimizations for
	resolving file names.

	* sensors/nfstrace/nfsdump2/*: Only print summaries of read/write
	packets and start a separate thread to read from the bpf socket.

	* tbsetup/tbswap.in: Stop transferring nfs accesses to boss' db
	until we figure out what we want to do with it.
parent be649889
......@@ -92,6 +92,7 @@ endif
fs-install:
@$(MAKE) -C tbsetup fs-install
@$(MAKE) -C sensors fs-install
opsfs-install: ops-install fs-install
@echo "Combined ops/fs install done."
......
......@@ -42,8 +42,10 @@
#
# daemon entry -- for the portmapper and such, also ignore jabber.
#
daemon * * * 0 0 0
jabber * * * 0 0 0
daemon * * * 0 0 0
jabber * * * 0 0 0
mysql * * * 0 0 0
nfstrace * * * 0 0 0
#
# The main elvind server.
......
/*
AND auto nice daemon - renice programs according to their CPU usage.
Copyright (C) 1999-2004 Patrick Schemitz <schemitz@users.sourceforge.net>
Copyright (C) 1999-2005 Patrick Schemitz <schemitz@users.sourceforge.net>
http://and.sourceforge.net/
This program is free software; you can redistribute it and/or modify
......@@ -422,7 +422,7 @@ void read_priorities ()
} else {
and_printf(0,"Priority database line %i with invalid UID: %s\n",
line_count, uid_s);
bad_count++;
// bad_count++;
continue;
}
/* Identify GID */
......@@ -435,7 +435,7 @@ void read_priorities ()
} else {
and_printf(0,"Priority database line %i with invalid GID: %s\n",
line_count, gid_s);
bad_count++;
// bad_count++;
continue;
}
/* figure parent mode */
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
#
# This makefile is different than all the others...
#
# It is intended to be run in place in the cvs tree to update the files,
# and doesn't install or build anything else. This is why it doesn't go
# through configure, etc.
#
# The easy way: do 'gmake all'
# You can also run the individual targets too.
all: db-create
db-create:
@rm -f ./.tmp-db-create.sql ./.tmp-create-diff
@sudo -u nfstrace -H mysqldump -d nfsdb > ./.tmp-db-create.sql
@-diff ./nfsdb-create.sql ./.tmp-db-create.sql > ./.tmp-create-diff
@if test -s ./.tmp-create-diff; \
then \
cat ./.tmp-create-diff; \
echo "NOTE: Don't forget to update nfsdb-migrate.txt!"; \
mv ./.tmp-db-create.sql ./nfsdb-create.sql; \
fi
@rm -f ./.tmp-create-diff ./.tmp-db-create.sql
......@@ -11,6 +11,8 @@ TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = sensors/nfstrace
NFSTRACESUPPORT = @NFSTRACESUPPORT@
include $(OBJDIR)/Makeconf
all: nfstrace.proxy nfsdump2db nfsdump nfstrace.init
......@@ -27,6 +29,8 @@ INSTALL_SBIN=$(PREFIX)/sbin
INSTALL_MAN=$(PREFIX)/man
PW=/usr/sbin/pw
NFSTRACE_HOME=/var/nfstrace
NFSTRACE_DBDIR=/var/db/nfstrace
$(SRCDIR)/nfsdump2/config.status:
cd $(SRCDIR)/nfsdump2 && ./configure
......@@ -39,31 +43,100 @@ $(SRCDIR)/nfsdump2/nfsdump: $(SRCDIR)/nfsdump2/config.status make.nfsdump
nfsdump: $(SRCDIR)/nfsdump2/nfsdump
cp $(SRCDIR)/nfsdump2/nfsdump .
client client-install:
client client-install control-install:
control-install: all
-mkdir -p $(INSTALL_DIR)/sbin
-mkdir -p $(INSTALL_DIR)/etc
-mkdir -p $(INSTALL_DIR)/etc/rc.d
$(NFSTRACE_HOME):
sudo mkdir -m 0750 $(NFSTRACE_HOME)
add-nfstrace-user: $(NFSTRACE_HOME)
@if ! id nfstrace > /dev/null 2>&1; then \
sudo $(PW) useradd nfstrace -d /nonexistent \
sudo $(PW) useradd nfstrace -d $(NFSTRACE_HOME) \
-s /sbin/nologin -u 50,200 \
-c "NFS Tracing Daemon"; \
fi
@if ! $(PW) groupshow bpf; then \
sudo $(PW) groupadd bpf; \
@if ! id -Gn mysql | grep nfstrace > /dev/null 2>&1; then \
sudo $(PW) usermod -n mysql -G "`id -Gn mysql` nfstrace"; \
fi
sudo chown nfstrace $(NFSTRACE_HOME)
sudo chgrp wheel $(NFSTRACE_HOME)
sudo chgrp nfstrace /dev/bpf0
sudo chmod g+r /dev/bpf0
$(NFSTRACE_DBDIR):
sudo mkdir -m 0750 -p $@
sudo chown nfstrace $@
sudo chgrp nfstrace $@
$(NFSTRACE_HOME)/dbpass:
head -c 32 /dev/urandom | md5 -q | head -c 8 > $@
sudo chown nfstrace $@
sudo chgrp wheel $@
sudo chmod o-r $@
@if test ! -s $@; then \
echo "error: generated empty password..."; \
rm $@; \
exit 1; \
fi
@if test ! -d /var/nfstrace; then \
sudo mkdir -m 0750 /var/nfstrace; \
$(NFSTRACE_HOME)/.my.cnf: $(NFSTRACE_HOME)/dbpass
echo "[client]" > $@
echo "user=nfstrace" >> $@
echo "password=`cat $(NFSTRACE_HOME)/dbpass`" >> $@
echo "[mysqldump]" >> $@
echo "user=nfstrace" >> $@
echo "password=`cat $(NFSTRACE_HOME)/dbpass`" >> $@
sudo chown nfstrace $@
sudo chgrp wheel $@
sudo chmod o-r $@
# XXX Needs to be updated to properly create the DB and user.
create-db: $(NFSTRACE_HOME)/.my.cnf $(NFSTRACE_DBDIR)
@if ! id mysql > /dev/null 2>&1; then \
:; \
elif sudo -u nfstrace -H mysqldump -d nfsdb > nfsdb-dump.sql; then \
perl $(TESTBED_SRCDIR)/utils/schemadiff nfsdb-dump.sql \
$(SRCDIR)/nfsdb-create.sql > nfsdb.diff; \
if test -s nfsdb.diff; then \
echo "error: nfsdb is out of sync"; \
cat nfsdb.diff; \
exit 1; \
fi \
else \
echo "create database nfsdb" | sudo -u root mysql; \
sudo -u nfstrace -H mysql nfsdb < $(SRCDIR)/nfsdb-create.sql; \
fi
sudo chown nfstrace /var/nfstrace
ifeq ($(NFSTRACESUPPORT),1)
fs-install: all add-nfstrace-user create-db
-mkdir -p $(INSTALL_DIR)/sbin
-mkdir -p $(INSTALL_DIR)/etc
-mkdir -p $(INSTALL_DIR)/etc/rc.d
$(INSTALL) -m 0755 nfsdump $(DESTDIR)$(INSTALL_SBINDIR)
$(INSTALL) -m 0755 $(SRCDIR)/nfsdump2db $(DESTDIR)$(INSTALL_SBINDIR)
$(INSTALL) -m 0755 $(SRCDIR)/nfstrace.proxy $(DESTDIR)$(INSTALL_SBINDIR)
$(INSTALL) -m 0755 nfstrace.init $(INSTALL_DIR)/etc/rc.d/nfstrace
-mkdir -p $(INSTALL_DIR)/man/man8
$(INSTALL) -m 0644 $(SRCDIR)/nfstrace.proxy.8 \
$(INSTALL_DIR)/man/man8/nfstrace.proxy.8
$(INSTALL) -m 0644 $(SRCDIR)/nfsdump2db.8 \
$(INSTALL_DIR)/man/man8/nfsdump2db.8
-mkdir -p $(INSTALL_DIR)/man/man7
$(INSTALL) -m 0644 $(SRCDIR)/nfstrace.7 \
$(INSTALL_DIR)/man/man7/nfstrace.7
install: all
$(INSTALL) -m 0755 nfsdump $(DESTDIR)$(INSTALL_SBIN)
$(INSTALL) -m 0755 $(SRCDIR)/nfsdump2db $(DESTDIR)$(INSTALL_SBIN)
$(INSTALL) -m 0755 $(SRCDIR)/nfstrace.proxy $(DESTDIR)$(INSTALL_SBIN)
$(INSTALL) -m 0755 nfstrace.init $(DESTDIR)$(INSTALL_ETC)/rc.d/nfstrace
-mkdir -p $(INSTALL_DIR)/opsdir/man/man8
$(INSTALL) -m 0644 $(SRCDIR)/nfstrace.proxy.8 \
$(INSTALL_DIR)/opsdir/man/man8/nfstrace.proxy.8
$(INSTALL) -m 0644 $(SRCDIR)/nfsdump2db.8 \
$(INSTALL_DIR)/opsdir/man/man8/nfsdump2db.8
-mkdir -p $(INSTALL_DIR)/opsdir/man/man7
$(INSTALL) -m 0644 $(SRCDIR)/nfstrace.7 \
$(INSTALL_DIR)/opsdir/man/man7/nfstrace.7
else
fs-install install:
endif
This diff is collapsed.
......@@ -17,7 +17,7 @@
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# @(#) $Header: /home/cvs_mirrors/cvs-public.flux.utah.edu/CVS/testbed/sensors/nfstrace/nfsdump2/Makefile.in,v 1.1 2005-11-28 15:44:00 stack Exp $ (LBL)
# @(#) $Header: /home/cvs_mirrors/cvs-public.flux.utah.edu/CVS/testbed/sensors/nfstrace/nfsdump2/Makefile.in,v 1.2 2006-02-02 16:16:17 stack Exp $ (LBL)
#
# Various configurable paths (remember to edit Makefile.in, not Makefile)
......@@ -38,10 +38,11 @@ INCLS = -I. @V_INCLS@
DEFS = @DEFS@
# Standard CFLAGS
CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
CFLAGS = $(CCOPT) $(DEFS) $(INCLS) -g -I/usr/local/include/pthread -I/usr/local/include/pthread/linuxthreads
# Standard LDFLAGS
LDFLAGS = @LDFLAGS@
#LDFLAGS = @LDFLAGS@ -pthread
LDFLAGS = @LDFLAGS@ -L/usr/local/lib -llthread -llgcc_r
# Standard LIBS
LIBS = @LIBS@
......@@ -59,7 +60,8 @@ INSTALL_DATA = @INSTALL_DATA@
CSRC = nfsdump.c machdep.c \
util.c gmt2local.c setsignal.c \
nfsrecord.c nfs_v3.c nfs_v2.c nfs_prot_xdr.c
nfsrecord.c nfs_v3.c nfs_v2.c nfs_prot_xdr.c packetTable.c mypcap.c \
listNode.c
LOCALSRC = @LOCALSRC@
GENSRC = version.c
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2005 University of Utah and the Flux Group.
* All rights reserved.
*/
/**
* @file listNode.c
*
* Implementation for the list node functions.
*/
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "listNode.h"
void lnRemove(struct lnMinNode *node)
{
node->ln_Pred->ln_Succ = node->ln_Succ;
node->ln_Succ->ln_Pred = node->ln_Pred;
}
void lnNewList(struct lnMinList *list)
{
list->lh_Head = (struct lnMinNode *)&(list->lh_Tail);
list->lh_Tail = 0;
list->lh_TailPred = (struct lnMinNode *)list;
}
void lnMoveList(struct lnMinList *dest, struct lnMinList *src)
{
if( lnEmptyList(src) )
{
lnNewList(dest);
}
else
{
dest->lh_Tail = NULL;
dest->lh_Head = src->lh_Head;
dest->lh_TailPred = src->lh_TailPred;
dest->lh_Head->ln_Pred = (struct lnMinNode *)dest;
dest->lh_TailPred->ln_Succ = (struct lnMinNode *)&dest->lh_Tail;
lnNewList(src);
}
}
void lnAppendList(struct lnMinList *dest, struct lnMinList *src)
{
if( !lnEmptyList(src) )
{
dest->lh_TailPred->ln_Succ = src->lh_Head;
src->lh_Head->ln_Pred = dest->lh_TailPred;
dest->lh_TailPred = src->lh_TailPred;
dest->lh_TailPred->ln_Succ =
(struct lnMinNode *)&dest->lh_Tail;
lnNewList(src);
}
}
void lnPrependList(struct lnMinList *dest, struct lnMinList *src)
{
if( !lnEmptyList(src) )
{
src->lh_TailPred->ln_Succ = dest->lh_Head;
dest->lh_Head->ln_Pred = src->lh_TailPred;
src->lh_Head->ln_Pred = (struct lnMinNode *)&dest->lh_Head;
dest->lh_Head = src->lh_Head;
lnNewList(src);
}
}
void lnAddHead(struct lnMinList *list, struct lnMinNode *node)
{
node->ln_Succ = list->lh_Head;
node->ln_Pred = (struct lnMinNode *)list;
list->lh_Head->ln_Pred = node;
list->lh_Head = node;
}
void lnAddTail(struct lnMinList *list, struct lnMinNode *node)
{
list->lh_TailPred->ln_Succ = node;
node->ln_Pred = list->lh_TailPred;
list->lh_TailPred = node;
node->ln_Succ = (struct lnMinNode *)&(list->lh_Tail);
}
struct lnMinNode *lnRemHead(struct lnMinList *list)
{
struct lnMinNode *remnode = 0;
if( list->lh_Head->ln_Succ )
{
remnode = list->lh_Head;
list->lh_Head = remnode->ln_Succ;
list->lh_Head->ln_Pred = (struct lnMinNode *)list;
}
return( remnode );
}
struct lnMinNode *lnRemTail(struct lnMinList *list )
{
struct lnMinNode *remnode = 0;
if( list->lh_TailPred->ln_Pred )
{
remnode = list->lh_TailPred;
list->lh_TailPred = remnode->ln_Pred;
list->lh_TailPred->ln_Succ =
(struct lnMinNode *)&(list->lh_Tail);
}
return( remnode);
}
void lnInsert(struct lnMinNode *pred, struct lnMinNode *node)
{
node->ln_Succ = pred->ln_Succ;
pred->ln_Succ = node;
node->ln_Pred = pred;
node->ln_Succ->ln_Pred = node;
}
void lnEnqueue(struct lnList *list, struct lnNode *node)
{
struct lnNode *curr;
int done = 0;
curr = list->lh_Head;
while( curr->ln_Succ && !done )
{
if( node->ln_Pri > curr->ln_Pri )
{
lnInsert((struct lnMinNode *)curr->ln_Pred,
(struct lnMinNode *)node);
done = 1;
}
curr = curr->ln_Succ;
}
if( !done )
lnAddTail((struct lnMinList *)list, (struct lnMinNode *)node);
}
struct lnNode *lnFindName(struct lnList *list, const char *name)
{
struct lnNode *curr, *retval = NULL;
curr = list->lh_Head;
while( (curr->ln_Succ != NULL) && (retval == NULL) )
{
if( strcmp(curr->ln_Name, name) == 0 )
{
retval = curr;
}
curr = curr->ln_Succ;
}
return( retval );
}
unsigned int lnCountNodes(struct lnMinList *list)
{
unsigned int retval = 0;
struct lnMinNode *curr;
curr = list->lh_Head;
while( curr->ln_Succ != NULL )
{
retval += 1;
curr = curr->ln_Succ;
}
return( retval );
}
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2005 University of Utah and the Flux Group.
* All rights reserved.
*/
/**
* @file listNode.h
*
* Amiga-style doubly linked list functions.
*/
#ifndef _list_node_h
#define _list_node_h
#include <assert.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Basic node structure that is used for doubly linked list.
*/
struct lnMinNode {
struct lnMinNode *ln_Succ;
struct lnMinNode *ln_Pred;
};
/**
* Extended node structure that is used for doubly linked lists that can be
* ordered by priority.
*/
struct lnNode {
struct lnNode *ln_Succ;
struct lnNode *ln_Pred;
int ln_Pri;
const char *ln_Name;
};
/**
* A combined head and tail for lists that contain lnMinNode's.
*/
struct lnMinList {
struct lnMinNode *lh_Head; /**< points to the head node */
struct lnMinNode *lh_Tail; /**< always == 0 */
struct lnMinNode *lh_TailPred; /**< points to the tail node */
};
/**
* A combined head and tail for lists that contain lnNode's.
*/
struct lnList {
struct lnNode *lh_Head;
struct lnNode *lh_Tail;
struct lnNode *lh_TailPred;
int lh_Pri;
const char *lh_Name;
};
/**
* Check a list to make sure its structure is sane.
*/
#define lnCheck(list) { \
assert((list)->lh_Head != NULL); \
assert((list)->lh_Tail == NULL); \
assert((list)->lh_TailPred != NULL); \
}
/**
* Remove a node from the list
*
* @param node The node to remove.
*/
void lnRemove(struct lnMinNode *node);
/**
* Initialize a list
*
* @param list The list object to initialize.
*/
void lnNewList(struct lnMinList *list);
/**
* Transfer the nodes on src to dest, overwriting any nodes on dest
*
* @param dest The destination list object.
* @param src The source list object.
*/
void lnMoveList(struct lnMinList *dest, struct lnMinList *src);
/**
* Append the nodes from src to dest.
*
* @param dest The destination list object.
* @param src The source list object.
*/
void lnAppendList(struct lnMinList *dest, struct lnMinList *src);
/**
* Prepend the nodes from src to dest.
*
* @param dest The destination list object.
* @param src The source list object.
*/
void lnPrependList(struct lnMinList *dest, struct lnMinList *src);
/**
* Add a node to the head of the list.
*
* @param list The list object the node is to be added to.
* @param node The node to add.
*/
void lnAddHead(struct lnMinList *list, struct lnMinNode *node);
/**
* Add a node to the tail of the list.
*
* @param list The list object the node is to be added to.
* @param node The node to add.
*/
void lnAddTail(struct lnMinList *list, struct lnMinNode *node);
/**
* Remove and return the node at the head of the list, or NULL if the list is
* empty.
*
* @param list A valid list object.
* @return The node at the head of 'list', or NULL if the list is empty.
*/
struct lnMinNode *lnRemHead(struct lnMinList *list);
/**
* Remove and return the node at the tail of the list, or NULL if the list is
* empty
*
* @param list A valid list object.
* @return The node at the tail of 'list', or NULL if the list is empty.
*/
struct lnMinNode *lnRemTail(struct lnMinList *list);
/**
* Check if a list is empty.
*
* @param list The list to check.
* @return True if the list is empty.
*/
#define lnEmptyList(list) \
((struct lnNode *)(list)->lh_TailPred == (struct lnNode *)(list))
/**
* Insert a node at a specific position in a list.
*
* @param pred The node in the list that the new node should be inserted after.
* @param node The node to insert.
*/
void lnInsert(struct lnMinNode *pred, struct lnMinNode *node);
/**
* Insert a node into a prioritized list.
*
* @param list An ordered list.
* @param node The node to insert.
*/
void lnEnqueue(struct lnList *list, struct lnNode *node);
/**
* Find a node with the given name.
*
* @param list The list to search.
* @param name The name to search for.
* @return The first node in the list that matches the given name or NULL if no
* match could be found.
*/
struct lnNode *lnFindName(struct lnList *list, const char *name);
/**
* Count the number of nodes in a list.
*
* @param list The list to scan.
* @return The number of nodes in the list.
*/
unsigned int lnCountNodes(struct lnMinList *list);
#ifdef __cplusplus
}
#endif
#endif
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <linuxthreads/pthread.h>
#include <pcap-int.h>
#include "listNode.h"
#define MPD_BUFFER_COUNT 128
static struct {
pthread_t mpd_reader;
pthread_mutex_t mpd_mutex;
pthread_cond_t mpd_cond;
pcap_handler mpd_callback;
struct lnMinList mpd_buflist;
struct lnMinList mpd_freelist;
char *mpd_buffer[MPD_BUFFER_COUNT];
int mpd_buflen[MPD_BUFFER_COUNT];
struct lnMinNode mpd_nodes[MPD_BUFFER_COUNT];
} mypcap_data;
static void *mypcap_reader(void *pcap)
{
struct lnMinNode *next_node = NULL;
pcap_t *p = pcap;
while (1) {
int cc, idx;
pthread_mutex_lock(&mypcap_data.mpd_mutex);
if (next_node != NULL) {
lnAddTail(&mypcap_data.mpd_buflist, next_node);
pthread_cond_signal(&mypcap_data.mpd_cond);
}
if ((next_node = lnRemHead(&mypcap_data.mpd_freelist))
== NULL) {
next_node = lnRemHead(&mypcap_data.mpd_buflist);
}
pthread_mutex_unlock(&mypcap_data.mpd_mutex);
idx = next_node - mypcap_data.mpd_nodes;
again:
cc = read(p->fd,
(char *)mypcap_data.mpd_buffer[idx],
p->bufsize);
if (cc < 0) {
/* Don't choke when we get ptraced */
switch (errno) {
case EINTR:
goto again;
case EWOULDBLOCK:
return (0);
}
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
pcap_strerror(errno));
return NULL;
}
mypcap_data.mpd_buflen[idx] = cc;
}
}
int mypcap_init(pcap_t *pd, pcap_handler callback)
{
int retval = 0;
mypcap_data.mpd_callback = callback;
if (pthread_mutex_init(&mypcap_data.mpd_mutex, NULL) != 0) {
fprintf(stderr, "error: pthread_mutex_init\n");
}
else if (pthread_cond_init(&mypcap_data.mpd_cond, NULL) != 0) {
fprintf(stderr, "error: pthread_cond_init\n");
}
else if (pthread_create(&mypcap_data.mpd_reader,
NULL,
mypcap_reader,
pd) != 0) {
fprintf(stderr, "error: pthread_cond_init\n");
}
else {
int lpc;
lnNewList(&mypcap_data.mpd_buflist);
lnNewList(&mypcap_data.mpd_freelist);
retval = 1;
for (lpc = 0; lpc < MPD_BUFFER_COUNT && retval; lpc++) {
if ((mypcap_data.mpd_buffer[lpc] =
malloc(pd->bufsize)) == NULL) {
retval = 0;
}
lnAddTail(&mypcap_data.mpd_freelist,
&mypcap_data.mpd_nodes[lpc]);
}
}
return retval;
}
int mypcap_read(pcap_t *pd, void *user)
{
static struct lnMinNode *node = NULL;
int idx, cc, retval = 0;
char *bp, *ep;
pthread_mutex_lock(&mypcap_data.mpd_mutex);
if (node != NULL) {
lnAddHead(&mypcap_data.mpd_freelist, node);
}
while ((node = lnRemHead(&mypcap_data.mpd_buflist)) == NULL) {
pthread_cond_wait(&mypcap_data.mpd_cond,
&mypcap_data.mpd_mutex);
}
pthread_mutex_unlock(&mypcap_data.mpd_mutex);
idx = node - mypcap_data.mpd_nodes;
bp = mypcap_data.mpd_buffer[idx];
cc = mypcap_data.mpd_buflen[idx];
/*
* Loop through each packet.
*/
#define bhp ((struct bpf_hdr *)bp)
ep = bp + cc;
while (bp < ep) {
register int caplen, hdrlen;
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;