aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/af_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r--net/netlink/af_netlink.c80
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
1381nlmsg_failure: 1384errout_skb:
1382 return -ENOBUFS; 1385 spin_unlock(&nlk->cb_lock);
1386 kfree_skb(skb);
1387errout:
1388 return err;
1383} 1389}
1384 1390
1385int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, 1391int 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
1460static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, 1466static 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 */
1561int 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
1550struct nl_seq_iter { 1585struct 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
1730extern void netlink_skb_parms_too_large(void);
1731
1732static int __init netlink_proto_init(void) 1765static 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);
1799EXPORT_SYMBOL(netlink_set_nonroot); 1831EXPORT_SYMBOL(netlink_set_nonroot);
1800EXPORT_SYMBOL(netlink_unicast); 1832EXPORT_SYMBOL(netlink_unicast);
1801EXPORT_SYMBOL(netlink_unregister_notifier); 1833EXPORT_SYMBOL(netlink_unregister_notifier);
1802 1834EXPORT_SYMBOL(nlmsg_notify);