diff options
author | spz <spz@pkgsrc.org> | 2015-08-23 17:02:58 +0000 |
---|---|---|
committer | spz <spz@pkgsrc.org> | 2015-08-23 17:02:58 +0000 |
commit | 81a43da78ddcf4a497e0e4791fb2dd81374e679e (patch) | |
tree | 8a2072f465a7c2f253ecc2dc610c1f35653d2604 /sysutils/xentools45 | |
parent | 217eb63d2995ee25d5b1f90dae1bf9f325a68a58 (diff) | |
download | pkgsrc-81a43da78ddcf4a497e0e4791fb2dd81374e679e.tar.gz |
add the security patches for XSA-137, XSA-138, XSA-139 and XSA-140 from
upstream.
Diffstat (limited to 'sysutils/xentools45')
-rw-r--r-- | sysutils/xentools45/Makefile | 4 | ||||
-rw-r--r-- | sysutils/xentools45/distinfo | 6 | ||||
-rw-r--r-- | sysutils/xentools45/patches/patch-XSA137 | 175 | ||||
-rw-r--r-- | sysutils/xentools45/patches/patch-XSA138 | 175 | ||||
-rw-r--r-- | sysutils/xentools45/patches/patch-XSA139 | 28 | ||||
-rw-r--r-- | sysutils/xentools45/patches/patch-XSA140 | 433 |
6 files changed, 818 insertions, 3 deletions
diff --git a/sysutils/xentools45/Makefile b/sysutils/xentools45/Makefile index e10395a3ad2..7776e0e2c9d 100644 --- a/sysutils/xentools45/Makefile +++ b/sysutils/xentools45/Makefile @@ -1,11 +1,11 @@ -# $NetBSD: Makefile,v 1.14 2015/08/18 07:31:18 wiz Exp $ +# $NetBSD: Makefile,v 1.15 2015/08/23 17:02:58 spz Exp $ VERSION= 4.5.1 VERSION_IPXE= 9a93db3f0947484e30e753bbd61a10b17336e20e DISTNAME= xen-${VERSION} PKGNAME= xentools45-${VERSION} -PKGREVISION= 4 +PKGREVISION= 5 CATEGORIES= sysutils MASTER_SITES= http://bits.xensource.com/oss-xen/release/${VERSION}/ diff --git a/sysutils/xentools45/distinfo b/sysutils/xentools45/distinfo index 500c72ae99d..2f457aea8ff 100644 --- a/sysutils/xentools45/distinfo +++ b/sysutils/xentools45/distinfo @@ -1,4 +1,4 @@ -$NetBSD: distinfo,v 1.9 2015/06/23 17:45:33 bouyer Exp $ +$NetBSD: distinfo,v 1.10 2015/08/23 17:02:58 spz Exp $ SHA1 (ipxe-git-9a93db3f0947484e30e753bbd61a10b17336e20e.tar.gz) = fecadf952821e830ce1a1d19655288eef8488f88 RMD160 (ipxe-git-9a93db3f0947484e30e753bbd61a10b17336e20e.tar.gz) = 539bfa12db7054228250d6dd380bbf96c1a040f8 @@ -18,6 +18,10 @@ SHA1 (patch-.._docs_man_xlcpupool.cfg.pod.5) = b44813af965e4d9d0d51c18b22d286736 SHA1 (patch-Makefile) = 5d5b9678ed9764275ee95f49d24e8538a0e8a01c SHA1 (patch-Rules.mk) = e0dc4234c35dc2d78afad4a90b0af829a6a10b50 SHA1 (patch-XSA135) = c27b9c495d7348864e9939f54574e3afc37a816a +SHA1 (patch-XSA137) = 3e65d46768eb3a09dd44c2d78e1760070718cb79 +SHA1 (patch-XSA138) = ef04f40621073b1e936dfeb3711c6e9ae2a896c2 +SHA1 (patch-XSA139) = 3b86a578c86f5a3ecb127dede4bccf51d6bc7687 +SHA1 (patch-XSA140) = 55ef4eb9c4d09ac327f9600ac7553e92b9cd0624 SHA1 (patch-blktap_drivers_Makefile) = 7cc53b2a0dea1694a969046ab8542271ca63f9e7 SHA1 (patch-configure) = d1a1b9c9e00dd79bb872190282006201510ce2c1 SHA1 (patch-examples_Makefile) = 5fe7bb876d254cf0c4f774ed0f08dcaea5b355ff diff --git a/sysutils/xentools45/patches/patch-XSA137 b/sysutils/xentools45/patches/patch-XSA137 new file mode 100644 index 00000000000..d36320e12d9 --- /dev/null +++ b/sysutils/xentools45/patches/patch-XSA137 @@ -0,0 +1,175 @@ +$NetBSD: patch-XSA137,v 1.1 2015/08/23 17:02:58 spz Exp $ + +patch for CVE-2015-3259 aka XSA-137 from: +http://xenbits.xen.org/xsa/xsa137.patch + +--- libxl/xl_cmdimpl.c.orig 2015-06-22 13:41:35.000000000 +0000 ++++ libxl/xl_cmdimpl.c +@@ -151,7 +151,7 @@ struct domain_create { + int console_autoconnect; + int checkpointed_stream; + const char *config_file; +- const char *extra_config; /* extra config string */ ++ char *extra_config; /* extra config string */ + const char *restore_file; + int migrate_fd; /* -1 means none */ + char **migration_domname_r; /* from malloc */ +@@ -4570,11 +4570,25 @@ int main_vm_list(int argc, char **argv) + return 0; + } + ++static void string_realloc_append(char **accumulate, const char *more) ++{ ++ /* Appends more to accumulate. Accumulate is either NULL, or ++ * points (always) to a malloc'd nul-terminated string. */ ++ ++ size_t oldlen = *accumulate ? strlen(*accumulate) : 0; ++ size_t morelen = strlen(more) + 1/*nul*/; ++ if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) { ++ fprintf(stderr,"Additional config data far too large\n"); ++ exit(-ERROR_FAIL); ++ } ++ ++ *accumulate = xrealloc(*accumulate, oldlen + morelen); ++ memcpy(*accumulate + oldlen, more, morelen); ++} ++ + int main_create(int argc, char **argv) + { + const char *filename = NULL; +- char *p; +- char extra_config[1024]; + struct domain_create dom_info; + int paused = 0, debug = 0, daemonize = 1, console_autoconnect = 0, + quiet = 0, monitor = 1, vnc = 0, vncautopass = 0; +@@ -4589,6 +4603,8 @@ int main_create(int argc, char **argv) + {0, 0, 0, 0} + }; + ++ dom_info.extra_config = NULL; ++ + if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) { + filename = argv[1]; + argc--; argv++; +@@ -4628,20 +4644,21 @@ int main_create(int argc, char **argv) + break; + } + +- extra_config[0] = '\0'; +- for (p = extra_config; optind < argc; optind++) { ++ memset(&dom_info, 0, sizeof(dom_info)); ++ ++ for (; optind < argc; optind++) { + if (strchr(argv[optind], '=') != NULL) { +- p += snprintf(p, sizeof(extra_config) - (p - extra_config), +- "%s\n", argv[optind]); ++ string_realloc_append(&dom_info.extra_config, argv[optind]); ++ string_realloc_append(&dom_info.extra_config, "\n"); + } else if (!filename) { + filename = argv[optind]; + } else { + help("create"); ++ free(dom_info.extra_config); + return 2; + } + } + +- memset(&dom_info, 0, sizeof(dom_info)); + dom_info.debug = debug; + dom_info.daemonize = daemonize; + dom_info.monitor = monitor; +@@ -4649,16 +4666,18 @@ int main_create(int argc, char **argv) + dom_info.dryrun = dryrun_only; + dom_info.quiet = quiet; + dom_info.config_file = filename; +- dom_info.extra_config = extra_config; + dom_info.migrate_fd = -1; + dom_info.vnc = vnc; + dom_info.vncautopass = vncautopass; + dom_info.console_autoconnect = console_autoconnect; + + rc = create_domain(&dom_info); +- if (rc < 0) ++ if (rc < 0) { ++ free(dom_info.extra_config); + return -rc; ++ } + ++ free(dom_info.extra_config); + return 0; + } + +@@ -4666,8 +4685,7 @@ int main_config_update(int argc, char ** + { + uint32_t domid; + const char *filename = NULL; +- char *p; +- char extra_config[1024]; ++ char *extra_config = NULL; + void *config_data = 0; + int config_len = 0; + libxl_domain_config d_config; +@@ -4705,15 +4723,15 @@ int main_config_update(int argc, char ** + break; + } + +- extra_config[0] = '\0'; +- for (p = extra_config; optind < argc; optind++) { ++ for (; optind < argc; optind++) { + if (strchr(argv[optind], '=') != NULL) { +- p += snprintf(p, sizeof(extra_config) - (p - extra_config), +- "%s\n", argv[optind]); ++ string_realloc_append(&extra_config, argv[optind]); ++ string_realloc_append(&extra_config, "\n"); + } else if (!filename) { + filename = argv[optind]; + } else { + help("create"); ++ free(extra_config); + return 2; + } + } +@@ -4722,7 +4740,8 @@ int main_config_update(int argc, char ** + rc = libxl_read_file_contents(ctx, filename, + &config_data, &config_len); + if (rc) { fprintf(stderr, "Failed to read config file: %s: %s\n", +- filename, strerror(errno)); return ERROR_FAIL; } ++ filename, strerror(errno)); ++ free(extra_config); return ERROR_FAIL; } + if (strlen(extra_config)) { + if (config_len > INT_MAX - (strlen(extra_config) + 2 + 1)) { + fprintf(stderr, "Failed to attach extra configration\n"); +@@ -4763,7 +4782,7 @@ int main_config_update(int argc, char ** + libxl_domain_config_dispose(&d_config); + + free(config_data); +- ++ free(extra_config); + return 0; + } + +@@ -7020,7 +7039,7 @@ int main_cpupoolcreate(int argc, char ** + { + const char *filename = NULL, *config_src=NULL; + const char *p; +- char extra_config[1024]; ++ char *extra_config = NULL; + int opt; + static struct option opts[] = { + {"defconfig", 1, 0, 'f'}, +@@ -7054,13 +7073,10 @@ int main_cpupoolcreate(int argc, char ** + break; + } + +- memset(extra_config, 0, sizeof(extra_config)); + while (optind < argc) { + if ((p = strchr(argv[optind], '='))) { +- if (strlen(extra_config) + 1 + strlen(argv[optind]) < sizeof(extra_config)) { +- strcat(extra_config, "\n"); +- strcat(extra_config, argv[optind]); +- } ++ string_realloc_append(&extra_config, "\n"); ++ string_realloc_append(&extra_config, argv[optind]); + } else if (!filename) { + filename = argv[optind]; + } else { diff --git a/sysutils/xentools45/patches/patch-XSA138 b/sysutils/xentools45/patches/patch-XSA138 new file mode 100644 index 00000000000..196066a7bd0 --- /dev/null +++ b/sysutils/xentools45/patches/patch-XSA138 @@ -0,0 +1,175 @@ +$NetBSD: patch-XSA138,v 1.1 2015/08/23 17:02:58 spz Exp $ + +patch for CVE-2015-5154 from XSA-138 from +http://xenbits.xen.org/xsa/xsa138-qemut-1.patch +http://xenbits.xen.org/xsa/xsa138-qemut-2.patch +http://xenbits.xen.org/xsa/xsa138-qemuu-1.patch +http://xenbits.xen.org/xsa/xsa138-qemuu-2.patch +http://xenbits.xen.org/xsa/xsa138-qemuu-3.patch + +--- qemu-xen/hw/ide/core.c.orig 2015-06-10 11:43:51.000000000 +0000 ++++ qemu-xen/hw/ide/core.c +@@ -1901,11 +1901,17 @@ void ide_data_writew(void *opaque, uint3 + } + + p = s->data_ptr; ++ if (p + 2 > s->data_end) { ++ return; ++ } ++ + *(uint16_t *)p = le16_to_cpu(val); + p += 2; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + } + + uint32_t ide_data_readw(void *opaque, uint32_t addr) +@@ -1922,11 +1928,17 @@ uint32_t ide_data_readw(void *opaque, ui + } + + p = s->data_ptr; ++ if (p + 2 > s->data_end) { ++ return 0; ++ } ++ + ret = cpu_to_le16(*(uint16_t *)p); + p += 2; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + return ret; + } + +@@ -1943,11 +1955,17 @@ void ide_data_writel(void *opaque, uint3 + } + + p = s->data_ptr; ++ if (p + 4 > s->data_end) { ++ return; ++ } ++ + *(uint32_t *)p = le32_to_cpu(val); + p += 4; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + } + + uint32_t ide_data_readl(void *opaque, uint32_t addr) +@@ -1964,11 +1982,17 @@ uint32_t ide_data_readl(void *opaque, ui + } + + p = s->data_ptr; ++ if (p + 4 > s->data_end) { ++ return 0; ++ } ++ + ret = cpu_to_le32(*(uint32_t *)p); + p += 4; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + return ret; + } + +--- qemu-xen/hw/ide/atapi.c.orig 2015-06-10 11:43:51.000000000 +0000 ++++ qemu-xen/hw/ide/atapi.c +@@ -879,6 +879,7 @@ static void cmd_start_stop_unit(IDEState + + if (pwrcnd) { + /* eject/load only happens for power condition == 0 */ ++ ide_atapi_cmd_ok(s); + return; + } + +--- qemu-xen-traditional/hw/ide.c.orig 2015-08-23 15:08:13.000000000 +0000 ++++ qemu-xen-traditional/hw/ide.c +@@ -3006,11 +3006,17 @@ static void ide_data_writew(void *opaque + buffered_pio_write(s, addr, 2); + + p = s->data_ptr; ++ if (p + 2 > s->data_end) { ++ return; ++ } ++ + *(uint16_t *)p = le16_to_cpu(val); + p += 2; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + } + + static uint32_t ide_data_readw(void *opaque, uint32_t addr) +@@ -3025,11 +3031,17 @@ static uint32_t ide_data_readw(void *opa + buffered_pio_read(s, addr, 2); + + p = s->data_ptr; ++ if (p + 2 > s->data_end) { ++ return 0; ++ } ++ + ret = cpu_to_le16(*(uint16_t *)p); + p += 2; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + return ret; + } + +@@ -3044,11 +3056,17 @@ static void ide_data_writel(void *opaque + buffered_pio_write(s, addr, 4); + + p = s->data_ptr; ++ if (p + 4 > s->data_end) { ++ return; ++ } ++ + *(uint32_t *)p = le32_to_cpu(val); + p += 4; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + } + + static uint32_t ide_data_readl(void *opaque, uint32_t addr) +@@ -3063,11 +3081,17 @@ static uint32_t ide_data_readl(void *opa + buffered_pio_read(s, addr, 4); + + p = s->data_ptr; ++ if (p + 4 > s->data_end) { ++ return 0; ++ } ++ + ret = cpu_to_le32(*(uint32_t *)p); + p += 4; + s->data_ptr = p; +- if (p >= s->data_end) ++ if (p >= s->data_end) { ++ s->status &= ~DRQ_STAT; + s->end_transfer_func(s); ++ } + return ret; + } + diff --git a/sysutils/xentools45/patches/patch-XSA139 b/sysutils/xentools45/patches/patch-XSA139 new file mode 100644 index 00000000000..ffff15d5cdd --- /dev/null +++ b/sysutils/xentools45/patches/patch-XSA139 @@ -0,0 +1,28 @@ +$NetBSD: patch-XSA139,v 1.1 2015/08/23 17:02:58 spz Exp $ + +patch for CVE-2015-5166 aka XSA-139 from +http://xenbits.xen.org/xsa/xsa139-qemuu-4.5.patch + +--- qemu-xen/hw/ide/piix.c.orig 2015-06-10 11:43:51.000000000 +0000 ++++ qemu-xen/hw/ide/piix.c +@@ -172,6 +172,7 @@ int pci_piix3_xen_ide_unplug(DeviceState + PCIIDEState *pci_ide; + DriveInfo *di; + int i = 0; ++ IDEDevice *idedev; + + pci_ide = PCI_IDE(dev); + +@@ -184,6 +185,12 @@ int pci_piix3_xen_ide_unplug(DeviceState + } + bdrv_close(di->bdrv); + pci_ide->bus[di->bus].ifs[di->unit].bs = NULL; ++ if (!(i % 2)) { ++ idedev = pci_ide->bus[di->bus].master; ++ } else { ++ idedev = pci_ide->bus[di->bus].slave; ++ } ++ idedev->conf.bs = NULL; + drive_put_ref(di); + } + } diff --git a/sysutils/xentools45/patches/patch-XSA140 b/sysutils/xentools45/patches/patch-XSA140 new file mode 100644 index 00000000000..64199e48c3e --- /dev/null +++ b/sysutils/xentools45/patches/patch-XSA140 @@ -0,0 +1,433 @@ +$NetBSD: patch-XSA140,v 1.1 2015/08/23 17:02:58 spz Exp $ + +patch for CVE-2015-5165 aka XSA-140 from +http://xenbits.xen.org/xsa/xsa140-qemuu-unstable-1.patch +http://xenbits.xen.org/xsa/xsa140-qemuu-unstable-2.patch +http://xenbits.xen.org/xsa/xsa140-qemuu-unstable-3.patch +http://xenbits.xen.org/xsa/xsa140-qemuu-unstable-4.patch +http://xenbits.xen.org/xsa/xsa140-qemuu-unstable-5.patch +http://xenbits.xen.org/xsa/xsa140-qemuu-unstable-6.patch +http://xenbits.xen.org/xsa/xsa140-qemuu-unstable-7.patch + +--- qemu-xen/hw/net/rtl8139.c.orig 2015-06-10 11:43:51.000000000 +0000 ++++ qemu-xen/hw/net/rtl8139.c +@@ -2161,6 +2161,11 @@ static int rtl8139_cplus_transmit_one(RT + { + DPRINTF("+++ C+ mode offloaded task checksum\n"); + ++ /* Large enough for Ethernet and IP headers? */ ++ if (saved_size < ETH_HLEN + sizeof(ip_header)) { ++ goto skip_offload; ++ } ++ + /* ip packet header */ + ip_header *ip = NULL; + int hlen = 0; +@@ -2171,223 +2176,235 @@ static int rtl8139_cplus_transmit_one(RT + size_t eth_payload_len = 0; + + int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12)); +- if (proto == ETH_P_IP) ++ if (proto != ETH_P_IP) + { +- DPRINTF("+++ C+ mode has IP packet\n"); ++ goto skip_offload; ++ } + +- /* not aligned */ +- eth_payload_data = saved_buffer + ETH_HLEN; +- eth_payload_len = saved_size - ETH_HLEN; +- +- ip = (ip_header*)eth_payload_data; +- +- if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { +- DPRINTF("+++ C+ mode packet has bad IP version %d " +- "expected %d\n", IP_HEADER_VERSION(ip), +- IP_HEADER_VERSION_4); +- ip = NULL; +- } else { +- hlen = IP_HEADER_LENGTH(ip); +- ip_protocol = ip->ip_p; +- ip_data_len = be16_to_cpu(ip->ip_len) - hlen; +- } ++ DPRINTF("+++ C+ mode has IP packet\n"); ++ ++ /* not aligned */ ++ eth_payload_data = saved_buffer + ETH_HLEN; ++ eth_payload_len = saved_size - ETH_HLEN; ++ ++ ip = (ip_header*)eth_payload_data; ++ ++ if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { ++ DPRINTF("+++ C+ mode packet has bad IP version %d " ++ "expected %d\n", IP_HEADER_VERSION(ip), ++ IP_HEADER_VERSION_4); ++ goto skip_offload; ++ } ++ ++ hlen = IP_HEADER_LENGTH(ip); ++ if (hlen < sizeof(ip_header) || hlen > eth_payload_len) { ++ goto skip_offload; + } + +- if (ip) ++ ip_protocol = ip->ip_p; ++ ++ ip_data_len = be16_to_cpu(ip->ip_len); ++ if (ip_data_len < hlen || ip_data_len > eth_payload_len) { ++ goto skip_offload; ++ } ++ ip_data_len -= hlen; ++ ++ if (txdw0 & CP_TX_IPCS) + { +- if (txdw0 & CP_TX_IPCS) +- { +- DPRINTF("+++ C+ mode need IP checksum\n"); ++ DPRINTF("+++ C+ mode need IP checksum\n"); + +- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */ +- /* bad packet header len */ +- /* or packet too short */ +- } +- else +- { +- ip->ip_sum = 0; +- ip->ip_sum = ip_checksum(ip, hlen); +- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", +- hlen, ip->ip_sum); +- } ++ ip->ip_sum = 0; ++ ip->ip_sum = ip_checksum(ip, hlen); ++ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n", ++ hlen, ip->ip_sum); ++ } ++ ++ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) ++ { ++ /* Large enough for the TCP header? */ ++ if (ip_data_len < sizeof(tcp_header)) { ++ goto skip_offload; + } + +- if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP) +- { +- int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK; ++ int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK; + +- DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d " +- "frame data %d specified MSS=%d\n", ETH_MTU, +- ip_data_len, saved_size - ETH_HLEN, large_send_mss); ++ DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d " ++ "frame data %d specified MSS=%d\n", ETH_MTU, ++ ip_data_len, saved_size - ETH_HLEN, large_send_mss); + +- int tcp_send_offset = 0; +- int send_count = 0; ++ int tcp_send_offset = 0; ++ int send_count = 0; + +- /* maximum IP header length is 60 bytes */ +- uint8_t saved_ip_header[60]; ++ /* maximum IP header length is 60 bytes */ ++ uint8_t saved_ip_header[60]; + +- /* save IP header template; data area is used in tcp checksum calculation */ +- memcpy(saved_ip_header, eth_payload_data, hlen); ++ /* save IP header template; data area is used in tcp checksum calculation */ ++ memcpy(saved_ip_header, eth_payload_data, hlen); + +- /* a placeholder for checksum calculation routine in tcp case */ +- uint8_t *data_to_checksum = eth_payload_data + hlen - 12; +- // size_t data_to_checksum_len = eth_payload_len - hlen + 12; ++ /* a placeholder for checksum calculation routine in tcp case */ ++ uint8_t *data_to_checksum = eth_payload_data + hlen - 12; ++ // size_t data_to_checksum_len = eth_payload_len - hlen + 12; + +- /* pointer to TCP header */ +- tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); ++ /* pointer to TCP header */ ++ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen); + +- int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); ++ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr); + +- /* ETH_MTU = ip header len + tcp header len + payload */ +- int tcp_data_len = ip_data_len - tcp_hlen; +- int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; ++ /* Invalid TCP data offset? */ ++ if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) { ++ goto skip_offload; ++ } + +- DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " +- "data len %d TCP chunk size %d\n", ip_data_len, +- tcp_hlen, tcp_data_len, tcp_chunk_size); ++ /* ETH_MTU = ip header len + tcp header len + payload */ ++ int tcp_data_len = ip_data_len - tcp_hlen; ++ int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen; + +- /* note the cycle below overwrites IP header data, +- but restores it from saved_ip_header before sending packet */ ++ DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP " ++ "data len %d TCP chunk size %d\n", ip_data_len, ++ tcp_hlen, tcp_data_len, tcp_chunk_size); + +- int is_last_frame = 0; ++ /* note the cycle below overwrites IP header data, ++ but restores it from saved_ip_header before sending packet */ + +- for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size) +- { +- uint16_t chunk_size = tcp_chunk_size; ++ int is_last_frame = 0; + +- /* check if this is the last frame */ +- if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) +- { +- is_last_frame = 1; +- chunk_size = tcp_data_len - tcp_send_offset; +- } +- +- DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", +- be32_to_cpu(p_tcp_hdr->th_seq)); +- +- /* add 4 TCP pseudoheader fields */ +- /* copy IP source and destination fields */ +- memcpy(data_to_checksum, saved_ip_header + 12, 8); +- +- DPRINTF("+++ C+ mode TSO calculating TCP checksum for " +- "packet with %d bytes data\n", tcp_hlen + +- chunk_size); +- +- if (tcp_send_offset) +- { +- memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); +- } +- +- /* keep PUSH and FIN flags only for the last frame */ +- if (!is_last_frame) +- { +- TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN); +- } +- +- /* recalculate TCP checksum */ +- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; +- p_tcpip_hdr->zeros = 0; +- p_tcpip_hdr->ip_proto = IP_PROTO_TCP; +- p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); +- +- p_tcp_hdr->th_sum = 0; +- +- int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); +- DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", +- tcp_checksum); +- +- p_tcp_hdr->th_sum = tcp_checksum; +- +- /* restore IP header */ +- memcpy(eth_payload_data, saved_ip_header, hlen); +- +- /* set IP data length and recalculate IP checksum */ +- ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size); +- +- /* increment IP id for subsequent frames */ +- ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id)); +- +- ip->ip_sum = 0; +- ip->ip_sum = ip_checksum(eth_payload_data, hlen); +- DPRINTF("+++ C+ mode TSO IP header len=%d " +- "checksum=%04x\n", hlen, ip->ip_sum); +- +- int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; +- DPRINTF("+++ C+ mode TSO transferring packet size " +- "%d\n", tso_send_size); +- rtl8139_transfer_frame(s, saved_buffer, tso_send_size, +- 0, (uint8_t *) dot1q_buffer); +- +- /* add transferred count to TCP sequence number */ +- p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq)); +- ++send_count; +- } +- +- /* Stop sending this frame */ +- saved_size = 0; +- } +- else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS)) ++ for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size) + { +- DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); ++ uint16_t chunk_size = tcp_chunk_size; + +- /* maximum IP header length is 60 bytes */ +- uint8_t saved_ip_header[60]; +- memcpy(saved_ip_header, eth_payload_data, hlen); ++ /* check if this is the last frame */ ++ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) ++ { ++ is_last_frame = 1; ++ chunk_size = tcp_data_len - tcp_send_offset; ++ } + +- uint8_t *data_to_checksum = eth_payload_data + hlen - 12; +- // size_t data_to_checksum_len = eth_payload_len - hlen + 12; ++ DPRINTF("+++ C+ mode TSO TCP seqno %08x\n", ++ be32_to_cpu(p_tcp_hdr->th_seq)); + + /* add 4 TCP pseudoheader fields */ + /* copy IP source and destination fields */ + memcpy(data_to_checksum, saved_ip_header + 12, 8); + +- if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) ++ DPRINTF("+++ C+ mode TSO calculating TCP checksum for " ++ "packet with %d bytes data\n", tcp_hlen + ++ chunk_size); ++ ++ if (tcp_send_offset) ++ { ++ memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size); ++ } ++ ++ /* keep PUSH and FIN flags only for the last frame */ ++ if (!is_last_frame) + { +- DPRINTF("+++ C+ mode calculating TCP checksum for " +- "packet with %d bytes data\n", ip_data_len); ++ TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN); ++ } + +- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; +- p_tcpip_hdr->zeros = 0; +- p_tcpip_hdr->ip_proto = IP_PROTO_TCP; +- p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); ++ /* recalculate TCP checksum */ ++ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; ++ p_tcpip_hdr->zeros = 0; ++ p_tcpip_hdr->ip_proto = IP_PROTO_TCP; ++ p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size); ++ ++ p_tcp_hdr->th_sum = 0; ++ ++ int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12); ++ DPRINTF("+++ C+ mode TSO TCP checksum %04x\n", ++ tcp_checksum); + +- tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12); ++ p_tcp_hdr->th_sum = tcp_checksum; + +- p_tcp_hdr->th_sum = 0; ++ /* restore IP header */ ++ memcpy(eth_payload_data, saved_ip_header, hlen); + +- int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); +- DPRINTF("+++ C+ mode TCP checksum %04x\n", +- tcp_checksum); ++ /* set IP data length and recalculate IP checksum */ ++ ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size); + +- p_tcp_hdr->th_sum = tcp_checksum; +- } +- else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) +- { +- DPRINTF("+++ C+ mode calculating UDP checksum for " +- "packet with %d bytes data\n", ip_data_len); ++ /* increment IP id for subsequent frames */ ++ ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id)); + +- ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; +- p_udpip_hdr->zeros = 0; +- p_udpip_hdr->ip_proto = IP_PROTO_UDP; +- p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); ++ ip->ip_sum = 0; ++ ip->ip_sum = ip_checksum(eth_payload_data, hlen); ++ DPRINTF("+++ C+ mode TSO IP header len=%d " ++ "checksum=%04x\n", hlen, ip->ip_sum); ++ ++ int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size; ++ DPRINTF("+++ C+ mode TSO transferring packet size " ++ "%d\n", tso_send_size); ++ rtl8139_transfer_frame(s, saved_buffer, tso_send_size, ++ 0, (uint8_t *) dot1q_buffer); ++ ++ /* add transferred count to TCP sequence number */ ++ p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq)); ++ ++send_count; ++ } + +- udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12); ++ /* Stop sending this frame */ ++ saved_size = 0; ++ } ++ else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS)) ++ { ++ DPRINTF("+++ C+ mode need TCP or UDP checksum\n"); + +- p_udp_hdr->uh_sum = 0; ++ /* maximum IP header length is 60 bytes */ ++ uint8_t saved_ip_header[60]; ++ memcpy(saved_ip_header, eth_payload_data, hlen); + +- int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); +- DPRINTF("+++ C+ mode UDP checksum %04x\n", +- udp_checksum); ++ uint8_t *data_to_checksum = eth_payload_data + hlen - 12; ++ // size_t data_to_checksum_len = eth_payload_len - hlen + 12; + +- p_udp_hdr->uh_sum = udp_checksum; +- } ++ /* add 4 TCP pseudoheader fields */ ++ /* copy IP source and destination fields */ ++ memcpy(data_to_checksum, saved_ip_header + 12, 8); + +- /* restore IP header */ +- memcpy(eth_payload_data, saved_ip_header, hlen); ++ if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP) ++ { ++ DPRINTF("+++ C+ mode calculating TCP checksum for " ++ "packet with %d bytes data\n", ip_data_len); ++ ++ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum; ++ p_tcpip_hdr->zeros = 0; ++ p_tcpip_hdr->ip_proto = IP_PROTO_TCP; ++ p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len); ++ ++ tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12); ++ ++ p_tcp_hdr->th_sum = 0; ++ ++ int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); ++ DPRINTF("+++ C+ mode TCP checksum %04x\n", ++ tcp_checksum); ++ ++ p_tcp_hdr->th_sum = tcp_checksum; + } ++ else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP) ++ { ++ DPRINTF("+++ C+ mode calculating UDP checksum for " ++ "packet with %d bytes data\n", ip_data_len); ++ ++ ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum; ++ p_udpip_hdr->zeros = 0; ++ p_udpip_hdr->ip_proto = IP_PROTO_UDP; ++ p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len); ++ ++ udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12); ++ ++ p_udp_hdr->uh_sum = 0; ++ ++ int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12); ++ DPRINTF("+++ C+ mode UDP checksum %04x\n", ++ udp_checksum); ++ ++ p_udp_hdr->uh_sum = udp_checksum; ++ } ++ ++ /* restore IP header */ ++ memcpy(eth_payload_data, saved_ip_header, hlen); + } + } + ++skip_offload: + /* update tally counter */ + ++s->tally_counters.TxOk; + |