2005-04-16 15:20:36 -07:00
/*
* Copyright ( C ) 2002 Jeff Dike < jdike @ karaya . com >
* Licensed under the GPL .
*/
# include <unistd.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>
# include <pcap.h>
# include <asm/types.h>
# include "net_user.h"
# include "pcap_user.h"
# include "user.h"
2006-10-19 23:28:20 -07:00
# include "um_malloc.h"
2005-04-16 15:20:36 -07:00
# define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
# define PCAP_FD(p) (*(int *)(p))
static void pcap_user_init ( void * data , void * dev )
{
struct pcap_data * pri = data ;
pcap_t * p ;
char errors [ PCAP_ERRBUF_SIZE ] ;
p = pcap_open_live ( pri - > host_if , MAX_PACKET , pri - > promisc , 0 , errors ) ;
if ( p = = NULL ) {
printk ( " pcap_user_init : pcap_open_live failed - '%s' \n " ,
errors ) ;
return ;
}
pri - > dev = dev ;
pri - > pcap = p ;
}
static int pcap_open ( void * data )
{
struct pcap_data * pri = data ;
__u32 netmask ;
int err ;
if ( pri - > pcap = = NULL )
2007-05-06 14:51:02 -07:00
return - ENODEV ;
2005-04-16 15:20:36 -07:00
if ( pri - > filter ! = NULL ) {
err = dev_netmask ( pri - > dev , & netmask ) ;
if ( err < 0 ) {
printk ( " pcap_open : dev_netmask failed \n " ) ;
2007-05-06 14:51:02 -07:00
return - EIO ;
2005-04-16 15:20:36 -07:00
}
pri - > compiled = um_kmalloc ( sizeof ( struct bpf_program ) ) ;
if ( pri - > compiled = = NULL ) {
printk ( " pcap_open : kmalloc failed \n " ) ;
2007-05-06 14:51:02 -07:00
return - ENOMEM ;
2005-04-16 15:20:36 -07:00
}
2007-05-06 14:51:02 -07:00
2005-04-16 15:20:36 -07:00
err = pcap_compile ( pri - > pcap ,
( struct bpf_program * ) pri - > compiled ,
pri - > filter , pri - > optimize , netmask ) ;
if ( err < 0 ) {
printk ( " pcap_open : pcap_compile failed - '%s' \n " ,
pcap_geterr ( pri - > pcap ) ) ;
2007-05-06 14:51:02 -07:00
return - EIO ;
2005-04-16 15:20:36 -07:00
}
err = pcap_setfilter ( pri - > pcap , pri - > compiled ) ;
if ( err < 0 ) {
printk ( " pcap_open : pcap_setfilter failed - '%s' \n " ,
pcap_geterr ( pri - > pcap ) ) ;
2007-05-06 14:51:02 -07:00
return - EIO ;
2005-04-16 15:20:36 -07:00
}
}
2007-05-06 14:51:02 -07:00
return PCAP_FD ( pri - > pcap ) ;
2005-04-16 15:20:36 -07:00
}
static void pcap_remove ( void * data )
{
struct pcap_data * pri = data ;
if ( pri - > compiled ! = NULL )
pcap_freecode ( pri - > compiled ) ;
pcap_close ( pri - > pcap ) ;
}
struct pcap_handler_data {
char * buffer ;
int len ;
} ;
static void handler ( u_char * data , const struct pcap_pkthdr * header ,
const u_char * packet )
{
int len ;
struct pcap_handler_data * hdata = ( struct pcap_handler_data * ) data ;
len = hdata - > len < header - > caplen ? hdata - > len : header - > caplen ;
memcpy ( hdata - > buffer , packet , len ) ;
hdata - > len = len ;
}
int pcap_user_read ( int fd , void * buffer , int len , struct pcap_data * pri )
{
struct pcap_handler_data hdata = ( ( struct pcap_handler_data )
{ . buffer = buffer ,
. len = len } ) ;
int n ;
n = pcap_dispatch ( pri - > pcap , 1 , handler , ( u_char * ) & hdata ) ;
if ( n < 0 ) {
printk ( " pcap_dispatch failed - %s \n " , pcap_geterr ( pri - > pcap ) ) ;
2007-05-06 14:51:02 -07:00
return - EIO ;
2005-04-16 15:20:36 -07:00
}
else if ( n = = 0 )
2007-05-06 14:51:02 -07:00
return 0 ;
return hdata . len ;
2005-04-16 15:20:36 -07:00
}
2006-09-27 01:50:33 -07:00
const struct net_user_info pcap_user_info = {
2005-04-16 15:20:36 -07:00
. init = pcap_user_init ,
. open = pcap_open ,
. close = NULL ,
. remove = pcap_remove ,
. set_mtu = NULL ,
. add_address = NULL ,
. delete_address = NULL ,
. max_packet = MAX_PACKET - ETH_HEADER_OTHER
} ;