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

📄 dhcp.c

📁 dhcp snooping for vxworks
💻 C
📖 第 1 页 / 共 2 页
字号:

/*******************************************************
文件名: dhcp.c
文件说明:
use for dhcp snooping & option82 functions

author : aibin 
time: 20071212;
modify record:
*******************************************************/

#include "dhcp.h"
#include "stdlib.h"
#include "inetLib.h"
#include <cli.h>

#ifdef _DHCP_

int flag_dhcp_snooping;
int flag_dhcp_option82;
char dhcp_trust_port [11];
int dhcp_snoop_debug;
int dhcp_option82_debug;
int dhcp_command_respons = 0;
char *p_dhcp_bind = NULL;
dhcp_option82_gsw option82_value_gsw;
#define DEFAULT_AcessNodeId "AN5116-02"
#ifdef _AN5116_06_
#define MaxDev 1
#else
#define MaxDev 2
#endif

int discard_no_82 = 1;
typedef struct bcm_filter_s {
    int		filter_opaque_type;
} bcm_filter_t;

extern bcm_filter_t *dhcp_control[MaxDev]; /*maxdev num 对-02,为2;对-06,为1*/


int dhcp_init(void)
{
	flag_dhcp_option82 = 1;
	flag_dhcp_snooping = 0;
	memset (dhcp_trust_port, 1, sizeof(dhcp_trust_port));

	dhcp_snoop_debug = 0;
	dhcp_option82_debug = 0;

	dhcp_2_cpu ();
	/*option82*/
	memset (&option82_value_gsw, 0, sizeof (dhcp_option82_gsw));
	option82_value_gsw.XCI = 0;
	option82_value_gsw.XPI = 0;
	strcpy (option82_value_gsw.AccessNodeIdentifier, DEFAULT_AcessNodeId);
	cl_dhcp_module_init();
}

int dhcp_del (void)
{
	if (dhcp_control[0] != NULL)
	{
		driver_destroy_dhcp();
		driver_destroy_uplink_dhcp();
		printf ("don't send dhcp to cpu\r\n");
	}
	else
	{
		printf ("already don't send dhcp to cpu\r\n");	
	}
	return 0;
}

int dhcp_2_cpu(void)
{
	if (dhcp_control[0] == NULL)
	{
 		driver_Set_Dhcp_To_Cpu();
		driver_Set_Uplink_Dhcp_To_Cpu();
		printf ("set dhcp to cpu\r\n");
	}
	else
	{
		printf ("already set dhcp to cpu\r\n");
	}
	return 0;
}

int onu_dhcp_debug = 0;
int an5006_15_dhcp_debug = 0;
char chport = 0;
char chonu = 0;
char chvlan = 0;
int chdhcp (char state, char onu,char onuPort)
{
	if (state ==1)
	{
		onu_dhcp_debug = 1;
		discard_no_82 = 0;
		chport = onuPort;
		chonu = onu;
	}
	else if (state ==0)
	{
			
		onu_dhcp_debug = 0;
		discard_no_82 = 1;
		chport = 0;
		chonu = 0;
	}
	return 0;
}

