...
 
Commits (2)
  • Mike Hibler's avatar
    Welcome back Big Endian, haven't seen you since the early 1990s! · 1220ad49
    Mike Hibler authored
    Hack support for big-endian. It appears to work, but I stopped testing
    when we found out the HP moonshot ARM cartridges are little-endian.
    
    The approach here is that little-endian is the "native" imagezip format.
    This makes backward compat easy and works most efficiently for the common
    (still 100%) case of little-endian machines.
    
    For frisbee, little-endian is also the default on-wire format...except
    for the master server protocol which properly uses network order.
    That should be fixed, but will require a version bump.
    
    This stuff will likely get pulled into the main branch when the next
    major version happens. RSN.
    1220ad49
  • Mike Hibler's avatar
    Oops, put default back to little-endian. · 1f246e8f
    Mike Hibler authored
    Had it big-endian for initial testing.
    1f246e8f
......@@ -107,7 +107,7 @@ CLIENTLIBS = -lrt -lz $(PTHREADLIBS)
else
CLIENTLIBS = -lz $(PTHREADLIBS)
endif
CLIENTOBJS = client.o frisbee.o checksum.o disksize.o $(SHAREDOBJS)
CLIENTOBJS = client.o frisbee.o checksum.o disksize.o header.o $(SHAREDOBJS)
SERVERFLAGS = $(CFLAGS)
SERVERLIBS = $(PTHREADLIBS)
......@@ -149,7 +149,7 @@ MSERVEROBJS += config_emulab.o
MSERVERLIBS += $(TESTBED_LIBOBJDIR)/libtb/libtb.a $(MYSQLLIBS)
endif
CFLAGS = -O2 -g -Wall -fno-builtin-log $(LDSTATIC) $(PTHREADCFLAGS) -DSTATS -DMASTER_SERVER
CFLAGS = -O2 -g -Wall -fno-builtin-log $(LDSTATIC) $(PTHREADCFLAGS) -DSTATS -DMASTER_SERVER -DENDIAN_HACK
LDFLAGS = $(LDSTATIC)
IUZFLAGS = -DFRISBEE
......@@ -266,6 +266,9 @@ disksize.o: $(FRISBEEDIR)/disksize.c
checksum.o: $(FRISBEEDIR)/checksum.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -I$(FRISBEEDIR) -o checksum.o $<
header.o: $(FRISBEEDIR)/header.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -I$(FRISBEEDIR) -o header.o $<
frisbee.o: $(FRISBEEDIR)/imageunzip.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -I$(FRISBEEDIR) -o frisbee.o $<
......
......@@ -42,6 +42,9 @@ PTHREADCFLAGS = -D_THREAD_SAFE -pthread
LINUXOPTS = -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE \
-D_XOPEN_SOURCE=500 -D_BSD_SOURCE=1
# XXX hack test of endian-ness
LINUXOPTS += -DENDIAN_HACK
#
# STATIC = yes|no|fail
#
......@@ -66,7 +69,7 @@ endif
CLIENTFLAGS = $(CFLAGS)
CLIENTLIBS = -lz -lrt $(PTHREADLIBS)
CLIENTOBJS = client.o frisbee.o checksum.o disksize.o $(SHAREDOBJS)
CLIENTOBJS = client.o frisbee.o checksum.o disksize.o header.o $(SHAREDOBJS)
SERVERFLAGS = $(CFLAGS)
SERVERLIBS = $(PTHREADLIBS)
......@@ -141,6 +144,9 @@ frisbee.o: $(IMAGEZIPDIR)/imageunzip.c
checksum.o: $(IMAGEZIPDIR)/checksum.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -DFRISBEE -I$(IMAGEZIPDIR) -o checksum.o $<
header.o: $(IMAGEZIPDIR)/header.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -DFRISBEE -I$(IMAGEZIPDIR) -o header.o $<
client.o: decls.h log.h utils.h trace.h
server.o: decls.h log.h utils.h trace.h
log.o: decls.h log.h
......
#
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# Copyright (c) 2000-2014 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -21,6 +21,10 @@
# }}}
#
# Set to 1 for "secure frisbee" support. Requires openssl libraries.
WITH_CRYPTO = 1
WITH_SIGNING = 1
#
# Makefile for the standalone version of frisbee.
# (Standalone meaning not part of the Netbed build environment.)
......@@ -38,7 +42,7 @@ PTHREADLIBS = -L/usr/local/lib -llthread -llgcc_r
CLIENTFLAGS = $(CFLAGS)
CLIENTLIBS = -lz $(PTHREADLIBS)
CLIENTOBJS = client.o frisbee.o $(SHAREDOBJS)
CLIENTOBJS = client.o frisbee.o checksum.o disksize.o header.o $(SHAREDOBJS)
SERVERFLAGS = $(CFLAGS)
SERVERLIBS = $(PTHREADLIBS)
......@@ -94,6 +98,15 @@ frisbee.o: $(IMAGEZIPDIR)/imageunzip.c
$(CC) -c $(CFLAGS) -DFRISBEE -I$(IMAGEZIPDIR) -o frisbee.o \
$(IMAGEZIPDIR)/imageunzip.c
disksize.o: $(IMAGEZIPDIR)/disksize.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -DFRISBEE -I$(IMAGEZIPDIR) -o disksize.o $<
checksum.o: $(IMAGEZIPDIR)/checksum.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -DFRISBEE -I$(IMAGEZIPDIR) -o checksum.o $<
header.o: $(IMAGEZIPDIR)/header.c
$(CC) -c $(CFLAGS) $(IUZFLAGS) -DFRISBEE -I$(IMAGEZIPDIR) -o header.o $<
client.o: decls.h log.h utils.h trace.h
server.o: decls.h log.h utils.h trace.h
log.o: decls.h log.h
......
......@@ -44,6 +44,43 @@
#include <sys/select.h>
#endif
/*
* Make the client/server explicitly speak little endian over the net.
* This is oh so wrong, but avoid compatibility issues for the moment.
*/
#ifdef ENDIAN_HACK
#ifdef __linux__
#include <endian.h>
#define _LITTLE_ENDIAN __LITTLE_ENDIAN
#define _BIG_ENDIAN __BIG_ENDIAN
#define _LITTLE_ENDIAN __LITTLE_ENDIAN
#define _BYTE_ORDER __BYTE_ORDER
#else
#include <sys/endian.h>
#endif
/* XXX temporary for testing: DO NOT CHANGE FROM _LITTLE_ENDIAN OTHERWISE */
//#define FRIS_BYTE_ORDER _BIG_ENDIAN
#define FRIS_BYTE_ORDER _LITTLE_ENDIAN
#if FRIS_BYTE_ORDER == _LITTLE_ENDIAN
#define htofris16(x) htole16(x)
#define htofris32(x) htole32(x)
#define htofris64(x) htole64(x)
#define fristoh16(x) le16toh(x)
#define fristoh32(x) le32toh(x)
#define fristoh64(x) le64toh(x)
#else
#define htofris16(x) htobe16(x)
#define htofris32(x) htobe32(x)
#define htofris64(x) htobe64(x)
#define fristoh16(x) be16toh(x)
#define fristoh32(x) be32toh(x)
#define fristoh64(x) be64toh(x)
#endif
#endif
#ifdef STATS
unsigned long nonetbufs;
#define DOSTAT(x) (x)
......@@ -92,7 +129,6 @@ GetIP(char *str, struct in_addr *in)
int
GetSockbufSize(void)
{
static int sbsize = 0;
if (sbsize == 0) {
......@@ -415,6 +451,218 @@ NetMCKeepAlive(void)
return 0;
}
/*
* Convert from wire format to host format.
*
* If there are any problems just stop and return,
* the caller will deal with errors.
*/
static void
PacketFromWire(Packet_t *p, int mlen)
{
#ifdef ENDIAN_HACK
#if _BYTE_ORDER != FRIS_BYTE_ORDER
if (mlen < sizeof(p->hdr))
return;
p->hdr.type = fristoh32(p->hdr.type);
p->hdr.subtype = fristoh32(p->hdr.subtype);
p->hdr.datalen = fristoh32(p->hdr.datalen);
p->hdr.srcip = fristoh32(p->hdr.srcip);
switch (p->hdr.subtype) {
case PKTSUBTYPE_BLOCK:
if (p->hdr.datalen < sizeof(p->msg.block))
return;
p->msg.block.chunk = fristoh32(p->msg.block.chunk);
p->msg.block.block = fristoh32(p->msg.block.block);
break;
case PKTSUBTYPE_REQUEST:
if (p->hdr.datalen < sizeof(p->msg.request))
return;
p->msg.request.chunk = fristoh32(p->msg.request.chunk);
p->msg.request.block = fristoh32(p->msg.request.block);
p->msg.request.count = fristoh32(p->msg.request.count);
break;
case PKTSUBTYPE_PREQUEST:
if (p->hdr.datalen < sizeof(p->msg.prequest))
return;
p->msg.prequest.chunk = fristoh32(p->msg.prequest.chunk);
p->msg.prequest.retries = fristoh32(p->msg.prequest.retries);
/* I think the blockmap is okay */
break;
case PKTSUBTYPE_JOIN:
if (p->hdr.datalen < sizeof(p->msg.join))
return;
p->msg.join.clientid = fristoh32(p->msg.join.clientid);
break;
case PKTSUBTYPE_JOIN2:
if (p->hdr.datalen < sizeof(p->msg.join2))
return;
p->msg.join2.clientid = fristoh32(p->msg.join2.clientid);
p->msg.join2.blockcount = fristoh32(p->msg.join2.blockcount);
p->msg.join2.chunksize = fristoh32(p->msg.join2.chunksize);
p->msg.join2.blocksize = fristoh32(p->msg.join2.blocksize);
p->msg.join2.bytecount = fristoh64(p->msg.join2.bytecount);
break;
case PKTSUBTYPE_LEAVE:
if (p->hdr.datalen < sizeof(p->msg.leave))
return;
p->msg.leave.clientid = fristoh32(p->msg.leave.clientid);
p->msg.leave.elapsed = fristoh32(p->msg.leave.elapsed);
break;
case PKTSUBTYPE_LEAVE2:
if (p->hdr.datalen < sizeof(p->msg.leave2))
return;
p->msg.leave2.clientid = fristoh32(p->msg.leave2.clientid);
p->msg.leave2.elapsed = fristoh32(p->msg.leave2.elapsed);
#define TWEAK32(F) p->msg.leave2.stats.u.v1.F = fristoh32(p->msg.leave2.stats.u.v1.F)
#define TWEAK64(F) p->msg.leave2.stats.u.v1.F = fristoh64(p->msg.leave2.stats.u.v1.F)
TWEAK32(runsec);
TWEAK32(runmsec);
TWEAK32(delayms);
TWEAK64(rbyteswritten);
TWEAK64(ebyteswritten);
TWEAK32(chunkbufs);
TWEAK32(maxreadahead);
TWEAK32(maxinprogress);
TWEAK32(pkttimeout);
TWEAK32(startdelay);
TWEAK32(idletimer);
TWEAK32(idledelay);
TWEAK32(redodelay);
TWEAK32(randomize);
TWEAK32(nochunksready);
TWEAK32(nofreechunks);
TWEAK32(dupchunk);
TWEAK32(dupblock);
TWEAK32(prequests);
TWEAK32(recvidles);
TWEAK32(joinattempts);
TWEAK32(requests);
TWEAK32(decompblocks);
TWEAK32(writeridles);
TWEAK32(writebufmem);
TWEAK32(lostblocks);
TWEAK32(rerequests);
TWEAK32(partialdrops);
TWEAK32(fullrerequests);
#undef TWEAK32
#undef TWEAK64
break;
}
#endif
#endif
}
/*
* Convert to wire format from host format.
*
* If there are any problems just stop and return,
* the caller will deal with errors.
*/
static void
PacketToWire(Packet_t *p, int mlen)
{
#ifdef ENDIAN_HACK
#if _BYTE_ORDER != FRIS_BYTE_ORDER
int32_t subtype, datalen;
if (mlen < sizeof(p->hdr))
return;
subtype = p->hdr.subtype;
datalen = p->hdr.datalen;
p->hdr.type = htofris32(p->hdr.type);
p->hdr.subtype = htofris32(p->hdr.subtype);
p->hdr.datalen = htofris32(p->hdr.datalen);
p->hdr.srcip = htofris32(p->hdr.srcip);
switch (subtype) {
case PKTSUBTYPE_BLOCK:
if (datalen < sizeof(p->msg.block))
return;
p->msg.block.chunk = htofris32(p->msg.block.chunk);
p->msg.block.block = htofris32(p->msg.block.block);
break;
case PKTSUBTYPE_REQUEST:
if (datalen < sizeof(p->msg.request))
return;
p->msg.request.chunk = htofris32(p->msg.request.chunk);
p->msg.request.block = htofris32(p->msg.request.block);
p->msg.request.count = htofris32(p->msg.request.count);
break;
case PKTSUBTYPE_PREQUEST:
if (datalen < sizeof(p->msg.prequest))
return;
p->msg.prequest.chunk = htofris32(p->msg.prequest.chunk);
p->msg.prequest.retries = htofris32(p->msg.prequest.retries);
/* I think the blockmap is okay */
break;
case PKTSUBTYPE_JOIN:
if (datalen < sizeof(p->msg.join))
return;
p->msg.join.clientid = htofris32(p->msg.join.clientid);
break;
case PKTSUBTYPE_JOIN2:
if (datalen < sizeof(p->msg.join2))
return;
p->msg.join2.clientid = htofris32(p->msg.join2.clientid);
p->msg.join2.blockcount = htofris32(p->msg.join2.blockcount);
p->msg.join2.chunksize = htofris32(p->msg.join2.chunksize);
p->msg.join2.blocksize = htofris32(p->msg.join2.blocksize);
p->msg.join2.bytecount = htofris64(p->msg.join2.bytecount);
break;
case PKTSUBTYPE_LEAVE:
if (datalen < sizeof(p->msg.leave))
return;
p->msg.leave.clientid = htofris32(p->msg.leave.clientid);
p->msg.leave.elapsed = htofris32(p->msg.leave.elapsed);
break;
case PKTSUBTYPE_LEAVE2:
if (datalen < sizeof(p->msg.leave2))
return;
p->msg.leave2.clientid = htofris32(p->msg.leave2.clientid);
p->msg.leave2.elapsed = htofris32(p->msg.leave2.elapsed);
#define TWEAK32(F) p->msg.leave2.stats.u.v1.F = htofris32(p->msg.leave2.stats.u.v1.F)
#define TWEAK64(F) p->msg.leave2.stats.u.v1.F = htofris64(p->msg.leave2.stats.u.v1.F)
TWEAK32(runsec);
TWEAK32(runmsec);
TWEAK32(delayms);
TWEAK64(rbyteswritten);
TWEAK64(ebyteswritten);
TWEAK32(chunkbufs);
TWEAK32(maxreadahead);
TWEAK32(maxinprogress);
TWEAK32(pkttimeout);
TWEAK32(startdelay);
TWEAK32(idletimer);
TWEAK32(idledelay);
TWEAK32(redodelay);
TWEAK32(randomize);
TWEAK32(nochunksready);
TWEAK32(nofreechunks);
TWEAK32(dupchunk);
TWEAK32(dupblock);
TWEAK32(prequests);
TWEAK32(recvidles);
TWEAK32(joinattempts);
TWEAK32(requests);
TWEAK32(decompblocks);
TWEAK32(writeridles);
TWEAK32(writebufmem);
TWEAK32(lostblocks);
TWEAK32(rerequests);
TWEAK32(partialdrops);
TWEAK32(fullrerequests);
#undef TWEAK32
#undef TWEAK64
break;
}
#endif
#endif
}
/*
* Look for a packet on the socket. Propogate the errors back to the caller
* exactly as the system call does. Remember that we set up a socket timeout
......@@ -459,6 +707,8 @@ PacketReceive(Packet_t *p)
FrisPfatal("PacketReceive(recvfrom)");
}
PacketFromWire(p, mlen);
/*
* Basic integrity checks
*/
......@@ -521,6 +771,8 @@ PacketSend(Packet_t *p, int *resends)
to.sin_port = sndportnum;
to.sin_addr.s_addr = mcastaddr.s_addr;
PacketToWire(p, len);
delays = 0;
while ((rc = sendto(sock, (void *)p, len, MSG_DONTWAIT,
(struct sockaddr *)&to, sizeof(to))) <= 0) {
......@@ -567,6 +819,8 @@ PacketReply(Packet_t *p)
to.sin_addr.s_addr = p->hdr.srcip;
p->hdr.srcip = myipaddr.s_addr;
PacketToWire(p, len);
while (sendto(sock, (void *)p, len, 0,
(struct sockaddr *)&to, sizeof(to)) < 0) {
if (errno != ENOBUFS)
......
......@@ -208,23 +208,23 @@ endif
include $(TESTBED_SRCDIR)/GNUmakerules
imagezip: $(SUBDIRS) imagezip.o disksize.o checksum.o version.o $(ZIPLIBS)
$(CC) $(CFLAGS) imagezip.o disksize.o checksum.o version.o $(ZIPLIBS) $(LIBS) -o imagezip
imagezip: $(SUBDIRS) imagezip.o disksize.o checksum.o version.o header.o $(ZIPLIBS)
$(CC) $(CFLAGS) imagezip.o disksize.o checksum.o version.o header.o $(ZIPLIBS) $(LIBS) -o imagezip
imagezip.o: imagezip.c
$(CC) -c $(ZIPCFLAGS) -o imagezip.o $<
imageunzip: imageunzip.o disksize.o checksum.o crc.o version.o
$(CC) $(CFLAGS) imageunzip.o disksize.o checksum.o crc.o version.o $(UNZIPLIBS) -o imageunzip
imageunzip: imageunzip.o disksize.o checksum.o crc.o version.o header.o
$(CC) $(CFLAGS) imageunzip.o disksize.o checksum.o crc.o version.o header.o $(UNZIPLIBS) -o imageunzip
imageunzip.o: imageunzip.c
$(CC) -c $(UNZIPCFLAGS) -o imageunzip.o $<
imagedump: imagedump.o checksum.o version.o
$(CC) $(CFLAGS) imagedump.o checksum.o version.o $(LIBS) -o imagedump
imagedump: imagedump.o checksum.o version.o header.o
$(CC) $(CFLAGS) imagedump.o checksum.o version.o header.o $(LIBS) -o imagedump
imagehash: imagehash.o version.o
$(CC) $(CFLAGS) imagehash.o version.o $(HASHLIBS) -o imagehash
imagehash: imagehash.o version.o header.o
$(CC) $(CFLAGS) imagehash.o version.o header.o $(HASHLIBS) -o imagehash
imagehash.o: imagehash.c
$(CC) -c $(HASHCFLAGS) -o imagehash.o $<
......
......@@ -116,16 +116,16 @@ endif
all: imagezip imageunzip imagedump
imagezip: imagezip.o checksum.o version.o $(FSOBJS) $(FSLIBS)
imagezip: imagezip.o checksum.o version.o header.o $(FSOBJS) $(FSLIBS)
$(CC) $(CFLAGS) $^ $(LIBS) -o imagezip
imageunzip: imageunzip.o checksum.o crc.o version.o disksize.o
imageunzip: imageunzip.o checksum.o crc.o version.o disksize.o header.o
$(CC) $(CFLAGS) $^ $(UNZIPLIBS) -o imageunzip
imageunzip.o: imageunzip.c
$(CC) -c $(UNZIPCFLAGS) -o $@ $<
imagedump: imagedump.o checksum.o version.o
imagedump: imagedump.o checksum.o version.o header.o
$(CC) $(CFLAGS) $^ $(LIBS) -o imagedump
version.c: imagezip.c imageunzip.c imagedump.c
......
/*
* Copyright (c) 2014 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
* This file is part of the Emulab network testbed software.
*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this file. If not, see <http://www.gnu.org/licenses/>.
*
* }}}
*/
#include "imagehdr.h"
/*
* Utils for manipulating imagezip metadata (headers).
*/
void header_to_std(void *buf)
{
#if _BYTE_ORDER != IZ_BYTE_ORDER
blockhdr_t *blkhdr = (blockhdr_t *) buf;
int magic = blkhdr->magic;
struct region *curregion, *regions;
int nregion = 0, nreloc = 0, i;
if (magic < COMPRESSED_V1 || magic > COMPRESSED_V4)
return;
nregion = blkhdr->regioncount;
blkhdr->magic = htoiz32(blkhdr->magic);
blkhdr->size = htoiz32(blkhdr->size);
blkhdr->blockindex = htoiz32(blkhdr->blockindex);
blkhdr->blocktotal = htoiz32(blkhdr->blocktotal);
blkhdr->regionsize = htoiz32(blkhdr->regionsize);
blkhdr->regioncount = htoiz32(blkhdr->regioncount);
if (magic >= COMPRESSED_V2) {
nreloc = blkhdr->reloccount;
blkhdr->firstsect = htoiz32(blkhdr->firstsect);
blkhdr->lastsect = htoiz32(blkhdr->lastsect);
blkhdr->reloccount = htoiz32(blkhdr->reloccount);
}
if (magic >= COMPRESSED_V4) {
blkhdr->enc_cipher = htoiz16(blkhdr->enc_cipher);
blkhdr->csum_type = htoiz16(blkhdr->csum_type);
}
switch (magic) {
case COMPRESSED_V1:
regions = (struct region *)((struct blockhdr_V1 *)blkhdr + 1);
break;
case COMPRESSED_V2:
case COMPRESSED_V3:
regions = (struct region *)((struct blockhdr_V2 *)blkhdr + 1);
break;
case COMPRESSED_V4:
regions = (struct region *)((struct blockhdr_V4 *)blkhdr + 1);
break;
}
curregion = regions;
for (i = 0; i < nregion; i++) {
curregion->start = htoiz32(curregion->start);
curregion->size = htoiz32(curregion->size);
curregion++;
}
if (nreloc > 0) {
struct blockreloc *reloc = (struct blockreloc *)curregion;
for (i = 0; i < nreloc; i++) {
reloc->type = htoiz32(reloc->type);
reloc->sector = htoiz32(reloc->sector);
reloc->sectoff = htoiz32(reloc->sectoff);
reloc->size = htoiz32(reloc->size);
}
}
#endif
}
void header_from_std(void *buf)
{
#if _BYTE_ORDER != IZ_BYTE_ORDER
blockhdr_t *blkhdr = (blockhdr_t *) buf;
int magic = iztoh32(blkhdr->magic);
struct region *curregion, *regions;
int nregion = 0, nreloc = 0, i;
/* XXX just return, the caller will also check the magic and fail */
if (magic < COMPRESSED_V1 || magic > COMPRESSED_V4)
return;
blkhdr->magic = iztoh32(blkhdr->magic);
blkhdr->size = iztoh32(blkhdr->size);
blkhdr->blockindex = iztoh32(blkhdr->blockindex);
blkhdr->blocktotal = iztoh32(blkhdr->blocktotal);
blkhdr->regionsize = iztoh32(blkhdr->regionsize);
blkhdr->regioncount = iztoh32(blkhdr->regioncount);
nregion = blkhdr->regioncount;
if (magic >= COMPRESSED_V2) {
blkhdr->firstsect = iztoh32(blkhdr->firstsect);
blkhdr->lastsect = iztoh32(blkhdr->lastsect);
blkhdr->reloccount = iztoh32(blkhdr->reloccount);
nreloc = blkhdr->reloccount;
}
if (magic >= COMPRESSED_V4) {
blkhdr->enc_cipher = iztoh16(blkhdr->enc_cipher);
blkhdr->csum_type = iztoh16(blkhdr->csum_type);
}
switch (magic) {
case COMPRESSED_V1:
regions = (struct region *)((struct blockhdr_V1 *)blkhdr + 1);
break;
case COMPRESSED_V2:
case COMPRESSED_V3:
regions = (struct region *)((struct blockhdr_V2 *)blkhdr + 1);
break;
case COMPRESSED_V4:
regions = (struct region *)((struct blockhdr_V4 *)blkhdr + 1);
break;
}
curregion = regions;
for (i = 0; i < nregion; i++) {
curregion->start = iztoh32(curregion->start);
curregion->size = iztoh32(curregion->size);
curregion++;
}
if (nreloc > 0) {
struct blockreloc *reloc = (struct blockreloc *)curregion;
for (i = 0; i < nreloc; i++) {
reloc->type = iztoh32(reloc->type);
reloc->sector = iztoh32(reloc->sector);
reloc->sectoff = iztoh32(reloc->sectoff);
reloc->size = iztoh32(reloc->size);
}
}
#endif
}
/*
* Copyright (c) 2000-2014 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
* This file is part of the Emulab network testbed software.
*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this file. If not, see <http://www.gnu.org/licenses/>.
*
* }}}
*/
extern void header_to_std(void *buf);
extern void header_from_std(void *buf);
......@@ -56,6 +56,7 @@
#endif
#include "imagehdr.h"
#include "checksum.h"
#include "header.h"
static int detail = 0;
static int dumpmap = 0;
......@@ -275,6 +276,7 @@ dumpfile(char *name, int fd)
count -= cc;
bp += cc;
}
header_from_std(chunkbuf);
if (chunkno == 0) {
blockhdr_t *hdr = (blockhdr_t *)chunkbuf;
......
......@@ -49,6 +49,7 @@
#include "imagehdr.h"
#include "imagehash.h"
#include "header.h"
#include "queue.h"
#ifndef linux
......@@ -522,7 +523,7 @@ spewhash(unsigned char *h, int hlen)
#ifdef TIMEIT
#include <machine/cpufunc.h>
static u_int64_t rcycles, hcycles, ccycles, dcycles;
static unsigned long long rcycles, hcycles, ccycles, dcycles;
#endif
static int
......@@ -981,6 +982,7 @@ hashchunk(int chunkno, char *chunkbufp, struct hashinfo **hinfop)
* Grab the header. It is uncompressed, and holds the real
* image size and the magic number. Advance the pointer too.
*/
header_from_std(chunkbufp);
blockhdr = (blockhdr_t *)chunkbufp;
chunkbufp += DEFAULTREGIONSIZE;
nregions += (uint32_t)blockhdr->regioncount;
......
......@@ -49,6 +49,46 @@
#define COMPRESSED_MAGIC_CURRENT COMPRESSED_V4
/*
* Standard "endian"ness of image metadata.
*
* Speaking of retrofits, we didn't consider endianness initially.
* Now, in the interest of backward compatibility and optimizing for
* the common case (which currently is 100% of our images), we declare
* little endian to be the "standard" format of imagezip images.
*
* The only reason it is configurable here is so that I can do some
* basic testing.
*/
#ifdef __linux__
#include <endian.h>
#define _LITTLE_ENDIAN __LITTLE_ENDIAN
#define _BIG_ENDIAN __BIG_ENDIAN
#define _LITTLE_ENDIAN __LITTLE_ENDIAN
#define _BYTE_ORDER __BYTE_ORDER
#else
#include <sys/endian.h>
#endif
//#define IZ_BYTE_ORDER _BIG_ENDIAN
#define IZ_BYTE_ORDER _LITTLE_ENDIAN
#if IZ_BYTE_ORDER == _LITTLE_ENDIAN
#define htoiz16(x) htole16(x)
#define htoiz32(x) htole32(x)
#define htoiz64(x) htole64(x)
#define iztoh16(x) le16toh(x)
#define iztoh32(x) le32toh(x)
#define iztoh64(x) le64toh(x)
#else
#define htoiz16(x) htobe16(x)
#define htoiz32(x) htobe32(x)
#define htoiz64(x) htobe64(x)
#define iztoh16(x) be16toh(x)
#define iztoh32(x) be32toh(x)
#define iztoh64(x) be64toh(x)
#endif
/*
* Each compressed block of the file has this little header on it.
* Since each block is independently compressed, we need to know
......
......@@ -46,6 +46,7 @@
#include "imagehdr.h"
#include "queue.h"
#include "checksum.h"
#include "header.h"
#ifndef NOTHREADS
#include <pthread.h>
#endif
......@@ -1398,6 +1399,7 @@ inflate_subblock(const char *chunkbufp)
* Grab the header. It is uncompressed, and holds the real
* image size and the magic number. Advance the pointer too.
*/
header_from_std((void *)chunkbufp);
blockhdr = (const blockhdr_t *) chunkbufp;
chunkbufp += DEFAULTREGIONSIZE;
......
......@@ -59,6 +59,7 @@
#include "sliceinfo.h"
#include "global.h"
#include "checksum.h"
#include "header.h"
#include "range.h"
#ifdef WITH_HASH
#include "hashmap/hashmap.h"
......@@ -618,6 +619,8 @@ main(int argc, char *argv[])
if (version || debug) {
fprintf(stderr, "%s\n", build_info);
fprintf(stderr, "Image format: %s-endian\n",
(IZ_BYTE_ORDER == _LITTLE_ENDIAN) ? "little" : "big");
if (version) {
fprintf(stderr, "Supports");
for (ch = 1; fsmap[ch].type != -1; ch++)
......@@ -2306,10 +2309,18 @@ compress_image(void)
* with the compression.
*/
if (do_checksum) {
assert(!compat);
int32_t rsize = blkhdr->regionsize;
checksum_start(blkhdr, csumalg);
checksum_chunk(output_buffer,
blkhdr->size + blkhdr->regionsize);
/* Checksum the header after first standardizing it */
header_to_std(output_buffer);
checksum_chunk(output_buffer, rsize);
header_from_std(output_buffer);
/* Checksum the rest */
checksum_chunk(output_buffer + rsize, blkhdr->size);
checksum_finish(blkhdr);
}
#endif
......@@ -2327,8 +2338,10 @@ compress_image(void)
#endif
/*
* Write out the finished chunk to disk.
* Write out the finished chunk to disk after first
* standarizing the header.
*/
header_to_std(output_buffer);
cc = devwrite(outfd, output_buffer, sizeof(output_buffer));
if (cc != sizeof(output_buffer)) {
if (cc < 0)
......@@ -2446,10 +2459,18 @@ compress_image(void)
* with the compression.
*/
if (do_checksum) {
assert(!compat);
int32_t rsize = blkhdr->regionsize;
checksum_start(blkhdr, csumalg);
checksum_chunk(output_buffer,
blkhdr->size + blkhdr->regionsize);
/* Checksum the header after first standardizing it */
header_to_std(output_buffer);
checksum_chunk(output_buffer, rsize);
header_from_std(output_buffer);
/* Checksum the rest */
checksum_chunk(output_buffer + rsize, blkhdr->size);
checksum_finish(blkhdr);
}
#endif
......@@ -2467,9 +2488,11 @@ compress_image(void)
#endif
/*
* Write out the finished chunk to disk, and
* start over from the beginning of the buffer.
* Write out the finished chunk to disk after first
* standarizing the header, and start over from the
* beginning of the buffer.
*/
header_to_std(output_buffer);
cc = devwrite(outfd, output_buffer, sizeof(output_buffer));
if (cc != sizeof(output_buffer)) {
if (cc < 0)
......@@ -2850,6 +2873,37 @@ compress_finish(uint32_t *subblksize)
return 1;
}
static void
output_uuid(char *imagename, char *uuidstr)
{
FILE *file;
char *fname;
if (strcmp(imagename, "-")) {
fname = malloc(strlen(imagename) + 8);
if (fname == NULL) {
fprintf(stderr, "No memory\n");
exit(1);
}
strcpy(fname, imagename);
strcat(fname, ".uuid");
} else {
fname = strdup("stdout.uuid");
}
file = fopen(fname, "w");
if (file == NULL) {
fprintf(stderr, "Cannot create keyfile %s\n", fname);
exit(1);
}
fprintf(file, "%s\n", uuidstr);
fclose(file);
fprintf(stderr, "UUID written to %s\n", fname);
free(fname);
}
#ifdef WITH_CRYPTO
/*
* Checksum functions
......@@ -2953,37 +3007,6 @@ output_public_key(char *imagename, RSA *key)
}
#endif
static void
output_uuid(char *imagename, char *uuidstr)
{
FILE *file;
char *fname;
if (strcmp(imagename, "-")) {
fname = malloc(strlen(imagename) + 8);
if (fname == NULL) {
fprintf(stderr, "No memory\n");
exit(1);
}
strcpy(fname, imagename);
strcat(fname, ".uuid");
} else {
fname = strdup("stdout.uuid");
}
file = fopen(fname, "w");
if (file == NULL) {
fprintf(stderr, "Cannot create keyfile %s\n", fname);
exit(1);
}
fprintf(file, "%s\n", uuidstr);
fclose(file);
fprintf(stderr, "UUID written to %s\n", fname);
free(fname);
}
void
checksum_chunk(uint8_t *buf, off_t size)
{
......