4,436
社区成员
发帖
与我相关
我的任务
分享
java不能做到吗,java中有一个socketOption,搞不懂和它有没有关系
#define MAXIPOPTLEN (40 - 1)
int add_ipopt(uint8_t ipopt_type, uint8_t ipopt_data_len, uint8_t *data, uint8_t *ipoptbuff, uint32_t optlen, uint8_t *ipopt_finish)
{
int i;
if(*ipopt_finish > 0)
return 0;
if(ipopt_type == IPOPT_EOL)
*ipopt_finish = 1;
return optlen + 1;
if(ipopt_type == IPOPT_NOP)
*(ipoptbuff) = 1;
return optlen + 1;
if(optlen + 2 + ipopt_data_len > MAXIPOPTLEN)
{
fprintf(stderr, "ip options build error: options length exceeds MAXIPOPTLEN");
exit(EXIT_FAILURE);
}
*(ipoptbuff ++) = ipopt_type;
*(ipoptbuff ++) = ipopt_data_len + 2;
for (i = 0; i < ipopt_data_len; i ++)
{
*(iptoptbuff ++) = *(data ++);
}
return optlen + 2 + (uint32_t)ipopt_data_len;
}
void mypcap_build_ipopt(uint8_t *packet)
{
uint8_t ipopt_finish = 0;
uint32_t optlen = 0;
struct iphdr *iphdr = (struct iphdr *)(packet + sizeof(struct ethhdr));
uint8_t *ipoptbuff = packet + sizeof(struct ethhdr) + sizeof(struct iphdr);
/* 这里用add_ipopt()函数填入各种option
... ...
optlen = add_ipopt(IPOPT_EOL, 0, NULL, ipoptbuff, optlen, &ipopt_finish); //最后必须填充IPOPT_EOL
/* 创建iphdr,计算csum */
... ...
}
但是毕竟option是一种无固定结构的数据类型,我暂时无法设计出能适应所有结构的函数(主要是大小端的问题)。
java我只是拿来和hadoop、elk交互和生成json,偶尔访问一下数据库,我肯定不会用它来做协议构造分析的开发,因为那是它的短板。就好像一般人不会拿管道煤气炉烧烤,除非是在是没有其它可以用,也不怕难吃(管道煤气有毒且有硫化物的臭味)
所以其实我不熟悉java,也不喜欢java(其实不怪java,主要是一般公司里用java的没有别人提供的框架,就啥也不会干了<框架就是超市里卖的盒饭,除了会加热他啥也不会,但居然和别人说他是个厨子>),但个人认为除了汇编以外,语言没有高下之分,只有使用的人的区别。java虽然处理内核级的问题也许性能比c低点儿,但肯定提供了能处理这种简单问题的库,你只需要构造好报文数据结构。
大致看了一下oracle java doc,没有找到raw socket,但有第三方提供的jpcap、jnetpcap等收发链路层的库。虽然我不太熟悉java,但我可以很肯定的说,如果是一个一年以上经验的誊写工来说,用java做你说的应该是没有难度,最多就是多看看手册。
另外你说的socketoption应该和c里的setsockopt/getsockopt对应,这个在oracle java doc里已经提到,在C里这个函数里是可以设置IPPROTO_IP的IP_OPTINOS,也就是ip option,但看oracle java doc的文档StandardSocketOptions里没有实现这个,估计是因为没有实现raw socket所以没有对网络层的设置就做了限制,避免不可预测错误。
最后再扯扯,ip options是需要设备和系统支持的,我不确定路由器等会不会把它丢弃,除非本身是做网络设备的,估计才会在ip options里下功夫,但用java做网络设备的底层?如果不是,那就真的没有必要在这里放自定义数据。
用什么语言不重要,但至少应该把Ethernet、IP、TCP/UDP的数据结构和协议规范基本清晰。 那知道怎么在 options中添加自定义信息吗,有何见解
那知道怎么在 options中添加自定义信息吗,有何见解
struct ip_opt
{
uint8_t ipt_code;
uint8_t ipt_len;
uint8_t *data;
} ipopt;
insert_custom_ipopt(struct ipopt *ipop_p, uint8_t *data_p, uint8_t *ipoptbuff, uint32_t *optlen)
{
//pseudo code:ipopt->len = length(ipopt->code) + length(ipopt->len) + length(*data); //length unit: bytes
int i;
if(iptopt_p-code > 1 || iptopt_p->len + 1 > optlen || ipopt_p->len + *optlen + 1 > MAXIPOPTLEN)
{
fprintf(stderr, "ip options build error: options length exceeds MAXIPOPTLEN");
exit(EXIT_FAILURE);
}
*((uint16_t *)iptoptbuff) + *optlen= htons(*((uint16_t *)ipopt_p));
ipopt_p = ipopt_p + 2;
//确保data是little endian
for (i = 0; i < ipopt_p->len -2 ; i ++)
{
*(iptoptbuff + i) = *(data + i);
}
*optlen = *optlen + ipopt_p->len;
}
...
int iolen = 0;
uint32_t *optlen = &iolen;
struct ipopt *ipopt_p = &ipopt
struct iphdr *iphdr = (struct iphdr *)(packet + sizeof(struct ethhdr));
uint8_t *ipoptbuff = packet + sizeof(struct ethhdr) + sizeof(struct iphdr)
...
memset(ipoptbuff, 0, 40)
ipopt.code = xxx;
ipopt.len = 40;
char data[37] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
myipopt.data = data;
insert_custom_ipopt(ipopt_p, data_p, ipoptbuff,optlen);
iphdr->ihl = 5 + iol / sizeof(uint32_t);
iphdr->check = 0;
iphdr->check = iphdr_csum(iphdr);
查看了RFC和wireshark的示例报文,得到以下几个概念:
1. ip options的总长必须是40byts(这个部分RFC没有找到,仅仅参考wireshark给的samplecaptures),如果不够用0填充
2. ipopt结构体的len必须包含ipopt->code和ipopt->len这两个字节的长度,即data的长度 + 2(这个部分RFC没有找到,仅仅参考wireshark给的samplecaptures)
3. ip options最后的字节必须是0
4.然后填充iphdr->ihl = 5 + iol / sizeof(uint32_t);
5. 最后再计算iphdr->check[quote=引用 17 楼 jlu_baqiaoyan 的回复:] 楼上为啥这么说,没听懂,IP报文头部不是有option这一块吗
楼上为啥这么说,没听懂,IP报文头部不是有option这一块吗
[quote=引用 11 楼 nswcfd 的回复:] 是Ip头的一部分,添加自定义选项之后还要修改iphdr->ihl字段 (表示ip头部的长度,注意除以4,也就是说ihl=5意味着长度是5*4=20字节; 由于Ihl字段长度只有4bit,所以最大值是15,表示长度为15*4=60字节; 去掉固定的20字节长度,只有40字节的空间可以用于添加ip option;)。
发送端ip_queue_xmit函数中可以自己添加个IP Option 在tcp_transmit_skb函数中也可以添加TCP Option 一般来说路由器的确不会丢包,但我试了,一般到网站后会被丢掉,可以在出口路由器的qdisc队列转发的过程中把该选项删除 如果要用户态程序可以使用该选项,可能还要修改接口函数。
是Ip头的一部分,添加自定义选项之后还要修改iphdr->ihl字段 (表示ip头部的长度,注意除以4,也就是说ihl=5意味着长度是5*4=20字节; 由于Ihl字段长度只有4bit,所以最大值是15,表示长度为15*4=60字节; 去掉固定的20字节长度,只有40字节的空间可以用于添加ip option;)。
SIP/DIP是源IP目的IP。 struct ip_options是存放option解析结果或待添加的option选项的,不是最终报文上的option结构。 最后报文里的选项就是 type length payload的结构,注意4byte对齐就行。 type注意避开已经在使用的IPOPT_XXX。