STGT:target userspace utils

// tgt.h
#ifndef __TGT_H__
#define __TGT_H__

#include <inttypes.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

#define TGT_IPC_ADDR  "/var/run/tgtd.ipc_abstract_namespace"

static int control_port=0; 	//defualt=3260 

enum tgtadm_op {
	OP_NEW,   	//--op new
	OP_DELETE, 	//--op delete
	OP_SHOW, 	//--op show
	OP_BIND, 	//--op bind
	OP_UNBIND, 	//--op unbind
	OP_UPDATE, 	//--op update
	OP_STATS, 	//--op stat
	OP_START, 	//--op start
	OP_STOP, 	//--op stop
};
enum tgtadm_mode {
	MODE_SYSTEM, 	// --mode system
	MODE_TARGET, 	// --mode target
	MODE_DEVICE, 	// --mode logicalunit
	MODE_PORTAL, 	// --mode portal
	MODE_LLD, 		// --mode lld 

	MODE_SESSION, 	//--mode session
	MODE_CONNECTION,//--mode connection
	MODE_ACCOUNT, 	//--mode account
};
enum tgtadm_errno {
	TGTADM_SUCCESS,
	TGTADM_UNKNOWN_ERR,
	TGTADM_NOMEM,
	TGTADM_NO_DRIVER,
	TGTADM_NO_TARGET,

	TGTADM_NO_LUN,
	TGTADM_NO_SESSION,
	TGTADM_NO_CONNECTION,
	TGTADM_NO_BINDING,
	TGTADM_TARGET_EXIST,
	TGTADM_LUN_EXIST,
	TGTADM_BINDING_EXIST,

	TGTADM_ACL_EXIST,
	TGTADM_ACL_NOEXIST,
	TGTADM_USER_EXIST,
	TGTADM_NO_USER,
	TGTADM_TOO_MANY_USER,
	TGTADM_INVALID_REQUEST,

	TGTADM_OUTACCOUNT_EXIST,
	TGTADM_TARGET_ACTIVE,
	TGTADM_LUN_ACTIVE,
	TGTADM_DRIVER_ACTIVE,
	TGTADM_UNSUPPORTED_OPERATION,
	TGTADM_UNKNOWN_PARAM,

	TGTADM_PREVENT_REMOVAL,
};
typedef enum tgtadm_errno tgtadm_err;

struct tgtadm_req {
	enum tgtadm_mode mode;
	enum tgtadm_op op;
	char lld[64];
	uint32_t len;
	int32_t tid;
	uint64_t sid;
	uint64_t lun;
	uint32_t cid;
	uint32_t host_no;
	uint32_t device_type;
	uint32_t ac_dir;
	uint32_t pack;
	uint32_t force;
};
struct tgtadm_rsp {
	uint32_t err;
	uint32_t len;
};


struct concat_buf{
	FILE *streamf;
	int err;
	int used;
	char *buf;
	size_t size;
};

static const char *tgtadm_strerror(int err)
{
	static const struct {
		enum tgtadm_errno err;
		char *desc;
	} errors[] = {
	{ TGTADM_SUCCESS, "success" },
	{ TGTADM_UNKNOWN_ERR, "unknown error" },
	{ TGTADM_NOMEM, "out of memory" },
	{ TGTADM_NO_DRIVER, "can't find the driver" },
	{ TGTADM_NO_TARGET, "can't find the target" },
	{ TGTADM_NO_LUN, "can't find the logical unit" },
	{ TGTADM_NO_SESSION, "can't find the session" },
	{ TGTADM_NO_CONNECTION, "can't find the connection" },
	{ TGTADM_NO_BINDING, "can't find the binding" },
	{ TGTADM_TARGET_EXIST, "this target already exists" },
	{ TGTADM_BINDING_EXIST, "this binding already exists" },
	{ TGTADM_LUN_EXIST, "this logical unit number already exists" },
	{ TGTADM_ACL_EXIST, "this access control rule already exists" },
	{ TGTADM_ACL_NOEXIST, "this access control rule does not exist" },
	{ TGTADM_USER_EXIST, "this account already exists" },
	{ TGTADM_NO_USER, "can't find the account" },
	{ TGTADM_TOO_MANY_USER, "too many accounts" },
	{ TGTADM_INVALID_REQUEST, "invalid request" },
	{ TGTADM_OUTACCOUNT_EXIST, "this target already has an outgoing account" },
	{ TGTADM_TARGET_ACTIVE, "this target is still active" },
	{ TGTADM_LUN_ACTIVE, "this logical unit is still active" },
	{ TGTADM_DRIVER_ACTIVE, "this driver is busy" },
	{ TGTADM_UNSUPPORTED_OPERATION, "this operation isn't supported" },
	{ TGTADM_UNKNOWN_PARAM, "unknown parameter" },
	{ TGTADM_PREVENT_REMOVAL, "this device has Prevent Removal set" }
	};
	int i;
	for (i = 0; i < ARRAY_SIZE(errors); ++i)
		if (errors[i].err == err)
		return errors[i].desc;
		return "(unknown tgtadm_errno)";
}

#endif


//tgt.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "tgt.h"

const char* LLD="iscsi";

void concat_buf_init(struct concat_buf *b){
	b->streamf=open_memstream(&b->buf,&b->size);
	b->err=b->streamf?0:errno;
	b->used=0;
}

int concat_printf(struct concat_buf *b,const char*format,...){
	va_list args;
	int nprinted;
	if(!b->err){
		va_start(args,format);
		nprinted=vfprintf(b->streamf,format,args);
		if(nprinted>=0)
			b->used += nprinted;
		else{
			b->err=nprinted;
			fclose(b->streamf);
			b->streamf =NULL;
		}
		va_end(args);
	}
	return b->err;
}

int concat_buf_finish(struct concat_buf *b){
	if(b->streamf){
		fclose(b->streamf);
		b->streamf=NULL;
		if(b->size)
			b->size++; 	//account for trailing NULL char
	}
	return b->err;
}

int concat_write(struct concat_buf *b, int fd, int offset)
{
	concat_buf_finish(b);
	if (b->err) {
		errno = b->err;
		return -1;
	}
	if (b->size - offset > 0)
	return write(fd, b->buf + offset, b->size - offset);
	else {
		errno = EINVAL;
		return -1;
	}
}

void concat_buf_release(struct concat_buf *b)
{
	concat_buf_finish(b);
	if (b->buf) {
		free(b->buf);
		memset(b, 0, sizeof(*b));
	}
}

int tgt_mgmt_connect(int *fd){
	int ret;
	struct sockaddr_un addr;
	char mgmt_path[256];
	*fd = socket(AF_LOCAL, SOCK_STREAM, 0);
	if (*fd < 0) {
		printf("can't create a socket!\n");
		return errno;
	}
	memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_LOCAL;
	sprintf(mgmt_path, "%s.%d", TGT_IPC_ADDR, control_port);
	strncpy(addr.sun_path, mgmt_path, sizeof(addr.sun_path));

	ret = connect(*fd, (struct sockaddr *) &addr, sizeof(addr));
	if (ret < 0)
		return errno;
	return 0;
}

int tgt_mgmt_rsp(int fd,struct tgtadm_req *req){
	struct tgtadm_rsp rsp;
	int ret,rest,len;
	retry:
	ret=recv(fd,&rsp,sizeof(rsp),MSG_WAITALL);
	if(ret<0){
		if(errno==EAGAIN) goto retry;
		else if(errno==EINTR)
			printf("interrupted by a signal!\n");
		else
			printf("can't get the response!\n");
		return errno;
	}else if(ret==0){
		printf("tgtd closed the socket!\n");
		return 0;
	}else if(ret!=sizeof(rsp)){
		printf("a partial response!\n");
		return 0;
	}

	if(rsp.err!=0){
		printf("%s!\n",tgtadm_strerror(rsp.err));
		return EINVAL;
	}

	rest=rsp.len-sizeof(rsp);
	if(!rest) return 0;

	while(rest){
		char buf[4096];
		memset(buf,0,sizeof(buf));
		len=sizeof(buf)-1;
		len=(len<rest?len:rest);
		ret=read(fd,buf,len);
		if(ret<=0){
			printf("\ncan't get the full response!\n");
			return errno;
		}
		fputs(buf,stdout);
		rest-=len;
	}
	return 0;
}

int tgt_mgmt_req(struct tgtadm_req *req,struct concat_buf*b){
	int ret,fd=0,done=0;
	req->len=sizeof(*req)+b->size;
	ret=tgt_mgmt_connect(&fd);
	if(ret<0){
		printf("can't connect to tgt daemon !\n");
		goto out;
	}
	ret=write(fd,req,sizeof(*req));
	if(ret<0||ret!=sizeof(*req)){
		printf("failed to send request hdr to tgt daemon!\n");
		ret=errno;
		goto out;
	}
	while(done<b->size){
		ret=concat_write(b,fd,done);
		if(ret>0)
			done+=ret;
		else if(errno!=EAGAIN){
			printf("failed to send request buf to tgt daemon!\n");
			ret=errno;
			goto out;
		}
	}
	printf("send to tgtd %d!\n",req->len);
	ret=tgt_mgmt_rsp(fd,req);
	out:
		if(fd>0) close(0);
		concat_buf_release(b);
		return ret;
}

int tgt_create_tgt(int tid,char *tgtname){
	struct tgtadm_req adm_req={0},*req=&adm_req;
	struct concat_buf b;
	int ret;
	strcpy(req->lld,LLD);//default
	req->mode=1; 		//MODE_TARGET
	req->op=0; 			//OP_NEW
	req->tid=tid;
	req->sid=req->cid=req->host_no=0;//default
	req->lun=-1; 		//default

	req->device_type=0; //default TYPE_DISK
	req->ac_dir=0;	//default 1=outgoing
	req->pack=0; 	//default
	req->force=0; 	//default 1=force
	concat_buf_init(&b);
	concat_printf(&b,"targetname=%s",tgtname);
	ret=concat_buf_finish(&b);
	if(ret){
		printf("failed to create request,errno:%d\n",ret);
		exit(ret);
	}
	ret=tgt_mgmt_req(req,&b);
	return ret;
}
int tgt_delete_tgt(int tid){
	struct tgtadm_req adm_req={0},*req=&adm_req;
	struct concat_buf b;
	int ret;
	strcpy(req->lld,LLD);//default
	req->mode=1; 		//MODE_TARGET
	req->op=1; 			//OP_DELETE
	req->tid=tid;
	req->sid=req->cid=req->host_no=0;//default
	req->lun=-1; 		//default

	req->device_type=req->ac_dir=req->pack=req->force=0; //default

	concat_buf_init(&b);
	ret=concat_buf_finish(&b);
	if(ret){
		printf("failed to create request,errno:%d\n",ret);
		exit(ret);
	}
	ret=tgt_mgmt_req(req,&b);
	return ret;
}
int tgt_add_lun(int tid,int lunid,char *lunname){
	struct tgtadm_req adm_req={0},*req=&adm_req;
	struct concat_buf b;
	int ret;
	strcpy(req->lld,LLD);//default
	req->mode=2; 		//MODE_DEVICE --mode logicalunit
	req->op=0; 			//OP_NEW
	req->tid=tid;
	req->sid=req->cid=req->host_no=0;//default
	req->lun=lunid;		//default

	req->device_type=req->ac_dir=req->pack=req->force=0; //default
	concat_buf_init(&b);
	concat_printf(&b,"path=%s",lunname);
	ret=concat_buf_finish(&b);
	if(ret){
		printf("failed to create request,errno:%d\n",ret);
		exit(ret);
	}
	ret=tgt_mgmt_req(req,&b);
	return ret;
}
int tgt_del_lun(int tid,int lunid){
	struct tgtadm_req adm_req={0},*req=&adm_req;
	struct concat_buf b;
	int ret;
	strcpy(req->lld,LLD);//default
	req->mode=2; 		//MODE_DEVICE --mode logicalunit
	req->op=1; 			//OP_DELETE
	req->tid=tid;
	req->sid=req->cid=req->host_no=0;//default
	req->lun=lunid;		//default

	req->device_type=req->ac_dir=req->pack=req->force=0; //default
	concat_buf_init(&b);
	ret=concat_buf_finish(&b);
	if(ret){
		printf("failed to create request,errno:%d\n",ret);
		exit(ret);
	}
	ret=tgt_mgmt_req(req,&b);
	return ret;
}
int tgt_bind_initiator(int tid,int type,char*init_name){
	struct tgtadm_req adm_req={0},*req=&adm_req;
	struct concat_buf b;
	int ret;
	strcpy(req->lld,LLD);//default
	req->mode=1; 		//MODE_TARGET
	req->op=3; 			//OP_BIND
	req->tid=tid;
	req->sid=req->cid=req->host_no=0;//default
	req->lun=-1; 		//default

	req->device_type=req->ac_dir=req->pack=req->force=0; //default
	concat_buf_init(&b);
	if(type==1){
		concat_printf(&b,"initiator-address=%s",init_name);
	}else if(type==0){
		concat_printf(&b,"initiator-name=%s",init_name);
	}else{
		printf("type error: \n");
	}
	ret=concat_buf_finish(&b);
	if(ret){
		printf("failed to create request,errno:%d\n",ret);
		exit(ret);
	}
	ret=tgt_mgmt_req(req,&b);
	return ret;
}
int tgt_unbind_initiator(int tid,int type,char*init_name){
	struct tgtadm_req adm_req={0},*req=&adm_req;
	struct concat_buf b;
	int ret;
	strcpy(req->lld,LLD);	//default
	req->mode=1; 			//MODE_TARGET
	req->op=4; 				//OP_BIND
	req->tid=tid;
	req->sid=req->cid=req->host_no=0;//default
	req->lun=-1; 		//default

	req->device_type=req->ac_dir=req->pack=req->force=0; //default

	concat_buf_init(&b);
	if(type==1){
		concat_printf(&b,"initiator-address=%s",init_name);
	}else if(type==0){
		concat_printf(&b,"initiator-name=%s",init_name);
	}else{
		printf("type error: \n");
	}
	ret=concat_buf_finish(&b);
	if(ret){
		printf("failed to create request,errno:%d\n",ret);
		exit(ret);
	}
	ret=tgt_mgmt_req(req,&b);
	return ret;
}

