/* * For backwards binary compatibility. The calculations done here can easily * result in buffer overreads and overwrites. You have been warned. And no, it * is not possible to fix, the API contains no information on the buffer's * boundary. libnet itself calls the safe function, libnet_inet_checksum(). So * should you. */ int libnet_do_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len) { uint16_t ip_len = 0; struct libnet_ipv4_hdr* ip4 = (struct libnet_ipv4_hdr *)iphdr; struct libnet_ipv6_hdr* ip6 = (struct libnet_ipv6_hdr *)iphdr; if(ip4->ip_v == 6) { ip_len = ntohs(ip6->ip_len); } else { ip_len = ntohs(ip4->ip_len); } return libnet_inet_checksum(l, iphdr, protocol, h_len, iphdr, iphdr + ip_len ); }
int libnet_win32_write_raw_ipv4(libnet_t *l, const uint8_t *payload, uint32_t payload_s) { static BYTE dst[ETHER_ADDR_LEN]; static BYTE src[ETHER_ADDR_LEN]; uint8_t *packet = NULL; uint32_t packet_s; LPPACKET lpPacket = NULL; DWORD remoteip = 0; DWORD BytesTransfered; NetType type; struct libnet_ipv4_hdr *ip_hdr = NULL; memset(dst, 0, sizeof(dst)); memset(src, 0, sizeof(src)); packet_s = payload_s + l->link_offset; packet = (uint8_t *)malloc(packet_s); if (packet == NULL) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): failed to allocate packet", __func__); return (-1); } /* FIXME all the return paths below, except the last, leak 'packet' */ /* we have to do the IP checksum */ /* FIXME MSVC warning is correct, checksum modifies its input. Fix is to build checksum inside the allocated 'packet' */ if (libnet_inet_checksum(l, payload, IPPROTO_IP, LIBNET_IPV4_H, payload, payload+payload_s) == -1) { /* error msg set in libnet_do_checksum */ return (-1); } /* MACs, IPs and other stuff... */ ip_hdr = (struct libnet_ipv4_hdr *)payload; memcpy(src, libnet_get_hwaddr(l), sizeof(src)); remoteip = ip_hdr->ip_dst.S_un.S_addr; /* check if the remote station is the local station */ if (remoteip == libnet_get_ipaddr4(l)) { memcpy(dst, src, sizeof(dst)); } else { memcpy(dst, libnet_win32_get_remote_mac(l, remoteip), sizeof(dst)); } PacketGetNetType(l->lpAdapter, &type); switch(type.LinkType) { case NdisMedium802_3: libnet_win32_build_fake_ethernet(dst, src, ETHERTYPE_IP, payload, payload_s, packet, l , 0); break; case NdisMedium802_5: libnet_win32_build_fake_token(dst, src, ETHERTYPE_IP, payload, payload_s, packet, l, 0); break; case NdisMediumFddi: break; case NdisMediumWan: case NdisMediumAtm: case NdisMediumArcnet878_2: default: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): network type (%d) is not supported", __func__, type.LinkType); return (-1); break; } BytesTransfered = -1; if ((lpPacket = PacketAllocatePacket()) == NULL) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): failed to allocate the LPPACKET structure", __func__); return (-1); } PacketInitPacket(lpPacket, packet, packet_s); /* PacketSendPacket returns a BOOLEAN */ if (PacketSendPacket(l->lpAdapter, lpPacket, TRUE)) { BytesTransfered = packet_s; } PacketFreePacket(lpPacket); free(packet); return (BytesTransfered); }