📄 netflash.c
字号:
if (lhdr.magic != htons(LITTLE_CRYPTO_MAGIC)) {#ifdef CONFIG_USER_NETFLASH_CRYPTO_OPTIONAL add_data(file_length, (char *)&lhdr, sizeof(struct little_header)); file_length += sizeof(struct little_header); return;#else error("size magic incorrect"); exit_failed(BAD_CRYPT_MAGIC);#endif } { unsigned short hlen = ntohs(lhdr.hlen); char tmp[hlen]; char t2[hlen]; int len; extract_data(hlen, tmp); len = RSA_public_decrypt(hlen, tmp, t2, pkey, RSA_PKCS1_PADDING); if (len == -1) { error("decrypt failed"); exit_failed(BAD_DECRYPT); } if (len != sizeof(struct header)) { error("Length mismatch %d %d\n", (int)sizeof(struct header), len); } memcpy(&hdr, t2, sizeof(struct header)); } RSA_free(pkey); if (hdr.magic != htonl(CRYPTO_MAGIC)) { error("image not cryptographically enabled"); exit_failed(NO_CRYPT); } /* Decrypt image if needed */ if (hdr.flags & FLAG_ENCRYPTED) { aes_context ac; char cin[AES_BLOCK_SIZE]; char cout[AES_BLOCK_SIZE]; unsigned long s; if ((file_length % AES_BLOCK_SIZE) != 0) { error("image size not miscable with cryptography"); exit_failed(BAD_CRYPT); } aes_set_key(&ac, hdr.aeskey, AESKEYSIZE, 0); /* Convert the body of the file */ for (fb = fileblocks, s = 0; s<file_length; s += AES_BLOCK_SIZE) { get_block(fb, s, cin, AES_BLOCK_SIZE); aes_decrypt(&ac, cin, cout); fb = put_block(fb, s, cout, AES_BLOCK_SIZE); } } /* Remove padding */ if (hdr.padsize) remove_data(hdr.padsize); /* Check MD5 sum if required */ { MD5_CTX ctx; unsigned char hash[16]; if (fileblocks != NULL && file_length >= 16) { MD5_Init(&ctx); for (fb = fileblocks; fb != NULL; fb = fb->next) MD5_Update(&ctx, fb->data, fb->length); MD5_Final(hash, &ctx); if (memcmp(hdr.md5, hash, MD5_DIGEST_LENGTH) != 0) { error("bad MD5 signature"); exit_failed(BAD_MD5_SIG); } } } printf("netflash: signed image approved\n");}#endif#ifdef CONFIG_USER_NETFLASH_DECOMPRESS/* Read the decompressed size from the gzip format */int decompress_size(){ unsigned char *sp = 0, *ep; int i, total, size; struct fileblock_t *fb; /* Get a pointer to the start of the inflated size */ total = 0; size = 0; if (fileblocks != NULL && file_length >= 4) { for (fb = fileblocks; fb != NULL; fb = fb->next) { if ((total + fb->length) >= (file_length - 4)) { sp = fb->data + (file_length - total - 4); break; } total += fb->length; } if (fb) { ep = fb->data + fb->length; for (i = 0; i < 4; i++) { if (sp >= ep) { fb = fb->next; sp = fb->data; ep = sp + fb->length; } size |= (*sp++) << (8*i); } } } return size;}/* * Skip bytes, ensuring at least 1 byte remains to be read. * Don't use this to skip past the last byte in the file. */int decompress_skip_bytes(int pos, int num){ while (zfb) { if (pos + num < zfb->length) return pos + num; num -= zfb->length - pos; pos = 0; zfb = zfb->next; } error("compressed image is too short"); exit_failed(IMAGE_SHORT); return 0;}int decompress_init(){ int pos, flg, xlen, size; zfb = fileblocks; pos = 0; /* Skip over gzip header */ pos = decompress_skip_bytes(pos, 2); if (zfb->data[pos] != 8) { error("image is compressed, unknown compression method"); exit_failed(UNKNOWN_COMP); } pos = decompress_skip_bytes(pos, 1); flg = zfb->data[pos]; pos = decompress_skip_bytes(pos, 1); /* Skip mod time, extended flag, and os */ pos = decompress_skip_bytes(pos, 6); /* Skip extra field */ if (flg & 0x04) { xlen = zfb->data[pos]; pos = decompress_skip_bytes(pos, 1); xlen += zfb->data[pos]<<8; pos = decompress_skip_bytes(pos, 1+xlen); } /* Skip file name */ if (flg & 0x08) { while (zfb->data[pos]) pos = decompress_skip_bytes(pos, 1); pos = decompress_skip_bytes(pos, 1); } /* Skip comment */ if (flg & 0x10) { while (zfb->data[pos]) pos = decompress_skip_bytes(pos, 1); pos = decompress_skip_bytes(pos, 1); } /* Skip CRC */ if (flg & 0x02) { pos = decompress_skip_bytes(pos, 2); } z.next_in = zfb->data + pos; z.avail_in = zfb->length - pos; z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; if (inflateInit2(&z, -MAX_WBITS) != Z_OK) { error("image is compressed, decompression failed"); exit_failed(BAD_DECOMP); } size = decompress_size(); if (size <= 0) { error("image is compressed, decompressed length is invalid"); exit_failed(BAD_DECOMP); } return size;}int decompress(char* data, int length){ int rc; z.next_out = data; z.avail_out = length; for (;;) { while (z.avail_in == 0) { zfb = zfb->next; if (!zfb) { error("unexpected end of file for decompression"); exit_failed(BAD_DECOMP); } z.next_in = zfb->data; z.avail_in = zfb->length; } rc = inflate(&z, Z_SYNC_FLUSH); if (rc == Z_OK) { if (z.avail_out == 0) return length; if (z.avail_in != 0) { /* Note: This shouldn't happen, but if it does then * need to add code to add another level of buffering * that we append file blocks to... */ error("decompression deadlock"); exit_failed(BAD_DECOMP); } } else if (rc == Z_STREAM_END) { return length - z.avail_out; } else { error("error during decompression: %x", rc); exit_failed(BAD_DECOMP); } }}int check_decompression(int doinflate){ if (doinflate) { if (fileblocks->length >= 2 && fileblocks->data[0] == gz_magic[0] && fileblocks->data[1] == gz_magic[1]) { image_length = decompress_init(); notice("image is compressed, decompressed length=%ld\n", image_length); } else { notice("image is not compressed"); } }#ifdef CONFIG_USER_NETFLASH_AUTODECOMPRESS else if (fileblocks->length >= 2 && fileblocks->data[0] == gz_magic[0] && fileblocks->data[1] == gz_magic[1]) { doinflate = 1; image_length = decompress_init(); notice("image is compressed, decompressed length=%ld\n", image_length); }#endif else { image_length = file_length; } return doinflate;}#endif/****************************************************************************//* * Local copies of the open/close/write used by tftp loader. * The idea is that we get tftp to do all the work of getting * the file over the network. The following code back ends * that process, preparing the read data for FLASH programming. */int local_creat(char *name, int flags){ return(fileno(nfd));}FILE *local_fdopen(int fd, char *flags){ return(nfd);}FILE *local_fopen(const char *name, const char *flags){ return(nfd);}int local_fclose(FILE *fp){ printf("\n"); fflush(stdout); sleep(1); return(0);}int local_fseek(FILE *fp, int offset, int whence){ /* Shouldn't happen... */ return(0);}int local_putc(int ch, FILE *fp){ /* Shouldn't happen... */ return(0);}int local_write(int fd, char *buf, int count){ add_data(file_offset, buf, count); file_offset += count; if (file_offset > file_length) file_length = file_offset; return(count);}/****************************************************************************/ extern int tftpmain(int argc, char *argv[]);extern int tftpsetbinary(int argc, char *argv[]);extern int tftpget(int argc, char *argv[]);/* * Call to tftp. This will initialize tftp and do a get operation. * This will call the local_write() routine with the data that is * fetched, and it will create the ioctl structure. */int tftpfetch(char *srvname, char *filename){ char *tftpargv[8]; int tftpmainargc = 0; tftpverbose = 0; /* Set to 1 for tftp trace info */ tftpargv[tftpmainargc++] = "tftp"; tftpargv[tftpmainargc++] = srvname;#ifdef CONFIG_USER_NETFLASH_SETSRC if (srcaddr != NULL) tftpargv[tftpmainargc++] = srcaddr;#endif tftpmain(tftpmainargc, tftpargv); tftpsetbinary(1, tftpargv); notice("fetching file \"%s\" from %s\n", filename, srvname); tftpargv[0] = "get"; tftpargv[1] = filename; tftpget(2, tftpargv); return(0);}/****************************************************************************/ extern int ftpmain(int argc, char *argv[]);extern void setbinary(void);extern void get(int argc, char *argv[]);extern void quit(void);/* * Call to ftp. This will initialize ftp and do a get operation. * This will call the local_write() routine with the data that is * fetched, and it will create the ioctl structure. */int ftpconnect(char *srvname){#ifdef FTP char *ftpargv[4]; ftpverbose = 0; /* Set to 1 for ftp trace info */ notice("login to remote host %s", srvname); ftpargv[0] = "ftp"; ftpargv[1] = srvname; ftpmain(2, ftpargv); return(0);#else error("no ftp support builtin"); return(-1);#endif /* FTP */}int ftpfetch(char *srvname, char *filename){#ifdef FTP char *ftpargv[4]; ftpverbose = 0; /* Set to 1 for ftp trace info */ notice("ftping file \"%s\" from %s", filename, srvname); setbinary(); /* make sure we are in binary mode */ ftpargv[0] = "get"; ftpargv[1] = filename; get(2, ftpargv); quit(); return(0);#else error("no ftp support builtin"); return(-1);#endif /* FTP */}/****************************************************************************/extern int openhttp(char *url);/* * When fetching file we need to even number of bytes in write * buffers. Otherwise FLASH programming will fail. This is mostly * only a problem with http for some reason. */int filefetch(char *filename){ int fd, i, j; unsigned char buf[1024]; if (strncmp(filename, "http://", 7) == 0) fd = openhttp(filename); else fd = open(filename, O_RDONLY); if (fd < 0) return(-1); for (;;) { printf("."); if ((i = read(fd, buf, sizeof(buf))) <= 0) break; if (i & 0x1) { /* Read more to make even sized buffer */ if ((j = read(fd, &buf[i], 1)) > 0) i += j; } add_data(file_offset, buf, i); file_offset += i; file_length = file_offset; } close(fd); printf("\n"); return(0);}/****************************************************************************/int samedev(struct stat *stat_dev, struct stat *stat_rootfs){ if (S_ISBLK(stat_dev->st_mode)) { if (stat_dev->st_rdev == stat_rootfs->st_dev) { return 1; }#if defined(CONFIG_NFTL_RW) /* Check for writing to nftla, with an nftla partition * as the root device. */ else if (major(stat_dev->st_rdev) == NFTL_MAJOR && major(stat_rootfs->st_dev) == NFTL_MAJOR && minor(stat_dev->st_rdev) == 0) { return 1; }#endif }#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULES) /* Check for matching block/character mtd devices. */ else if (S_ISCHR(stat_dev->st_mode)) { if (major(stat_dev->st_rdev) == MTD_CHAR_MAJOR && major(stat_rootfs->st_dev) == MTD_BLOCK_MAJOR && (minor(stat_dev->st_rdev) >> 1) == minor(stat_rootfs->st_dev)) { return 1; } }#endif return 0;}/* * Check if we are writing to the root filesystem. */int flashing_rootfs(char *rdev){ static struct stat stat_rootfs, stat_flash; /* First a generic check: * is the rootfs device the same as the flash device? */ if (stat("/", &stat_rootfs) != 0) { error("stat(\"/\") failed (errno=%d)", errno); exit_failed(BAD_ROOTFS); } if (samedev(&stat_rdev, &stat_rootfs)) return 1; /* Secondly, a platform specific check: * /dev/flash/all and /dev/flash/image and /dev/flash/rootfs * can overlap, check if we are writing to any of these, and the * root device is /dev/flash/image or /dev/flash/rootfs. * XXX: checking device numbers would be better than strcmp */ else if (!strcmp(rdev, "/dev/flash/all") || !strcmp(rdev, "/dev/flash/image") || !strcmp(rdev, "/dev/flash/rootfs")) { if (stat("/dev/flash/image", &stat_flash) == 0 && samedev(&stat_flash, &stat_rootfs)) return 1; if (stat("/dev/flash/rootfs", &stat_flash) == 0 && samedev(&stat_flash, &stat_rootfs)) return 1; } return 0;}/****************************************************************************//* * Search for a process and send a signal to it. */int killprocname(const char *name, int signo){ DIR *dir; struct dirent *entry; FILE *f; char path[32]; char line[64]; int ret = 0; dir = opendir("/proc"); if (!dir) return 0; while ((entry = readdir(dir)) != NULL) { if (!isdigit(*entry->d_name)) continue; sprintf(path, "/proc/%s/status", entry->d_name); if ((f = fopen(path, "r")) == NULL) continue; while (fgets(line, sizeof(line), f) != NULL) { if (line[strlen(line)-1] == '\n') { line[strlen(line)-1] = '\0'; if (strncmp(line, "Name:\t", 6) == 0 && strcmp(line+6, name) == 0) { kill(atoi(entry->d_name), signo); ret = 1; } } } fclose(f); } closedir(dir); return ret;}/****************************************************************************//* * Read a process pid file and send a signal to it. */void killprocpid(char *file, int signo){ FILE* f; pid_t pid; char value[16]; f = fopen(file, "r"); if (f == NULL) return; if (fread(value, 1, sizeof(value), f) > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -