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

📄 gclient.c

📁 openGFS , a kind of file system.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *    Copyright 2000-2001 Sistina Software, Inc. *    Portions Copyright 2001 The OpenGFS Project * *    This is free software released under the GNU General Public License. *    There is no warranty for this software.  See the file COPYING for *    details. * *    See the file AUTHORS for a list of contributors. * *//* * This is a user level interface for setting up and configuring the * gnbd client devices. *//* * AUDIT: <Alan> *	Audited for security flaws *	- Fixed multiple buffer overflows [LOCAL, TRUSTED NETWORK] *	- Fixed network DNS assumption insecurity [NETWORK] *	TODO *	- We need an authentication mechanism. Right now gclient will do *	  arbitarily dumb things and it really needs to. */#define HELPER_PROGRAM#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <sys/ioctl.h>#include <netdb.h>#include <errno.h>#include <dirent.h>#include <ctype.h>#include "gnbd.h"int message_flag = 1;#define printm(fmt, args...)\{\	if(message_flag != 0) \		fprintf(stderr, "gclient: " fmt, ##args); \}typedef struct devlist_s {	char name[300];	struct devlist_s *next;} devlist_t;int match(char *name, devlist_t * ptr){	while (ptr != NULL) {		if (strcmp(name, ptr->name) == 0)			return 0;		ptr = ptr->next;	}	return -1;}devlist_t *getnext(devlist_t * ptr){	if (ptr == NULL)		return NULL;	return (ptr->next);}devlist_t *add(char *name, devlist_t * head){	devlist_t *ptr;	devlist_t *tmp = (devlist_t *) malloc(sizeof(devlist_t));	snprintf(tmp->name, 300, "%s", name);	tmp->next = NULL;	if (head == NULL)		return tmp;	ptr = head;	while (ptr->next != NULL)		ptr = ptr->next;	ptr->next = tmp;	return head;}devlist_t *clear(devlist_t * ptr){	devlist_t *tmp;	while (ptr != NULL) {		tmp = ptr;		ptr = ptr->next;		free(tmp);	}	return NULL;}int do_device_remove(int comm_fd, int minor_nr){	gnbd_device_t dev;	errno = 0;	dev.name = NULL;	dev.length = 0;	dev.action = GNBD_DEV_REMOVE;	dev.minor_nr = minor_nr;	if (ioctl(comm_fd, GNBD_DEVICE, &dev) < 0)		return -1;	return 0;}int do_disconnect(int comm_fd, char *dev_name){	struct stat st;	gnbd_action_t act;	char path[300];	errno = 0;	memset(&act, 0, sizeof(gnbd_action_t));	snprintf(path, 300, "/dev/gnbd/%s", dev_name);	if (stat(path, &st) < 0)		return -1;	act.device = minor(st.st_rdev);	act.action = GNBD_ACT_Disconnect;	if (ioctl(comm_fd, GNBD_ACTION, &act) < 0)		return -1;	return 0;}int do_connect(int comm_fd, uint16_t minor_nr){	gnbd_action_t act;	errno = 0;	memset(&act, 0, sizeof(gnbd_action_t));	act.device = minor_nr;	act.action = GNBD_ACT_Connect;	if (ioctl(comm_fd, GNBD_ACTION, &act) < 0)		return -1;	return 0;}int do_setipport(int comm_fd, uint16_t minor_nr, uint16_t port,		 struct in_addr ipaddr){	gnbd_action_t act;	errno = 0;	memset(&act, 0, sizeof(gnbd_action_t));	act.device = minor_nr;	act.port = htons(port);	act.ip = (uint32_t) ipaddr.s_addr;	act.action = GNBD_ACT_SetIPPort;	if (ioctl(comm_fd, GNBD_ACTION, &act) < 0) {		perror("ioctl failed");		return -1;	}	return 0;}int get_proc_data(char *buf, int len){	int n;	int bytes = 0;	int proc_fd;	proc_fd = open("/proc/gnbd", O_RDONLY);	if (proc_fd < 0) {		fprintf(stderr, "could not open /proc/gnbd: %s\n",			strerror(errno));		return -1;	}	while ((n = read(proc_fd, buf + bytes, len - bytes)) != 0) {		if (n < 0 && errno != EINTR) {			fprintf(stderr, "list request failed: %s\n",				strerror(errno));			close(proc_fd);			return -1;		}		bytes += n;	}	if (bytes < len)		buf[bytes] = 0;	else		buf[len - 1] = 0;	close(proc_fd);	return bytes;}int proc_match(char *name){	char buf[4096];	char *nameptr, *bufptr;	int bytes;	bytes = get_proc_data(buf, 4096);	if (bytes < 0)		return -1;	bufptr = buf;	while ((nameptr = strchr(bufptr, '/')) != NULL) {		nameptr++;		bufptr = strchr(nameptr, '/');		if (bufptr == NULL) {			perror("/proc/gnbd formatted incorrectly\n");			return -1;		}		*bufptr++ = 0;		if (strcmp(name, nameptr) == 0)			return 1;	}	return 0;}int do_device_create(int comm_fd, char *dev_name){	int err;	gnbd_device_t dev;	errno = 0;	err = proc_match(dev_name);	if (err < 0) {		fprintf(stderr, "errored trying proc_match\n");		return -1;	}	if (err == 1) {		errno = EEXIST;		return -1;	}	dev.name = dev_name;	dev.length = strlen(dev_name) + 1;	dev.action = GNBD_DEV_CREATE;	if (ioctl(comm_fd, GNBD_DEVICE, &dev) < 0) {		fprintf(stderr, "errored in ioctl\n");		return -1;	}	return dev.minor_nr;}int connect_to_server(char *hostname, uint16_t port, struct in_addr *ip_addr){	int sock_fd;	struct sockaddr_in server;	struct hostent *hp;	sock_fd = socket(AF_INET, SOCK_STREAM, 0);	if (sock_fd < 0) {		fprintf(stderr, "error creating socket: %s\n",			strerror(errno));		return -1;	}	server.sin_family = AF_INET;	hp = gethostbyname(hostname);	if (hp == NULL) {		fprintf(stderr, "cannot resolve host ip from name %s: %s",			hostname, strerror(errno));		return -1;	}	if (memcpy(&(server.sin_addr.s_addr), hp->h_addr, hp->h_length) ==	    NULL) {		fprintf(stderr, "cannot copy host address: %s\n",			strerror(errno));		return -1;	}	if (ip_addr != NULL)		ip_addr->s_addr = server.sin_addr.s_addr;	server.sin_port = htons(port);	if (connect(sock_fd, (struct sockaddr *) &server, sizeof(server)) <	    0) {		close(sock_fd);		fprintf(stderr, "error connecting to server: %s\n",			strerror(errno));		return -1;	}	return sock_fd;}int stomith(char *hostname){	uint32_t stomithip;	int bytes;	struct hostent *hp;	int sock_fd;	devlist_t *listptr, *iplist = NULL;	char buf[4096];	char *ipaddr, *bufptr;	hp = gethostbyname(hostname);	if (hp == NULL) {		fprintf(stderr,			"cannot resolve stomith host ip from name %s: %s\n",			hostname, strerror(errno));		return 1;	}	if (memcpy(&stomithip, hp->h_addr, hp->h_length) == NULL) {		fprintf(stderr, "cannot copy host address: %s\n",			strerror(errno));		return 1;	}	bufptr = (char *) &stomithip;	/* fprintf(stderr, "the stomith ip is %d.%d.%d.%d\n", (int)*bufptr,	   (int)*(bufptr+1), (int)*(bufptr+2), (int)*(bufptr+3)); */	bytes = get_proc_data(buf, 4096);	if (bytes < 0)		return 1;	bufptr = buf;	while ((ipaddr = strstr(bufptr, "IP :")) != NULL) {		ipaddr += 5;		if ((bufptr = strchr(ipaddr, '\n')) == NULL) {			fprintf(stderr, "malformed /proc/gnbd entry\n");			goto fail;		}		*bufptr++ = 0;		if (match(ipaddr, iplist) < 0)			iplist = add(ipaddr, iplist);	}	listptr = iplist;	while (listptr != NULL) {		sock_fd =		    connect_to_server(listptr->name, (unsigned int) 14243,				      NULL);		if (sock_fd < 0) {			fprintf(stderr,				"cannot connect to the server: %s\n",				strerror(errno));			goto fail;		}		write(sock_fd, "stom", 5);		write(sock_fd, (char *) &stomithip, 4);		read(sock_fd, buf, 5);		write(sock_fd, "bye", 4);		close(sock_fd);		if (strcmp(buf, "fail") == 0) {			fprintf(stderr,				"server is closing, cannot stomith\n");			goto fail;		}		listptr = getnext(listptr);	}	fprintf(stderr, "%s stomithed\n", hostname);	iplist = clear(iplist);	return 0;      fail:	iplist = clear(iplist);	return 1;}int getserver(char *hostname){	int n;	int total;	int sock_fd;	char buf[300];	char *port;	sock_fd = connect_to_server(hostname, (unsigned int) 14243, NULL);	if (sock_fd < 0)		return -1;	write(sock_fd, "port", 5);	printf("GNBD's on host: %s\n", hostname);	while (1) {		total = 0;		do {			n = read(sock_fd, buf+total, 300-total);			if (n < 0) {				close(sock_fd);				fprintf(stderr,					"error reading from the server: %s\n",					strerror(errno));				return -1;			}			total += n;		} while (buf[total - 1] != 0 && total!=300);			if(total==300)		{			fprintf(stderr, "error reading from server: reply too long.\n");			return -1;		}		if (strncmp(buf, "bye", 3) == 0)			break;		if ((port = strchr(buf, '/')) == NULL) {			fprintf(stderr, "malformed server message: %s\n",				buf);			close(sock_fd);			return -1;		}		*port++ = 0;		printf("Port: %5s  Name: %s\n", port, buf);		if (write(sock_fd, "next", 5) != 5) {			fprintf(stderr,				"error writing to the server: %s\n",				strerror(errno));			close(sock_fd);			return -1;		}	}	write(sock_fd, "quit", 5);	close(sock_fd);	return 0;}int validate_devs(int comm_fd){	DIR *dp;	int major_nr;	uint16_t minor_nr;	char buf[4096];	int bytes;	char *name;	char *minor;	char *bufptr;	char path[300];	devlist_t *save_list = NULL;	devlist_t *del_list = NULL;	devlist_t *list_ptr = NULL;	struct dirent *entry;	bytes = get_proc_data(buf, 4096);	if (bytes < 0)		return -1;	name = strchr(buf, ':');	name = name + 2;	bufptr = strchr(name, '\n');	*bufptr = 0;	major_nr = (int) strtoul(name, &bufptr, 0);	if (major_nr == 0 || bufptr == name) {		perror("couldn't find the major number for gnbd");		return -1;	}	bufptr++;	while ((name = strchr(bufptr, '/')) != NULL) {		name++;		bufptr = strchr(name, '/');		*bufptr++ = 0;		minor = strchr(bufptr, ':');		minor = minor + 2;		minor_nr = (uint16_t) strtoul(minor, &bufptr, 0);		if (minor_nr == 0 || bufptr == minor) {			fprintf(stderr,				"couldn't find the minor number for %s: %s\n",				name, strerror(errno));			return -1;		}		bufptr++;		if (do_connect(comm_fd, minor_nr) < 0) {			if (do_device_remove(comm_fd, (int) minor_nr) < 0) {				fprintf(stderr,					"couldn't remove bad device '%s': %s\n",					name, strerror(errno));				return -1;			}			printm("invalid GNBD '%s' removed\n", name);		} else {			save_list = add(name, save_list);		}	}	dp = opendir("/dev/gnbd/");	if (dp == NULL) {		perror("error opening directory /dev/gnbd");		clear(save_list);		return -1;	}	errno = 0;	while ((entry = readdir(dp)) != NULL) {		if (strcmp(entry->d_name, ".") == 0 ||		    strcmp(entry->d_name, "..") == 0)			continue;		if (match(entry->d_name, save_list) < 0)			del_list = add(entry->d_name, del_list);	}	clear(save_list);	if (closedir(dp) < 0) {		perror("error closeing directory /dev/gnbd");		save_list = clear(save_list);		del_list = clear(del_list);		return -1;	}	list_ptr = del_list;	while (list_ptr != NULL) {		snprintf(path, 300, "/dev/gnbd/%s", list_ptr->name);		if (remove(strcat(path, list_ptr->name)) < 0) {			fprintf(stderr, "error removing %s: %s\n", path,				strerror(errno));			del_list = clear(save_list);			del_list = clear(del_list);			return -1;		}		printm("removed file %s\n", path);		list_ptr = getnext(list_ptr);	}	del_list = clear(del_list);	return major_nr;}int list(void){	int i;	int bytes;	char *bufptr;	char buf[4096];	bytes = get_proc_data(buf, 4096);	if (bytes < 0)		return -1;	for (i = 0; i < bytes; i++)		if (buf[i] == '/')			buf[i] = ' ';	bufptr = strchr(buf, '\n');	if (bufptr == NULL || bufptr >= &buf[bytes]) {		perror("incorrectly formatted /proc/gnbd file?!?\n");		return -1;	}	printf("GNBD's currently registered%s", bufptr);	return 0;}int get_major_nr(void){	char buf[31];	int bytes;	char *major;	char *tail;

⌨️ 快捷键说明

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