/* * Copyright c Realtek Semiconductor Corporation, 2002 * All rights reserved. * * Program : Code for packet generation * Abstract : * Author : * $Id: pktGen.c,v 1.1 2012/10/24 04:18:57 ikevin362 Exp $ */ #include "protoForm.h" #include "pktForm.h" #include "utility.h" #include "pktGen.h" #include <linux/inet.h> //#define _MSG /* * pktGen() - Generate a packet as you want * before setting conf u should bzero conf struct for default value * The returned value is the packet length. * The length does not included L2 CRC, however, the L2 CRC is followed after the tail of packet. */ uint32 pktGen(rtl8651_PktConf_t *Pktptr, int8 *buff){ rtl8651_PktConf_t pkt, *ptr = &pkt; uint32 pktLen; int8 dummy[16]={0}; int8* PayloadPtr = dummy; uint32 l2Flag; // copy pkt conf to fake pkt memcpy(ptr, Pktptr, sizeof(rtl8651_PktConf_t)); // End of test case if (ptr->pktType == _PKT_STOP){ // ptr->pktType=_PKT_TYPE_ETHER; return 0; } /* Ether-Header */ if (memcmp(ptr->conf_smac, PayloadPtr, 6) == 0){ // default smac set_mac (ptr->conf_smac, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03); } if (memcmp(ptr->conf_dmac, PayloadPtr, 6) == 0){ // default dmac (unicast) set_mac (ptr->conf_dmac, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c); } /* IP */ if (ptr->conf_sip == 0){ // default sip ptr->conf_sip = 0xc0a80101; // 192.168.1.1 } if (ptr->conf_dip == 0){ // default dip (unicast) ptr->conf_dip = 0x8c710101; // 140.113.1.1 } if (ptr->ip.version == 0){ ptr->ip.version = 4; } if (ptr->ip.headerLen == 0){ ptr->ip.headerLen = 20; } if (ptr->ip.ttl == 0){ ptr->ip.ttl = 255; } /* IPV6 */ if( memcmp(ptr->conf_v6dip,PayloadPtr,16)==0 ){ in6_pton("2001:0db8:85a3:08d3:1319:8a2e:0001:1111" ,-1,&(ptr->conf_v6dip),-1,NULL ); } if( memcmp(ptr->conf_v6sip,PayloadPtr,16)==0 ){ in6_pton("2001:0db8:85a3:08d3:1319:8a2e:0001:2222" ,-1,&(ptr->conf_v6dip),-1,NULL ); } if(ptr->ipv6.version==0){ ptr->ipv6.version =6; } if(ptr->ipv6.hoplmt==0){ ptr->ipv6.hoplmt =255; } /* Payload */ if ((ptr->payload.length == 0) || (ptr->payload.content == NULL)){ pktLen = 0; }else{ // int i; pktLen = ptr->payload.length; PayloadPtr = ptr->payload.content; // for(i=0;i<pktLen;i++) // PayloadPtr[i]=i; } #ifdef _MSG rtlglue_printf("\t* Packet Payload Length\t\t[%d]\n", pktLen); #endif /* l2Flag */ l2Flag = ptr->l2Flag; // rtlglue_printf("the l2flag is :[%d]\n", l2Flag); // rtlglue_printf("the pktType is: [%d]\n", ptr->pktType ); // for 50B,(50 is also ok), when AUTOADD, we don't change ethertype #if 0 if (ptr->conf_Flags & pkt_PKTHDR_PPPOE_AUTOADD){ l2Flag &= ~L2_PPPoE; } if (ptr->conf_Flags & pkt_PKTHDR_VLAN_AUTOADD){ l2Flag &= ~L2_VLAN; } #endif // rtlglue_printf("before switch prt->pktType\n"); switch (ptr->pktType){ // rtlglue_printf("just in switch pktType\n"); case _PKT_TYPE_ETHER: #ifdef _MSG rtlglue_printf("\t* Generate ETHER packet..."); #endif protoForm_vsp_ether(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->llc.dsap, ptr->llc.ssap, ptr->pppoe.type, ptr->pppoe.session, ptr->conf_ethtype, PayloadPtr, &pktLen); break; case _PKT_TYPE_IPX: #ifdef _MSG rtlglue_printf("\t* Generate IPX packet..."); #endif protoForm_vsp_ipx(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, //ptr->llc.dsap, ptr->llc.ssap, ptr->pppoe.type, ptr->pppoe.session, ptr->ipx.type, ptr->ipx.dnet, ptr->ipx.dnode, ptr->ipx.dsock, ptr->ipx.snet, ptr->ipx.snode, ptr->ipx.ssock, PayloadPtr, &pktLen); break; case _PKT_TYPE_ARP: #ifdef _MSG rtlglue_printf("\t* Generate ARP packet..."); #endif protoForm_vs_arp(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->arp.mac_src, ptr->arp.ip_src, ptr->arp.mac_dst, ptr->arp.ip_dst, ptr->arp.op, &pktLen); break; case _PKT_TYPE_IP: #ifdef _MSG rtlglue_printf("\t* Generate IP packet..."); #endif protoForm_vsp_ip(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->ip.protocol, PayloadPtr, ptr->ErrFlag, &pktLen); break; case _PKT_TYPE_PPTP: #ifdef _MSG rtlglue_printf("\t* Generate PPTP packet..."); #endif protoForm_vsp_pptp(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->pptp.callid, ptr->pptp.seqno, ptr->pptp.ackno, PayloadPtr, ptr->ErrFlag, &pktLen); break; case _PKT_TYPE_ICMP: #ifdef _MSG rtlglue_printf("\t* Generate ICMP packet..."); #endif if (ptr->ip.offset){ protoForm_vsp_ip(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, 1, PayloadPtr, ptr->ErrFlag, &pktLen); }else{ protoForm_vsp_icmp(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->icmp.type, ptr->icmp.code, ptr->icmp.id, ptr->icmp.seq, PayloadPtr, ptr->ErrFlag, &pktLen); } break; case _PKT_TYPE_IGMP: #ifdef _MSG rtlglue_printf("\t* Generate IGMP packet..."); #endif { int8 private_buff[2048]; int8 *buffptr = private_buff; uint32 grlen = 0; if (ptr->igmp.ver == 3) { if ((ptr->igmp.type != IGMP_V3_MEMBERSHIP_REPORT) && (ptr->igmp.type != IGMP_MEMBERSHIP_QUERY)) return 0; } if ((ptr->igmp.ver == 3) && (ptr->igmp.type == IGMP_V3_MEMBERSHIP_REPORT)) { // generate group record if ((grlen = grGen(ptr->igmp.grCfg, ptr->igmp.rnofg, private_buff)) == 0) return 0; // group record generate error buffptr = (int8 *)((uint32)private_buff + grlen); } if (pktLen && PayloadPtr) memcpy(buffptr, PayloadPtr, pktLen); pktLen += grlen; protoForm_vsp_igmp(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->igmp.ver, ptr->igmp.type, ptr->igmp.respTime, ptr->igmp.gaddr, ptr->igmp.qrsq, ptr->igmp.qqic, ptr->igmp.qnofs, ptr->igmp.qslist, ptr->igmp.rnofg, private_buff, ptr->ErrFlag, &pktLen); } break; case _PKT_TYPE_TCP: #ifdef _MSG rtlglue_printf("\t* Generate TCP packet..."); #endif if (ptr->ip.offset){ protoForm_vsp_ip(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, 6, PayloadPtr, ptr->ErrFlag, &pktLen); }else{ if (ptr->conf_tcp_flag & TH_SYN) { int8 tcp_option[4]; int8 *option_ptr = tcp_option; if (ptr->conf_tcp_mss == 0) { ptr->conf_tcp_mss = 1460; // default mss } *((uint8*)option_ptr) = 2; // kind *((uint8*)(option_ptr+1)) = 4; // length *((uint16*)(option_ptr+2)) = htons(ptr->conf_tcp_mss); //mss protoForm_vsp_tcp_option(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->conf_sport, ptr->conf_dport, ptr->conf_tcp_seq, ptr->conf_tcp_ack, ptr->conf_tcp_flag, ptr->conf_tcp_win, tcp_option, 4, PayloadPtr, ptr->ErrFlag, &pktLen); } else { protoForm_vsp_tcp(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->conf_sport, ptr->conf_dport, ptr->conf_tcp_seq, ptr->conf_tcp_ack, ptr->conf_tcp_flag, ptr->conf_tcp_win, PayloadPtr, ptr->ErrFlag, &pktLen); } } break; case _PKT_TYPE_UDP: #ifdef _MSG rtlglue_printf("\t* Generate UDP packet..."); #endif if (ptr->ip.offset){ protoForm_vsp_ip(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, 17, PayloadPtr, ptr->ErrFlag, &pktLen); }else{ protoForm_vsp_udp(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->conf_sport, ptr->conf_dport, PayloadPtr, ptr->ErrFlag, &pktLen); } break; case _PKT_TYPE_UDP_OPTION: #ifdef _MSG rtlglue_printf("\t* Generate UDP packet with option..."); #endif if (ptr->ip.offset) { protoForm_vsp_ip_opt(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, 17, PayloadPtr, ptr->ErrFlag, &pktLen); }else{ protoForm_vsp_udp_opt(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->conf_sport, ptr->conf_dport, PayloadPtr, ptr->ErrFlag, &pktLen); } break; case _PKT_TYPE_IPV6: // rtlglue_printf("in IPV6"); #ifdef _MSG rtlglue_printf("\t* Generate IPV6 packet!"); #endif protoForm_vsp_ipv6(buff, l2Flag, ptr->extHdr, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ipv6.version, ptr->ipv6.priority, ptr->ipv6.flowlbl, ptr->ipv6.hoplmt, ptr->conf_v6sip, ptr->conf_v6dip, ptr->rhdr.hdrlen, ptr->rhdr.segments_left, ptr->rhdr.dip, PayloadPtr, ptr->ErrFlag, &pktLen); break; case _PKT_TYPE_V6ICMP: #ifdef _MSG rtlglue_printf("\t* Generate V6ICMP packet!"); #endif protoForm_vsp_v6icmp(buff, l2Flag, ptr->extHdr, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ipv6.version, ptr->ipv6.priority, ptr->ipv6.flowlbl, ptr->ipv6.hoplmt, ptr->conf_v6sip, ptr->conf_v6dip, ptr->rhdr.hdrlen, ptr->rhdr.segments_left, ptr->rhdr.dip, ptr->icmp.type, ptr->icmp.code, ptr->icmp.id, ptr->icmp.seq, PayloadPtr, ptr->ErrFlag, &pktLen); break; case _PKT_TYPE_V6TCP: #ifdef _MSG rtlglue_printf("\t* Generate V6TCP packet!"); #endif protoForm_vsp_v6tcp(buff, l2Flag, ptr->extHdr, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ipv6.version, ptr->ipv6.priority, ptr->ipv6.flowlbl, ptr->ipv6.hoplmt, ptr->conf_v6sip, ptr->conf_v6dip, ptr->rhdr.hdrlen, ptr->rhdr.segments_left, ptr->rhdr.dip, ptr->conf_sport, ptr->conf_dport, ptr->conf_tcp_seq, ptr->conf_tcp_ack, ptr->conf_tcp_flag, ptr->conf_tcp_win, PayloadPtr, ptr->ErrFlag, &pktLen); break; case _PKT_TYPE_V6UDP: #ifdef _MSG rtlglue_printf("\t* Generate V6UDP packet!"); #endif protoForm_vsp_v6udp(buff, l2Flag, ptr->extHdr, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ipv6.version, ptr->ipv6.priority, ptr->ipv6.flowlbl, ptr->ipv6.hoplmt, ptr->conf_v6sip, ptr->conf_v6dip, ptr->rhdr.hdrlen, ptr->rhdr.segments_left, ptr->rhdr.dip, ptr->conf_sport, ptr->conf_dport, PayloadPtr, ptr->ErrFlag, &pktLen); break; case _PKT_TYPE_SELFDF_PROTOCOL: #ifdef _MSG rtlglue_printf("\t* Generate UDP packet..."); #endif if (ptr->ip.offset){ protoForm_vsp_ip(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->ip.protocol, PayloadPtr, ptr->ErrFlag, &pktLen); }else{ protoForm_vsp_udp(buff, l2Flag, ptr->conf_dmac, ptr->conf_smac, ptr->vlan.vid, ptr->vlan.cfi, ptr->vlan.prio, ptr->pppoe.type, ptr->pppoe.session, ptr->ip.version, ptr->ip.headerLen, ptr->ip.tos, ptr->ip.id, ptr->ip.diffserv, ptr->ip.mf, ptr->ip.offset, ptr->ip.ttl, ptr->conf_sip, ptr->conf_dip, ptr->conf_sport, ptr->conf_dport, PayloadPtr, ptr->ErrFlag, &pktLen); } break; default: rtlglue_printf("\t* Unknown pkt type[%d], Abort!\n", ptr->pktType); } /* for 50B,(50 is also ok), when AUTOADD, we don't change ethertype */ #if 0 if (ptr->conf_Flags & pkt_PKTHDR_PPPOE_AUTOADD){ l2FormLayer3Type(l2Flag, buff, 0x8864); } #endif /* If packet is smaller than 60 bytes, add tailer padding. */ if (pktLen < 60) { #if 0 /* Padding has been done in l2FormCrc(). */ memset(&buff[pktLen], 0x20/*Ethernet standard*/, (60 - pktLen)); #endif pktLen = 60; } #ifdef _MSG rtlglue_printf("\tSUCCESS!!\n"); rtlglue_printf ("\t* Packet length\t\t\t[%d]\n", pktLen); #endif return pktLen; } uint32 grGen(rtl8651_IgmpGrConf_t *grCfg, uint32 grCnt, int8 *buff) { rtl8651_IgmpGrConf_t *cfgptr; igmpGr_t* ptr; uint32 grLen = 0; uint32 cnt; if (!buff || !grCfg) goto out; ptr = (igmpGr_t*)buff; cfgptr = grCfg; for (cnt = 0 ; cnt < grCnt ; cnt ++, cfgptr ++) { // generate uint32 i; uint32 *ss, *sd; ptr->igmp_gr_rt = cfgptr->type; ptr->igmp_gr_auxlen = cfgptr->auxlen; ptr->igmp_gr_nofs = htons(cfgptr->nofs); ptr->igmp_gr_group = htonl(cfgptr->gaddr); sd = &(ptr->src_list); ss = cfgptr->slist; for ( i = 0 ; i < cfgptr->nofs ; i ++) { *sd = htonl(*ss); sd ++; ss ++; } if (cfgptr->auxlen && cfgptr->auxdata) memcpy((void*)sd, cfgptr->auxdata, cfgptr->auxlen); grLen += (8 + (4 * cfgptr->nofs) + cfgptr->auxlen); ptr = (igmpGr_t *)((uint32)ptr + (uint32)(8 + (4 * cfgptr->nofs) + cfgptr->auxlen)); } out: return grLen; }