ipt_ULOG.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * netfilter module for userspace packet logging daemons
  3.  *
  4.  * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
  5.  *
  6.  * 2000/09/22 ulog-cprange feature added
  7.  * 2001/01/04 in-kernel queue as proposed by Sebastian Zander 
  8.  *  <zander@fokus.gmd.de>
  9.  * 2001/01/30 per-rule nlgroup conflicts with global queue. 
  10.  *            nlgroup now global (sysctl)
  11.  * 2001/04/19 ulog-queue reworked, now fixed buffer size specified at
  12.  *        module loadtime -HW
  13.  * 2002/07/07 remove broken nflog_rcv() function -HW
  14.  * 2002/08/29 fix shifted/unshifted nlgroup bug -HW
  15.  *
  16.  * Released under the terms of the GPL
  17.  *
  18.  * This module accepts two parameters: 
  19.  * 
  20.  * nlbufsiz:
  21.  *   The parameter specifies how big the buffer for each netlink multicast
  22.  * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
  23.  * get accumulated in the kernel until they are sent to userspace. It is
  24.  * NOT possible to allocate more than 128kB, and it is strongly discouraged,
  25.  * because atomically allocating 128kB inside the network rx softirq is not
  26.  * reliable. Please also keep in mind that this buffer size is allocated for
  27.  * each nlgroup you are using, so the total kernel memory usage increases
  28.  * by that factor.
  29.  *
  30.  * flushtimeout:
  31.  *   Specify, after how many clock ticks (intel: 100 per second) the queue
  32.  * should be flushed even if it is not full yet.
  33.  *
  34.  * ipt_ULOG.c,v 1.21 2002/08/29 10:54:34 laforge Exp
  35.  */
  36. #include <linux/module.h>
  37. #include <linux/version.h>
  38. #include <linux/config.h>
  39. #include <linux/spinlock.h>
  40. #include <linux/socket.h>
  41. #include <linux/skbuff.h>
  42. #include <linux/kernel.h>
  43. #include <linux/timer.h>
  44. #include <linux/netlink.h>
  45. #include <linux/netdevice.h>
  46. #include <linux/mm.h>
  47. #include <linux/socket.h>
  48. #include <linux/netfilter_ipv4/ip_tables.h>
  49. #include <linux/netfilter_ipv4/ipt_ULOG.h>
  50. #include <linux/netfilter_ipv4/lockhelp.h>
  51. #include <net/sock.h>
  52. #include <linux/bitops.h>
  53. MODULE_LICENSE("GPL");
  54. MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
  55. MODULE_DESCRIPTION("IP tables userspace logging module");
  56. #define ULOG_NL_EVENT 111 /* Harald's favorite number */
  57. #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */
  58. #if 0
  59. #define DEBUGP(format, args...) printk(__FILE__ ":" __FUNCTION__ ":" 
  60.        format, ## args)
  61. #else
  62. #define DEBUGP(format, args...)
  63. #endif
  64. #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format, ## args); } while (0)
  65. static unsigned int nlbufsiz = 4096;
  66. MODULE_PARM(nlbufsiz, "i");
  67. MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
  68. static unsigned int flushtimeout = 10 * HZ;
  69. MODULE_PARM(flushtimeout, "i");
  70. MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
  71. /* global data structures */
  72. typedef struct {
  73. unsigned int qlen; /* number of nlmsgs' in the skb */
  74. struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */
  75. struct sk_buff *skb; /* the pre-allocated skb */
  76. struct timer_list timer; /* the timer function */
  77. } ulog_buff_t;
  78. static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; /* array of buffers */
  79. static struct sock *nflognl; /* our socket */
  80. static size_t qlen; /* current length of multipart-nlmsg */
  81. DECLARE_LOCK(ulog_lock); /* spinlock */
  82. /* send one ulog_buff_t to userspace */
  83. static void ulog_send(unsigned int nlgroupnum)
  84. {
  85. ulog_buff_t *ub = &ulog_buffers[nlgroupnum];
  86. if (timer_pending(&ub->timer)) {
  87. DEBUGP("ipt_ULOG: ulog_send: timer was pending, deletingn");
  88. del_timer(&ub->timer);
  89. }
  90. /* last nlmsg needs NLMSG_DONE */
  91. if (ub->qlen > 1)
  92. ub->lastnlh->nlmsg_type = NLMSG_DONE;
  93. NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum);
  94. DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %un",
  95. ub->qlen, nlgroup);
  96. netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC);
  97. ub->qlen = 0;
  98. ub->skb = NULL;
  99. ub->lastnlh = NULL;
  100. }
  101. /* timer function to flush queue in ULOG_FLUSH_INTERVAL time */
  102. static void ulog_timer(unsigned long data)
  103. {
  104. DEBUGP("ipt_ULOG: timer function called, calling ulog_sendn");
  105. /* lock to protect against somebody modifying our structure
  106.  * from ipt_ulog_target at the same time */
  107. LOCK_BH(&ulog_lock);
  108. ulog_send(data);
  109. UNLOCK_BH(&ulog_lock);
  110. }
  111. struct sk_buff *ulog_alloc_skb(unsigned int size)
  112. {
  113. struct sk_buff *skb;
  114. /* alloc skb which should be big enough for a whole
  115.  * multipart message. WARNING: has to be <= 131000
  116.  * due to slab allocator restrictions */
  117. skb = alloc_skb(nlbufsiz, GFP_ATOMIC);
  118. if (!skb) {
  119. PRINTR("ipt_ULOG: can't alloc whole buffer %ub!n",
  120. nlbufsiz);
  121. /* try to allocate only as much as we need for 
  122.  * current packet */
  123. skb = alloc_skb(size, GFP_ATOMIC);
  124. if (!skb)
  125. PRINTR("ipt_ULOG: can't even allocate %ubn", size);
  126. }
  127. return skb;
  128. }
  129. static unsigned int ipt_ulog_target(struct sk_buff **pskb,
  130.     unsigned int hooknum,
  131.     const struct net_device *in,
  132.     const struct net_device *out,
  133.     const void *targinfo, void *userinfo)
  134. {
  135. ulog_buff_t *ub;
  136. ulog_packet_msg_t *pm;
  137. size_t size, copy_len;
  138. struct nlmsghdr *nlh;
  139. struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
  140. /* ffs == find first bit set, necessary because userspace
  141.  * is already shifting groupnumber, but we need unshifted.
  142.  * ffs() returns [1..32], we need [0..31] */
  143. unsigned int groupnum = ffs(loginfo->nl_group) - 1;
  144. /* calculate the size of the skb needed */
  145. if ((loginfo->copy_range == 0) ||
  146.     (loginfo->copy_range > (*pskb)->len)) {
  147. copy_len = (*pskb)->len;
  148. } else {
  149. copy_len = loginfo->copy_range;
  150. }
  151. size = NLMSG_SPACE(sizeof(*pm) + copy_len);
  152. ub = &ulog_buffers[groupnum];
  153. LOCK_BH(&ulog_lock);
  154. if (!ub->skb) {
  155. if (!(ub->skb = ulog_alloc_skb(size)))
  156. goto alloc_failure;
  157. } else if (ub->qlen >= loginfo->qthreshold ||
  158.    size > skb_tailroom(ub->skb)) {
  159. /* either the queue len is too high or we don't have 
  160.  * enough room in nlskb left. send it to userspace. */
  161. ulog_send(groupnum);
  162. if (!(ub->skb = ulog_alloc_skb(size)))
  163. goto alloc_failure;
  164. }
  165. DEBUGP("ipt_ULOG: qlen %d, qthreshold %dn", ub->qlen, 
  166. loginfo->qthreshold);
  167. /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
  168. nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, 
  169. size - sizeof(*nlh));
  170. ub->qlen++;
  171. pm = NLMSG_DATA(nlh);
  172. /* copy hook, prefix, timestamp, payload, etc. */
  173. pm->data_len = copy_len;
  174. pm->timestamp_sec = (*pskb)->stamp.tv_sec;
  175. pm->timestamp_usec = (*pskb)->stamp.tv_usec;
  176. pm->mark = (*pskb)->nfmark;
  177. pm->hook = hooknum;
  178. if (loginfo->prefix[0] != '')
  179. strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
  180. else
  181. *(pm->prefix) = '';
  182. if (in && in->hard_header_len > 0
  183.     && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
  184.     && in->hard_header_len <= ULOG_MAC_LEN) {
  185. memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
  186. pm->mac_len = in->hard_header_len;
  187. }
  188. if (in)
  189. strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
  190. else
  191. pm->indev_name[0] = '';
  192. if (out)
  193. strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name));
  194. else
  195. pm->outdev_name[0] = '';
  196. if (copy_len)
  197. memcpy(pm->payload, (*pskb)->data, copy_len);
  198. /* check if we are building multi-part messages */
  199. if (ub->qlen > 1) {
  200. ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
  201. }
  202. /* if threshold is reached, send message to userspace */
  203. if (qlen >= loginfo->qthreshold) {
  204. if (loginfo->qthreshold > 1)
  205. nlh->nlmsg_type = NLMSG_DONE;
  206. }
  207. ub->lastnlh = nlh;
  208. /* if timer isn't already running, start it */
  209. if (!timer_pending(&ub->timer)) {
  210. ub->timer.expires = jiffies + flushtimeout;
  211. add_timer(&ub->timer);
  212. }
  213. UNLOCK_BH(&ulog_lock);
  214. return IPT_CONTINUE;
  215. nlmsg_failure:
  216. PRINTR("ipt_ULOG: error during NLMSG_PUTn");
  217. alloc_failure:
  218. PRINTR("ipt_ULOG: Error building netlink messagen");
  219. UNLOCK_BH(&ulog_lock);
  220. return IPT_CONTINUE;
  221. }
  222. static int ipt_ulog_checkentry(const char *tablename,
  223.        const struct ipt_entry *e,
  224.        void *targinfo,
  225.        unsigned int targinfosize,
  226.        unsigned int hookmask)
  227. {
  228. struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
  229. if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ulog_info))) {
  230. DEBUGP("ipt_ULOG: targinfosize %u != 0n", targinfosize);
  231. return 0;
  232. }
  233. if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '') {
  234. DEBUGP("ipt_ULOG: prefix term %in",
  235.        loginfo->prefix[sizeof(loginfo->prefix) - 1]);
  236. return 0;
  237. }
  238. if (loginfo->qthreshold > ULOG_MAX_QLEN) {
  239. DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLENn",
  240. loginfo->qthreshold);
  241. return 0;
  242. }
  243. return 1;
  244. }
  245. static struct ipt_target ipt_ulog_reg =
  246.     { {NULL, NULL}, "ULOG", ipt_ulog_target, ipt_ulog_checkentry, NULL,
  247. THIS_MODULE
  248. };
  249. static int __init init(void)
  250. {
  251. int i;
  252. DEBUGP("ipt_ULOG: init modulen");
  253. if (nlbufsiz >= 128*1024) {
  254. printk("Netlink buffer has to be <= 128kBn");
  255. return -EINVAL;
  256. }
  257. /* initialize ulog_buffers */
  258. for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
  259. memset(&ulog_buffers[i], 0, sizeof(ulog_buff_t));
  260. init_timer(&ulog_buffers[i].timer);
  261. ulog_buffers[i].timer.function = ulog_timer;
  262. ulog_buffers[i].timer.data = i;
  263. }
  264. nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
  265. if (!nflognl)
  266. return -ENOMEM;
  267. if (ipt_register_target(&ipt_ulog_reg) != 0) {
  268. sock_release(nflognl->socket);
  269. return -EINVAL;
  270. }
  271. return 0;
  272. }
  273. static void __exit fini(void)
  274. {
  275. ulog_buff_t *ub;
  276. int i;
  277. DEBUGP("ipt_ULOG: cleanup_modulen");
  278. ipt_unregister_target(&ipt_ulog_reg);
  279. sock_release(nflognl->socket);
  280. /* remove pending timers and free allocated skb's */
  281. for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
  282. ub = &ulog_buffers[i];
  283. if (timer_pending(&ub->timer)) {
  284. DEBUGP("timer was pending, deletingn");
  285. del_timer(&ub->timer);
  286. }
  287. if (ub->skb) {
  288. kfree_skb(ub->skb);
  289. ub->skb = NULL;
  290. }
  291. }
  292. }
  293. module_init(init);
  294. module_exit(fini);