diff options
author | Daniel Seither <post@tiwoc.de> | 2010-06-21 19:25:54 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-06-22 17:05:06 -0400 |
commit | e4cb3720bfcf8b57b4c5a2adbbb6b5967af53432 (patch) | |
tree | 491b8589349073bad72aa1d2dddce33d82b33977 /drivers/staging/batman-adv/icmp_socket.c | |
parent | 11f79decfd4e33e29694075a859f529e6d4321ad (diff) |
Staging: batman-adv: record route for ICMP messages
The standard layer 3 ping utility can use the record route (RR) option
of IP to collect route data for sent ping messages (ping -R). This
patch introduces comparable functionality for batman-adv ICMP messages.
The patch adds a second batman ICMP packet format (icmp_packet_rr) such
that up to 17 MAC addresses can be recorded (sufficient for up to 8
hops per direction). When no RR is wanted, the old icmp_packet without
the RR overhead can be sent.
Signed-off-by: Daniel Seither <post@tiwoc.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
[sven.eckelmann@gmx.de: Rework on top of current version]
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/batman-adv/icmp_socket.c')
-rw-r--r-- | drivers/staging/batman-adv/icmp_socket.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c index d4411cbe350..08a5f7b7b11 100644 --- a/drivers/staging/batman-adv/icmp_socket.c +++ b/drivers/staging/batman-adv/icmp_socket.c | |||
@@ -32,7 +32,8 @@ | |||
32 | static struct socket_client *socket_client_hash[256]; | 32 | static struct socket_client *socket_client_hash[256]; |
33 | 33 | ||
34 | static void bat_socket_add_packet(struct socket_client *socket_client, | 34 | static void bat_socket_add_packet(struct socket_client *socket_client, |
35 | struct icmp_packet *icmp_packet); | 35 | struct icmp_packet_rr *icmp_packet, |
36 | size_t icmp_len); | ||
36 | 37 | ||
37 | void bat_socket_init(void) | 38 | void bat_socket_init(void) |
38 | { | 39 | { |
@@ -110,6 +111,7 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf, | |||
110 | struct socket_client *socket_client = | 111 | struct socket_client *socket_client = |
111 | (struct socket_client *)file->private_data; | 112 | (struct socket_client *)file->private_data; |
112 | struct socket_packet *socket_packet; | 113 | struct socket_packet *socket_packet; |
114 | size_t packet_len; | ||
113 | int error; | 115 | int error; |
114 | unsigned long flags; | 116 | unsigned long flags; |
115 | 117 | ||
@@ -138,14 +140,15 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf, | |||
138 | spin_unlock_irqrestore(&socket_client->lock, flags); | 140 | spin_unlock_irqrestore(&socket_client->lock, flags); |
139 | 141 | ||
140 | error = __copy_to_user(buf, &socket_packet->icmp_packet, | 142 | error = __copy_to_user(buf, &socket_packet->icmp_packet, |
141 | sizeof(struct icmp_packet)); | 143 | socket_packet->icmp_len); |
142 | 144 | ||
145 | packet_len = socket_packet->icmp_len; | ||
143 | kfree(socket_packet); | 146 | kfree(socket_packet); |
144 | 147 | ||
145 | if (error) | 148 | if (error) |
146 | return -EFAULT; | 149 | return -EFAULT; |
147 | 150 | ||
148 | return sizeof(struct icmp_packet); | 151 | return packet_len; |
149 | } | 152 | } |
150 | 153 | ||
151 | static ssize_t bat_socket_write(struct file *file, const char __user *buff, | 154 | static ssize_t bat_socket_write(struct file *file, const char __user *buff, |
@@ -153,9 +156,10 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
153 | { | 156 | { |
154 | struct socket_client *socket_client = | 157 | struct socket_client *socket_client = |
155 | (struct socket_client *)file->private_data; | 158 | (struct socket_client *)file->private_data; |
156 | struct icmp_packet icmp_packet; | 159 | struct icmp_packet_rr icmp_packet; |
157 | struct orig_node *orig_node; | 160 | struct orig_node *orig_node; |
158 | struct batman_if *batman_if; | 161 | struct batman_if *batman_if; |
162 | size_t packet_len = sizeof(struct icmp_packet); | ||
159 | uint8_t dstaddr[ETH_ALEN]; | 163 | uint8_t dstaddr[ETH_ALEN]; |
160 | unsigned long flags; | 164 | unsigned long flags; |
161 | 165 | ||
@@ -166,10 +170,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
166 | return -EINVAL; | 170 | return -EINVAL; |
167 | } | 171 | } |
168 | 172 | ||
169 | if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet))) | 173 | if (len >= sizeof(struct icmp_packet_rr)) |
174 | packet_len = sizeof(struct icmp_packet_rr); | ||
175 | |||
176 | if (!access_ok(VERIFY_READ, buff, packet_len)) | ||
170 | return -EFAULT; | 177 | return -EFAULT; |
171 | 178 | ||
172 | if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet))) | 179 | if (__copy_from_user(&icmp_packet, buff, packet_len)) |
173 | return -EFAULT; | 180 | return -EFAULT; |
174 | 181 | ||
175 | if (icmp_packet.packet_type != BAT_ICMP) { | 182 | if (icmp_packet.packet_type != BAT_ICMP) { |
@@ -191,7 +198,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
191 | if (icmp_packet.version != COMPAT_VERSION) { | 198 | if (icmp_packet.version != COMPAT_VERSION) { |
192 | icmp_packet.msg_type = PARAMETER_PROBLEM; | 199 | icmp_packet.msg_type = PARAMETER_PROBLEM; |
193 | icmp_packet.ttl = COMPAT_VERSION; | 200 | icmp_packet.ttl = COMPAT_VERSION; |
194 | bat_socket_add_packet(socket_client, &icmp_packet); | 201 | bat_socket_add_packet(socket_client, &icmp_packet, packet_len); |
195 | goto out; | 202 | goto out; |
196 | } | 203 | } |
197 | 204 | ||
@@ -218,13 +225,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
218 | if (batman_if->if_status != IF_ACTIVE) | 225 | if (batman_if->if_status != IF_ACTIVE) |
219 | goto dst_unreach; | 226 | goto dst_unreach; |
220 | 227 | ||
221 | memcpy(icmp_packet.orig, | 228 | memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN); |
222 | batman_if->net_dev->dev_addr, | 229 | |
223 | ETH_ALEN); | 230 | if (packet_len == sizeof(struct icmp_packet_rr)) |
231 | memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); | ||
224 | 232 | ||
225 | send_raw_packet((unsigned char *)&icmp_packet, | 233 | send_raw_packet((unsigned char *)&icmp_packet, |
226 | sizeof(struct icmp_packet), | 234 | packet_len, batman_if, dstaddr); |
227 | batman_if, dstaddr); | ||
228 | 235 | ||
229 | goto out; | 236 | goto out; |
230 | 237 | ||
@@ -232,7 +239,7 @@ unlock: | |||
232 | spin_unlock_irqrestore(&orig_hash_lock, flags); | 239 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
233 | dst_unreach: | 240 | dst_unreach: |
234 | icmp_packet.msg_type = DESTINATION_UNREACHABLE; | 241 | icmp_packet.msg_type = DESTINATION_UNREACHABLE; |
235 | bat_socket_add_packet(socket_client, &icmp_packet); | 242 | bat_socket_add_packet(socket_client, &icmp_packet, packet_len); |
236 | out: | 243 | out: |
237 | return len; | 244 | return len; |
238 | } | 245 | } |
@@ -278,7 +285,8 @@ err: | |||
278 | } | 285 | } |
279 | 286 | ||
280 | static void bat_socket_add_packet(struct socket_client *socket_client, | 287 | static void bat_socket_add_packet(struct socket_client *socket_client, |
281 | struct icmp_packet *icmp_packet) | 288 | struct icmp_packet_rr *icmp_packet, |
289 | size_t icmp_len) | ||
282 | { | 290 | { |
283 | struct socket_packet *socket_packet; | 291 | struct socket_packet *socket_packet; |
284 | unsigned long flags; | 292 | unsigned long flags; |
@@ -289,8 +297,8 @@ static void bat_socket_add_packet(struct socket_client *socket_client, | |||
289 | return; | 297 | return; |
290 | 298 | ||
291 | INIT_LIST_HEAD(&socket_packet->list); | 299 | INIT_LIST_HEAD(&socket_packet->list); |
292 | memcpy(&socket_packet->icmp_packet, icmp_packet, | 300 | memcpy(&socket_packet->icmp_packet, icmp_packet, icmp_len); |
293 | sizeof(struct icmp_packet)); | 301 | socket_packet->icmp_len = icmp_len; |
294 | 302 | ||
295 | spin_lock_irqsave(&socket_client->lock, flags); | 303 | spin_lock_irqsave(&socket_client->lock, flags); |
296 | 304 | ||
@@ -319,10 +327,11 @@ static void bat_socket_add_packet(struct socket_client *socket_client, | |||
319 | wake_up(&socket_client->queue_wait); | 327 | wake_up(&socket_client->queue_wait); |
320 | } | 328 | } |
321 | 329 | ||
322 | void bat_socket_receive_packet(struct icmp_packet *icmp_packet) | 330 | void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet, |
331 | size_t icmp_len) | ||
323 | { | 332 | { |
324 | struct socket_client *hash = socket_client_hash[icmp_packet->uid]; | 333 | struct socket_client *hash = socket_client_hash[icmp_packet->uid]; |
325 | 334 | ||
326 | if (hash) | 335 | if (hash) |
327 | bat_socket_add_packet(hash, icmp_packet); | 336 | bat_socket_add_packet(hash, icmp_packet, icmp_len); |
328 | } | 337 | } |