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