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

📄 vqp.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * vqp.c	Functions to send/receive VQP packets. * * Version:	$Id: vqp.c,v 1.4 2008/01/05 17:58:44 nbk Exp $ * *   This library is free software; you can redistribute it and/or *   modify it under the terms of the GNU Lesser General Public *   License as published by the Free Software Foundation; either *   version 2.1 of the License, or (at your option) any later version. * *   This library is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *   Lesser General Public License for more details. * *   You should have received a copy of the GNU Lesser General Public *   License along with this library; if not, write to the Free Software *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2007 Alan DeKok <aland@deployingradius.com> */#include	<freeradius-devel/ident.h>RCSID("$Id: vqp.c,v 1.4 2008/01/05 17:58:44 nbk Exp $");#include	<freeradius-devel/libradius.h>#include	<freeradius-devel/udpfromto.h>#include	<freeradius-devel/vqp.h>#ifdef WITH_VMPS/* *  http://www.openbsd.org/cgi-bin/cvsweb/src/usr.sbin/tcpdump/print-vqp.c * *  Some of how it works: * *  http://www.hackingciscoexposed.com/pdf/chapter12.pdf * * VLAN Query Protocol (VQP) * *    0                   1                   2                   3 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |    Version    |    Opcode     | Response Code |  Data Count   | *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |                         Transaction ID                        | *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |                            Type (1)                           | *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |             Length            |            Data               / *   /                                                               / *   /                                                               / *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |                            Type (n)                           | *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *   |             Length            |            Data               / *   /                                                               / *   /                                                               / *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * VQP is layered over UDP.  The default destination port is 1589. * */#define VQP_HDR_LEN (8)#define VQP_VERSION (1)#define VQP_MAX_ATTRIBUTES (12)/* *	Wrapper for sendto which handles sendfromto, IPv6, and all *	possible combinations. * *	FIXME:  This is just a copy of rad_sendto(). *	Duplicate code is bad. */static int vqp_sendto(int sockfd, void *data, size_t data_len, int flags,		      fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr,		      int dst_port){	struct sockaddr_storage	dst;	socklen_t		sizeof_dst = sizeof(dst);#ifdef WITH_UDPFROMTO	struct sockaddr_storage	src;	socklen_t		sizeof_src = sizeof(src);	memset(&src, 0, sizeof(src));#endif	memset(&dst, 0, sizeof(dst));	/*	 *	IPv4 is supported.	 */	if (dst_ipaddr->af == AF_INET) {		struct sockaddr_in	*s4;		s4 = (struct sockaddr_in *)&dst;		sizeof_dst = sizeof(struct sockaddr_in);		s4->sin_family = AF_INET;		s4->sin_addr = dst_ipaddr->ipaddr.ip4addr;		s4->sin_port = htons(dst_port);#ifdef WITH_UDPFROMTO		s4 = (struct sockaddr_in *)&src;		sizeof_src = sizeof(struct sockaddr_in);		s4->sin_family = AF_INET;		s4->sin_addr = src_ipaddr->ipaddr.ip4addr;#endif	/*	 *	IPv6 MAY be supported.	 */#ifdef HAVE_STRUCT_SOCKADDR_IN6	} else if (dst_ipaddr->af == AF_INET6) {		struct sockaddr_in6	*s6;		s6 = (struct sockaddr_in6 *)&dst;		sizeof_dst = sizeof(struct sockaddr_in6);				s6->sin6_family = AF_INET6;		s6->sin6_addr = dst_ipaddr->ipaddr.ip6addr;		s6->sin6_port = htons(dst_port);#ifdef WITH_UDPFROMTO		return -1;	/* UDPFROMTO && IPv6 are not supported */#if 0		s6 = (struct sockaddr_in6 *)&src;		sizeof_src = sizeof(struct sockaddr_in6);		s6->sin6_family = AF_INET6;		s6->sin6_addr = src_ipaddr->ipaddr.ip6addr;#endif /* #if 0 */#endif /* WITH_UDPFROMTO */#endif /* HAVE_STRUCT_SOCKADDR_IN6 */	} else return -1;   /* Unknown address family, Die Die Die! */#ifdef WITH_UDPFROMTO	/*	 *	Only IPv4 is supported for udpfromto.	 *	 *	And if they don't specify a source IP address, don't	 *	use udpfromto.	 */	if ((dst_ipaddr->af == AF_INET) ||	    (src_ipaddr->af != AF_UNSPEC)) {		return sendfromto(sockfd, data, data_len, flags,				  (struct sockaddr *)&src, sizeof_src, 				  (struct sockaddr *)&dst, sizeof_dst);	}#else	src_ipaddr = src_ipaddr; /* -Wunused */#endif	/*	 *	No udpfromto, OR an IPv6 socket, fail gracefully.	 */	return sendto(sockfd, data, data_len, flags, 		      (struct sockaddr *)&dst, sizeof_dst);}/* *	Wrapper for recvfrom, which handles recvfromto, IPv6, and all *	possible combinations. * *	FIXME:  This is copied from rad_recvfrom, with minor edits. */static ssize_t vqp_recvfrom(int sockfd, uint8_t **pbuf, int flags,			    fr_ipaddr_t *src_ipaddr, uint16_t *src_port,			    fr_ipaddr_t *dst_ipaddr, uint16_t *dst_port){	struct sockaddr_storage	src;	struct sockaddr_storage	dst;	socklen_t		sizeof_src = sizeof(src);	socklen_t	        sizeof_dst = sizeof(dst);	ssize_t			data_len;	uint8_t			header[4];	void			*buf;	size_t			len;	memset(&src, 0, sizeof_src);	memset(&dst, 0, sizeof_dst);	/*	 *	Get address family, etc. first, so we know if we	 *	need to do udpfromto.	 *	 *	FIXME: udpfromto also does this, but it's not	 *	a critical problem.	 */	if (getsockname(sockfd, (struct sockaddr *)&dst,			&sizeof_dst) < 0) return -1;	/*	 *	Read the length of the packet, from the packet.	 *	This lets us allocate the buffer to use for	 *	reading the rest of the packet.	 */	data_len = recvfrom(sockfd, header, sizeof(header), MSG_PEEK,			    (struct sockaddr *)&src, &sizeof_src);	if (data_len < 0) return -1;	/*	 *	Too little data is available, discard the packet.	 */	if (data_len < 4) {		recvfrom(sockfd, header, sizeof(header), flags, 			 (struct sockaddr *)&src, &sizeof_src);		return 0;		/*		 *	Invalid version, packet type, or too many		 *	attributes.  Die.		 */	} else if ((header[0] != VQP_VERSION) ||		   (header[1] < 1) ||		   (header[1] > 4) ||		   (header[3] > VQP_MAX_ATTRIBUTES)) {		recvfrom(sockfd, header, sizeof(header), flags,			 (struct sockaddr *)&src, &sizeof_src);		return 0;	} else {		/* we got 4 bytes of data. */		/*		 *	We don't care about the contents for now...		 */#if 0		/*		 *	How many attributes are in the packet.		 */		len = header[3];		if ((header[1] == 1) || (header[1] == 3)) {			if (len != VQP_MAX_ATTRIBUTES) {				recvfrom(sockfd, header, sizeof(header), 0,					 (struct sockaddr *)&src, &sizeof_src);				return 0;			}			/*			 *	Maximum length we support.			 */			len = (12 * (4 + 4 + 253));		} else {			if (len != 2) {				recvfrom(sockfd, header, sizeof(header), 0, 				 (struct sockaddr *)&src, &sizeof_src);				return 0;			}			/*			 *	Maximum length we support.			 */			len = (12 * (4 + 4 + 253));		}#endif	}	/*	 *	For now, be generous.	 */	len = (12 * (4 + 4 + 253));	buf = malloc(len);	if (!buf) return -1;	/*	 *	Receive the packet.  The OS will discard any data in the	 *	packet after "len" bytes.	 */#ifdef WITH_UDPFROMTO	if (dst.ss_family == AF_INET) {		data_len = recvfromto(sockfd, buf, len, flags,				      (struct sockaddr *)&src, &sizeof_src, 				      (struct sockaddr *)&dst, &sizeof_dst);	} else#endif		/*		 *	No udpfromto, OR an IPv6 socket.  Fail gracefully.		 */		data_len = recvfrom(sockfd, buf, len, flags, 				    (struct sockaddr *)&src, &sizeof_src);	if (data_len < 0) {		free(buf);		return data_len;	}	/*	 *	Check address families, and update src/dst ports, etc.	 */	if (src.ss_family == AF_INET) {		struct sockaddr_in	*s4;		s4 = (struct sockaddr_in *)&src;		src_ipaddr->af = AF_INET;		src_ipaddr->ipaddr.ip4addr = s4->sin_addr;		*src_port = ntohs(s4->sin_port);		s4 = (struct sockaddr_in *)&dst;		dst_ipaddr->af = AF_INET;		dst_ipaddr->ipaddr.ip4addr = s4->sin_addr;		*dst_port = ntohs(s4->sin_port);#ifdef HAVE_STRUCT_SOCKADDR_IN6	} else if (src.ss_family == AF_INET6) {		struct sockaddr_in6	*s6;		s6 = (struct sockaddr_in6 *)&src;		src_ipaddr->af = AF_INET6;		src_ipaddr->ipaddr.ip6addr = s6->sin6_addr;		*src_port = ntohs(s6->sin6_port);		s6 = (struct sockaddr_in6 *)&dst;		dst_ipaddr->af = AF_INET6;		dst_ipaddr->ipaddr.ip6addr = s6->sin6_addr;		*dst_port = ntohs(s6->sin6_port);#endif	} else {		free(buf);		return -1;	/* Unknown address family, Die Die Die! */	}		/*	 *	Different address families should never happen.	 */	if (src.ss_family != dst.ss_family) {		free(buf);		return -1;	}	/*	 *	Tell the caller about the data	 */	*pbuf = buf;	return data_len;}RADIUS_PACKET *vqp_recv(int sockfd){	uint8_t *ptr;	ssize_t length;	uint32_t id;	RADIUS_PACKET *packet;	/*	 *	Allocate the new request data structure	 */	if ((packet = malloc(sizeof(*packet))) == NULL) {		librad_log("out of memory");		return NULL;	}	memset(packet, 0, sizeof(*packet));	packet->data_len = vqp_recvfrom(sockfd, &packet->data, 0,					&packet->src_ipaddr, &packet->src_port,					&packet->dst_ipaddr, &packet->dst_port);	/*	 *	Check for socket errors.	 */	if (packet->data_len < 0) {		librad_log("Error receiving packet: %s", strerror(errno));		/* packet->data is NULL */		free(packet);		return NULL;	}	/*	 *	We can only receive packets formatted in a way we	 *	expect.  However, we accept MORE attributes in a	 *	packet than normal implementations may send.	 */	if (packet->data_len < VQP_HDR_LEN) {		librad_log("VQP packet is too short");		rad_free(&packet);

⌨️ 快捷键说明

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