⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aoe.c

📁 Virtual EtherDrive&#174 blade AoE target.
💻 C
字号:
// aoe.c: the ATA over Ethernet virtual EtherDrive (R) blade#include "config.h"#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <netinet/in.h>#include "dat.h"#include "fns.h"enum {	Nmasks= 32,	Alen= 6,};uchar masks[Nmasks*Alen];int nmasks;char config[Nconfig];int nconfig = 0;int maxscnt = 2;char *ifname;voidaoead(int fd)			// advertise the virtual blade{	uchar buf[2000];	Conf *p;	int i;	p = (Conf *)buf;	memset(p, 0, sizeof *p);	memset(p->h.dst, 0xff, 6);	memmove(p->h.src, mac, 6);	p->h.type = htons(0x88a2);	p->h.flags = Resp;	p->h.maj = htons(shelf);	p->h.min = slot;	p->h.cmd = Config;	p->bufcnt = htons(Bufcount);	p->scnt = maxscnt = (getmtu(sfd, ifname) - sizeof (Ata)) / 512;	p->firmware = htons(FWV);	p->vercmd = 0x10 | Qread;	memcpy(p->data, config, nconfig);	p->len = htons(nconfig);	if (nmasks == 0)	if (putpkt(fd, buf, sizeof *p - sizeof p->data + nconfig) == -1) {		perror("putpkt aoe id");		return;	}	for (i=0; i<nmasks; i++) {		memcpy(p->h.dst, &masks[i*Alen], Alen);		if (putpkt(fd, buf, sizeof *p - sizeof p->data + nconfig) == -1)			perror("putpkt aoe id");	}}intisbcast(uchar *ea)		// replace with assembler routine{	uchar *b = (uchar *)"\377\377\377\377\377\377";	return memcmp(ea, b, 6) == 0;}long longgetlba(uchar *p){	vlong v;	int i;	v = 0;	for (i = 0; i < 6; i++)		v |= (vlong)(*p++) << i * 8;	return v;}intaoeata(Ata *p, int pktlen)	// do ATA reqeust{	Ataregs r;	int len = 60;	int n;	r.lba = getlba(p->lba);	r.sectors = p->sectors;	r.feature = p->err;	r.cmd = p->cmd;	if (atacmd(&r, (uchar *)(p+1), maxscnt*512, pktlen - sizeof(*p)) < 0) {		p->h.flags |= Error;		p->h.error = BadArg;		return len;	}	if (!(p->aflag & Write))	if ((n = p->sectors)) {		n -= r.sectors;		len = sizeof (Ata) + (n*512);	}	p->sectors = r.sectors;	p->err = r.err;	p->cmd = r.status;	return len;}#define QCMD(x) ((x)->vercmd & 0xf)// yes, this makes unnecessary copies.intconfcmd(Conf *p, int payload)	// process conf request{	int len;	len = ntohs(p->len);	if (QCMD(p) != Qread)	if (len > Nconfig || len > payload)		return 0;	// if you can't play nice ...	switch (QCMD(p)) {	case Qtest:		if (len != nconfig)			return 0;		// fall thru	case Qprefix:		if (len > nconfig)			return 0;		if (memcmp(config, p->data, len))			return 0;		// fall thru	case Qread:		break;	case Qset:		if (nconfig)		if (nconfig != len || memcmp(config, p->data, len)) {			p->h.flags |= Error;			p->h.error = ConfigErr;			break;		}		// fall thru	case Qfset:		nconfig = len;		memcpy(config, p->data, nconfig);		break;	default:		p->h.flags |= Error;		p->h.error = BadArg;	}	memmove(p->data, config, nconfig);	p->len = htons(nconfig);	p->bufcnt = htons(Bufcount);	p->scnt = maxscnt = (getmtu(sfd, ifname) - sizeof (Ata)) / 512;	p->firmware = htons(FWV);	p->vercmd = 0x10 | QCMD(p);	// aoe v.1	return nconfig + sizeof *p - sizeof p->data;}voiddoaoe(Aoehdr *p, int n){	int len;	enum {	// config query header size		CHDR_SIZ = sizeof(Conf) - sizeof(((Conf *)0)->data),	};	switch (p->cmd) {	case ATAcmd:		if (n < sizeof(Ata))			return;		len = aoeata((Ata*)p, n);		break;	case Config:		if (n < CHDR_SIZ)			return;		len = confcmd((Conf *)p, n - CHDR_SIZ);		if (len == 0)			return;		break;	default:		p->error = BadCmd;		len = 1024;		break;	}	memmove(p->dst, p->src, 6);	memmove(p->src, mac, 6);	p->maj = htons(shelf);	p->min = slot;	p->flags |= Resp;	if (putpkt(sfd, (uchar *) p, len) == -1) {		perror("write to network");		exit(1);	}}voidaoe(void){	Aoehdr *p;	uchar *buf;	int n, sh;	enum { bufsz = 1<<16, };	buf = malloc(bufsz);	aoead(sfd);	for (;;) {		n = getpkt(sfd, buf, bufsz);		if (n < 0) {			perror("read network");			exit(1);		}		if (n < sizeof(Aoehdr))			continue;		p = (Aoehdr *) buf;		if (ntohs(p->type) != 0x88a2)			continue;		if (p->flags & Resp)			continue;		sh = ntohs(p->maj);		if (sh != shelf && sh != (ushort)~0)			continue;		if (p->min != slot && p->min != (uchar)~0)			continue;		if (nmasks && !maskok(p->src))			continue;		doaoe(p, n);	}	free(buf);}voidusage(void){	fprintf(stderr, "usage: %s [ -m mac[,mac...] ] shelf slot netif filename\n", 		progname);	exit(1);}/* parseether from plan 9 */intparseether(uchar *to, char *from){	char nip[4];	char *p;	int i;	p = from;	for(i = 0; i < 6; i++){		if(*p == 0)			return -1;		nip[0] = *p++;		if(*p == 0)			return -1;		nip[1] = *p++;		nip[2] = 0;		to[i] = strtoul(nip, 0, 16);		if(*p == ':')			p++;	}	return 0;}voidsetmask(char *ml){	char *p;	int n;	for (; ml; ml=p) {		p = strchr(ml, ',');		if (p)			*p++ = '\0';		n = parseether(&masks[nmasks*Alen], ml);		if (n < 0)			fprintf(stderr, "ignoring mask %s, parseether failure\n", ml);		else			nmasks++;	}}intmaskok(uchar *ea){	int i, ok = 0;	for (i=0; !ok && i<nmasks; i++)		ok = memcmp(ea, &masks[i*Alen], Alen) == 0;	return ok;}intmain(int argc, char **argv){	int ch, omode = O_RDONLY;	struct stat s;	setbuf(stdin, NULL);	atainit();	progname = *argv;	while ((ch = getopt(argc, argv, "m:")) != -1) {		switch (ch) {		case 'm':			setmask(optarg);			break;		case '?':		default:			usage();		}	}	argc -= optind;	argv += optind;	if (argc != 4)		usage();	if (stat(argv[3], &s) < 0) {		perror("stat");		exit(1);	}	if (s.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))		omode = O_RDWR;	bfd = open(argv[3], omode);	if (bfd == -1) {		perror("open");		exit(1);	}	shelf = atoi(argv[0]);	slot = atoi(argv[1]);	size = getsize(bfd);	size /= 512;	ifname = argv[2];	sfd = dial(ifname);	getea(sfd, ifname, mac);	printf("pid %ld: e%d.%d, %lld sectors %s\n",		(long) getpid(), shelf, slot, size,		omode == O_RDWR ? "O_RDWR" : "O_RDONLY");	fflush(stdout);	aoe();	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -