代码拉取完成,页面将自动刷新
package main
import (
"log"
)
const (
GOOSE_TYPE_ID uint32 = 35000 //[2]byte{0x88, 0xb8}
SV_TYPE_ID uint32 = 35002 //[2]byte{0x88, 0xba}
)
// 以太网报文头
type EtherHeader struct {
DstHwaddr []byte
LocHwaddr []byte
VlanTag []byte
TypeId uint32
AppId uint32
}
/* VLAN_ID and VLAN_PRI set in CID(hex mode) ex: "123" = 0x123
CID文件定义了VLAN的参数, 16进制格式; 构建以太网报文头的802.1Q VLAN标记
<Address>
<P type="MAC-Address">01-0C-CD-01-00-01</P>
<P type="APPID">4000</P>
<P type="VLAN-ID">123</P>
<P type="VLAN-PRIORITY">4</P>
</Address>
VLAN_ID = 0x123 VLAN-PRI = 0x4*/
func BuildVlanTag(VLAN_ID uint16, VLAN_PRI uint16) []byte {
VLAN_TAG := [4]byte{0x81, 0x00}
vlan_tag := (VLAN_PRI << 5) | VLAN_ID // PRI: 3bit=4; CFI: 1bit=0; VLANID: 12bit=0x0123
VLAN_TAG[2] = byte(vlan_tag >> 8)
VLAN_TAG[3] = byte(vlan_tag & 0xff)
return VLAN_TAG[0:]
}
// 将以太网包分解为 header(目标mac地址,源mac地址,类型ID(GOOSE为'\x88\xb8',SV为'\x88\xba')),APDU数据包; 如果不是GOOSE或SV,则APDU为b''
func UnpackEtherPacket(pkt []byte) (header EtherHeader, apdu []byte) {
header = EtherHeader{}
header.DstHwaddr = pkt[0:6]
header.LocHwaddr = pkt[6:12]
var DATA_PKT []byte
if pkt[12] == 0x81 && pkt[13] == 0x00 { //# QTAG Prefix (IEEE 802.1Q)
header.VlanTag = pkt[12:16]
header.TypeId = DecodeUint(pkt[16:18]) // 报文类型:GOOSE SV 等
DATA_PKT = pkt[18:]
} else {
//header.VlanTag
header.TypeId = DecodeUint(pkt[12:14])
DATA_PKT = pkt[14:]
}
if header.TypeId >= 0x600 { // 大于0x600表示类型,小于为长度
if header.TypeId == GOOSE_TYPE_ID || header.TypeId == SV_TYPE_ID { // GOOSE or SV
header.AppId = DecodeUint(DATA_PKT[0:2])
//DATA_LEN = struct.unpack('>H', DATA_PKT[2:4])[0]
//APDU_LEN = DATA_LEN - 8
apdu = DATA_PKT[8:]
} else { // not goose or sv packet
log.Println("UnpackEtherPacket: not goose or sv packet.")
}
} else { // unknown packet
log.Println("UnpackEtherPacket: unknown packet.")
}
return header, apdu
}
// APP_ID and VLAN_ID and VLAN_PRI set in CID(hex mode) "123" = 0x123
/*
<Address>
<P type="MAC-Address">01-0C-CD-01-00-01</P>
<P type="APPID">3000</P>
<P type="VLAN-ID">123</P>
<P type="VLAN-PRIORITY">4</P>
</Address>
举例:
header = {
'DstHwaddr': b'\x01\x0c\xcd\x01\x00\x01', # from CID ,前4字节固定,后2字节用户定义: goose: b'\x01\x0c\xcd\x01' + (b'\x00\x00' ~ b'\xff\xff'); sv: b'\x01\x0c\xcd\x04' + (b'\x00\x00' ~ b'\xff\xff')
'LocHwaddr':sock.local_hwaddr, # from local iface hardware
'TypeId':GOOSE_TYPE_ID, # goose:b'\x88\xb8'; sv: b'\x88\xba'
'AppId':b'\x30\x00', # from CID
'VlanTag':build_vlan_tag(0x123, 0x4) # 可为空, 例:b'\x81\x23', 共16bit: PRI: 3bit=0x4; CFI: 1bit=0; VLANID: 12bit=0x0123
}
*/
func PackEtherPacket(header EtherHeader, apdu []byte) []byte {
if header.TypeId != GOOSE_TYPE_ID && header.TypeId != SV_TYPE_ID {
log.Println("PackEtherPacket: not goose or sv packet.")
return nil
}
packet := make([]byte, 26+len(apdu))
idx := 0
copy(packet[idx:], header.DstHwaddr)
idx += 6
copy(packet[idx:], header.LocHwaddr)
idx += 6
if len(header.VlanTag) != 0 {
copy(packet[idx:], header.VlanTag)
idx += 4
}
EncodeUint(header.TypeId, packet[idx:idx+2])
idx += 2
EncodeUint(header.AppId, packet[idx:idx+2])
idx += 2
EncodeUint(uint32(len(apdu)+8), packet[idx:idx+2])
idx += 2
EncodeUint(0, packet[idx:idx+4])
idx += 4
copy(packet[idx:], apdu)
idx += len(apdu)
return packet[:idx]
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。