diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/drivers/pcap_user.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/um/drivers/pcap_user.c')
-rw-r--r-- | arch/um/drivers/pcap_user.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c new file mode 100644 index 000000000000..edfcb29273e1 --- /dev/null +++ b/arch/um/drivers/pcap_user.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> | ||
3 | * Licensed under the GPL. | ||
4 | */ | ||
5 | |||
6 | #include <unistd.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <string.h> | ||
9 | #include <errno.h> | ||
10 | #include <pcap.h> | ||
11 | #include <asm/types.h> | ||
12 | #include "net_user.h" | ||
13 | #include "pcap_user.h" | ||
14 | #include "user.h" | ||
15 | |||
16 | #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) | ||
17 | |||
18 | #define PCAP_FD(p) (*(int *)(p)) | ||
19 | |||
20 | static void pcap_user_init(void *data, void *dev) | ||
21 | { | ||
22 | struct pcap_data *pri = data; | ||
23 | pcap_t *p; | ||
24 | char errors[PCAP_ERRBUF_SIZE]; | ||
25 | |||
26 | p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); | ||
27 | if(p == NULL){ | ||
28 | printk("pcap_user_init : pcap_open_live failed - '%s'\n", | ||
29 | errors); | ||
30 | return; | ||
31 | } | ||
32 | |||
33 | pri->dev = dev; | ||
34 | pri->pcap = p; | ||
35 | } | ||
36 | |||
37 | static int pcap_open(void *data) | ||
38 | { | ||
39 | struct pcap_data *pri = data; | ||
40 | __u32 netmask; | ||
41 | int err; | ||
42 | |||
43 | if(pri->pcap == NULL) | ||
44 | return(-ENODEV); | ||
45 | |||
46 | if(pri->filter != NULL){ | ||
47 | err = dev_netmask(pri->dev, &netmask); | ||
48 | if(err < 0){ | ||
49 | printk("pcap_open : dev_netmask failed\n"); | ||
50 | return(-EIO); | ||
51 | } | ||
52 | |||
53 | pri->compiled = um_kmalloc(sizeof(struct bpf_program)); | ||
54 | if(pri->compiled == NULL){ | ||
55 | printk("pcap_open : kmalloc failed\n"); | ||
56 | return(-ENOMEM); | ||
57 | } | ||
58 | |||
59 | err = pcap_compile(pri->pcap, | ||
60 | (struct bpf_program *) pri->compiled, | ||
61 | pri->filter, pri->optimize, netmask); | ||
62 | if(err < 0){ | ||
63 | printk("pcap_open : pcap_compile failed - '%s'\n", | ||
64 | pcap_geterr(pri->pcap)); | ||
65 | return(-EIO); | ||
66 | } | ||
67 | |||
68 | err = pcap_setfilter(pri->pcap, pri->compiled); | ||
69 | if(err < 0){ | ||
70 | printk("pcap_open : pcap_setfilter failed - '%s'\n", | ||
71 | pcap_geterr(pri->pcap)); | ||
72 | return(-EIO); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | return(PCAP_FD(pri->pcap)); | ||
77 | } | ||
78 | |||
79 | static void pcap_remove(void *data) | ||
80 | { | ||
81 | struct pcap_data *pri = data; | ||
82 | |||
83 | if(pri->compiled != NULL) | ||
84 | pcap_freecode(pri->compiled); | ||
85 | |||
86 | pcap_close(pri->pcap); | ||
87 | } | ||
88 | |||
89 | struct pcap_handler_data { | ||
90 | char *buffer; | ||
91 | int len; | ||
92 | }; | ||
93 | |||
94 | static void handler(u_char *data, const struct pcap_pkthdr *header, | ||
95 | const u_char *packet) | ||
96 | { | ||
97 | int len; | ||
98 | |||
99 | struct pcap_handler_data *hdata = (struct pcap_handler_data *) data; | ||
100 | |||
101 | len = hdata->len < header->caplen ? hdata->len : header->caplen; | ||
102 | memcpy(hdata->buffer, packet, len); | ||
103 | hdata->len = len; | ||
104 | } | ||
105 | |||
106 | int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) | ||
107 | { | ||
108 | struct pcap_handler_data hdata = ((struct pcap_handler_data) | ||
109 | { .buffer = buffer, | ||
110 | .len = len }); | ||
111 | int n; | ||
112 | |||
113 | n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); | ||
114 | if(n < 0){ | ||
115 | printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); | ||
116 | return(-EIO); | ||
117 | } | ||
118 | else if(n == 0) | ||
119 | return(0); | ||
120 | return(hdata.len); | ||
121 | } | ||
122 | |||
123 | struct net_user_info pcap_user_info = { | ||
124 | .init = pcap_user_init, | ||
125 | .open = pcap_open, | ||
126 | .close = NULL, | ||
127 | .remove = pcap_remove, | ||
128 | .set_mtu = NULL, | ||
129 | .add_address = NULL, | ||
130 | .delete_address = NULL, | ||
131 | .max_packet = MAX_PACKET - ETH_HEADER_OTHER | ||
132 | }; | ||
133 | |||
134 | /* | ||
135 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
136 | * Emacs will notice this stuff at the end of the file and automatically | ||
137 | * adjust the settings for this buffer only. This must remain at the end | ||
138 | * of the file. | ||
139 | * --------------------------------------------------------------------------- | ||
140 | * Local variables: | ||
141 | * c-file-style: "linux" | ||
142 | * End: | ||
143 | */ | ||