以太网EthernetII,LLC,SNAP判断

部分 标准 Ethernet II 你给出的 802.3 + LLC/SNAP
DMAC 6B 6B
SMAC 6B 6B
第 3 字段 Type(协议) Length(数据长度)
后面紧跟 数据 LLC(3B) + SNAP(5B)
LLC/SNAP 有(共 8B)
协议位置 帧头第 3 字段 SNAP 里的 Type 字段
总头部长度 14B 14+8 = 22B
常见场景 以太网、PC 正常发包 802.11 无线转有线、旧桥接、某些 AP 转发

 

image

 

image

 

#include <stdio.h>
#include <stdint.h>

// ---------------------------
// 结构体定义:严格按字节对齐
// ---------------------------
#pragma pack(push, 1)  // 关键!禁止编译器自动对齐

// 以太网头部 (14字节)
typedef struct {
    uint8_t  dmac[6];    // 目的MAC
    uint8_t  smac[6];    // 源MAC
    uint16_t len_type;   // 长度 OR 类型
} eth_header_t;

// LLC 头部 (3字节)
typedef struct {
    uint8_t  dsap;
    uint8_t  ssap;
    uint8_t  control;
} llc_header_t;

// SNAP 头部 (5字节)
typedef struct {
    uint8_t  oui[3];
    uint16_t type;
} snap_header_t;

#pragma pack(pop)

// ---------------------------
// 解析函数
// ---------------------------
void parse_frame(const uint8_t *frame, int frame_len)
{
    // 1. 先取出以太网头部
    eth_header_t *eth = (eth_header_t *)frame;
    uint16_t len_type = ntohs(eth->len_type);  // 转主机字节序

    printf("=== 以太网解析 ===\n");
    printf("DMAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
           eth->dmac[0], eth->dmac[1], eth->dmac[2],
           eth->dmac[3], eth->dmac[4], eth->dmac[5]);
    printf("SMAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
           eth->smac[0], eth->smac[1], eth->smac[2],
           eth->smac[3], eth->smac[4], eth->smac[5]);
    printf("len_type = 0x%04x (%d)\n", len_type, len_type);

    // ---------------------------
    // 2. 判断是 Length 还是 Type
    // ---------------------------
    if (len_type >= 0x0600) {
        // ------------------------------------
        // Ethernet II 帧:Type,无 LLC/SNAP
        // ------------------------------------
        printf("→ 这是 Ethernet II 帧 (Type)\n");
        printf("→ 上层协议类型: 0x%04x\n", len_type);
        printf("→ 无 LLC 头,无 SNAP 头\n");
    }
    else if (len_type <= 0x05DC) {
        // ------------------------------------
        // 802.3 帧:Length → 一定有 LLC
        // ------------------------------------
        printf("→ 这是 802.3 帧 (Length)\n");
        printf("→ 数据长度: %d 字节\n", len_type);

        // 取出 LLC 头 (紧跟在以太网头后面)
        const uint8_t *llc_ptr = frame + sizeof(eth_header_t);
        llc_header_t *llc = (llc_header_t *)llc_ptr;

        printf("\n=== LLC 头部解析 ===\n");
        printf("DSAP: 0x%02x\n", llc->dsap);
        printf("SSAP: 0x%02x\n", llc->ssap);
        printf("Control: 0x%02x\n", llc->control);

        // ------------------------------------
        // 判断是否为 SNAP 帧
        // ------------------------------------
        if (llc->dsap == 0xAA && llc->ssap == 0xAA && llc->control == 0x03) {
            printf("→ 这是 LLC/SNAP 帧\n");

            // SNAP 头紧跟在 LLC 后面
            const uint8_t *snap_ptr = llc_ptr + sizeof(llc_header_t);
            snap_header_t *snap = (snap_header_t *)snap_ptr;
            uint16_t snap_type = ntohs(snap->type);

            printf("\n=== SNAP 头部解析 ===\n");
            printf("OUI: %02x:%02x:%02x\n", snap->oui[0], snap->oui[1], snap->oui[2]);
            printf("SNAP Type (上层协议): 0x%04x\n", snap_type);
        }
        else {
            printf("→ 纯 LLC 帧,无 SNAP\n");
        }
    }
    else {
        printf("→ 非法字段 (1501~1535)\n");
    }
}

// ---------------------------
// 测试用例
// ---------------------------
int main()
{
    // 构造一个 802.3 + LLC + SNAP 测试帧
    uint8_t test_frame[] = {
        0x00,0x11,0x22,0x33,0x44,0x55,       // DMAC
        0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,       // SMAC
        0x00,0x2E,                           // Length = 46 (<=1500)
        0xAA,0xAA,0x03,                      // LLC (SNAP 标志)
        0x00,0x00,0x00,                      // OUI
        0x08,0x00,                           // SNAP Type = IPv4
        0x00,0x00,0x00,0x00                  // 数据...
    };

    parse_frame(test_frame, sizeof(test_frame));
    return 0;
}

 

posted on 2026-04-17 11:50  sudochen  阅读(7)  评论(0)    收藏  举报

导航