/*++ Copyright(c) 1998,99 Microsoft Corporation Module Name: tcpip.c Abstract: Windows Load Balancing Service (WLBS) Driver - IP/TCP/UDP support Author: kyrilf --*/ #include #include "wlbsip.h" #include "univ.h" #include "wlbsparm.h" #include "params.h" #include "log.h" /* GLOBALS */ static ULONG log_module_id = LOG_MODULE_TCPIP; /* constant encoded shadow computer name that will replace our cluster name */ static UCHAR nbt_encoded_shadow_name [NBT_ENCODED_NAME_LEN] = NBT_ENCODED_NAME_SHADOW; /* PROCEDURES */ BOOLEAN Tcpip_init ( PTCPIP_CTXT ctxtp, PVOID parameters) { ULONG i, j; PCVY_PARAMS params = (PCVY_PARAMS) parameters; /* extract cluster computer name from full internet name */ j = 0; while (params -> domain_name [j] != 0) { if (params -> domain_name [j] == L'.' || params -> domain_name [j] == 0) break; j ++; } /* build encoded cluster computer name for checking against arriving NBT session requests */ for (i = 0; i < NBT_NAME_LEN; i ++) { if (i >= j) { ctxtp -> nbt_encoded_cluster_name [2 * i] = NBT_ENCODE_FIRST (' '); ctxtp -> nbt_encoded_cluster_name [2 * i + 1] = NBT_ENCODE_SECOND (' '); } else { ctxtp -> nbt_encoded_cluster_name [2 * i] = NBT_ENCODE_FIRST (toupper ((UCHAR) (params -> domain_name [i]))); ctxtp -> nbt_encoded_cluster_name [2 * i + 1] = NBT_ENCODE_SECOND (toupper ((UCHAR) (params -> domain_name [i]))); } } return TRUE; } /* Tcpip_init */ VOID Tcpip_nbt_handle ( PTCPIP_CTXT ctxtp, PIP_HDR ip_hdrp, PTCP_HDR tcp_hdrp, ULONG len, PNBT_HDR nbt_hdrp) { PUCHAR called_name; ULONG i; /* if this is an NBT session request packet, check to see if it's calling the cluster machine name, which should be replaced with the shadow name */ if (len >= sizeof (NBT_HDR) && NBT_GET_PKT_TYPE (nbt_hdrp) == NBT_SESSION_REQUEST) { /* pass the field length byte - assume all names are NBT_ENCODED_NAME_LEN bytes long */ called_name = NBT_GET_CALLED_NAME (nbt_hdrp) + 1; /* match called name to cluster name */ for (i = 0; i < NBT_ENCODED_NAME_LEN; i ++) { if (called_name [i] != ctxtp -> nbt_encoded_cluster_name [i]) break; } /* replace cluster computer name with the shadom name */ if (i >= NBT_ENCODED_NAME_LEN) { USHORT checksum; for (i = 0; i < NBT_ENCODED_NAME_LEN; i ++) called_name [i] = nbt_encoded_shadow_name [i]; /* re-compute checksum */ checksum = Tcpip_chksum (ctxtp, ip_hdrp, (PUCHAR) tcp_hdrp, TCPIP_PROTOCOL_TCP); TCP_SET_CHKSUM (tcp_hdrp, checksum); } } } /* end Tcpip_nbt_handle */ USHORT Tcpip_chksum ( PTCPIP_CTXT ctxtp, PIP_HDR ip_hdrp, PUCHAR prot_hdrp, ULONG prot) { ULONG checksum = 0, i, len; PUCHAR ptr; USHORT original, tmp; /* preserve original checksum */ if (prot == TCPIP_PROTOCOL_TCP) { original = TCP_GET_CHKSUM ((PTCP_HDR) prot_hdrp); TCP_SET_CHKSUM ((PTCP_HDR) prot_hdrp, 0); } else if (prot == TCPIP_PROTOCOL_UDP) { original = UDP_GET_CHKSUM ((PUDP_HDR) prot_hdrp); UDP_SET_CHKSUM ((PUDP_HDR) prot_hdrp, 0); } else { original = IP_GET_CHKSUM (ip_hdrp); IP_SET_CHKSUM (ip_hdrp, 0); } /* computer appropriate checksum for specified protocol */ if (prot != TCPIP_PROTOCOL_IP) { /* checksum in computed over the source IP address, destination IP address, protocol (6 for TCP), TCP segment length value and entire TCP segment (setting checksum field within TCP header to 0). code is taken from page 185 of "Internetworking with TCP/IP: Volume II" by Comer/Stevens, 1991 */ ptr = (PUCHAR) IP_GET_SRC_ADDR_PTR (ip_hdrp); /* 2*IP_ADDR_LEN bytes = IP_ADDR_LEN shorts */ for (i = 0; i < IP_ADDR_LEN; i ++, ptr += 2) checksum += (ULONG) ((ptr [0] << 8) | ptr [1]); } if (prot == TCPIP_PROTOCOL_TCP) { len = IP_GET_PLEN (ip_hdrp) - IP_GET_HLEN (ip_hdrp) * sizeof (ULONG); checksum += TCPIP_PROTOCOL_TCP + len; ptr = prot_hdrp; } else if (prot == TCPIP_PROTOCOL_UDP) { len = IP_GET_PLEN (ip_hdrp) - IP_GET_HLEN (ip_hdrp) * sizeof (ULONG); checksum += TCPIP_PROTOCOL_UDP + UDP_GET_LEN ((PUDP_HDR) prot_hdrp); ptr = prot_hdrp; } else { len = IP_GET_HLEN (ip_hdrp) * sizeof (ULONG); ptr = (PUCHAR) ip_hdrp; prot_hdrp = (PUCHAR) ip_hdrp; } for (i = 0; i < len / 2; i ++, ptr += 2) checksum += (ULONG) ((ptr [0] << 8) | ptr [1]); if (len % 2) checksum += (ULONG) (prot_hdrp [len - 1] << 8); checksum = (checksum >> 16) + (checksum & 0xffff); checksum += (checksum >> 16); /* restore original checksum */ if (prot == TCPIP_PROTOCOL_TCP) { TCP_SET_CHKSUM ((PTCP_HDR) prot_hdrp, original); } else if (prot == TCPIP_PROTOCOL_UDP) { UDP_SET_CHKSUM ((PUDP_HDR) prot_hdrp, original); } else { IP_SET_CHKSUM (ip_hdrp, original); } return (USHORT) (~checksum & 0xffff); } /* end Tcpip_chksum */