蓝盟IT外包,通过JNI移植tracepath跟踪路由链并提供给应用程序

发布者:上海IT外包来源:http://www.lanmon.net点击数:1464

蓝盟IT小贴士,来喽!
Linux的tracepath命令跟踪到目标主机的数据路由信息,并检测MTU值。 它跟踪路径到目的地,沿着这条路径发现MTU。 使用UDP端口或几个随机端口。
作者:工匠若水源:码农每日一题|2020-12-10 08:39收藏分享
背景
Linux的tracepath命令跟踪到目标主机的数据路由信息,并检测MTU值。 它跟踪路径到目的地,沿着这条路径发现MTU。 使用UDP端口或几个随机端口。 类似于跟踪,但不需要超级用户权限。 另外,没有华丽的选项。
Android也是移植的,源代码的放置位置是platform/external/IP  utils/trace  Path6. c。 直接移植tracepath6.c而不是tracepath.c的原因是tracepath6支持IPV6和IPV4两种模式,tracepath.c只支持IPV4,因此在穿梭后直接完整两种模式
最近正在调查网络诊断的涵盖能力,所以顺利移植了。 大致效果如下。
demo效应
移植后马上拿到地址ber/Android-Trace  Path,给你尽可能小的星星,闪闪发光。
开始移植。
我想捡现成的,我去看了platform/external/IP  utils/trace  path6. c源代码。 这个商品是直接写死的默认假设IPV6模式,需要不同模式的情况下,自己执行命令时传递模式参数,不支持自己的动态识别模式,所以需要移植改造。
定义Java接口规则
为了便于使用app,必须在JNI中包装在Java层接口中,并有以下约定:
package  cn.Yan.Android.trace  Path;
publicfinalclassandroidtracepath
静态。
system.loadlibrary  (' trace  path-compat  ' )
}privatestatelistenermstatelistener;
publicandroidtracepath  (statelistenerstatelistener  ) )
this.mstate  listener=state  listener;
}
//业务端调用启动跟踪路径的方法。 hostName是你的域名或ip
publicvoidstarttrace  (string  hostname  )
nativeInit  ();
nativeStartTrace(hostName  )
}
公共本机void  native  init  ();
publicnativevoidnativestarttrace  (字符串主机名称) :
public  void  native  onstart  () )
if  (空)!=mStateListener) { ) )
mStateListener.onStart  ();
}
}
publicvoidnativeonupdate  (字符串更新) )
if  (空)!=mStateListener) { ) )
mStateListener.onUpdate(update  ) :
}
}
public  void  native  onend  () )
if  (空)!=mStateListener) { ) )
mStateListener.onEnd  ();
}
}
//tracepath回调状态
公共接口状态监听器)。。
void  onStart  ();
void  on  update  (字符串更新)void  onEnd  ();
}
}
其次是与JNI层对应的接口。 这里什么也没说,是件旧夹克。 无论是一键生成、动态映射还是随便摆弄,都可以调用tracepath6.c源代码。
我们重点是改造tracepath6.c。 因为这是默认编译后可执行文件,所以通过cmake需要依赖编译,所以他的main方法的入口不适合我们。 需要改造(重命名方法即可)。
用跟踪路径函数替换//int  main(int  argc,char  **argv  )
int跟踪路径(int  argc、char  **argv  )
因为这需要调用到我们的JNI包装界面(apicompat.c  ),所以我们让他创建了一个新的头文件,泄露了这个方法的报纸,如下所示。
//tracepath6.h
# ifndefandroidtracepath  _ trace  path6_ h
# defineandroidtracepath  _ trace  path6_ h
int跟踪路径(int  argc、char** arg  )
# endif//Android  trace  Path  _ trace  Path6_ h
连接到ipv4的手机网络运行时,需要躺在插槽里跪下,定位代码发现tracepath6.c中有写死模式,动态适应。 改造点如下。
……。
sa_family_t  family=AF_UNSPEC; /在此,将初始值的AF_INET6置换为AF_UNSPEC
……。
int跟踪路径(int  argc、char  **argv  )
{
……。
memset(hints,0,sizeof(hints  ) );
hints.ai_family=AF_UNSPEC; /在此将family变量替换为AF_UNSPEC
hints.ai_socktype=SOCK_DGRAM;
hints.ai_protocol=IPPROTO_UDP;
#ifdef  USE_IDN
hints.ai_flags=AI_IDN;#endif
gai=getaddrinfo(argv[0]、pbuf、hints、ai0 )
if  (gai) { ) )
fprintf(stderr,' getaddrinfo: %s\n  ',gai_strerror(gai  ) )
return  1;
}
fd=-1;
for  (ai=ai0; ai; ai=大于ai-ai  _ next  ) )
/这里的段落判断family的逻辑删除
IF  (比AI-AI  _ Family大!=AF_INET6
大于ai-ai_Family!=AF_INET
连续;
大于Family=ai-ai_Family
FD=socket  (大于AI-AI  _ Family,大于ai-ai_socktype,大于ai-ai_protocol  )
if  (软盘小于0 )
连续;
memcpy(target、ai-大于ai_addr、sizeof(target  ) )
大于targetlen=ai-ai_addrlen
break
}
……。
}
贯穿整个过程的模式保持为全局family变量类型,默认情况下,如果变更为AF_UNSPEC,则自动检测到类型,如果与AF_INET6或AF_INET一致,则执行自己的对应逻辑,与IPV6
此操作将产生结果,但无法将tracepath打印结果输出到Java层回调。 有必要继续改造。 常见的想法是将tracepath6.c的printf函数实现为JNI回调Java方法,很麻烦。 我们还在采用穿梭机的模式。 如下所示。
//tracepath6.c
#include  '././apicompat.h  '
# define  printf  (. ) callback  on  update  (_ _ va  _ args  _ _ )
如上所述,printf可以通过宏直接替换JNI接口层的callbackOnUpdate函数,该函数的作用是调用Java方法,返回数据。这个基本ok了,但最后的优化是tracepath6.c最初写的是可执行程序,现在移植到了so中,所以不能直接exit。 在相关的地方,需要用return代替问题。 这样就能完美地解决一切。

文/上海蓝盟  IT外包专家

IT外包
>
400-635-8089
立即
咨询
电话咨询
服务热线
400-635-8089
微信咨询
微信咨询
微信咨询
公众号
公众号
公众号
返回顶部