aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/batman-adv/icmp_socket.c
diff options
context:
space:
mode:
authorDaniel Seither <post@tiwoc.de>2010-06-21 19:25:54 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-06-22 17:05:06 -0400
commite4cb3720bfcf8b57b4c5a2adbbb6b5967af53432 (patch)
tree491b8589349073bad72aa1d2dddce33d82b33977 /drivers/staging/batman-adv/icmp_socket.c
parent11f79decfd4e33e29694075a859f529e6d4321ad (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.c45
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 @@
32static struct socket_client *socket_client_hash[256]; 32static struct socket_client *socket_client_hash[256];
33 33
34static void bat_socket_add_packet(struct socket_client *socket_client, 34static 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
37void bat_socket_init(void) 38void 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
151static ssize_t bat_socket_write(struct file *file, const char __user *buff, 154static 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);
233dst_unreach: 240dst_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);
236out: 243out:
237 return len; 244 return len;
238} 245}
@@ -278,7 +285,8 @@ err:
278} 285}
279 286
280static void bat_socket_add_packet(struct socket_client *socket_client, 287static 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
322void bat_socket_receive_packet(struct icmp_packet *icmp_packet) 330void 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}