ip6t_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 <linux/icmpv6.h>
  9. #include <net/udp.h>
  10. #include <net/tcp.h>
  11. #include <net/ipv6.h>
  12. #include <linux/netfilter_ipv6/ip6_tables.h>
  13. MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
  14. MODULE_DESCRIPTION("IP6 tables LOG target module");
  15. MODULE_LICENSE("GPL");
  16. struct in_device;
  17. #include <net/route.h>
  18. #include <linux/netfilter_ipv6/ip6t_LOG.h>
  19. #if 0
  20. #define DEBUGP printk
  21. #else
  22. #define DEBUGP(format, args...)
  23. #endif
  24. #define NIP6(addr) 
  25. ntohs((addr).s6_addr16[0]), 
  26. ntohs((addr).s6_addr16[1]), 
  27. ntohs((addr).s6_addr16[2]), 
  28. ntohs((addr).s6_addr16[3]), 
  29. ntohs((addr).s6_addr16[4]), 
  30. ntohs((addr).s6_addr16[5]), 
  31. ntohs((addr).s6_addr16[6]), 
  32. ntohs((addr).s6_addr16[7])
  33. struct esphdr {
  34. __u32   spi;
  35. }; /* FIXME evil kludge */
  36.         
  37. /* Use lock to serialize, so printks don't overlap */
  38. static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
  39. /* takes in current header and pointer to the header */
  40. /* if another header exists, sets hdrptr to the next header
  41.    and returns the new header value, else returns 0 */
  42. static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t **hdrptr)
  43. {
  44. u_int8_t hdrlen, nexthdr = 0;
  45. switch(currenthdr){
  46. case IPPROTO_AH:
  47. /* whoever decided to do the length of AUTH for ipv6
  48. in 32bit units unlike other headers should be beaten...
  49. repeatedly...with a large stick...no, an even LARGER
  50. stick...no, you're still not thinking big enough */
  51. nexthdr = **hdrptr;
  52. hdrlen = *hdrptr[1] * 4 + 8;
  53. *hdrptr = *hdrptr + hdrlen;
  54. break;
  55. /*stupid rfc2402 */
  56. case IPPROTO_DSTOPTS:
  57. case IPPROTO_ROUTING:
  58. case IPPROTO_HOPOPTS:
  59. nexthdr = **hdrptr;
  60. hdrlen = *hdrptr[1] * 8 + 8;
  61. *hdrptr = *hdrptr + hdrlen;
  62. break;
  63. case IPPROTO_FRAGMENT:
  64. nexthdr = **hdrptr;
  65. *hdrptr = *hdrptr + 8;
  66. break;
  67. }
  68. return nexthdr;
  69. }
  70. /* One level of recursion won't kill us */
  71. static void dump_packet(const struct ip6t_log_info *info,
  72. struct ipv6hdr *ipv6h, int recurse)
  73. {
  74. u_int8_t currenthdr = ipv6h->nexthdr;
  75. u_int8_t *hdrptr;
  76. int fragment;
  77. /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */
  78. printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->saddr));
  79. printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
  80. /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
  81. printk("LEN=%u TC=%u HOPLIMIT=%u FLOWLBL=%u ",
  82.        ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr),
  83.        (ntohl(*(u_int32_t *)ipv6h) & 0x0ff00000) >> 20,
  84.        ipv6h->hop_limit,
  85.        (ntohl(*(u_int32_t *)ipv6h) & 0x000fffff));
  86. fragment = 0;
  87. hdrptr = (u_int8_t *)(ipv6h + 1);
  88. while (currenthdr) {
  89. if ((currenthdr == IPPROTO_TCP) ||
  90.     (currenthdr == IPPROTO_UDP) ||
  91.     (currenthdr == IPPROTO_ICMPV6))
  92. break;
  93. /* Max length: 48 "OPT (...) " */
  94. printk("OPT ( ");
  95. switch (currenthdr) {
  96. case IPPROTO_FRAGMENT: {
  97. struct frag_hdr *fhdr = (struct frag_hdr *)hdrptr;
  98. /* Max length: 11 "FRAG:65535 " */
  99. printk("FRAG:%u ", ntohs(fhdr->frag_off) & 0xFFF8);
  100. /* Max length: 11 "INCOMPLETE " */
  101. if (fhdr->frag_off & __constant_htons(0x0001))
  102. printk("INCOMPLETE ");
  103. printk("ID:%08x ", fhdr->identification);
  104. if (ntohs(fhdr->frag_off) & 0xFFF8)
  105. fragment = 1;
  106. break;
  107. }
  108. case IPPROTO_DSTOPTS:
  109. case IPPROTO_ROUTING:
  110. case IPPROTO_HOPOPTS:
  111. break;
  112. /* Max Length */
  113. case IPPROTO_AH:
  114. case IPPROTO_ESP:
  115. if (info->logflags & IP6T_LOG_IPOPT) {
  116. struct esphdr *esph = (struct esphdr *)hdrptr;
  117. int esp = (currenthdr == IPPROTO_ESP);
  118. /* Max length: 4 "ESP " */
  119. printk("%s ",esp ? "ESP" : "AH");
  120. /* Length: 15 "SPI=0xF1234567 " */
  121. printk("SPI=0x%x ", ntohl(esph->spi) );
  122. break;
  123. }
  124. default:
  125. break;
  126. }
  127. printk(") ");
  128. currenthdr = ip6_nexthdr(currenthdr, &hdrptr);
  129. }
  130. switch (currenthdr) {
  131. case IPPROTO_TCP: {
  132. struct tcphdr *tcph = (struct tcphdr *)hdrptr;
  133. /* Max length: 10 "PROTO=TCP " */
  134. printk("PROTO=TCP ");
  135. if (fragment)
  136. break;
  137. /* Max length: 20 "SPT=65535 DPT=65535 " */
  138. printk("SPT=%u DPT=%u ",
  139.        ntohs(tcph->source), ntohs(tcph->dest));
  140. /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
  141. if (info->logflags & IP6T_LOG_TCPSEQ)
  142. printk("SEQ=%u ACK=%u ",
  143.        ntohl(tcph->seq), ntohl(tcph->ack_seq));
  144. /* Max length: 13 "WINDOW=65535 " */
  145. printk("WINDOW=%u ", ntohs(tcph->window));
  146. /* Max length: 9 "RES=0x3F " */
  147. printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
  148. /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
  149. if (tcph->cwr)
  150. printk("CWR ");
  151. if (tcph->ece)
  152. printk("ECE ");
  153. if (tcph->urg)
  154. printk("URG ");
  155. if (tcph->ack)
  156. printk("ACK ");
  157. if (tcph->psh)
  158. printk("PSH ");
  159. if (tcph->rst)
  160. printk("RST ");
  161. if (tcph->syn)
  162. printk("SYN ");
  163. if (tcph->fin)
  164. printk("FIN ");
  165. /* Max length: 11 "URGP=65535 " */
  166. printk("URGP=%u ", ntohs(tcph->urg_ptr));
  167. if ((info->logflags & IP6T_LOG_TCPOPT)
  168.     && tcph->doff * 4 != sizeof(struct tcphdr)) {
  169. unsigned int i;
  170. /* Max length: 127 "OPT (" 15*4*2chars ") " */
  171. printk("OPT (");
  172. for (i =sizeof(struct tcphdr); i < tcph->doff * 4; i++)
  173. printk("%02X", ((u_int8_t *)tcph)[i]);
  174. printk(") ");
  175. }
  176. break;
  177. }
  178. case IPPROTO_UDP: {
  179. struct udphdr *udph = (struct udphdr *)hdrptr;
  180. /* Max length: 10 "PROTO=UDP " */
  181. printk("PROTO=UDP ");
  182. if (fragment)
  183. break;
  184. /* Max length: 20 "SPT=65535 DPT=65535 " */
  185. printk("SPT=%u DPT=%u LEN=%u ",
  186.        ntohs(udph->source), ntohs(udph->dest),
  187.        ntohs(udph->len));
  188. break;
  189. }
  190. case IPPROTO_ICMPV6: {
  191. struct icmp6hdr *icmp6h = (struct icmp6hdr *)hdrptr;
  192. /* Max length: 13 "PROTO=ICMPv6 " */
  193. printk("PROTO=ICMPv6 ");
  194. if (fragment)
  195. break;
  196. /* Max length: 18 "TYPE=255 CODE=255 " */
  197. printk("TYPE=%u CODE=%u ", icmp6h->icmp6_type, icmp6h->icmp6_code);
  198. switch (icmp6h->icmp6_type) {
  199. case ICMPV6_ECHO_REQUEST:
  200. case ICMPV6_ECHO_REPLY:
  201. /* Max length: 19 "ID=65535 SEQ=65535 " */
  202. printk("ID=%u SEQ=%u ",
  203. ntohs(icmp6h->icmp6_identifier),
  204. ntohs(icmp6h->icmp6_sequence));
  205. break;
  206. case ICMPV6_MGM_QUERY:
  207. case ICMPV6_MGM_REPORT:
  208. case ICMPV6_MGM_REDUCTION:
  209. break;
  210. case ICMPV6_PARAMPROB:
  211. /* Max length: 17 "POINTER=ffffffff " */
  212. printk("POINTER=%08x ", ntohl(icmp6h->icmp6_pointer));
  213. /* Fall through */
  214. case ICMPV6_DEST_UNREACH:
  215. case ICMPV6_PKT_TOOBIG:
  216. case ICMPV6_TIME_EXCEED:
  217. /* Max length: 3+maxlen */
  218. if (recurse) {
  219. printk("[");
  220. dump_packet(info, (struct ipv6hdr *)(icmp6h + 1), 0);
  221. printk("] ");
  222. }
  223. /* Max length: 10 "MTU=65535 " */
  224. if (icmp6h->icmp6_type == ICMPV6_PKT_TOOBIG)
  225. printk("MTU=%u ", ntohl(icmp6h->icmp6_mtu));
  226. }
  227. break;
  228. }
  229. /* Max length: 10 "PROTO 255 " */
  230. default:
  231. printk("PROTO=%u ", currenthdr);
  232. }
  233. }
  234. static unsigned int
  235. ip6t_log_target(struct sk_buff **pskb,
  236. unsigned int hooknum,
  237. const struct net_device *in,
  238. const struct net_device *out,
  239. const void *targinfo,
  240. void *userinfo)
  241. {
  242. struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
  243. const struct ip6t_log_info *loginfo = targinfo;
  244. char level_string[4] = "< >";
  245. level_string[1] = '0' + (loginfo->level % 8);
  246. spin_lock_bh(&log_lock);
  247. printk(level_string);
  248. printk("%sIN=%s OUT=%s ",
  249. loginfo->prefix,
  250. in ? in->name : "",
  251. out ? out->name : "");
  252. if (in && !out) {
  253. /* MAC logging for input chain only. */
  254. printk("MAC=");
  255. if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
  256. int i;
  257. unsigned char *p = (*pskb)->mac.raw;
  258. for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
  259. printk("%02x%c", *p,
  260.        i==(*pskb)->dev->hard_header_len - 1
  261.        ? ' ':':');
  262. } else
  263. printk(" ");
  264. }
  265. dump_packet(loginfo, ipv6h, 1);
  266. printk("n");
  267. spin_unlock_bh(&log_lock);
  268. return IP6T_CONTINUE;
  269. }
  270. static int ip6t_log_checkentry(const char *tablename,
  271.        const struct ip6t_entry *e,
  272.        void *targinfo,
  273.        unsigned int targinfosize,
  274.        unsigned int hook_mask)
  275. {
  276. const struct ip6t_log_info *loginfo = targinfo;
  277. if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_log_info))) {
  278. DEBUGP("LOG: targinfosize %u != %un",
  279.        targinfosize, IP6T_ALIGN(sizeof(struct ip6t_log_info)));
  280. return 0;
  281. }
  282. if (loginfo->level >= 8) {
  283. DEBUGP("LOG: level %u >= 8n", loginfo->level);
  284. return 0;
  285. }
  286. if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '') {
  287. DEBUGP("LOG: prefix term %in",
  288.        loginfo->prefix[sizeof(loginfo->prefix)-1]);
  289. return 0;
  290. }
  291. return 1;
  292. }
  293. static struct ip6t_target ip6t_log_reg
  294. = { { NULL, NULL }, "LOG", ip6t_log_target, ip6t_log_checkentry, NULL, 
  295.     THIS_MODULE };
  296. static int __init init(void)
  297. {
  298. if (ip6t_register_target(&ip6t_log_reg))
  299. return -EINVAL;
  300. return 0;
  301. }
  302. static void __exit fini(void)
  303. {
  304. ip6t_unregister_target(&ip6t_log_reg);
  305. }
  306. module_init(init);
  307. module_exit(fini);