| 1 | /* ltt-control.c |
| 2 | * |
| 3 | * LTT control module over a netlink socket. |
| 4 | * |
| 5 | * Inspired from Relay Apps, by Tom Zanussi and iptables |
| 6 | * |
| 7 | * Copyright 2005 - |
| 8 | * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> |
| 9 | */ |
| 10 | |
| 11 | #include <linux/init.h> |
| 12 | #include <linux/module.h> |
| 13 | #include <linux/ltt-core.h> |
| 14 | #include <linux/netlink.h> |
| 15 | #include <linux/inet.h> |
| 16 | #include <linux/ip.h> |
| 17 | #include <linux/security.h> |
| 18 | #include <linux/skbuff.h> |
| 19 | #include <linux/types.h> |
| 20 | #include <net/sock.h> |
| 21 | #include "ltt-control.h" |
| 22 | |
| 23 | |
| 24 | #define LTTCTLM_BASE 0x10 |
| 25 | #define LTTCTLM_CONTROL (LTTCTLM_BASE + 1) /* LTT control message */ |
| 26 | |
| 27 | static struct sock *socket; |
| 28 | |
| 29 | void ltt_control_input(struct sock *sk, int len) |
| 30 | { |
| 31 | struct sk_buff *skb; |
| 32 | struct nlmsghdr *nlh = NULL; |
| 33 | u8 *payload = NULL; |
| 34 | lttctl_peer_msg_t *msg; |
| 35 | int err; |
| 36 | |
| 37 | printk(KERN_ALERT "ltt-control ltt_control_input\n"); |
| 38 | |
| 39 | while ((skb = skb_dequeue(&sk->sk_receive_queue)) |
| 40 | != NULL) { |
| 41 | |
| 42 | nlh = (struct nlmsghdr *)skb->data; |
| 43 | |
| 44 | if(security_netlink_recv(skb)) { |
| 45 | netlink_ack(skb, nlh, EPERM); |
| 46 | kfree_skb(skb); |
| 47 | continue; |
| 48 | } |
| 49 | |
| 50 | /* process netlink message pointed by skb->data */ |
| 51 | err = EINVAL; |
| 52 | payload = NLMSG_DATA(nlh); |
| 53 | /* process netlink message with header pointed by |
| 54 | * nlh and payload pointed by payload |
| 55 | */ |
| 56 | if(nlh->nlmsg_len != sizeof(lttctl_peer_msg_t) + sizeof(struct nlmsghdr)) { |
| 57 | printk(KERN_ALERT "ltt-control bad message length\n"); |
| 58 | netlink_ack(skb, nlh, EINVAL); |
| 59 | kfree_skb(skb); |
| 60 | continue; |
| 61 | } |
| 62 | msg = (lttctl_peer_msg_t*)payload; |
| 63 | |
| 64 | switch(msg->op) { |
| 65 | case OP_CREATE: |
| 66 | err = ltt_control(LTT_CONTROL_CREATE_TRACE, msg->trace_name, |
| 67 | msg->args); |
| 68 | break; |
| 69 | case OP_DESTROY: |
| 70 | err = ltt_control(LTT_CONTROL_DESTROY_TRACE, msg->trace_name, |
| 71 | msg->args); |
| 72 | break; |
| 73 | case OP_START: |
| 74 | err = ltt_control(LTT_CONTROL_START, msg->trace_name, |
| 75 | msg->args); |
| 76 | break; |
| 77 | case OP_STOP: |
| 78 | err = ltt_control(LTT_CONTROL_STOP, msg->trace_name, |
| 79 | msg->args); |
| 80 | break; |
| 81 | default: |
| 82 | err = EBADRQC; |
| 83 | printk(KERN_INFO "ltt-control invalid operation\n"); |
| 84 | } |
| 85 | netlink_ack(skb, nlh, err); |
| 86 | kfree_skb(skb); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | |
| 91 | static int ltt_control_init(void) |
| 92 | { |
| 93 | printk(KERN_ALERT "ltt-control init\n"); |
| 94 | |
| 95 | socket = netlink_kernel_create(NETLINK_LTT, 1, |
| 96 | ltt_control_input, THIS_MODULE); |
| 97 | if(socket == NULL) return -EPERM; |
| 98 | else return 0; |
| 99 | } |
| 100 | |
| 101 | static void ltt_control_exit(void) |
| 102 | { |
| 103 | printk(KERN_ALERT "ltt-control exit\n"); |
| 104 | |
| 105 | sock_release(socket->sk_socket); |
| 106 | } |
| 107 | |
| 108 | |
| 109 | module_init(ltt_control_init) |
| 110 | module_exit(ltt_control_exit) |
| 111 | |
| 112 | MODULE_LICENSE("GPL"); |
| 113 | MODULE_AUTHOR("Mathieu Desnoyers"); |
| 114 | MODULE_DESCRIPTION("Linux Trace Toolkit Controller"); |
| 115 | |