如何为PPP数据包创建FCS?

时间:2010-11-29 22:12:15

标签: checksum ethernet ppp pppoe

我正在尝试在Ubuntu GNU / Linux机器上创建软件模拟,它将像PPPoE一样工作。我希望这个模拟器取出传出的数据包,剥离以太网头,插入PPP标志(7E,FF,03,00和21)并将IP层信息放在PPP数据包中。我遇到了数据之后的FCS问题。据我所知,我使用的单元调制解调器使用CRC16-CCITT方法具有2字节FCS。我发现了几个可以计算这个校验和的软件,但它们都不会产生串行线路上的内容(我有一个串口线“嗅探器”,它显示了调制解调器发送的所有内容)。

我一直在研究pppd和linux内核本身的来源,我可以看到它们都有一种向数据添加FCS的方法。这似乎很难实现,因为我没有内核黑客的经验。有人能想出一种简单的方法(最好是用Python)来计算与内核生成的FCS相匹配的FCS吗?

感谢。

P.S。如果有人想要,我可以添加我收到的数据输出样本到串口调制解调器。

3 个答案:

答案 0 :(得分:0)

我最近在测试代码以杀死ppp连接时做了类似的事情。 这对我有用:

# RFC 1662 Appendix C

def mkfcstab():
    P = 0x8408

    def valiter():
        for b in range(256):
            v = b
            i = 8
            while i:
                v = (v >> 1) ^ P if v & 1 else v >> 1
                i -= 1

            yield v & 0xFFFF

    return tuple(valiter())

fcstab = mkfcstab()

PPPINITFCS16 = 0xffff  # Initial FCS value
PPPGOODFCS16 = 0xf0b8  # Good final FCS value

def pppfcs16(fcs, bytelist):
    for b in bytelist:
        fcs = (fcs >> 8) ^ fcstab[(fcs ^ b) & 0xff]
    return fcs

获取值:

fcs = pppfcs16(PPPINITFCS16, (ord(c) for c in frame)) ^ 0xFFFF

并交换字节(我使用chr((fcs& 0xFF00)>> 8),chr(fcs& 0x00FF))

答案 1 :(得分:0)

来自mbed.org PPP-Blinky:

// http://www.sunshine2k.de/coding/javascript/crc/crc_js.html - Correctly calculates
// the 16-bit FCS (crc) on our frames (Choose CRC16_CCITT_FALSE)

int crc;

void crcReset()
{
    crc=0xffff;   // crc restart
}

void crcDo(int x) // cumulative crc
{
    for (int i=0; i<8; i++) {
        crc=((crc&1)^(x&1))?(crc>>1)^0x8408:crc>>1; // crc calculator
        x>>=1;
    }
}

int crcBuf(char * buf, int size) // crc on an entire block of memory
{
    crcReset();
    for(int i=0; i<size; i++)crcDo(*buf++);
    return crc;
}

答案 2 :(得分:0)

使用了简单的python库crcmod。

import crcmod   #pip3 install crcmod
fcsData = "A0 19 03 61 DC"
fcsData=''.join(fcsData.split(' '))
print(fcsData)
crc16 = crcmod.mkCrcFun(0x11021, rev=True,initCrc=0x0000, xorOut=0xFFFF)
print(hex(crc16(bytes.fromhex(fcsData))))
fcs=hex(crc16(bytes.fromhex(fcsData)))