📄 usr_targ_x86.c
字号:
/* * $Id: usr_targ_x86.c,v 1.3 2001/04/21 04:07:01 mbrown Exp $ * * Implements iSCSI user space target * * Changes : * * $Log: usr_targ_x86.c,v $ * Revision 1.3 2001/04/21 04:07:01 mbrown * more bug fixing, mount readonly works, use the new DISK file, it * contains a valid ext2 partition * * Revision 1.2 2001/04/19 15:16:50 mbrown * devices now show up, fdisk still causes a kernel panic, * checkin per jhawkins' request * * Revision 1.1 2001/04/06 04:06:06 mbrown * Usermode target. Modified version of UNH Interoperability Lab's version * * *//* Credits: * * Most of the ideas expressed, and some verbatim code was borrowed from * Chris Loveland and other members of the UNH Ineroperability Lab's * userspace target iSCSI implementation found here: * ftp://ftp.iol.unh.edu/pub/iscsi/iscsi-3_init.tgz */#include <sys/types.h>#include <linux/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <netinet/in.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <scsi/scsi.h>/* junk to let me include iscsi.h */typedef unsigned char u8;typedef unsigned int u32;typedef unsigned short u16;typedef int s32;typedef short s16;typedef unsigned long long int u64;typedef long long int s64;struct socket {};#include "iscsi.h"typedef unsigned char byte;#define BUF_LEN 2000int init_server();int rx_login(int sock, iscsi_header_t *);int rx_scsi_cmd(int sock, iscsi_header_t *);int rx_scsi_data(int sock, iscsi_header_t *);static void DUMP_DATA (void *start, int len){ int i; unsigned char *tmp = start; for (i=0; i<len; i++) { if ((i % 4) == 0) { printf ("\n\t0x"); } printf ("%02x", tmp[i]); } printf ("\n");}static __inline__ u64 be_to_cpu64 (u64 u){ byte *a = (byte *) &u; byte tmp; int i; if (sizeof(u64) != 8) { fprintf(stderr, "u64 IS NOT 8 BYTES!!!!!\n"); } for (i=0; i<sizeof(u64) / 2; i++) { tmp = a[i]; a[i] = a[sizeof(u64) - i - 1]; a[sizeof(u64) - i - 1] = tmp; } return u;}static __inline__ iscsi_header_t be_to_cpu_iscsi (iscsi_header_t hdr){ printf ("RX Header:\n"); iscsi_print_header (&hdr); switch (hdr.op) { /*case ISCSI_OP_NOP_OUT: hdr.nop_out.len = ntohl(hdr.nop_out.len); hdr.nop_out.lun = be_to_cpu64(hdr.nop_out.lun); hdr.nop_out.itt = ntohl(hdr.nop_out.itt); hdr.nop_out.ttt = ntohl(hdr.nop_out.ttt); hdr.nop_out.cmd_rn = ntohl(hdr.nop_out.cmd_rn); hdr.nop_out.exp_stat_rn = ntohl(hdr.nop_out.exp_stat_rn); hdr.nop_out.exp_data_rn = ntohl(hdr.nop_out.exp_data_rn); return hdr;*/ case ISCSI_OP_SCSI_CMD: hdr.scsi_cmd.len = ntohl(hdr.scsi_cmd.len); hdr.scsi_cmd.lun = be_to_cpu64(hdr.scsi_cmd.lun); hdr.scsi_cmd.itt = ntohl(hdr.scsi_cmd.itt); hdr.scsi_cmd.exp_data_len = ntohl(hdr.scsi_cmd.exp_data_len); hdr.scsi_cmd.cmd_rn = ntohl(hdr.scsi_cmd.cmd_rn); hdr.scsi_cmd.exp_stat_rn = ntohl(hdr.scsi_cmd.exp_stat_rn); return hdr; case ISCSI_OP_LOGIN_CMD: hdr.login_cmd.len = ntohl (hdr.login_cmd.len); hdr.login_cmd.cid = ntohs (hdr.login_cmd.cid); hdr.login_cmd.isid = ntohs (hdr.login_cmd.isid); hdr.login_cmd.tsid = ntohs (hdr.login_cmd.tsid); hdr.login_cmd.itt = ntohl (hdr.login_cmd.itt); hdr.login_cmd.init_cmd_rn = ntohl (hdr.login_cmd.init_cmd_rn); return hdr; case ISCSI_OP_WRITE_DATA: hdr.scsi_write.len = ntohl (hdr.scsi_write.len); hdr.scsi_write.lun = be_to_cpu64 (hdr.scsi_write.lun); hdr.scsi_write.itt = ntohl (hdr.scsi_write.itt); hdr.scsi_write.ttt = ntohl (hdr.scsi_write.ttt); hdr.scsi_write.exp_stat_rn = ntohl (hdr.scsi_write.exp_stat_rn); hdr.scsi_write.buf_offset = ntohl (hdr.scsi_write.buf_offset); return hdr; case ISCSI_OP_TASK_CMD: case ISCSI_OP_TEXT_CMD: case ISCSI_OP_LOGOUT_CMD: case ISCSI_OP_SACK_REQ: default: printf ("iscsi - ntoh - Unimplemented Byte Conversion\n"); } return hdr;}static __inline__ iscsi_header_t cpu_to_be_iscsi (iscsi_header_t hdr){ switch (hdr.op) { case ISCSI_OP_SCSI_RSP: hdr.scsi_rsp.len = htonl(hdr.scsi_rsp.len); hdr.scsi_rsp.itt = htonl(hdr.scsi_rsp.itt); hdr.scsi_rsp.resid_cnt = htonl(hdr.scsi_rsp.resid_cnt); hdr.scsi_rsp.stat_rn = htonl(hdr.scsi_rsp.stat_rn); hdr.scsi_rsp.exp_cmd_rn = htonl(hdr.scsi_rsp.exp_cmd_rn); hdr.scsi_rsp.max_cmd_rn = htonl(hdr.scsi_rsp.max_cmd_rn); hdr.scsi_rsp.sense_len = htons(hdr.scsi_rsp.sense_len); hdr.scsi_rsp.bidi_resid_cnt = htonl(hdr.scsi_rsp.bidi_resid_cnt); break; case ISCSI_OP_LOGIN_RSP: hdr.login_rsp.len = htonl (hdr.login_rsp.len); hdr.login_rsp.isid = htons (hdr.login_rsp.isid); hdr.login_rsp.tsid = htons (hdr.login_rsp.tsid); hdr.login_rsp.itt = htonl (hdr.login_rsp.itt); hdr.login_rsp.init_stat_rn = htonl (hdr.login_rsp.init_stat_rn); hdr.login_rsp.exp_cmd_rn = htonl (hdr.login_rsp.exp_cmd_rn); hdr.login_rsp.max_cmd_rn = htonl (hdr.login_rsp.max_cmd_rn); break; case ISCSI_OP_READ_DATA: hdr.scsi_read.len = htonl (hdr.scsi_read.len); hdr.scsi_read.itt = htonl (hdr.scsi_read.itt); hdr.scsi_read.ttt = htonl (hdr.scsi_read.ttt); hdr.scsi_read.data_rn_stat_rn = htonl (hdr.scsi_read.data_rn_stat_rn); hdr.scsi_read.exp_cmd_rn = htonl (hdr.scsi_read.exp_cmd_rn); hdr.scsi_read.max_cmd_rn = htonl (hdr.scsi_read.max_cmd_rn); hdr.scsi_read.buf_offset = htonl (hdr.scsi_read.buf_offset); hdr.scsi_read.resid_cnt = htonl (hdr.scsi_read.resid_cnt); break; case ISCSI_OP_R2T: hdr.r2t.len = htonl (hdr.r2t.len); hdr.r2t.itt = htonl (hdr.r2t.itt); hdr.r2t.ttt = htonl (hdr.r2t.ttt); hdr.r2t.exp_cmd_rn = htonl (hdr.r2t.exp_cmd_rn); hdr.r2t.max_cmd_rn = htonl (hdr.r2t.max_cmd_rn); hdr.r2t.desired_data_len = htonl (hdr.r2t.desired_data_len); hdr.r2t.buf_offset = htonl (hdr.r2t.buf_offset); break; case ISCSI_OP_NOP_IN: case ISCSI_OP_TASK_RSP: case ISCSI_OP_TEXT_RSP: case ISCSI_OP_LOGOUT_RSP: case ISCSI_OP_ASYNC_EVENT: case ISCSI_OP_REJECT: default: printf ("iscsi - hton - Unimplemented Byte Conversion\n"); } printf ("TX Header:\n"); iscsi_print_header (&hdr); return hdr;}void iscsi_print_header (void *hdr) { register int i; byte *buf=hdr; for (i=0; i<ISCSI_HDR_SIZE; i++) { if (i % 4 == 0) { printf ("\n\t0x"); } printf ("%02x", buf[i]); } printf ("\n");}struct cmd_table{ u32 block_no; u32 num_blocks; u32 data_dir; u32 task_id; u32 received; byte opcode; struct cmd_table * next;};#define DO_FILE_IO 1#define WRITE_TYPE 2#define READ_TYPE 1#define NONE_TYPE 0struct cmd_table * cmnds = NULL;u32 cur_statrn = 1;u32 exp_cmdrn = 0;u32 global_fd;int main(int argc, char * argv[]){ int sock; int bytes_read, bytes_to_read; iscsi_header_t hdr; #if DO_FILE_IO if (argc == 2){ global_fd = open(argv[1], O_RDWR); } else{ printf("need to specify a file to use as disk\n"); return 0; }#endif sock = init_server(); while (1) { bytes_to_read = ISCSI_HDR_SIZE; printf ("Reading new iscsi hdr......\n"); while (bytes_to_read){ if ((bytes_read = read (sock, ((byte *) &hdr) + (ISCSI_HDR_SIZE - bytes_to_read), bytes_to_read)) == -1) { perror ("read() failed"); exit(1); } if (bytes_read == 0) { printf ("Client disconnected\n"); exit(0); } bytes_to_read -= bytes_read; if (bytes_to_read) { printf ("warning - short read\n"); } } /* convert byte ordering */ hdr = be_to_cpu_iscsi (hdr); switch (hdr.op){ case ISCSI_OP_LOGIN_CMD: printf ("Processing iscsi login command\n"); rx_login(sock, &hdr); break; case ISCSI_OP_SCSI_CMD: printf ("Processing iscsi scsi command\n"); rx_scsi_cmd(sock, &hdr); break; case ISCSI_OP_WRITE_DATA: printf ("Processing iscsi write data\n"); rx_scsi_data(sock, &hdr); break; default: printf ("BOGUS MESSAGE:\n"); iscsi_print_header (&hdr); exit(1); } }}int rx_login(int sock, iscsi_header_t *hdr){ int bytes_to_write = ISCSI_HDR_SIZE, bytes_written; iscsi_header_t rsp; memset (&rsp, 0, ISCSI_HDR_SIZE); rsp.op = ISCSI_OP_LOGIN_RSP; rsp.login_rsp.F_reserved1 |= ISCSI_F_BIT; /* turn on F-bit */ rsp.login_rsp.len = 0; rsp.login_rsp.version_active = 1; /* conform to UNH's kernel target */ rsp.login_rsp.isid = hdr->login_cmd.isid; rsp.login_rsp.tsid = 0x1; rsp.login_rsp.init_stat_rn = cur_statrn; exp_cmdrn = rsp.login_rsp.exp_cmd_rn = rsp.login_rsp.max_cmd_rn = hdr->login_cmd.init_cmd_rn + 1; rsp.login_rsp.status = ISCSI_LOGIN_ACCEPT; rsp = cpu_to_be_iscsi (rsp); printf ("writing iscsi login response\n"); while (bytes_to_write) { if ((bytes_written = write (sock, ((byte *) &rsp) + (ISCSI_HDR_SIZE - bytes_to_write), bytes_to_write)) == -1) { perror ("write failed\n"); exit(1); } if (bytes_written == 0) { perror ("Client disconnected\n"); exit(1); } bytes_to_write -= bytes_written; if (bytes_to_write) { printf ("warning - short write\n"); } } return 0;}int rx_scsi_data(int sock, iscsi_header_t *hdr){ iscsi_header_t rsp; char *buffer; int len, bytes_to_read, bytes_read, bytes_to_write = ISCSI_HDR_SIZE, bytes_written; struct cmd_table * cur_cmnd; struct cmd_table * trail_cmnd; len = bytes_to_read = hdr->scsi_write.len; buffer = malloc(bytes_to_read); cur_cmnd = cmnds; while (cur_cmnd && cur_cmnd->task_id != hdr->scsi_write.ttt){ cur_cmnd = cur_cmnd->next; } if (cur_cmnd == NULL){ printf("couldnt find matching cmnd\n"); free(buffer); exit(1); } while (bytes_to_read){ if ((bytes_read = read (sock, buffer + (len - bytes_to_read), bytes_to_read)) == -1) { perror ("read() failed\n"); exit(1); } if (bytes_read == 0) { printf ("Client disconnected\n"); exit(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -