7d98230a73
Some network device cleanup. When setup_etheraddr found a globally valid MAC being assigned to an interface, it went ahead and used it rather than assigning a random MAC like the other cases do. This isn't really an error like the others, but it seems consistent to make it behave the same. We were getting some duplicate kfree() in the error case in eth_configure because platform_device_unregister frees buffers that the error cases following tried to free again. The pcap initialization routine wasn't doing the proper printk of its information, causing a printk of the first part of that line to be unterminated by a newline. The pcap code had a bunch of style violations, which are now fixed. pcap_setup wasn't returning false when it detected an unrecognized option. The printks in pcap_user all got UM_KERN_BLAH prepended to their format strings. pcap_remove now checks for a non-NULL pcap structure before it calls pcap_close. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Acked-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
138 lines
2.9 KiB
C
138 lines
2.9 KiB
C
/*
|
|
* 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"
|
|
#include "um_malloc.h"
|
|
#include "kern_constants.h"
|
|
|
|
#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
|
|
|
|
#define PCAP_FD(p) (*(int *)(p))
|
|
|
|
static int 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(UM_KERN_ERR "pcap_user_init : pcap_open_live failed - "
|
|
"'%s'\n", errors);
|
|
return -EINVAL;
|
|
}
|
|
|
|
pri->dev = dev;
|
|
pri->pcap = p;
|
|
return 0;
|
|
}
|
|
|
|
static int pcap_open(void *data)
|
|
{
|
|
struct pcap_data *pri = data;
|
|
__u32 netmask;
|
|
int err;
|
|
|
|
if(pri->pcap == NULL)
|
|
return -ENODEV;
|
|
|
|
if(pri->filter != NULL){
|
|
err = dev_netmask(pri->dev, &netmask);
|
|
if(err < 0){
|
|
printk(UM_KERN_ERR "pcap_open : dev_netmask failed\n");
|
|
return -EIO;
|
|
}
|
|
|
|
pri->compiled = um_kmalloc(sizeof(struct bpf_program));
|
|
if(pri->compiled == NULL){
|
|
printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
err = pcap_compile(pri->pcap,
|
|
(struct bpf_program *) pri->compiled,
|
|
pri->filter, pri->optimize, netmask);
|
|
if(err < 0){
|
|
printk(UM_KERN_ERR "pcap_open : pcap_compile failed - "
|
|
"'%s'\n", pcap_geterr(pri->pcap));
|
|
return -EIO;
|
|
}
|
|
|
|
err = pcap_setfilter(pri->pcap, pri->compiled);
|
|
if(err < 0){
|
|
printk(UM_KERN_ERR "pcap_open : pcap_setfilter "
|
|
"failed - '%s'\n", pcap_geterr(pri->pcap));
|
|
return -EIO;
|
|
}
|
|
}
|
|
|
|
return PCAP_FD(pri->pcap);
|
|
}
|
|
|
|
static void pcap_remove(void *data)
|
|
{
|
|
struct pcap_data *pri = data;
|
|
|
|
if(pri->compiled != NULL)
|
|
pcap_freecode(pri->compiled);
|
|
|
|
if(pri->pcap != NULL)
|
|
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(UM_KERN_ERR "pcap_dispatch failed - %s\n",
|
|
pcap_geterr(pri->pcap));
|
|
return -EIO;
|
|
}
|
|
else if(n == 0)
|
|
return 0;
|
|
return hdata.len;
|
|
}
|
|
|
|
const struct net_user_info pcap_user_info = {
|
|
.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
|
|
};
|