2011-07-06 59 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头文件,这使得工作变得非常简单。

相关问题