int tgt_show_tgt(int tid){
	struct tgtadm_req adm_req={0},*req=&adm_req;
	struct concat_buf b;
	int ret;
	strcpy(req->lld,LLD);	//default
	req->mode=1; 			//MODE_TARGET
	req->op=2; 				//OP_SHOW
	req->tid=tid?tid:-1;	// 0=ALL
	req->sid=req->cid=req->host_no=0;//default
	req->lun=-1; 			//default

	req->device_type=req->ac_dir=req->pack=req->force=0; //default

	concat_buf_init(&b);
	ret=concat_buf_finish(&b);
	if(ret){
		printf("failed to create request,errno:%d\n",ret);
		exit(ret);
	}
	ret=tgt_mgmt_req(req,&b);
	return ret;
}

int main(int argc,char*argv[]){
	  //tgt_show_tgt(0);
	//tgt_create_tgt(2,"guoming");
	//tgt_add_lun(2,1,"/dev/sdb3");
	//tgt_bind_initiator(1,1,"192.168.1.0/24");
	//tgt_unbind_initiator(1,1,"ALL");
	tgt_unbind_initiator(1,1,"192.168.1.180");
	tgt_bind_initiator(1,0,"cgm88s");
	//tgt_del_lun(2,1);
	//tgt_delete_tgt(2);
}


你可能感兴趣的:(STGT:target userspace utils)