Use kqueue to respond to more than one event type - kqueue

When an event is registered with kqueue an ID relating to that event
type is supplied; for example a file descriptor is used to identify a file to
watch
int kq;
struct kevent ke;
kq = kqueue();
fd = open(argv[1], O_RDONLY);
EV_SET(&ke, fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE | NOTE_RENAME, 0, NULL);
kevent(kq, &ke, 1, NULL, 0, NULL);
while (1) {
kevent(kq, NULL, 0, &ke, 1, NULL);
/* respond to file system event */
}
Now if I also need to respond to other event types such signals we need a new
instance of kqueue so as to avoid a conflict with the ident argument of
kevent().
kq_sig = kqueue();
struct kevent ke_sig;
/* set the handler and ignore SIGINT */
signal(SIGINT, SIG_IGN);
EV_SET(&ke_sig, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
kevent(kq_sig, &ke_sig, 1, NULL, 0, NULL);
while (1) {
kevent(kq_sig, NULL, 0, &ke_sig, 1, NULL);
/* respond signals */
}
Watching more than one event type appears to necessitate multiple threads that
act on shared state (receiving a signal could close a file descriptor for
example).
Is there a more general mechanism for sending a message from one thread to another using
kqueue? In some cases I can conceive of enabling and disabling a filter as a
means of edge-triggering another kevent.

The kevent struct actually provides info about the event that occured:
struct kevent {
uintptr_t ident; /* identifier for this event */
int16_t filter; /* filter for event */
uint16_t flags; /* general flags */
uint32_t fflags; /* filter-specific flags */
intptr_t data; /* filter-specific data */
void *udata; /* opaque user data identifier */
};
You must be interested in:
ident that in your case returns either fd or SIGINT;
filter that (still in your case) returns either EVFILT_VNODE or EVFILT_SIGNAL;
fflag that in the EVFILT_VNODE will tell you if the file descriptor event was NOTE_DELETE or NOTE_RENAME.
You can register two kevent structures to a single queue and then use these structure members to determine if the event was related to a file descriptor or a signal.
Here is a complete example that demonstrates how to do this:
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
int
main(int argc, char** argv)
{
/* A single kqueue */
int kq = kqueue();
/* Two kevent structs */
struct kevent *ke = malloc(sizeof(struct kevent) * 2);
/* Initialise one struct for the file descriptor, and one for SIGINT */
int fd = open(argv[1], O_RDONLY);
EV_SET(ke, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_DELETE | NOTE_RENAME, 0, NULL);
signal(SIGINT, SIG_IGN);
EV_SET(ke + 1, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
/* Register for the events */
if(kevent(kq, ke, 2, NULL, 0, NULL) < 0)
perror("kevent");
while(1) {
memset(ke, 0x00, sizeof(struct kevent));
if(kevent(kq, NULL, 0, ke, 1, NULL) < 0)
perror("kevent");
switch(ke->filter)
{
/* File descriptor event: let's examine what happened to the file */
case EVFILT_VNODE:
printf("Events %d on file descriptor %d\n", ke->fflags, (int) ke->ident);
if(ke->fflags & NOTE_DELETE)
printf("The unlink() system call was called on the file referenced by the descriptor.\n");
if(ke->fflags & NOTE_WRITE)
printf("A write occurred on the file referenced by the descriptor.\n");
if(ke->fflags & NOTE_EXTEND)
printf("The file referenced by the descriptor was extended.\n");
if(ke->fflags & NOTE_ATTRIB)
printf("The file referenced by the descriptor had its attributes changed.\n");
if(ke->fflags & NOTE_LINK)
printf("The link count on the file changed.\n");
if(ke->fflags & NOTE_RENAME)
printf("The file referenced by the descriptor was renamed.\n");
if(ke->fflags & NOTE_REVOKE)
printf("Access to the file was revoked via revoke(2) or the underlying fileystem was unmounted.");
break;
/* Signal event */
case EVFILT_SIGNAL:
printf("Received %s\n", strsignal(ke->ident));
exit(42);
break;
/* This should never happen */
default:
printf("Unknown filter\n");
}
}
}
Note that here we use a single thread, which is way more efficient and requires no further synchronization in the user space.

Related

Is there any way to print from Google Chrome to thermal printer (escpos) in local network without using apps like QZ tray?

Are PWA functionality (service-worker) can help or there no way to do that?
This document contains a sample program that prints easily using the socket interface in C language.
UB-E04 Technical Reference Guide
It seems that the equivalent can be implemented using JavaScript WebSocket.
This article is available in both Japanese and English, and both provide examples of using WebSocket easily from vanilla JavaScript.
5分で動かせるwebsocketのサンプル3つ / WebSocket Tutorials
Introducing WebSockets: Bringing Sockets to the Web
The following is a sample program in Linux C language described in the document.
Sending to a printer can be done with such a simple program.
The data to be sent must be created in the format described in the ESC/POS command reference.
/* TCP9100 programming sample for LINUX
* HOW TO BUILD
* cc ltcp.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
int main(int argc, char* argv[])
{
int sock;
struct sockaddr_in addr;
if (argc != 2) {
printf("usage: ltcp <ip address>\n");
exit(1);
}
/* create socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket()");
exit(1);
}
/* initialize the parameter */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(9100);
addr.sin_addr.s_addr = inet_addr(argv[1]);
/* connect */
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("connect()");
}
printf("connected\n");
/* send data */
send(sock, "EPSON UB-E04\n", 13, 0);
/* close socket */
close(sock);
return 0;
}

