📄 dhcp.c
字号:
/*******************************************************
文件名: 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 + -