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

📄 smux.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
					if(result<0) {						oid_copy(suffix, v->name, v->namelen);						suffix_len = v->namelen;					}					*val = (*v->findVar) (v, suffix, &suffix_len, exact,					val_len, &write_method);					*reqid_len = suffix_len + subtree->name_len;					if (*val) {						*val_type = v->type;						return 0;					}				}			}		}	}	memcpy (reqid, save, savelen * sizeof(oid));	*reqid_len = savelen;	return SNMP_ERR_NOSUCHNAME;}/* GET message header. */static char *smux_parse_get_header (char *ptr, size_t *len, long *reqid){	u_char type;	long errstat;	long errindex;	/* Request ID. */	ptr = asn_parse_int (ptr, len, &type, reqid, sizeof (*reqid));	DEBUG2 ("SMUX GET reqid: %ld len: %d", *reqid, (int) *len);	/* Error status. */	ptr = asn_parse_int (ptr, len, &type, &errstat, sizeof (errstat));	DEBUG2 ("SMUX GET errstat %ld len: %d", errstat, *len);	/* Error index. */	ptr = asn_parse_int (ptr, len, &type, &errindex, sizeof (errindex));	DEBUG2 ("SMUX GET errindex %ld len: %d", errindex, *len);	return ptr;}static voidsmux_parse_set (char *ptr, size_t len, int action){	long reqid;	oid my_oid[MAX_OID_LEN];	size_t oid_len;	u_char val_type;	void *val;	size_t val_len;	int ret;	DEBUG2 ("SMUX SET(%s) message parse: len %d",			(RESERVE1 == action) ? "RESERVE1" : ((FREE == action) ? "FREE" : "COMMIT"),			len);	/* Parse SET message header. */	ptr = smux_parse_get_header (ptr, &len, &reqid);	/* Parse SET message object ID. */	ptr = smux_var (ptr, len, my_oid, &oid_len, &val_len, &val_type, &val);	ret = smux_set (my_oid, &oid_len, val_type, val, val_len, action);	DEBUG2 ("SMUX SET ret %d", ret);	/* Return result. */	if (RESERVE1 == action)		smux_getresp_send (my_oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);}static voidsmux_parse_get (char *ptr, size_t len, int exact){	long reqid;	oid my_oid[MAX_OID_LEN];	size_t oid_len;	u_char val_type;	const void *val;	size_t val_len;	int ret;	DEBUG2 ("SMUX GET message parse: len %d", len);	/* Parse GET message header. */	ptr = smux_parse_get_header (ptr, &len, &reqid);	/* Parse GET message object ID. We needn't the value come */	ptr = smux_var (ptr, len, my_oid, &oid_len, NULL, NULL, NULL);	/* Traditional getstatptr. */	if (exact)		ret = smux_get (my_oid, &oid_len, exact, &val_type, &val, &val_len);	else		ret = smux_getnext (my_oid, &oid_len, exact, &val_type, &val, &val_len);	/* Return result. */	if (ret == 0)		smux_getresp_send (my_oid, oid_len, reqid, 0, 0, val_type, val, val_len);	else		smux_getresp_send (my_oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);}/* Parse SMUX_CLOSE message. */static voidsmux_parse_close (char *ptr, int len){	long reason = 0;	while (len--) {		reason = (reason << 8) | (long) *ptr;		ptr++;	}	DEBUG ("SMUX_CLOSE with reason: %ld", reason);}/* SMUX_RRSP message. */static voidsmux_parse_rrsp (char *ptr, int len){	char val;	long errstat;	ptr = asn_parse_int (ptr, &len, &val, &errstat, sizeof (errstat));	DEBUG2 ("SMUX_RRSP value: %d errstat: %ld", val, errstat);}/* Parse SMUX message. */static intsmux_parse (char *ptr, int len){	/* this buffer we'll use for SOUT message. We could allocate it with malloc and		 save only static pointer/lenght, but IMHO static buffer is a faster solusion */	static u_char sout_save_buff[SMUXMAXPKTSIZE];	static int sout_save_len = 0;	int len_income = len; /* see note below: YYY */	u_char type;	u_char rollback;	rollback = ptr[2]; /* important only for SMUX_SOUT */process_rest: /* see note below: YYY */	/* Parse SMUX message type and subsequent length. */	ptr = asn_parse_header (ptr, &len, &type);	DEBUG2 ("SMUX message received type: %d rest len: %d", type, len);	switch (type) {		case SMUX_OPEN:			/* Open must be not send from SNMP agent. */			DEBUG ("SMUX_OPEN received: resetting connection.");			return -1;			break;		case SMUX_RREQ:			/* SMUX_RREQ message is invalid for us. */			DEBUG ("SMUX_RREQ received: resetting connection.");			return -1;			break;		case SMUX_SOUT:			/* SMUX_SOUT message is now valied for us. */			DEBUG2 ("SMUX_SOUT(%s)", rollback ? "rollback" : "commit");			if (sout_save_len > 0) {				smux_parse_set (sout_save_buff, sout_save_len, rollback ? FREE : COMMIT);				sout_save_len = 0;			} else				DEBUG ("SMUX_SOUT sout_save_len=%d - invalid", (int) sout_save_len);			if (len_income > 3) {				/* YYY: this strange code has to solve the "slow peer"				   problem: When agent sends SMUX_SOUT message it doesn't				   wait any responce and may send some next message to				   subagent. Then the peer in 'smux_read()' will recieve				   from socket the 'concatenated' buffer, contaning both				   SMUX_SOUT message and the next one				   (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check: if				   the buffer is longer than 3 ( length of SMUX_SOUT ), we				   must process the rest of it.	This effect may be observed				   if DEBUG is set to >1 */					ptr++;					len = len_income - 3;					goto process_rest;				}			break;		case SMUX_GETRSP:			/* SMUX_GETRSP message is invalid for us. */			DEBUG ("SMUX_GETRSP received: resetting connection.");			return -1;			break;		case SMUX_CLOSE:			/* Close SMUX connection. */			DEBUG2 ("SMUX_CLOSE");			smux_parse_close (ptr, len);			return -1;			break;		case SMUX_RRSP:			/* This is response for register message. */			DEBUG2 ("SMUX_RRSP");			smux_parse_rrsp (ptr, len);			break;		case SMUX_GET:			/* Exact request for object id. */			DEBUG2 ("SMUX_GET");			smux_parse_get (ptr, len, 1);			break;		case SMUX_GETNEXT:			/* Next request for object id. */			DEBUG2 ("SMUX_GETNEXT");			smux_parse_get (ptr, len, 0);			break;		case SMUX_SET:			/* SMUX_SET is supported with some limitations. */			DEBUG2 ("SMUX_SET");			/* save the data for future SMUX_SOUT */			memcpy (sout_save_buff, ptr, len);			sout_save_len = len;			smux_parse_set (ptr, len, RESERVE1);			break;		default:			DEBUG ("Unknown type: %d", type);			break;	}	return 0;}/* SMUX message read function. */intsmux_read (){	int len;	u_char buf[SMUXMAXPKTSIZE];	int ret;	rad_snmp.smux_event=SMUX_NONE;	DEBUG2 ("SMUX read start");	/* Read message from SMUX socket. */	len = recv (rad_snmp.smux_fd, buf, SMUXMAXPKTSIZE, 0);	if (len < 0) {		DEBUG ("Can't read all SMUX packet: %s", strerror (errno));		close (rad_snmp.smux_fd);		rad_snmp.smux_fd = -1;		rad_snmp.smux_event=SMUX_CONNECT;		return -1;	}	if (len == 0) {		DEBUG ("SMUX connection closed: %d", rad_snmp.smux_fd);		close (rad_snmp.smux_fd);		rad_snmp.smux_fd = -1;		rad_snmp.smux_event=SMUX_CONNECT;		return -1;	}	DEBUG2 ("SMUX read len: %d", len);	/* Parse the message. */	ret = smux_parse (buf, len);	if (ret < 0) {		close (rad_snmp.smux_fd);		rad_snmp.smux_fd = -1;		rad_snmp.smux_event=SMUX_CONNECT;		return -1;	}	rad_snmp.smux_event=SMUX_READ;	return 0;}intsmux_open(void){	u_char buf[BUFSIZ];	u_char *ptr;	int len;	u_long smux_proto_version;	u_char rad_progname[] = "radiusd";	smux_oid_dump ("SMUX open oid", smux_oid, smux_oid_len);	DEBUG2 ("SMUX open progname: %s", rad_progname);	DEBUG2 ("SMUX open password: %s", rad_snmp.smux_password);	ptr = buf;	len = BUFSIZ;	/* SMUX Header.	As placeholder. */	ptr = asn_build_header (ptr, &len, (u_char) SMUX_OPEN, 0);	/* SMUX Open. */	smux_proto_version = 0;	ptr = asn_build_int (ptr, &len,			(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),			&smux_proto_version, sizeof (u_long));	/* SMUX connection oid. */	ptr = asn_build_objid (ptr, &len,			(u_char)			(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),			smux_oid, smux_oid_len);	/* SMUX connection description. */	ptr = asn_build_string (ptr, &len,			(u_char)			(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),			rad_progname, strlen (rad_progname));	/* SMUX connection password. */	ptr = asn_build_string (ptr, &len,			(u_char)			(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),			rad_snmp.smux_password, strlen(rad_snmp.smux_password));	/* Fill in real SMUX header.	We exclude ASN header size (2). */	len = BUFSIZ;	asn_build_header (buf, &len, (u_char) SMUX_OPEN, (ptr - buf) - 2);	return send (rad_snmp.smux_fd, buf, (ptr - buf), 0);}intsmux_register(void){	u_char buf[BUFSIZ];	u_char *ptr;	int len, ret;	long priority;	long operation;	struct subtree *subtree;	struct list *l;	ret = 0;	for (l = treelist; l; l=l->next) {		subtree = l->data;		ptr = buf;		len = BUFSIZ;		/* SMUX RReq Header. */		ptr = asn_build_header (ptr, &len, (u_char) SMUX_RREQ, 0);		/* Register MIB tree. */		ptr = asn_build_objid (ptr, &len,				(u_char)				(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),				subtree->name, subtree->name_len);		/* Priority. */		priority = -1;		ptr = asn_build_int (ptr, &len,				(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),				&priority, sizeof (u_long));		/* Operation. */		operation = rad_snmp.snmp_write_access ? 2 : 1; /* Register R/O or R/W */		ptr = asn_build_int (ptr, &len,				(u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),				&operation, sizeof (u_long));		smux_oid_dump ("SMUX register oid", subtree->name, subtree->name_len);		DEBUG2 ("SMUX register priority: %ld", priority);		DEBUG2 ("SMUX register operation: %ld", operation);		len = BUFSIZ;		asn_build_header (buf, &len, (u_char) SMUX_RREQ, (ptr - buf) - 2);		ret = send (rad_snmp.smux_fd, buf, (ptr - buf), 0);		if (ret < 0)			return ret;		}	return ret;}/* Try to connect to SNMP agent. */intsmux_connect (){	int ret;	rad_snmp.smux_event=SMUX_NONE;	DEBUG2 ("SMUX connect try %d", rad_snmp.smux_failures + 1);	/* Make socket.	Try to connect. */	rad_snmp.smux_fd = smux_sock ();	if (rad_snmp.smux_fd < 0) {		if (++rad_snmp.smux_failures < rad_snmp.smux_max_failures)			rad_snmp.smux_event=SMUX_CONNECT;		return 0;	}	/* Send OPEN PDU. */	ret = smux_open ();	if (ret < 0) {		DEBUG ("SMUX open message send failed: %s", strerror (errno));		close (rad_snmp.smux_fd);		rad_snmp.smux_fd = -1;		rad_snmp.smux_event=SMUX_CONNECT;		return -1;	}	/* Send any outstanding register PDUs. */	ret = smux_register ();	if (ret < 0) {		DEBUG ("SMUX register message send failed: %s", strerror (errno));		close (rad_snmp.smux_fd);		rad_snmp.smux_fd = -1;		rad_snmp.smux_event=SMUX_CONNECT;		return -1;	}	/* Everything goes fine. */	rad_snmp.smux_event=SMUX_READ;	return 0;}/* Clear all SMUX related resources. */voidsmux_stop(void){	rad_snmp.smux_event=SMUX_NONE;	if (rad_snmp.smux_fd >= 0)		close (rad_snmp.smux_fd);	rad_snmp.smux_fd = -1;}intsmux_str2oid (char *str, oid *my_oid, size_t *oid_len){	int len;	int val;	len = 0;	val = 0;	*oid_len = 0;	if (*str == '.')		str++;	if (*str == '\0')		return 0;	while (1) {		if (! isdigit ((int) *str))			return -1;		while (isdigit ((int) *str)) {			val *= 10;			val += (*str - '0');			str++;		}		if (*str == '\0')			break;		if (*str != '.')			return -1;		my_oid[len++] = val;		val = 0;		str++;	}	my_oid[len++] = val;	*oid_len = len;	return 0;}oid *smux_oid_dup (oid *objid, size_t objid_len){	oid *new;	new = (oid *)rad_malloc(sizeof (oid) * objid_len);	oid_copy (new, objid, objid_len);	return new;}intsmux_header_generic (struct variable *v, oid *name, size_t *length, int exact,		size_t *var_len, WriteMethod **write_method){	oid fulloid[MAX_OID_LEN];	int ret;	oid_copy (fulloid, v->name, v->namelen);	fulloid[v->namelen] = 0;	/* Check against full instance. */	ret = oid_compare (name, *length, fulloid, v->namelen + 1);	/* Check single instance. */	if ((exact && (ret != 0)) || (!exact && (ret >= 0)))	return MATCH_FAILED;	/* In case of getnext, fill in full instance. */	memcpy (name, fulloid, (v->namelen + 1) * sizeof (oid));	*length = v->namelen + 1;	*write_method = 0;	*var_len = sizeof(long);		/* default to 'long' results */	return MATCH_SUCCEEDED;}/* Initialize some values then schedule first SMUX connection. */voidsmux_init (oid defoid[], size_t defoid_len){	smux_oid = defoid;	smux_oid_len = defoid_len;}/* Register subtree to smux master tree. */voidsmux_register_mib(const char *descr, struct variable *var, size_t width,		int num, oid name[], size_t namelen){	struct subtree *tree, *tt;	struct list *l, *ll;	tree = (struct subtree *)rad_malloc(sizeof(struct subtree));	oid_copy (tree->name, name, namelen);	tree->name_len = namelen;	tree->variables = var;	tree->variables_num = num;	tree->variables_width = width;	tree->registered = 0;	l = (struct list *)rad_malloc(sizeof(struct list));	l->data = tree;	l->next = NULL;/* Build a treelist sorted by the name. This makes GETNEXT simpler */	if (treelist == NULL) {		treelist = l;		return;	}	tt = (struct subtree*) treelist->data;	if (oid_compare(name, namelen, tt->name, tt->name_len) < 0) {		l->next = treelist;		treelist = l;		return;	}	for (ll = treelist; ll->next; ll=ll->next) {		tt = (struct subtree*) ll->next->data;		if (oid_compare(name, namelen, tt->name, tt->name_len) < 0) {			l->next = ll->next;			ll->next = l;			return;		}	}	ll->next = l;}voidsmux_start(void){	rad_snmp.smux_event=SMUX_CONNECT;	smux_connect();}#endif /* WITH_SNMP */

⌨️ 快捷键说明

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