]> err.no Git - linux-2.6/blobdiff - net/ipv4/inet_diag.c
[MAC80211]: remove turbo modes
[linux-2.6] / net / ipv4 / inet_diag.c
index 62c2e9f7e11f689aa225337c009251ecf6eb349a..031cc4856b49bed9da51060bb01bc4c01d6edd81 100644 (file)
@@ -11,6 +11,7 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
@@ -112,7 +113,7 @@ static int inet_csk_diag_fill(struct sock *sk,
        }
 #endif
 
-#define EXPIRES_IN_MS(tmo)  ((tmo - jiffies) * 1000 + HZ - 1) / HZ
+#define EXPIRES_IN_MS(tmo)  DIV_ROUND_UP((tmo - jiffies) * 1000, HZ)
 
        if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
                r->idiag_timer = 1;
@@ -190,7 +191,7 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
        r->id.idiag_dst[0]    = tw->tw_daddr;
        r->idiag_state        = tw->tw_substate;
        r->idiag_timer        = 3;
-       r->idiag_expires      = (tmo * 1000 + HZ - 1) / HZ;
+       r->idiag_expires      = DIV_ROUND_UP(tmo * 1000, HZ);
        r->idiag_rqueue       = 0;
        r->idiag_wqueue       = 0;
        r->idiag_uid          = 0;
@@ -806,68 +807,47 @@ done:
        return skb->len;
 }
 
-static inline int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
-       if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
-               return 0;
+       int hdrlen = sizeof(struct inet_diag_req);
 
-       if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX)
-               goto err_inval;
+       if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX ||
+           nlmsg_len(nlh) < hdrlen)
+               return -EINVAL;
 
        if (inet_diag_table[nlh->nlmsg_type] == NULL)
                return -ENOENT;
 
-       if (NLMSG_LENGTH(sizeof(struct inet_diag_req)) > skb->len)
-               goto err_inval;
-
-       if (nlh->nlmsg_flags&NLM_F_DUMP) {
-               if (nlh->nlmsg_len >
-                   (4 + NLMSG_SPACE(sizeof(struct inet_diag_req)))) {
-                       struct rtattr *rta = (void *)(NLMSG_DATA(nlh) +
-                                                sizeof(struct inet_diag_req));
-                       if (rta->rta_type != INET_DIAG_REQ_BYTECODE ||
-                           rta->rta_len < 8 ||
-                           rta->rta_len >
-                           (nlh->nlmsg_len -
-                            NLMSG_SPACE(sizeof(struct inet_diag_req))))
-                               goto err_inval;
-                       if (inet_diag_bc_audit(RTA_DATA(rta), RTA_PAYLOAD(rta)))
-                               goto err_inval;
+       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+               if (nlmsg_attrlen(nlh, hdrlen)) {
+                       struct nlattr *attr;
+
+                       attr = nlmsg_find_attr(nlh, hdrlen,
+                                              INET_DIAG_REQ_BYTECODE);
+                       if (attr == NULL ||
+                           nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
+                           inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
+                               return -EINVAL;
                }
+
                return netlink_dump_start(idiagnl, skb, nlh,
                                          inet_diag_dump, NULL);
-       } else
-               return inet_diag_get_exact(skb, nlh);
+       }
 
-err_inval:
-       return -EINVAL;
+       return inet_diag_get_exact(skb, nlh);
 }
 
-
-static inline void inet_diag_rcv_skb(struct sk_buff *skb)
-{
-       if (skb->len >= NLMSG_SPACE(0)) {
-               int err;
-               struct nlmsghdr *nlh = nlmsg_hdr(skb);
-
-               if (nlh->nlmsg_len < sizeof(*nlh) ||
-                   skb->len < nlh->nlmsg_len)
-                       return;
-               err = inet_diag_rcv_msg(skb, nlh);
-               if (err || nlh->nlmsg_flags & NLM_F_ACK)
-                       netlink_ack(skb, nlh, err);
-       }
-}
+static DEFINE_MUTEX(inet_diag_mutex);
 
 static void inet_diag_rcv(struct sock *sk, int len)
 {
-       struct sk_buff *skb;
-       unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
+       unsigned int qlen = 0;
 
-       while (qlen-- && (skb = skb_dequeue(&sk->sk_receive_queue))) {
-               inet_diag_rcv_skb(skb);
-               kfree_skb(skb);
-       }
+       do {
+               mutex_lock(&inet_diag_mutex);
+               netlink_run_queue(sk, &qlen, &inet_diag_rcv_msg);
+               mutex_unlock(&inet_diag_mutex);
+       } while (qlen);
 }
 
 static DEFINE_SPINLOCK(inet_diag_register_lock);
@@ -917,8 +897,8 @@ static int __init inet_diag_init(void)
        if (!inet_diag_table)
                goto out;
 
-       idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, 0, inet_diag_rcv,
-                                       THIS_MODULE);
+       idiagnl = netlink_kernel_create(&init_net, NETLINK_INET_DIAG, 0,
+                                       inet_diag_rcv, NULL, THIS_MODULE);
        if (idiagnl == NULL)
                goto out_free_table;
        err = 0;