summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Fries <David@Fries.net>2014-01-15 23:29:20 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-07 18:40:17 -0500
commit5dbf5671c73f23c2dd7082c0a14da4e7e902983a (patch)
treefc3de8720f299aa9795aa2123cb670a16dbcc13d
parentac8f73305eea8a12fdcb6090417eb93a74efbcbd (diff)
w1: reply only to the requester portid
Unicast one wire replies back to the sender portid to avoid multiple programs getting each other's messages, especially as the response can't be uniquely identified with the sequence coming from the requesting program when both programs generate the same id. Continue to broadcast events such as add/remove master/slave devices. Signed-off-by: David Fries <David@Fries.net> Acked-by: Evgeniy Polyakov <zbr@ioremap.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/w1/w1.h5
-rw-r--r--drivers/w1/w1_netlink.c42
2 files changed, 30 insertions, 17 deletions
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index a096ef40119e..390a7307fb41 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -210,6 +210,11 @@ struct w1_master
210 struct w1_bus_master *bus_master; 210 struct w1_bus_master *bus_master;
211 211
212 u32 seq; 212 u32 seq;
213 /* port id to send netlink responses to. The value is temporarily
214 * stored here while processing a message, set after locking the
215 * mutex, zero before unlocking the mutex.
216 */
217 u32 portid;
213}; 218};
214 219
215/** 220/**
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index b63109ada5a7..a5dc21934cf2 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -45,7 +45,7 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
45 45
46 memcpy(w, msg, sizeof(struct w1_netlink_msg)); 46 memcpy(w, msg, sizeof(struct w1_netlink_msg));
47 47
48 cn_netlink_send(m, 0, 0, GFP_KERNEL); 48 cn_netlink_send(m, dev->portid, 0, GFP_KERNEL);
49} 49}
50 50
51static void w1_send_slave(struct w1_master *dev, u64 rn) 51static void w1_send_slave(struct w1_master *dev, u64 rn)
@@ -60,7 +60,7 @@ static void w1_send_slave(struct w1_master *dev, u64 rn)
60 60
61 if (avail < 8) { 61 if (avail < 8) {
62 msg->ack++; 62 msg->ack++;
63 cn_netlink_send(msg, 0, 0, GFP_KERNEL); 63 cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL);
64 64
65 msg->len = sizeof(struct w1_netlink_msg) + 65 msg->len = sizeof(struct w1_netlink_msg) +
66 sizeof(struct w1_netlink_cmd); 66 sizeof(struct w1_netlink_cmd);
@@ -131,7 +131,7 @@ static int w1_get_slaves(struct w1_master *dev,
131 } 131 }
132 132
133 msg->ack = 0; 133 msg->ack = 0;
134 cn_netlink_send(msg, 0, 0, GFP_KERNEL); 134 cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL);
135 135
136 dev->priv = NULL; 136 dev->priv = NULL;
137 dev->priv_size = 0; 137 dev->priv_size = 0;
@@ -142,7 +142,7 @@ static int w1_get_slaves(struct w1_master *dev,
142} 142}
143 143
144static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr, 144static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr,
145 struct w1_netlink_cmd *cmd) 145 struct w1_netlink_cmd *cmd, u32 portid)
146{ 146{
147 void *data; 147 void *data;
148 struct w1_netlink_msg *h; 148 struct w1_netlink_msg *h;
@@ -173,7 +173,7 @@ static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr,
173 173
174 memcpy(c->data, cmd->data, c->len); 174 memcpy(c->data, cmd->data, c->len);
175 175
176 err = cn_netlink_send(cm, 0, 0, GFP_KERNEL); 176 err = cn_netlink_send(cm, portid, 0, GFP_KERNEL);
177 177
178 kfree(data); 178 kfree(data);
179 179
@@ -188,11 +188,11 @@ static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg,
188 switch (cmd->cmd) { 188 switch (cmd->cmd) {
189 case W1_CMD_TOUCH: 189 case W1_CMD_TOUCH:
190 w1_touch_block(dev, cmd->data, cmd->len); 190 w1_touch_block(dev, cmd->data, cmd->len);
191 w1_send_read_reply(msg, hdr, cmd); 191 w1_send_read_reply(msg, hdr, cmd, dev->portid);
192 break; 192 break;
193 case W1_CMD_READ: 193 case W1_CMD_READ:
194 w1_read_block(dev, cmd->data, cmd->len); 194 w1_read_block(dev, cmd->data, cmd->len);
195 w1_send_read_reply(msg, hdr, cmd); 195 w1_send_read_reply(msg, hdr, cmd, dev->portid);
196 break; 196 break;
197 case W1_CMD_WRITE: 197 case W1_CMD_WRITE:
198 w1_write_block(dev, cmd->data, cmd->len); 198 w1_write_block(dev, cmd->data, cmd->len);
@@ -283,7 +283,8 @@ static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
283 return w1_process_command_io(sl->master, msg, hdr, cmd); 283 return w1_process_command_io(sl->master, msg, hdr, cmd);
284} 284}
285 285
286static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd) 286static int w1_process_command_root(struct cn_msg *msg,
287 struct w1_netlink_msg *mcmd, u32 portid)
287{ 288{
288 struct w1_master *m; 289 struct w1_master *m;
289 struct cn_msg *cn; 290 struct cn_msg *cn;
@@ -316,7 +317,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
316 mutex_lock(&w1_mlock); 317 mutex_lock(&w1_mlock);
317 list_for_each_entry(m, &w1_masters, w1_master_entry) { 318 list_for_each_entry(m, &w1_masters, w1_master_entry) {
318 if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) { 319 if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) {
319 cn_netlink_send(cn, 0, 0, GFP_KERNEL); 320 cn_netlink_send(cn, portid, 0, GFP_KERNEL);
320 cn->ack++; 321 cn->ack++;
321 cn->len = sizeof(struct w1_netlink_msg); 322 cn->len = sizeof(struct w1_netlink_msg);
322 w->len = 0; 323 w->len = 0;
@@ -329,7 +330,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
329 id++; 330 id++;
330 } 331 }
331 cn->ack = 0; 332 cn->ack = 0;
332 cn_netlink_send(cn, 0, 0, GFP_KERNEL); 333 cn_netlink_send(cn, portid, 0, GFP_KERNEL);
333 mutex_unlock(&w1_mlock); 334 mutex_unlock(&w1_mlock);
334 335
335 kfree(cn); 336 kfree(cn);
@@ -337,7 +338,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
337} 338}
338 339
339static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg, 340static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg,
340 struct w1_netlink_cmd *rcmd, int error) 341 struct w1_netlink_cmd *rcmd, int portid, int error)
341{ 342{
342 struct cn_msg *cmsg; 343 struct cn_msg *cmsg;
343 struct w1_netlink_msg *msg; 344 struct w1_netlink_msg *msg;
@@ -364,7 +365,7 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
364 cmsg->len += sizeof(*cmd); 365 cmsg->len += sizeof(*cmd);
365 } 366 }
366 367
367 error = cn_netlink_send(cmsg, 0, 0, GFP_KERNEL); 368 error = cn_netlink_send(cmsg, portid, 0, GFP_KERNEL);
368 kfree(cmsg); 369 kfree(cmsg);
369 370
370 return error; 371 return error;
@@ -375,6 +376,7 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
375 */ 376 */
376struct w1_cb_block { 377struct w1_cb_block {
377 atomic_t refcnt; 378 atomic_t refcnt;
379 u32 portid; /* Sending process port ID */
378 struct cn_msg msg; 380 struct cn_msg msg;
379 /* cn_msg data */ 381 /* cn_msg data */
380 /* one or more variable length struct w1_cb_node */ 382 /* one or more variable length struct w1_cb_node */
@@ -399,6 +401,7 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
399 struct w1_netlink_cmd *cmd = NULL; 401 struct w1_netlink_cmd *cmd = NULL;
400 402
401 mutex_lock(&dev->mutex); 403 mutex_lock(&dev->mutex);
404 dev->portid = node->block->portid;
402 if (sl && w1_reset_select_slave(sl)) 405 if (sl && w1_reset_select_slave(sl))
403 err = -ENODEV; 406 err = -ENODEV;
404 407
@@ -417,7 +420,8 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
417 err = w1_process_command_master(dev, &node->block->msg, 420 err = w1_process_command_master(dev, &node->block->msg,
418 node->m, cmd); 421 node->m, cmd);
419 422
420 w1_netlink_send_error(&node->block->msg, node->m, cmd, err); 423 w1_netlink_send_error(&node->block->msg, node->m, cmd,
424 node->block->portid, err);
421 err = 0; 425 err = 0;
422 426
423 cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); 427 cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
@@ -425,12 +429,14 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
425 } 429 }
426 430
427 if (!cmd || err) 431 if (!cmd || err)
428 w1_netlink_send_error(&node->block->msg, node->m, cmd, err); 432 w1_netlink_send_error(&node->block->msg, node->m, cmd,
433 node->block->portid, err);
429 434
430 if (sl) 435 if (sl)
431 w1_unref_slave(sl); 436 w1_unref_slave(sl);
432 else 437 else
433 atomic_dec(&dev->refcnt); 438 atomic_dec(&dev->refcnt);
439 dev->portid = 0;
434 mutex_unlock(&dev->mutex); 440 mutex_unlock(&dev->mutex);
435 441
436 mutex_lock(&dev->list_mutex); 442 mutex_lock(&dev->list_mutex);
@@ -476,10 +482,12 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
476 node_count*sizeof(struct w1_cb_node); 482 node_count*sizeof(struct w1_cb_node);
477 block = kmalloc(size, GFP_KERNEL); 483 block = kmalloc(size, GFP_KERNEL);
478 if (!block) { 484 if (!block) {
479 w1_netlink_send_error(msg, m, NULL, -ENOMEM); 485 w1_netlink_send_error(msg, m, NULL, nsp->portid,
486 -ENOMEM);
480 return; 487 return;
481 } 488 }
482 atomic_set(&block->refcnt, 1); 489 atomic_set(&block->refcnt, 1);
490 block->portid = nsp->portid;
483 memcpy(&block->msg, msg, sizeof(*msg) + msg->len); 491 memcpy(&block->msg, msg, sizeof(*msg) + msg->len);
484 node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len); 492 node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len);
485 } 493 }
@@ -509,7 +517,7 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
509 if (sl) 517 if (sl)
510 dev = sl->master; 518 dev = sl->master;
511 } else { 519 } else {
512 err = w1_process_command_root(msg, m); 520 err = w1_process_command_root(msg, m, nsp->portid);
513 goto out_cont; 521 goto out_cont;
514 } 522 }
515 523
@@ -538,7 +546,7 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
538 546
539out_cont: 547out_cont:
540 if (err) 548 if (err)
541 w1_netlink_send_error(msg, m, NULL, err); 549 w1_netlink_send_error(msg, m, NULL, nsp->portid, err);
542 msg_len -= sizeof(struct w1_netlink_msg) + m->len; 550 msg_len -= sizeof(struct w1_netlink_msg) + m->len;
543 m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); 551 m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len);
544 552