Unable to use CMSIS library in Atollic

I am trying to use CFFT function for my STM32 microcontroller in Atollic TrueStudio. But I am unable to use any of the DSP functions. I get the error -
undefined reference to `arm_cfft_f32' and undefined reference to 'arm_cfft_sR_f32_len16'. I don't know what the problem is because it works on Keil. What am I doing wrong?
#include "stm32f4xx.h"
#include "arm_math.h"
#include "arm_const_structs.h"
#include "core_cm4.h"
#include "math.h"
#define TEST_LENGTH_SAMPLES 32
float32_t ffttestip[TEST_LENGTH_SAMPLES]={0};
static float32_t ffttestop[TEST_LENGTH_SAMPLES/2];
/* Private macro */
/* Private variables */
/* Private function prototypes */
/* Private functions */
uint32_t fftSize = 16;
uint8_t ifftFlag = 0;
uint8_t doBitReverse = 1;
int main(void)
{
int i = 0;
i=15;
i=pow(i,2);
/**
* IMPORTANT NOTE!
* The symbol VECT_TAB_SRAM needs to be defined when building the project
* if code has been located to RAM and interrupts are used.
* Otherwise the interrupt table located in flash will be used.
* See also the <system_*.c> file and how the SystemInit() function updates
* SCB->VTOR register.
* E.g. SCB->VTOR = 0x20000000;
*/
/* TODO - Add your application code here */
arm_cfft_f32(&arm_cfft_sR_f32_len16, ffttestip, ifftFlag, doBitReverse);
/* Infinite loop */
while(1);
}
EDIT - additionally,I get the following error -
Info: Internal Builder is used for build
arm-atollic-eabi-g++ -o fftreal.elf Libraries\STM32F4xx_StdPeriph_Driver\src\misc.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_adc.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_can.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_crc.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_cryp.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_cryp_aes.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_cryp_des.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_cryp_tdes.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dac.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dbgmcu.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dcmi.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_dma.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_exti.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_flash.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_fsmc.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_gpio.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_hash.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_hash_md5.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_hash_sha1.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_i2c.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_iwdg.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_pwr.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_rcc.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_rng.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_rtc.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_sdio.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_spi.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_syscfg.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_tim.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_usart.o Libraries\STM32F4xx_StdPeriph_Driver\src\stm32f4xx_wwdg.o src\main.o src\startup_stm32f40xx.o src\stm32f4xx_it.o src\system_stm32f4xx.o src\tiny_printf.o -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -T../stm32f4_flash.ld -specs=nosys.specs -static -Wl,-cref,-u,Reset_Handler -Wl,-Map=fftreal.map -Wl,--gc-sections -Wl,--defsym=malloc_getpagesize_P=0x1000 -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group -specs=nano.specs
src\main.o: In function `main':
E:\truestudio workspace\fftreal\Debug/..\src/main.cpp:70: undefined reference to `arm_rfft_f32'
collect2.exe: error: ld returned 1 exit status
First of all drop this old unsupported SPL.
Secondly you need to add the .c files containing the CMSIS DSP functions to your project.
Finally - your program as I see does not have anything in common with the C++ so why your project is set as C++?

How to create out-of-tree QEMU devices?

Two possible mechanisms come to mind:
IPC like the existing QMP and QAPI
QEMU loads a shared library plugin that contains the model
Required capabilities (of course all possible through the C API, but not necessarily IPC APIs):
inject interrupts
register callbacks for register access
modify main memory
Why I want this:
use QEMU as a submodule and leave its source untouched
additional advantages only present for IPC methods:
write the models in any language I want
use a non-GPL license for my device
I'm aware of in-tree devices as explained at: How to add a new device in QEMU source code? which are the traditional way of doing things.
What I've found so far:
interrupts: could only find NMI generation with the nmi monitor command
IO ports: IO possible with i and o monitor commands, so I'm fine there
main memory:
the ideal solution would be to map memory to host directly, but that seems hard:
http://kvm.vger.kernel.narkive.com/rto1dDqn/sharing-variables-memory-between-host-and-guest
https://www.linux-kvm.org/images/e/e8/0.11.Nahanni-CamMacdonell.pdf
http://www.fp7-save.eu/papers/SCALCOM2016.pdf
memory read is possible through the x and xp monitor commands
could not find how to write to memory with monitor commands. But I think the GDB API supports, so it should not be too hard to implement.
The closest working piece of code I could find was: https://github.com/texane/vpcie , which serializes PCI on both sides, and sends it through QEMU's TCP API. But this is more inefficient and intrusive, as it requires extra setup on both guest and host.
This create out of tree PCI device , it just display device in lspci..
It will ease faster PCI driver implementation as it will act as module,
can we extend this to to have similar functionality as edu-pci of QEMU.?
https://github.com/alokprasad/pci-hacking/blob/master/ksrc/virtual_pcinet/virtual_pci.c
/*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/fs.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/version.h>
#include<linux/kernel.h>
#define PCI_VENDOR_ID_XTREME 0x15b3
#define PCI_DEVICE_ID_XTREME_VNIC 0x1450
static struct pci_bus *vbus;
static struct pci_sysdata *sysdata;
static DEFINE_PCI_DEVICE_TABLE( vpci_dev_table) = {
{PCI_DEVICE(PCI_VENDOR_ID_XTREME, PCI_DEVICE_ID_XTREME_VNIC)},
{0}
};
MODULE_DEVICE_TABLE(pci, vpci_dev_table);
int vpci_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
switch (where) {
case PCI_VENDOR_ID:
*val = PCI_VENDOR_ID_XTREME | PCI_DEVICE_ID_XTREME_VNIC << 16;
/* our id */
break;
case PCI_COMMAND:
*val = 0;
break;
case PCI_HEADER_TYPE:
*val = PCI_HEADER_TYPE_NORMAL;
break;
case PCI_STATUS:
*val = 0;
break;
case PCI_CLASS_REVISION:
*val = (4 << 24) | (0 << 16) | 1;
/* network class, ethernet controller, revision 1 */ /*2 or 4*/
break;
case PCI_INTERRUPT_PIN:
*val = 0;
break;
case PCI_SUBSYSTEM_VENDOR_ID:
*val = 0;
break;
case PCI_SUBSYSTEM_ID:
*val = 0;
break;
default:
*val = 0;
/* sensible default */
}
return 0;
}
int vpci_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
switch (where) {
case PCI_BASE_ADDRESS_0:
case PCI_BASE_ADDRESS_1:
case PCI_BASE_ADDRESS_2:
case PCI_BASE_ADDRESS_3:
case PCI_BASE_ADDRESS_4:
case PCI_BASE_ADDRESS_5:
break;
}
return 0;
}
struct pci_ops vpci_ops = {
.read = vpci_read,
.write = vpci_write
};
void vpci_remove_vnic()
{
struct pci_dev *pcidev = NULL;
if (vbus == NULL)
return;
pci_remove_bus_device(pcidev);
pci_dev_put(pcidev);
}
EXPORT_SYMBOL( vpci_remove_vnic);
void vpci_vdev_remove(struct pci_dev *dev)
{
}
static struct pci_driver vpci_vdev_driver = {
.name = "Xtreme-Virtual-NIC1",
.id_table = vpci_dev_table,
.remove = vpci_vdev_remove
};
int vpci_bus_init(void)
{
struct pci_dev *pcidev = NULL;
sysdata = kzalloc(sizeof(void *), GFP_KERNEL);
vbus = pci_scan_bus_parented(NULL, 2, & vpci_ops, sysdata);
//vbus = pci_create_root_bus(NULL,i,& vpci_ops, sysdata,NULL);
//if (vbus != NULL)
//break;
memset(sysdata, 0, sizeof(void *));
if (vbus == NULL) {
kfree(sysdata);
return -EINVAL;
}
if (pci_register_driver(& vpci_vdev_driver) < 0) {
pci_remove_bus(vbus);
vbus = NULL;
return -EINVAL;
}
pcidev = pci_scan_single_device(vbus, 0);
if (pcidev == NULL)
return 0;
else
pci_dev_get(pcidev);
pci_bus_add_devices(vbus);
return 0;
}
void vpci_bus_remove(void)
{
if (vbus) {
pci_unregister_driver(&vpci_vdev_driver);
device_unregister(vbus->bridge);
pci_remove_bus(vbus);
kfree(sysdata);
vbus = NULL;
}
}
static int __init pci_init(void)
{
printk( "module loaded");
vpci_bus_init();
return 0;
}
static void __exit pci_exit(void)
{
printk(KERN_ALERT "unregister PCI Device\n");
pci_unregister_driver(&vpci_vdev_driver);
}
module_init(pci_init);
module_exit(pci_exit);
MODULE_LICENSE("GPL");
There is at least one fork of QEMU I'm aware of that offers shared library plugins for QEMU... but it's a fork of QEMU 4.0.
https://github.com/cromulencellc/qemu-shoggoth
It is possible to build out of tree plugins with this fork, though it's not documented.
On Nov 11 2019 Peter Maydell, a major QEMU contributor, commented on another Stack Overflow question that:
Device plugins are specifically off the menu, because upstream does not want to provide a nice easy mechanism for people to use to have out-of-tree non-GPL/closed-source devices.
So it seems that QEMU devs oppose this idea at that point in time. It is worth learning about the QEMU plugin system though which might come handy for related applications in any case: How to count the number of guest instructions QEMU executed from the beginning to the end of a run?
This is a shame. Imagine if the Linux kernel didn't have a kernel module interface! I suggest QEMU expose this interface, but just don't make it stable, so that it won't impose a developer burden, and which gives the upside that those who merge won't have as painful rebases.

Understanding cuda heap memory limitations per thread

This question is about heap size limitation in cuda.
Having visited some questions concerning this topic, including this one:
new operator in kernel .. strange behaviour
I've made some tests. Given a kernel as follow:
#include <cuda.h>
#include <cuda_runtime.h>
#define CUDA_CHECK( err ) __cudaSafeCall( err, __FILE__, __LINE__ )
#define CUDA_CHECK_ERROR() __cudaCheckError( __FILE__, __LINE__ )
inline void __cudaSafeCall( cudaError err, const char *file, const int line )
{
if ( cudaSuccess != err )
{
fprintf( stderr, "cudaSafeCall() failed at %s:%i : %s\n",
file, line, cudaGetErrorString( err ) );
exit( -1 );
}
return;
}
inline void __cudaCheckError( const char *file, const int line )
{
cudaError err = cudaGetLastError();
if ( cudaSuccess != err )
{
fprintf( stderr, "cudaCheckError() failed at %s:%i : %s\n",
file, line, cudaGetErrorString( err ) );
exit( -1 );
}
return;
}
#include <stdio>
#define NP 900000
__device__ double *temp;
__device__ double *temp2;
__global__
void test(){
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i==0){
temp = new double[NP];
//temp2 = new double[NP];
}
if(i==0){
for(int k=0;k<NP;k++){
temp[i] = 1.;
if(k%1000 == 0){
printf("%d : %g\n", k, temp[i]);
}
}
}
if(i==0){
delete(temp);
//delete(temp2);
}
}
int main(){
//cudaDeviceSetLimit(cudaLimitMallocHeapSize, 32*1024*1024);
//for(int k=0;k<2;k++){
test<<<ceil((float)NP/512), 512>>>();
CUDA_CHECK_ERROR();
//}
return 0;
}
I want to test the heap size limitation.
Dynamically allocating one array (temp) with one thread which size is
roughly over 960,000*sizeof(double) (close to 8MB, which is the
default limit of the heap size) gives an error : ok. 900,000 works. (does someone know how to calculate the true limit?)
Rising the heap size limit allows to allocate more memory : normal, ok.
Back to a 8MB heap size, allocating one array per thread with TWO threads (so, replacing if (i==0) by if(i==0 || i==1), each one 900,000 * sizeof(double) fails. But 450,000*sizeof(double) each, works. Still ok.
Here comes my problem : allocating TWO arrays with ONE thread (so, temp and temp2 for thread 0), each 900,000 * sizeof(double) works too, but it should not? Indeed when I try to write in both arrays, it fails. But anyone has an idea why this different behaviour in allocation when using two arrays with one thread instead of two arrays with two threads?
EDIT : another test, which I find interesting for those who, like me, would be learning the usage of heap :
5. Executing the kernel two times, with one array of size 900,000 * sizeof(double) allocated by the single thread 0, works if there is the delete. If delete is omitted, it will fail the second time, but the first call will be executed.
EDIT 2 : how to allocate a device-wide variable once but writable by all threads (not from host, using dynamic allocation in device code)?
Probably you are not testing for a returned null-pointer on the new operation, which is a valid method in C++ for the operator to report a failure.
When I modify your code as follows, I get the message "second new failed":
#include <stdio.h>
#define NP 900000
__device__ double *temp;
__device__ double *temp2;
__global__
void test(){
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i==0){
temp = new double[NP];
if (temp == 0) {printf("first new failed\n"); return;}
temp2 = new double[NP];
if (temp2 == 0) {printf("second new failed\n"); return;}
}
if(i==0){
for(int k=0;k<NP;k++){
temp[i] = 1.;
if(k%1000 == 0){
printf("%d : %g\n", k, temp[i]);
}
}
}
if(i==0){
delete(temp);
delete(temp2);
}
}
int main() {
test<<<1,1>>>();
cudaDeviceSynchronize();
return 0;
}
It's convenient if you provide a complete, compilable code, for others to work with, just as I have.
For your first EDIT question, it's not surprising that the second new will work if the first is deleted. The first allocates nearly all of the 8MB available. If you delete that allocation, then the second one will succeed. Referring to the documentation, we see that memory allocated dynamically in this fashion lives for the entire lifetime of the cuda context, or until a corresponding delete operation is performed (i.e. not just a single kernel call. The completion of the kernel does not necessarily free the allocation.)
For your second EDIT question, you are already demonstrating a method, using your __device__ double *temp; pointer, by which one thread can allocate storage which all threads can access. You will have a problem across blocks, however, because there is no guarantee of synchronization order amongst blocks or execution order amongst blocks, so if you allocate from thread 0 in block 0, that is only useful if block 0 executes before other blocks. You could come up with a complicated scheme to check if the variable allocation was already done (perhaps by testing the pointer for NULL, and also perhaps using atomics) but it creates fragile code. It's better to plan your global allocations ahead of time and allocate accordingly from the host.

linux libpcap programming

A same program can be run successfully on Opensuse 12.1 (x64)
While can't be run on Fedora 16 (x64)
on Fedora 16 , it displayed "Err calling pcap_compile"
I don't know what difference between these OS, I think they are quite same, But I make sure Opensuse 12.1 can filter and capture packet successfully.
int init_capture() {
int i;
char *dev;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* descr;
const u_char *packet;
struct pcap_pkthdr hdr; /* pcap.h */
struct ether_header *eptr; /* net/ethernet.h */
struct bpf_program fp;
char portfilter[20]= "dst port 1521";
bpf_u_int32 maskp;
bpf_u_int32 netp;
/* grab a device to peak into... */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
printf("%s\n", errbuf);
exit(1);
}
pcap_lookupnet(dev,&netp,&maskp,errbuf);
/* open device for reading */
descr = pcap_open_live(dev, BUFSIZ, 0, -1, errbuf);
if (descr == NULL) {
printf("pcap_open_live(): %s\n", errbuf);
exit(1);
}
if (pcap_compile(descr,&fp,portfilter,0,netp) == -1)
{
printf("Err calling pcap_compile\n");
exit(1);
}
if (pcap_setfilter(descr,&fp) == -1)
{
printf("Err setting filter \n");
exit(1);
}
/* allright here we call pcap_loop(..) and pass in our callback function */
/* int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)*/
/* If you are wondering what the user argument is all about, so am I!! */
pcap_loop(descr, -1, capture_callback, NULL);
fprintf(stdout, "\nDone processing packets... wheew!\n");
return 0;
}
If pcap_compile() fails, you should do
printf("Err calling pcap_compile: %s\n", pcap_geterr(descr));
and see what problem it's reporting. That might help us determine what's going wrong on Fedora; without knowing what the failure is, it's hard to determine what how to fix it - the filter is one that should work on any link-layer type that supports IP, and pcap_lookupdev() should always return such a device.
However, pcap_lookupnet() could conceivably fail if, for example, you're opening a device that has no IPv4 address assigned to it. If it fails, you should probably just pass 0 as both netp and maskp - you might just initialize them to 0 before calling pcap_lookupnet(). That shouldn't make a difference, however - the net and mask shouldn't be required for a filter such as dst port 1521.
(BTW, -1 is not a valid timeout argument to pcap_open_live() - I'd use 1000 instead - but that might be OK on Linux; the open would fail if it weren't valid, but the open isn't failing for you, as it's reporting an error in pcap_compile().)