[Suspend2][ 09/13] [Suspend2] Netlink receive message routines.

From: Nigel Cunningham
Date: Tue Jun 27 2006 - 01:00:14 EST


Suspend2's routines for receiving netlink messages. We don't accept
that many messages, so the logic is pretty simple.

Signed-off-by: Nigel Cunningham <nigel@xxxxxxxxxxxx>

kernel/power/netlink.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/kernel/power/netlink.c b/kernel/power/netlink.c
index 9094c92..c5b4bea 100644
--- a/kernel/power/netlink.c
+++ b/kernel/power/netlink.c
@@ -171,3 +171,89 @@ static int nl_ready(struct user_helper_d
return 0;
}

+static int suspend_nl_gen_rcv_msg(struct user_helper_data *uhd,
+ struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+ int type;
+ int *data;
+ int err;
+
+ /* Let the more specific handler go first. It returns
+ * 1 for valid messages that it doesn't know. */
+ if ((err = uhd->rcv_msg(skb, nlh)) != 1)
+ return err;
+
+ type = nlh->nlmsg_type;
+
+ /* Only allow one task to receive NOFREEZE privileges */
+ if (type == NETLINK_MSG_NOFREEZE_ME && uhd->pid != -1) {
+ printk("Received extra nofreeze me requests.\n");
+ return -EBUSY;
+ }
+
+ data = (int*)NLMSG_DATA(nlh);
+
+ switch (type) {
+ case NETLINK_MSG_NOFREEZE_ME:
+ if ((err = nl_set_nofreeze(uhd, nlh->nlmsg_pid)) != 0)
+ return err;
+ break;
+ case NETLINK_MSG_GET_DEBUGGING:
+ send_whether_debugging(uhd);
+ break;
+ case NETLINK_MSG_READY:
+ if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(int))) {
+ printk("Invalid ready mesage.\n");
+ return -EINVAL;
+ }
+ if ((err = nl_ready(uhd, *data)) != 0)
+ return err;
+ break;
+ }
+
+ return 0;
+}
+
+static void suspend_user_rcv_skb(struct user_helper_data *uhd,
+ struct sk_buff *skb)
+{
+ int err;
+ struct nlmsghdr *nlh;
+
+ while (skb->len >= NLMSG_SPACE(0)) {
+ u32 rlen;
+
+ nlh = (struct nlmsghdr *) skb->data;
+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+ return;
+
+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+ if (rlen > skb->len)
+ rlen = skb->len;
+
+ if ((err = suspend_nl_gen_rcv_msg(uhd, skb, nlh)) != 0)
+ netlink_ack(skb, nlh, err);
+ else if (nlh->nlmsg_flags & NLM_F_ACK)
+ netlink_ack(skb, nlh, 0);
+ skb_pull(skb, rlen);
+ }
+}
+
+static void suspend_netlink_input(struct sock *sk, int len)
+{
+ struct user_helper_data *uhd = uhd_list;
+
+ while (uhd && uhd->netlink_id != sk->sk_protocol)
+ uhd= uhd->next;
+
+ BUG_ON(!uhd);
+
+ do {
+ struct sk_buff *skb;
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ suspend_user_rcv_skb(uhd, skb);
+ put_skb(uhd, skb);
+ }
+ } while (uhd->nl && uhd->nl->sk_receive_queue.qlen);
+}
+

--
Nigel Cunningham nigel at suspend2 dot net
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/