diff options
author | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 22:03:52 -0400 |
---|---|---|
committer | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 22:03:52 -0400 |
commit | 1aedf2ccc60fade26c46fae12e28664d0da3f199 (patch) | |
tree | d91083e3079f1ddb942a382ac2b5a7525570ad59 /net/netlink/af_netlink.c | |
parent | dfdc58ba354adb80d67c99f7be84f95a8e02e466 (diff) | |
parent | 1ab9dd0902df4f4ff56fbf672220549090ab28ba (diff) |
Merge mulgrave-w:git/linux-2.6
Conflicts:
include/linux/blkdev.h
Trivial merge to incorporate tag prototypes.
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r-- | net/netlink/af_netlink.c | 80 |
1 files changed, 56 insertions, 24 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 8b85036ba8e3..d56e0d21f919 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1147,7 +1147,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1147 | if (len > sk->sk_sndbuf - 32) | 1147 | if (len > sk->sk_sndbuf - 32) |
1148 | goto out; | 1148 | goto out; |
1149 | err = -ENOBUFS; | 1149 | err = -ENOBUFS; |
1150 | skb = alloc_skb(len, GFP_KERNEL); | 1150 | skb = nlmsg_new(len, GFP_KERNEL); |
1151 | if (skb==NULL) | 1151 | if (skb==NULL) |
1152 | goto out; | 1152 | goto out; |
1153 | 1153 | ||
@@ -1341,19 +1341,18 @@ static int netlink_dump(struct sock *sk) | |||
1341 | struct netlink_callback *cb; | 1341 | struct netlink_callback *cb; |
1342 | struct sk_buff *skb; | 1342 | struct sk_buff *skb; |
1343 | struct nlmsghdr *nlh; | 1343 | struct nlmsghdr *nlh; |
1344 | int len; | 1344 | int len, err = -ENOBUFS; |
1345 | 1345 | ||
1346 | skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL); | 1346 | skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL); |
1347 | if (!skb) | 1347 | if (!skb) |
1348 | return -ENOBUFS; | 1348 | goto errout; |
1349 | 1349 | ||
1350 | spin_lock(&nlk->cb_lock); | 1350 | spin_lock(&nlk->cb_lock); |
1351 | 1351 | ||
1352 | cb = nlk->cb; | 1352 | cb = nlk->cb; |
1353 | if (cb == NULL) { | 1353 | if (cb == NULL) { |
1354 | spin_unlock(&nlk->cb_lock); | 1354 | err = -EINVAL; |
1355 | kfree_skb(skb); | 1355 | goto errout_skb; |
1356 | return -EINVAL; | ||
1357 | } | 1356 | } |
1358 | 1357 | ||
1359 | len = cb->dump(skb, cb); | 1358 | len = cb->dump(skb, cb); |
@@ -1365,8 +1364,12 @@ static int netlink_dump(struct sock *sk) | |||
1365 | return 0; | 1364 | return 0; |
1366 | } | 1365 | } |
1367 | 1366 | ||
1368 | nlh = NLMSG_NEW_ANSWER(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI); | 1367 | nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI); |
1369 | memcpy(NLMSG_DATA(nlh), &len, sizeof(len)); | 1368 | if (!nlh) |
1369 | goto errout_skb; | ||
1370 | |||
1371 | memcpy(nlmsg_data(nlh), &len, sizeof(len)); | ||
1372 | |||
1370 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1373 | skb_queue_tail(&sk->sk_receive_queue, skb); |
1371 | sk->sk_data_ready(sk, skb->len); | 1374 | sk->sk_data_ready(sk, skb->len); |
1372 | 1375 | ||
@@ -1378,8 +1381,11 @@ static int netlink_dump(struct sock *sk) | |||
1378 | netlink_destroy_callback(cb); | 1381 | netlink_destroy_callback(cb); |
1379 | return 0; | 1382 | return 0; |
1380 | 1383 | ||
1381 | nlmsg_failure: | 1384 | errout_skb: |
1382 | return -ENOBUFS; | 1385 | spin_unlock(&nlk->cb_lock); |
1386 | kfree_skb(skb); | ||
1387 | errout: | ||
1388 | return err; | ||
1383 | } | 1389 | } |
1384 | 1390 | ||
1385 | int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | 1391 | int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, |
@@ -1431,11 +1437,11 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | |||
1431 | int size; | 1437 | int size; |
1432 | 1438 | ||
1433 | if (err == 0) | 1439 | if (err == 0) |
1434 | size = NLMSG_SPACE(sizeof(struct nlmsgerr)); | 1440 | size = nlmsg_total_size(sizeof(*errmsg)); |
1435 | else | 1441 | else |
1436 | size = NLMSG_SPACE(4 + NLMSG_ALIGN(nlh->nlmsg_len)); | 1442 | size = nlmsg_total_size(sizeof(*errmsg) + nlmsg_len(nlh)); |
1437 | 1443 | ||
1438 | skb = alloc_skb(size, GFP_KERNEL); | 1444 | skb = nlmsg_new(size, GFP_KERNEL); |
1439 | if (!skb) { | 1445 | if (!skb) { |
1440 | struct sock *sk; | 1446 | struct sock *sk; |
1441 | 1447 | ||
@@ -1451,16 +1457,15 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) | |||
1451 | 1457 | ||
1452 | rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, | 1458 | rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, |
1453 | NLMSG_ERROR, sizeof(struct nlmsgerr), 0); | 1459 | NLMSG_ERROR, sizeof(struct nlmsgerr), 0); |
1454 | errmsg = NLMSG_DATA(rep); | 1460 | errmsg = nlmsg_data(rep); |
1455 | errmsg->error = err; | 1461 | errmsg->error = err; |
1456 | memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr)); | 1462 | memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh)); |
1457 | netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); | 1463 | netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); |
1458 | } | 1464 | } |
1459 | 1465 | ||
1460 | static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | 1466 | static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, |
1461 | struct nlmsghdr *, int *)) | 1467 | struct nlmsghdr *, int *)) |
1462 | { | 1468 | { |
1463 | unsigned int total_len; | ||
1464 | struct nlmsghdr *nlh; | 1469 | struct nlmsghdr *nlh; |
1465 | int err; | 1470 | int err; |
1466 | 1471 | ||
@@ -1470,8 +1475,6 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | |||
1470 | if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len) | 1475 | if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len) |
1471 | return 0; | 1476 | return 0; |
1472 | 1477 | ||
1473 | total_len = min(NLMSG_ALIGN(nlh->nlmsg_len), skb->len); | ||
1474 | |||
1475 | if (cb(skb, nlh, &err) < 0) { | 1478 | if (cb(skb, nlh, &err) < 0) { |
1476 | /* Not an error, but we have to interrupt processing | 1479 | /* Not an error, but we have to interrupt processing |
1477 | * here. Note: that in this case we do not pull | 1480 | * here. Note: that in this case we do not pull |
@@ -1483,7 +1486,7 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, | |||
1483 | } else if (nlh->nlmsg_flags & NLM_F_ACK) | 1486 | } else if (nlh->nlmsg_flags & NLM_F_ACK) |
1484 | netlink_ack(skb, nlh, 0); | 1487 | netlink_ack(skb, nlh, 0); |
1485 | 1488 | ||
1486 | skb_pull(skb, total_len); | 1489 | netlink_queue_skip(nlh, skb); |
1487 | } | 1490 | } |
1488 | 1491 | ||
1489 | return 0; | 1492 | return 0; |
@@ -1546,6 +1549,38 @@ void netlink_queue_skip(struct nlmsghdr *nlh, struct sk_buff *skb) | |||
1546 | skb_pull(skb, msglen); | 1549 | skb_pull(skb, msglen); |
1547 | } | 1550 | } |
1548 | 1551 | ||
1552 | /** | ||
1553 | * nlmsg_notify - send a notification netlink message | ||
1554 | * @sk: netlink socket to use | ||
1555 | * @skb: notification message | ||
1556 | * @pid: destination netlink pid for reports or 0 | ||
1557 | * @group: destination multicast group or 0 | ||
1558 | * @report: 1 to report back, 0 to disable | ||
1559 | * @flags: allocation flags | ||
1560 | */ | ||
1561 | int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid, | ||
1562 | unsigned int group, int report, gfp_t flags) | ||
1563 | { | ||
1564 | int err = 0; | ||
1565 | |||
1566 | if (group) { | ||
1567 | int exclude_pid = 0; | ||
1568 | |||
1569 | if (report) { | ||
1570 | atomic_inc(&skb->users); | ||
1571 | exclude_pid = pid; | ||
1572 | } | ||
1573 | |||
1574 | /* errors reported via destination sk->sk_err */ | ||
1575 | nlmsg_multicast(sk, skb, exclude_pid, group, flags); | ||
1576 | } | ||
1577 | |||
1578 | if (report) | ||
1579 | err = nlmsg_unicast(sk, skb, pid); | ||
1580 | |||
1581 | return err; | ||
1582 | } | ||
1583 | |||
1549 | #ifdef CONFIG_PROC_FS | 1584 | #ifdef CONFIG_PROC_FS |
1550 | struct nl_seq_iter { | 1585 | struct nl_seq_iter { |
1551 | int link; | 1586 | int link; |
@@ -1727,8 +1762,6 @@ static struct net_proto_family netlink_family_ops = { | |||
1727 | .owner = THIS_MODULE, /* for consistency 8) */ | 1762 | .owner = THIS_MODULE, /* for consistency 8) */ |
1728 | }; | 1763 | }; |
1729 | 1764 | ||
1730 | extern void netlink_skb_parms_too_large(void); | ||
1731 | |||
1732 | static int __init netlink_proto_init(void) | 1765 | static int __init netlink_proto_init(void) |
1733 | { | 1766 | { |
1734 | struct sk_buff *dummy_skb; | 1767 | struct sk_buff *dummy_skb; |
@@ -1740,8 +1773,7 @@ static int __init netlink_proto_init(void) | |||
1740 | if (err != 0) | 1773 | if (err != 0) |
1741 | goto out; | 1774 | goto out; |
1742 | 1775 | ||
1743 | if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)) | 1776 | BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)); |
1744 | netlink_skb_parms_too_large(); | ||
1745 | 1777 | ||
1746 | nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL); | 1778 | nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL); |
1747 | if (!nl_table) | 1779 | if (!nl_table) |
@@ -1799,4 +1831,4 @@ EXPORT_SYMBOL(netlink_set_err); | |||
1799 | EXPORT_SYMBOL(netlink_set_nonroot); | 1831 | EXPORT_SYMBOL(netlink_set_nonroot); |
1800 | EXPORT_SYMBOL(netlink_unicast); | 1832 | EXPORT_SYMBOL(netlink_unicast); |
1801 | EXPORT_SYMBOL(netlink_unregister_notifier); | 1833 | EXPORT_SYMBOL(netlink_unregister_notifier); |
1802 | 1834 | EXPORT_SYMBOL(nlmsg_notify); | |