2011-07-06 61 views
0
#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或不那麼它應該一次訪問四個數據包,並檢查第三個字節(在這種情況下是30)是否啓用。如果未啓用,則訪問接下來的四個字節並檢查字節是否啓用。我編寫了程序,但它不工作。請人幫我,我是不能夠訪問的array.if我給cout<<temp[0]它給垃圾值單個元素如何檢查位被允許或不以十六進制數字的陣列

請幫

+1

'ptr1'是一個指向'uint16_t'的指針,所以'+ 1'將地址增加**兩個**字節。只需取消劇組,並將'ptr1'設爲'uint8_t *'。另外,誰是'ptr'? –

+5

只需搜索0x8847來識別MPLS數據包就相當有風險。這個序列很可能以某種方式隨機出現在數據包中,導致錯誤的檢測。你應該實際上'解碼'堆棧直到IP頭部。 – KillianDS

+0

要將'temp [0]'等字節輸出到'cout',您需要首先將其轉換爲int。否則,它會嘗試將其顯示爲可打印的字符。 – interjay

回答

1

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

一般來說,直接從內存中讀取大於8位的值(例如uint16_t或uint32_t)可能不是一個好主意,因爲您的程序在小端和大端處理器上的行爲不同。正如ydroneaud在評論中提到的那樣,一些處理器將無法讀取這些值,因爲您從未對齊的地址讀取這些值。

+0

不要忘記對齊問題 – ydroneaud

+0

「不是一個好主意」...另外,因爲uint8_t數組可能無法正確對齊16位讀取,從而在某些硬件上導致SIGBUS或類似問題。 –

+0

謝謝,我添加了對齊問題。 – interjay

1

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

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; 

編輯:從您需要首先轉換爲某種整型數組打印單個字節。這是因爲uint8_t最有可能的類型爲unsigned char,其被cout解釋爲字符代碼。然後,你需要將cout設置爲十六進制方式:

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

編輯2:有一個在您check_bit()宏出現錯誤。宏不是一個函數,而是一個原樣複製的文本(替換參數),其位置是提及其名稱的地方。它必須是

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

或定義的函數:

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

感謝help.iam無法訪問這些十六進制值。如何訪問這些值? – Akshatha

+0

@Akshatha,我添加了一個關於打印字節的部分。看看它是否回答你的問題。 – SnakE

+0

非常感謝我現在能夠訪問值 – Akshatha

0

一點點摸索出我的意見的版本:你實際上應該解碼網絡協議棧,以確保如果MPLS是目前, 0x8847值在負載,尋址方案等某處不太可能發生。

實際上,你應該解碼網絡堆棧。讓我們假設你以ethernet frame開頭。首先請注意,大多數應用程序會向您提供來自目的地mac地址的數據,前導碼等都會被丟棄。所以第13和第14字節是類型字段。這告訴你什麼是封裝在以太網中,這通常是0x0800的含義。 0x8847表示單播靜態MPLS標籤。其他選項也是可能的,例如ipv6或vlan標籤(如下所述)。但是請注意,您可以確定使用哪些偏移量。您知道封裝在mac幀中的內容以及封裝數據的起始位置(第15個八位字節)。當然,你會發現那裏有可選的q-tags,我在下面解釋。

現在當你正在尋找0x8847我想你有直接的MPLS通過以太網,在這種情況下,你不應該走得更遠,但如果你的堆棧更復雜,你將不得不解碼下一個封裝的數據(例如IP),並將這些大小考慮在內,直到找到您的MPLS報頭。

對於以太網有2個有點常見的選項,那是dot1q和qinq標記或vlan標記。 dot1q將4個字節添加到以太網報頭,您可以識別出這是因爲類型字段將爲0x8100,在這種情況下,實際類型字段(封裝的內容)將是4個字節,還有一個字節(所以第17個字節)和封裝數據將從第19個字節開始。使用qinq時,類型將爲0x9100,實際類型將繼續爲8個字節,因此第21個字節中的封裝數據可從第23個字節開始查找。

當然,解碼整個網絡堆棧實現將是瘋狂的。首先,您可以忽略尋址,QoS等...。你大多需要找到下一個標題的類型以及它的起始位置(這可以受諸如dot1q之類的可選字段的影響)。通常你事先知道你的系統上有哪種類型的堆棧。因此它需要研究這些頭文件並找到固定的偏移量,以找到您的MPLS頭文件,這使得工作變得非常簡單。

相關問題