ipt_LOG.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This is a module which is used for logging packets.
  3.  */
  4. #include <linux/module.h>
  5. #include <linux/skbuff.h>
  6. #include <linux/ip.h>
  7. #include <linux/spinlock.h>
  8. #include <net/icmp.h>
  9. #include <net/udp.h>
  10. #include <net/tcp.h>
  11. #include <linux/netfilter_ipv4/ip_tables.h>
  12. struct in_device;
  13. #include <net/route.h>
  14. #include <linux/netfilter_ipv4/ipt_LOG.h>
  15. #if 0
  16. #define DEBUGP printk
  17. #else
  18. #define DEBUGP(format, args...)
  19. #endif
  20. struct esphdr {
  21. __u32   spi;
  22. }; /* FIXME evil kludge */
  23.         
  24. /* Use lock to serialize, so printks don't overlap */
  25. static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
  26. /* One level of recursion won't kill us */
  27. static void dump_packet(const struct ipt_log_info *info,
  28. struct iphdr *iph, unsigned int len, int recurse)
  29. {
  30. void *protoh = (u_int32_t *)iph + iph->ihl;
  31. unsigned int datalen = len - iph->ihl * 4;
  32. /* Important fields:
  33.  * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
  34. /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
  35. printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
  36.        NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
  37. /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
  38. printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
  39.        ntohs(iph->tot_len), iph->tos & IPTOS_TOS_MASK,
  40.        iph->tos & IPTOS_PREC_MASK, iph->ttl, ntohs(iph->id));
  41. /* Max length: 6 "CE DF MF " */
  42. if (ntohs(iph->frag_off) & IP_CE)
  43. printk("CE ");
  44. if (ntohs(iph->frag_off) & IP_DF)
  45. printk("DF ");
  46. if (ntohs(iph->frag_off) & IP_MF)
  47. printk("MF ");
  48. /* Max length: 11 "FRAG:65535 " */
  49. if (ntohs(iph->frag_off) & IP_OFFSET)
  50. printk("FRAG:%u ", ntohs(iph->frag_off) & IP_OFFSET);
  51. if ((info->logflags & IPT_LOG_IPOPT)
  52.     && iph->ihl * 4 != sizeof(struct iphdr)) {
  53. unsigned int i;
  54. /* Max length: 127 "OPT (" 15*4*2chars ") " */
  55. printk("OPT (");
  56. for (i = sizeof(struct iphdr); i < iph->ihl * 4; i++)
  57. printk("%02X", ((u_int8_t *)iph)[i]);
  58. printk(") ");
  59. }
  60. switch (iph->protocol) {
  61. case IPPROTO_TCP: {
  62. struct tcphdr *tcph = protoh;
  63. /* Max length: 10 "PROTO=TCP " */
  64. printk("PROTO=TCP ");
  65. if (ntohs(iph->frag_off) & IP_OFFSET)
  66. break;
  67. /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  68. if (datalen < sizeof (*tcph)) {
  69. printk("INCOMPLETE [%u bytes] ", datalen);
  70. break;
  71. }
  72. /* Max length: 20 "SPT=65535 DPT=65535 " */
  73. printk("SPT=%u DPT=%u ",
  74.        ntohs(tcph->source), ntohs(tcph->dest));
  75. /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
  76. if (info->logflags & IPT_LOG_TCPSEQ)
  77. printk("SEQ=%u ACK=%u ",
  78.        ntohl(tcph->seq), ntohl(tcph->ack_seq));
  79. /* Max length: 13 "WINDOW=65535 " */
  80. printk("WINDOW=%u ", ntohs(tcph->window));
  81. /* Max length: 9 "RES=0x3F " */
  82. printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
  83. /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
  84. if (tcph->cwr)
  85. printk("CWR ");
  86. if (tcph->ece)
  87. printk("ECE ");
  88. if (tcph->urg)
  89. printk("URG ");
  90. if (tcph->ack)
  91. printk("ACK ");
  92. if (tcph->psh)
  93. printk("PSH ");
  94. if (tcph->rst)
  95. printk("RST ");
  96. if (tcph->syn)
  97. printk("SYN ");
  98. if (tcph->fin)
  99. printk("FIN ");
  100. /* Max length: 11 "URGP=65535 " */
  101. printk("URGP=%u ", ntohs(tcph->urg_ptr));
  102. if ((info->logflags & IPT_LOG_TCPOPT)
  103.     && tcph->doff * 4 != sizeof(struct tcphdr)) {
  104. unsigned int i;
  105. /* Max length: 127 "OPT (" 15*4*2chars ") " */
  106. printk("OPT (");
  107. for (i =sizeof(struct tcphdr); i < tcph->doff * 4; i++)
  108. printk("%02X", ((u_int8_t *)tcph)[i]);
  109. printk(") ");
  110. }
  111. break;
  112. }
  113. case IPPROTO_UDP: {
  114. struct udphdr *udph = protoh;
  115. /* Max length: 10 "PROTO=UDP " */
  116. printk("PROTO=UDP ");
  117. if (ntohs(iph->frag_off) & IP_OFFSET)
  118. break;
  119. /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  120. if (datalen < sizeof (*udph)) {
  121. printk("INCOMPLETE [%u bytes] ", datalen);
  122. break;
  123. }
  124. /* Max length: 20 "SPT=65535 DPT=65535 " */
  125. printk("SPT=%u DPT=%u LEN=%u ",
  126.        ntohs(udph->source), ntohs(udph->dest),
  127.        ntohs(udph->len));
  128. break;
  129. }
  130. case IPPROTO_ICMP: {
  131. struct icmphdr *icmph = protoh;
  132. static size_t required_len[NR_ICMP_TYPES+1]
  133. = { [ICMP_ECHOREPLY] = 4,
  134.     [ICMP_DEST_UNREACH]
  135.     = 8 + sizeof(struct iphdr) + 8,
  136.     [ICMP_SOURCE_QUENCH]
  137.     = 8 + sizeof(struct iphdr) + 8,
  138.     [ICMP_REDIRECT]
  139.     = 8 + sizeof(struct iphdr) + 8,
  140.     [ICMP_ECHO] = 4,
  141.     [ICMP_TIME_EXCEEDED]
  142.     = 8 + sizeof(struct iphdr) + 8,
  143.     [ICMP_PARAMETERPROB]
  144.     = 8 + sizeof(struct iphdr) + 8,
  145.     [ICMP_TIMESTAMP] = 20,
  146.     [ICMP_TIMESTAMPREPLY] = 20,
  147.     [ICMP_ADDRESS] = 12,
  148.     [ICMP_ADDRESSREPLY] = 12 };
  149. /* Max length: 11 "PROTO=ICMP " */
  150. printk("PROTO=ICMP ");
  151. if (ntohs(iph->frag_off) & IP_OFFSET)
  152. break;
  153. /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  154. if (datalen < 4) {
  155. printk("INCOMPLETE [%u bytes] ", datalen);
  156. break;
  157. }
  158. /* Max length: 18 "TYPE=255 CODE=255 " */
  159. printk("TYPE=%u CODE=%u ", icmph->type, icmph->code);
  160. /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  161. if (icmph->type <= NR_ICMP_TYPES
  162.     && required_len[icmph->type]
  163.     && datalen < required_len[icmph->type]) {
  164. printk("INCOMPLETE [%u bytes] ", datalen);
  165. break;
  166. }
  167. switch (icmph->type) {
  168. case ICMP_ECHOREPLY:
  169. case ICMP_ECHO:
  170. /* Max length: 19 "ID=65535 SEQ=65535 " */
  171. printk("ID=%u SEQ=%u ",
  172.        ntohs(icmph->un.echo.id),
  173.        ntohs(icmph->un.echo.sequence));
  174. break;
  175. case ICMP_PARAMETERPROB:
  176. /* Max length: 14 "PARAMETER=255 " */
  177. printk("PARAMETER=%u ",
  178.        ntohl(icmph->un.gateway) >> 24);
  179. break;
  180. case ICMP_REDIRECT:
  181. /* Max length: 24 "GATEWAY=255.255.255.255 " */
  182. printk("GATEWAY=%u.%u.%u.%u ", NIPQUAD(icmph->un.gateway));
  183. /* Fall through */
  184. case ICMP_DEST_UNREACH:
  185. case ICMP_SOURCE_QUENCH:
  186. case ICMP_TIME_EXCEEDED:
  187. /* Max length: 3+maxlen */
  188. if (recurse) {
  189. printk("[");
  190. dump_packet(info,
  191.     (struct iphdr *)(icmph + 1),
  192.     datalen-sizeof(struct icmphdr),
  193.     0);
  194. printk("] ");
  195. }
  196. /* Max length: 10 "MTU=65535 " */
  197. if (icmph->type == ICMP_DEST_UNREACH
  198.     && icmph->code == ICMP_FRAG_NEEDED)
  199. printk("MTU=%u ", ntohs(icmph->un.frag.mtu));
  200. }
  201. break;
  202. }
  203. /* Max Length */
  204. case IPPROTO_AH:
  205. case IPPROTO_ESP: {
  206. struct esphdr *esph = protoh;
  207. int esp= (iph->protocol==IPPROTO_ESP);
  208. /* Max length: 10 "PROTO=ESP " */
  209. printk("PROTO=%s ",esp? "ESP" : "AH");
  210. if (ntohs(iph->frag_off) & IP_OFFSET)
  211. break;
  212. /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  213. if (datalen < sizeof (*esph)) {
  214. printk("INCOMPLETE [%u bytes] ", datalen);
  215. break;
  216. }
  217. /* Length: 15 "SPI=0xF1234567 " */
  218. printk("SPI=0x%x ", ntohl(esph->spi) );
  219. break;
  220. }
  221. /* Max length: 10 "PROTO 255 " */
  222. default:
  223. printk("PROTO=%u ", iph->protocol);
  224. }
  225. /* Proto    Max log string length */
  226. /* IP:      40+46+6+11+127 = 230 */
  227. /* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
  228. /* UDP:     10+max(25,20) = 35 */
  229. /* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
  230. /* ESP:     10+max(25)+15 = 50 */
  231. /* AH:      9+max(25)+15 = 49 */
  232. /* unknown: 10 */
  233. /* (ICMP allows recursion one level deep) */
  234. /* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
  235. /* maxlen = 230+   91  + 230 + 252 = 803 */
  236. }
  237. static unsigned int
  238. ipt_log_target(struct sk_buff **pskb,
  239.        unsigned int hooknum,
  240.        const struct net_device *in,
  241.        const struct net_device *out,
  242.        const void *targinfo,
  243.        void *userinfo)
  244. {
  245. struct iphdr *iph = (*pskb)->nh.iph;
  246. const struct ipt_log_info *loginfo = targinfo;
  247. char level_string[4] = "< >";
  248. level_string[1] = '0' + (loginfo->level % 8);
  249. spin_lock_bh(&log_lock);
  250. printk(level_string);
  251. printk("%sIN=%s OUT=%s ",
  252.        loginfo->prefix,
  253.        in ? in->name : "",
  254.        out ? out->name : "");
  255. if (in && !out) {
  256. /* MAC logging for input chain only. */
  257. printk("MAC=");
  258. if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)iph) {
  259. int i;
  260. unsigned char *p = (*pskb)->mac.raw;
  261. for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
  262. printk("%02x%c", *p,
  263.        i==(*pskb)->dev->hard_header_len - 1
  264.        ? ' ':':');
  265. } else
  266. printk(" ");
  267. }
  268. dump_packet(loginfo, iph, (*pskb)->len, 1);
  269. printk("n");
  270. spin_unlock_bh(&log_lock);
  271. return IPT_CONTINUE;
  272. }
  273. static int ipt_log_checkentry(const char *tablename,
  274.       const struct ipt_entry *e,
  275.       void *targinfo,
  276.       unsigned int targinfosize,
  277.       unsigned int hook_mask)
  278. {
  279. const struct ipt_log_info *loginfo = targinfo;
  280. if (targinfosize != IPT_ALIGN(sizeof(struct ipt_log_info))) {
  281. DEBUGP("LOG: targinfosize %u != %un",
  282.        targinfosize, IPT_ALIGN(sizeof(struct ipt_log_info)));
  283. return 0;
  284. }
  285. if (loginfo->level >= 8) {
  286. DEBUGP("LOG: level %u >= 8n", loginfo->level);
  287. return 0;
  288. }
  289. if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '') {
  290. DEBUGP("LOG: prefix term %in",
  291.        loginfo->prefix[sizeof(loginfo->prefix)-1]);
  292. return 0;
  293. }
  294. return 1;
  295. }
  296. static struct ipt_target ipt_log_reg
  297. = { { NULL, NULL }, "LOG", ipt_log_target, ipt_log_checkentry, NULL, 
  298.     THIS_MODULE };
  299. static int __init init(void)
  300. {
  301. if (ipt_register_target(&ipt_log_reg))
  302. return -EINVAL;
  303. return 0;
  304. }
  305. static void __exit fini(void)
  306. {
  307. ipt_unregister_target(&ipt_log_reg);
  308. }
  309. module_init(init);
  310. module_exit(fini);
  311. MODULE_LICENSE("GPL");