簡體   English   中英

如何在十六進制數字數組中檢查一個位是否啟用

[英]how to check a bit is enabled or not in array of hexadecimal digit

#include<iostream>
#define check_bit(var,pos) {return (var & (1 << pos))!=0;}

using namespace std;

int main()
{
uint8_t temp[150]={0x00,0x02,0x17,0xe2,0x1c,0xa8,0x00,0x30,0x96,0xe1,0x8c, 0x38,
 0x88, 0x47, 0x00 ,0x01 ,
0x30, 0xfe, 0x00, 0x01 ,0x31, 0xfe, 0x45, 0x00,  0x00 ,0x64, 0x3b, 0x89 ,0x00, 0
x00 ,0xfe, 0x01 ,
0x33, 0x5a, 0xc0 ,0xa8 ,0x79 ,0x02 ,0x0a, 0x0a,  0x0a, 0x01, 0x08, 0x00, 0xe3, 0
x86, 0x00, 0xea,
0x01, 0xd2, 0x00, 0x00, 0x00, 0x05, 0x02, 0x6a, 0x95 ,0x98, 0xab ,0xcd ,0xab, 0x
cd ,0xab, 0xcd,
0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,  0xab, 0xcd ,0xab, 0xcd ,0xab ,0
xcd ,0xab, 0xcd,
0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd,  0xab, 0xcd ,0xab ,0xcd ,0xab ,0
xcd, 0xab ,0xcd,
0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd , 0xab, 0xcd ,0xab, 0xcd, 0xab, 0
xcd, 0xab ,0xcd,
0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd , 0xab, 0xcd
};

uint16_t *ptr1=(uint16_t*)&temp[0];

while(!(*(ptr1+0)==0x88 && *(ptr1+1)==0x47))
{
ptr1++;
}

cout<<"MPLS packet";

uint32_t *ptr2=(uint32_t*)&temp[0];

cout<<"4 bytes accessed at a time";

ptr2++;

while(check_bit(*(ptr+3),7)!=1)
{
cout<<"bottom of the stack:label 0";
ptr2++;
}
cout<<"mpls label:1";
return 0;
}

該程序旨在通過一次訪問兩個字節並檢查是否存在 88 和 47 個數據包來識別數據包是否為 MPLS,如果是 MPLS 數據包,則它應該一次訪問四個數據包並檢查第 3 個字節(在這種情況下為 30)是是否啟用。如果未啟用,則訪問接下來的四個字節並檢查字節是否啟用。我已經編寫了程序,但它不起作用。請有人幫助我。我無法訪問數組的單個元素。如果我給cout<<temp[0]它給出垃圾值

請幫忙

我注意到的第一件事是您的代碼查找連續的 16 位值 0x88 和 0x47,但在數據包本身中,這些值似乎是 8 位(每個 1 個字節)。 如果ptr1更改為uint8_t* ,它將能夠找到值。 我不知道代碼的 rest 的正確行為是什么,所以我無法檢查。

一般來說,在這里直接從 memory 讀取大於 8 位的值(例如 uint16_t 或 uint32_t)可能不是一個好主意,因為您的程序在 little-endian 和 big-endian 處理器上的行為會有所不同。 正如 ydroneaud 在評論中提到的那樣,某些處理器將無法讀取這些值,因為您從未對齊的地址讀取它們。

我想我可以修復你的程序,但你最好聽聽其他比我更了解網絡知識的人。

uint8_t *ptr=temp;

while(ptr[0]!=0x88 || ptr[1]!=0x47)
{
    ptr++;
}

cout<<"MPLS packet";

ptr+=2;

cout<<"4 bytes accessed at a time";

while(!check_bit(ptr[2],7))
{
    cout<<"bottom of the stack:label 0";
    ptr+=4;
}
cout<<"mpls label:1";
return 0;

編輯:要打印數組中的單個字節,您需要先將它們轉換為一些 integer 類型。 這是因為uint8_t很可能被類型化為unsigned charcout將其解釋為字符代碼。 然后你需要將cout設置為十六進制模式:

cout << hex << (int)ptr[2] << endl;

編輯 2:您的check_bit()宏中存在錯誤。 宏不是 function,而是在提及其名稱的地方按原樣復制的一段文本(替換參數)。 肯定是

#define check_bit(var,pos) (((var)&(1<<(pos)))!=0)

或者定義一個 function 代替:

bool check_bit(int var, int pos) {return (var & (1 << pos))!=0;}

我的評論的一個更詳細的版本:您實際上應該解碼網絡堆棧以確保 MPLS 是否存在,0x8847 值不太可能出現在有效負載、尋址方案等的某個地方。

要真正做到這一點,您應該解碼網絡堆棧。 讓我們假設您從以太網框架開始。 首先請注意,大多數應用程序會為您提供從目標 mac 地址開始的數據,前導碼等將被丟棄。 所以第 13 和第 14 字節是類型字段。 這告訴你以太網中封裝了什么,這通常是 0x0800,意思是 IP。 0x8847 表示單播 static MPLS label。 其他選項也是可能的,例如 ipv6 或 vlan 標簽(如下所述)。 但請注意,您可以確定使用哪些偏移量。 您知道 mac 幀中封裝了什么以及這些封裝數據從哪里開始(第 15 個八位字節)。 當然你會看到那里有可選的 q-tags,我在下面解釋這些。

現在,當您正在尋找 0x8847 時,我猜您在以太網上有直接的 MPLS,在這種情況下,您不應再使用 go,但如果您的堆棧更復雜,您還必須解碼下一個封裝的數據(例如 IP)和考慮到這些大小,直到您可以找到您的 MPLS header。

對於以太網,有 2 個比較常見的選項,即 dot1q 和 qinq 標記,或 vlan 標記。 dot1q 將 4 個字節添加到以太網 header,您可以識別這一點,因為類型字段將為 0x8100,在這種情況下,實際類型字段(被封裝的)將是 4 個字節再增加一個(即第 17 個字節)和封裝的數據將從第 19 個字節開始。 使用 qinq 類型將是 0x9100 並且實際類型將是 8 個字節,因此第 21 個字節,從第 23 個字節開始可以找到封裝的數據。

當然,解碼整個網絡堆棧實現會很瘋狂。 首先,您可以忽略尋址、QoS、...。 您主要需要找到下一個 header 的類型以及它從哪里開始(這可能會受到 dot1q 等可選字段的影響)。 通常,您事先知道系統上有哪種堆棧。 因此,它涉及研究這些標頭並找到可以找到 MPLS header 的固定偏移量,這使工作變得非常簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM