/* * NAT module for NetBIOS datagram service * Matt Chapman */ #include #include #include #include #include #include #include #include MODULE_DESCRIPTION("NAT module for NetBIOS datagram service"); MODULE_AUTHOR("Matt Chapman "); /* UDP port for the datagram service */ #define NETBIOS_PORT 138 /* fixed part of a NetBIOS header */ struct netbios_hdr { u_int8_t nodetype; u_int8_t flags; u_int16_t dgramid; u_int32_t srcip; u_int16_t srcport; u_int16_t length; u_int16_t offset; }; /* do translation on a NetBIOS packet */ static unsigned int netbios_nat(struct ip_conntrack *ct, struct ip_nat_info *info, enum ip_conntrack_info ctinfo, unsigned int hooknum, struct sk_buff **pskb) { struct iphdr *iph = (*pskb)->nh.iph; struct udphdr *udph = (void *)iph + iph->ihl * 4; unsigned int udplen = (*pskb)->len - iph->ihl * 4; unsigned int datalen = udplen - sizeof(struct udphdr); struct netbios_hdr *nbh; int dir; /* deny short packets */ if (datalen < sizeof(struct netbios_hdr)) return NF_DROP; /* only mangle things once: during POST_ROUTING in original direction, and during PRE_ROUTING in reply direction */ dir = CTINFO2DIR(ctinfo); if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL) || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) return NF_ACCEPT; /* change addresses inside NetBIOS header */ nbh = (struct netbios_hdr *)((char *)udph + sizeof(struct udphdr)); nbh->srcip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; nbh->srcport = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port; /* fix checksums */ (*pskb)->csum = csum_partial((char *)nbh, datalen, 0); udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP, csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum)); ip_send_check(iph); /* done */ return NF_ACCEPT; } static struct ip_nat_helper netbios_helper = { { NULL, NULL }, { { 0, { __constant_htons(NETBIOS_PORT) } }, { 0, { 0 }, IPPROTO_UDP } }, { { 0, { 0xFFFF } }, { 0, { 0 }, 0xFFFF } }, netbios_nat, "netbios" }; static int __init init(void) { return ip_nat_helper_register(&netbios_helper); } static void __exit fini(void) { ip_nat_helper_unregister(&netbios_helper); } module_init(init); module_exit(fini);