int add_option82_to_packet (char *packet, char *p_option82, short origin_len, short *new_len)
{
	char buf[1400];
	char buf2[200];
	char *p;
	char option82_temp[300];
	char gsw_temp[100];
	unsigned short option_len, len;
	short len_change = 0;
	unsigned short old_len;
	char VlanTagOffset =0;
	int rack,frame,slotno,portsel, vpi, vci;
	char pName[20];
	char *p_find;

	memset (option82_temp, 0, sizeof (option82_temp));
	memset (buf, 0, sizeof (buf));
	memset (buf2, 0, sizeof (buf2));

	/*如果源包里没有option82,则将其添加到最后*/
	if (*p_option82 == 0xff)
	{
	/*	if (onu_dhcp_debug)
		{
			sprintf (buf, "0 0/0/0:0.0 0/0/0/0/0/0/EPON00000001 0/0/12 EP");
		}
		else if (an5006_15_dhcp_debug)
		{
			sprintf (buf, "0 0/0/0:0.0 IPDSLAM/1/2/3/0/24:8.35");
		}*/
		if (onu_dhcp_debug)
		{
			sprintf (buf, "0 0/0/0:%d.%d %s/%d/%d/%d/0/0/EPON%08d 0/0/%d EP", option82_value_gsw.XPI, option82_value_gsw.XCI, option82_value_gsw.AccessNodeIdentifier
			, option82_value_gsw.ANI_rack, option82_value_gsw.ANI_frame, option82_value_gsw.ANI_slot, chonu, chport);
		}
		else
		{
			sprintf (buf, "0 0/0/0:%d.%d %s/%d/%d/%d/0/0/", option82_value_gsw.XPI, option82_value_gsw.XCI, option82_value_gsw.AccessNodeIdentifier
			, option82_value_gsw.ANI_rack, option82_value_gsw.ANI_frame, option82_value_gsw.ANI_slot);
		}
		len = strlen(buf);
		len_change = len+ 4+2;
	}

	/*如果已经有option82字段,加入gsw信息*/
	else
	{
		/*截取gsw需要填写的字节*/
		memcpy (buf, p_option82+4, 19);

		/*如果是从5006-15传来*/
		if (strstr (buf, "IPDSLAM") != NULL)  
		{
			memcpy (buf, p_option82+4, *(p_option82+3));
			sscanf(buf, "0 0/0/0:0.0 IPDSLAM/%d/%d/%d/0/%d:%d.%d", &rack, &frame, &slotno, &portsel, &vpi, &vci);
			/*printf (" rack=%d, fram= %d, slotno=%d, portsel=%d, vpi=%d, vci= %d\r\n", rack, frame, slotno, portsel, vpi, vci);*/
			old_len = *(p_option82+3);
			sprintf (buf, "0 0/0/0:%d.%d %s/%d/%d/%d/0/0 ONUAN5006_15/%d/0/%d:atm/%d.%d EP", option82_value_gsw.XPI, option82_value_gsw.XCI, option82_value_gsw.AccessNodeIdentifier
			, option82_value_gsw.ANI_rack, option82_value_gsw.ANI_frame, option82_value_gsw.ANI_slot, slotno, portsel, vpi, vci);
			len = strlen(buf);
			len_change = len - old_len;
			
		}
		
		else if (strncmp (buf, "0 0/0/0:0.0 0/0/0/0", 19) != 0)
		{
			/*unknown option82 value or ec2 insert wrong value*/
			return -1;
		}
		else
		{
			old_len = *(p_option82+3);
			memcpy (buf2, p_option82+23, old_len-19);
			if (typepacket)
			printf ("buf2= %s\r\n", option82_temp);
			memset (buf,0, sizeof (buf));
			sprintf (buf, "0 0/0/0:%d.%d %s/%d/%d/%d%s", option82_value_gsw.XPI, option82_value_gsw.XCI, option82_value_gsw.AccessNodeIdentifier
				, option82_value_gsw.ANI_rack, option82_value_gsw.ANI_frame, option82_value_gsw.ANI_slot, buf2);
			len = strlen(buf);
			len_change = len - old_len;
			
		}
	}
	p = option82_temp;
	*p = 82; /*tag*/
	p++;
	*p = 4+ len; /*length of opton82 value, including 2 sub string*/
	if (*p >255)
	return -1;
	p++;
	*p = 1; /*sub string 01*/
	p++;
	*p = len; /*length of sub 01*/
	p++;
	memcpy (p, buf, len);
	p = p + len;
	*p = 2; /*sub string 02*/
	p++;
	*p = 0; /*length of sub 02*/
	p++;
	*p = 0xff; /*end of options*/
	p++;

	len = p- option82_temp;
	memcpy (p_option82, option82_temp, len);

	if (typepacket)
	printf ("%s\r\n", option82_temp);

	if (htons (*((unsigned short *) (packet + PROTOCOL_OFFSET))) == VLAN_8021Q)   /*有VLAN TAG */
       {
		VlanTagOffset = VLAN_TAG_LENTH;   
	}
	p = packet;
	len = *(short *)(packet+16+VlanTagOffset);
	*(short *)(packet+ VlanTagOffset +16) = htons (len+ len_change);       /*new ip length*/
	memset ((unsigned char *)(packet + 14 + VlanTagOffset +10), 0, 2); /*clear old checksum*/
	CaculateChecksum((unsigned char *)(packet + 14 + VlanTagOffset),20,10);   /*calculate ip checksum*/

	len = *(short *)(packet+38+VlanTagOffset);
	*(short *)(packet+ VlanTagOffset +38) = htons (len+ len_change);       /*new udp length*/
	*(short *)(packet+ VlanTagOffset +40) = 0;                                         /*udp checksum set to 0*/ 

	*new_len = origin_len+ len_change;
}

/*slot is inter_slot*/
int tell_slot_dhcp_bind(char slot)
{
	char buf[10];
	char *p;

	memset (buf, 0, sizeof (buf));
	p = buf;
	*p = translateslot_out (slot);

	dm_MakeCmdPkt_EPON (*p, 0x1051, buf, 10);
} 

void add_vlan_to_origin (char *origin, short len, short vlan, char *new_pkt, short *new_len, short *new_vlan)
{
	char *p;
	
	p = new_pkt;
	memcpy (p, origin, 12);
	p = p+12;
	*(short *)p = 0x8100;
	p = p+2;
	*(short *)p = htons(vlan);
	p = p +2;
	memcpy (p, origin+12, len-12);
	*new_len = len + 4;
	*new_vlan = vlan;
	if (chvlan)
	*new_vlan = chvlan;
}

void send_dhcp_to_uplink (char *pkt, short len, short vlan, char tag)
{
	char usport;
		
		if (dhcp_option82_debug)
		typePkt (pkt, len);
	
		if (vlan == 4088)
		{
			for (usport = MIN_UPLINK_PORT; usport <= MAX_UPLINK_PORT; usport++)
			br_send_MSC (usport, (u_char *)pkt, len, 0);	/*向所有上联端口发送 */
		}
		else
		{
			for (usport = MIN_UPLINK_PORT; usport <= MAX_UPLINK_PORT; usport++)
			br_send_MSC (usport, (u_char *)pkt, len, tag);
		}
}

int isTrustedPort (char inter_slot)
{

}

/*return: -1 discard; 1 send new packet*/
int dhcp_receive (char *origin_packet, short len, char slot, short vlan, char *new_packet, short *new_len, short *new_vlan)
{
	char *p_origin = origin_packet;
	char VlanTagOffset = 0;
	unsigned short udp_dest_port = 0;
	unsigned short udp_src_port = 0;
	unsigned char /*OptionTag, */OptionLength;
	int OptionTag;
	char next_option_tag = 0;
	short option_tag_offset = 0;
	char type = 0;
	char *p_option82 = NULL;
	unsigned char option82_next_option;
	char *p, *p_end_option;

	if (slot <= MAX_DOWN_SLOT)
	{
		option82_value_gsw.ANI_slot = translateslot_out (slot);
	}
	
	PRINTFDHCP("receive dhcp pakcet slot = %d vlan=%d\r\n", slot, vlan);
	if(dhcp_option82_debug || dhcp_snoop_debug)
	typePkt (origin_packet, len);

	if(len<340)
	{
	       PRINTFDHCP("DHCP length %d less than 340!\n",len);
	       return -1;
	}

	/*根据wjp的要求,所有包都需要打tag发出,因此首先对加入的包打上tag*/
	if (htons (*((unsigned short *) (p_origin + PROTOCOL_OFFSET))) == VLAN_8021Q)   /*有VLAN TAG */
       {
		VlanTagOffset = VLAN_TAG_LENTH;   
		memcpy (new_packet, origin_packet, len);
	}
	else 
	{
		add_vlan_to_origin (origin_packet, len, vlan, new_packet, new_len, new_vlan);
		/*if (typepacket)
		typePkt (new_packet, 60);*/
		VlanTagOffset = VLAN_TAG_LENTH;
	}
	p_origin = new_packet;
		

       if(htons (*((short *) (p_origin + PROTOCOL_OFFSET + VlanTagOffset))) != IP_PROTOCOL)
       {
                PRINTFDHCP("Not IP Packet!\n");
                 return - 1;
       }

	if(*(p_origin + IP_PROTOCOL_OFFSET + VlanTagOffset) != UDP_PROTOCOL)
	{
	          PRINTFDHCP("Not UDP Packet!\n");
	           return -1;
	 }

	/*udp_src_port = htons (*((short *) (p_origin + UDP_SRC_PORT_OFFSET + VlanTagOffset));*/
	p = p_origin + UDP_SRC_PORT_OFFSET + VlanTagOffset;
	udp_src_port = htons (*(unsigned short *)p);
	p = p_origin + UDP_SRC_PORT_OFFSET + VlanTagOffset + 2;
	udp_dest_port = htons (*(unsigned short *)p);
	/*printf ("udp src port %d, dest port %d\r\n", udp_src_port, udp_dest_port);*/
	/*udp_dest_port = htons (*((short *) (p_origin + UDP_SRC_PORT_OFFSET + VlanTagOffset+2));*/
	if (udp_src_port != DHCP_DEST_PORT_UDP && udp_dest_port != DHCP_DEST_PORT_UDP)
	{
		PRINTFDHCP("Not DHCP Packet!\n");
	       return -1;
	}

	OptionTag = *(p_origin+VlanTagOffset+FIRST_DHCP_OPTION_OFFSET);
	OptionLength = *(p_origin+VlanTagOffset+FIRST_DHCP_OPTION_OFFSET + 1);
	option_tag_offset = VlanTagOffset+FIRST_DHCP_OPTION_OFFSET;
	while(OptionTag != 0xff)
	{
		PRINTFDHCP("optiontag = %d\r\n", OptionTag);
	/*	if (typepacket)
		typePkt (p_origin+option_tag_offset, OptionLength+2);*/
		switch (OptionTag)
		{
			case DHCP_MESSAGE_TYPE_OPTION:
				type = *(p_origin+option_tag_offset+2);
				PRINTFDHCP("type = %d\r\n", type);
				if (type == DHCPDISCOVER && slot >MAX_DOWN_SLOT)
				{
					PRINTFDHCP("discovery DHCP from uplink port %d\n",slot);
					return -1;
				}
				if (type == DHCP_TYPE_OFFER || type == DHCP_TYPE_ACK ||type == DHCP_TYPE_NAK )
				{
					if (flag_dhcp_snooping && dhcp_trust_port[slot-17])/*aibin 20080322*/
					{
						PRINTFSNOOP ("dhcp snooping enable, untrusted port discard dhcp offer and ack packets\r\n");
						return -1;
				
					}
					else
					{
						PRINTFSNOOP("pass trusted port, send origin packet out1\r\n");
						return 1;
					}
				}
				break;

			case DHCP_82_TYPE_OPTION:
				p_option82 = option_tag_offset+p_origin;
				break;

			default:
				break;
		}
		OptionLength = *(p_origin+1+option_tag_offset);
		option_tag_offset = option_tag_offset + 2+ OptionLength;
		if (OptionTag == 82)
		{
			option82_next_option =  *(p_origin+option_tag_offset);
		}
		OptionTag = *(p_origin+option_tag_offset);
		if(option_tag_offset >1200)
		{
			PRINTFSNOOP("dhcp packet length more than 1200\r\n ");
			return -1;
		}
	}

	p_end_option = p_origin+option_tag_offset;

	if (type == DHCP_TYPE_DISCOVERY || type == DHCP_TYPE_REQUEST || type == DHCP_TYPE_DECLINE || type == DHCP_TYPE_INFORM || type == DHCP_TYPE_RELEASE)
	{
		
		if (flag_dhcp_option82)
		{
			if (p_option82 == NULL)
			{
				PRINTFOPTION82("ec2 didn't add option82 to the packet, discard!\r\n");
				if (discard_no_82)
				return -1;
				add_option82_to_packet (new_packet, p_end_option, len, new_len);
				send_dhcp_to_uplink (new_packet,*new_len,vlan,1);
				return 1;
			}
			if (option82_next_option != 0xff)
			{
				PRINTFOPTION82 ("ec2 not add the option82 to the last, discard!\r\n");
				return -1;
			}
			add_option82_to_packet (new_packet, p_option82,  len, new_len);
			send_dhcp_to_uplink (new_packet,*new_len, vlan, 1);
			return 1;
		}
		else
		{
			if (p_option82 != NULL)
			{
				PRINTFOPTION82 ("discard dhcp packet with option82 when option82 funtion diabled\r\n");
				return -1;	
			}
		}
	}

	PRINTFDHCP("send origin packet out2\r\n");
	return 1;
}

int receive_dhcp_command_from_ec2 (char *buf, short len)
{
	if (len >= MAX_DHCP_SLOT_BIND_BUF)
	{
		PRINTFSNOOP ("slot binding table is too large\r\n");
		return -1;
	}

	memcpy (p_dhcp_bind, buf, len);
	dhcp_command_respons = 1;
	return 0;
}

void showsize(void)
{
	printf ("sizeof(dhcp_binding_item) = %d\r\n", sizeof(dhcp_binding_item));
}
	
int dhcp_wait_time = 5;
/*slot is inter slot*/
int show_dhcp_snooping_bind(char slot, struct vty *vty)
{
	int count, i;
	short len;
	char *p;
	char out_slot;
	dhcp_binding_item *item;
	struct in_addr gip;
	short seq;
	unsigned int ip;
	char mac5;
	char mac4;
	char mac3;
	char mac2;
	char mac1;
	char mac0;
	short vlan;
	unsigned short lease_time;
	unsigned short lease_age;
	unsigned char onu;
	int reserve;

	out_slot = translateslot_out (slot);
/*	if (SlotType(slot) == -1)
	{
		vty_out(vty, "slot %d is unconnected\r\n", slot);
		return -1;
	}
*/
	dhcp_command_respons = 0;
	p_dhcp_bind = (char *)malloc (MAX_DHCP_SLOT_BIND_BUF);
	if (p_dhcp_bind == NULL)
	{
		PRINTFSNOOP("\r\nmalloc memory failed");
		return -1;
	}
	memset (p_dhcp_bind, 0, sizeof (MAX_DHCP_SLOT_BIND_BUF));

	tell_slot_dhcp_bind(slot);
	
	count = dhcp_wait_time* (sysClkRateGet () / 10);
	for (i = 0; i < count; i++)
	{
		taskDelay (10);
		/*收到响应*/
		if (dhcp_command_respons == 1)
		{
			break;	
		}
	}

	/*only for test*/
	/*test_response (slot);*/

	if (dhcp_command_respons)
	{
		if (typepacket)
		typePkt (p_dhcp_bind, 100);

		p = p_dhcp_bind;
		
		if (*p != out_slot)
		{
			vty_out(vty, "\r\nresponse table not query slot %d", out_slot);
		}
		vty_out (vty, "No. mac               ip             lease  leaseAge vlan onu\r\n");     
		p++;
		count = *(short *)p;
		p = p+2;
		while (count)
		{
			seq = *(short *)p;
			p = p +2;
			ip = *(unsigned int *)p;
			p = p + 4;
			mac0 = *p;
			p++;
			mac1 = *p;
			p++;
			mac2 = *p;
			p++;
			mac3 = *p;
			p++;
			mac4 = *p;
			p++;
			mac5 = *p;
			p++;
			vlan = *(short *)p;
			p = p +2;
			lease_time = *(unsigned int *)p;
			p = p + 4;
			lease_age = *(unsigned int *)p;
			p = p + 4;	
			onu = *p;
			p++;
			reserve = *(unsigned int *)p;
			p = p + 4;	
			gip.s_addr = ip;
			vty_out (vty, "%-4d%02x:%02x:%02x:%02x:%02x:%02x %-15s%-7d%-9d%-5d%d\r\n", seq, mac0,  mac1,  mac2,  mac3,  mac4,  mac5, inet_ntoa(gip), lease_time, lease_age, vlan, onu);
			count--;
		}
	}
	else
	{
		vty_out (vty, "not receive dhcp snooping table from slot\r\n");
	}
	free (p_dhcp_bind);
	p_dhcp_bind = NULL;
	dhcp_command_respons = 0;
	return 0;
}

/*inter slot*/
void send_dhcp_snoop_cfg_2slot(char slot)
{	
	char buf[10];
	char *p;
	
	memset (buf, 0, sizeof (buf));
	p = buf;
	*p = translateslot_out (slot);
	p++;
	*p = flag_dhcp_snooping;
	dm_MakeCmdPkt_EPON ( translateslot_out (slot), 0x1050, buf, 10);	
}

void test_response(char slot)
{
	char buf[100];
	char *p;

	memset (buf, 0, sizeof (buf));
	p = buf;
	*p = translateslot_out(slot);
	p++;
	*(short *)p= 2;
	p = p + 2;
	*(short *)p = 1;
	p = p+2;
	*(unsigned int *)p = 0xa191212;
	p = p+4;
	*p = 0;
	p++;
	*p = 1;
	p++;
	*p = 2;
	p++;
	*p = 3;
	p++;
	*p = 4;
	p++;
	*p = 5;
	p++;
	*(short *)p = 4033;
	p = p + 2;
	*(unsigned int *)p = 3000;
	p = p + 4;
	*(unsigned int  *)p = 2000;
	p = p + 4;
	*p = 128;
	p = p + 5;

	*(short *)p = 2;
	p = p+2;
	*(unsigned int *)p = 0xa191313;
	p = p+4;

⌨️ 快捷键说明

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