회사에서 게이트웨이 어플리케이션을 만들었다.
장치에서 데이터를 가져와 LWM2M으로 서버와 통신하는 그런 어플리케이션이다.
원래는 LTE모듈로 UDP 송신하는 단순한 통신방식이였다.
그런데, 보고서까지 작성한 프로젝트를 가져와서 수정을 해야 한다고 한다.
LTE모듈이 아닌 다른 라우터 장치로 서버와 통신을 해야한다고 한다.
근데 그 라우터 장치는 TCP만 지원한다고 한다.
그럼 서버에 어떻게 보내야 할까?
UDP 패킷을 만들고, 그 위에 TCP를 씌워야 한다는 팀장님.
장치가 TCP로 보내면 저쪽에서 Proxy server가 UDP 패킷을 server로 전송한다는 것이다.
GW - Router - Proxy server - server
이러한 구조가 된다는 것이다.
TCP는 어짜피 장치가 만들어주기 때문에 UDP Raw packet만 만들어주면 되겠지만, 테스트를 위해서 TCP send 부분도 만들었다.

Windows도 Raw header를 만들 수 있다고 하는데, Linux 만 해오던 사람이라 잘 모르겠다.
netinet 헤더에서 UDP/IP header 를 가져왔다.
<linux/ip.h> 와 <linux/udp.h> 를 사용해도 됐던걸로 알고 있다.

Buffer는 패킷이 저장되는 부분이다.
IP header가 UDP header보다 앞에 있어야 하므로 IP header의 위치를 먼저 잡아주고, UDP header의 위치를 잡아주었다.

Sockaddr_in 구조체는 TCP 로 전송을 테스트하기 위한 구조체다.
알아서 connect에 넣어주면 처리해준다.
TCP는 라우터 장치가 해주기 때문에 어렵게 가지 않았다.

진짜로 필요한 부분은 UDP/IP header를 만드는 곳이다.
UDP 의 header는 간단하다.
애초부터 비신뢰성, 신속 통신을 위해 있는 프로토콜이라 8bytes 크기를 가지고 있다.
적당히 source port, destination port 그리고 길이를 넣어주면 끝이다.
IP header는 조금 복잡한다.
IPv6 header는 IPv4 보다는 간단하지만, 내가 써야하는건 IPv4 이다.
그래도 검색하면 다 나오니 그렇게 어렵지 않다.
내가 넣은 부분은 다음과 같다.
saddr, daddr : source address, destination address
ihl : Header length
version : version
tos : type of service
tot_len : total length (IP header + UDP header + payload)
id : identification 이라 되어있는데, source port를 넣었다. wireshark로 찍어보면 맞는것같더라.
ttl : time to live
protocol : 17 (UDP)
Source, Destination 주소는 Proxy server와 server의 주소를 넣었다.
그렇지 않으면 Proxy server가 server와 UDP로 통신을 하지 못할테니깐.

Header를 전부 만들고 Header 뒤에 내용물을 넣는다.
단순히 Header의 길이만큼 앞을 빼주고 memory copy 하면 된다.
패킷이 다 만들어졌으면 전체를 checksum 계산 해준다.
IP header의 check에 이게 정확이 안들어가 있으면 자꾸 패킷을 버리더라.
전체 패킷이 완성되었으니 write로 TCP 송신을 한다.
뭔가 내용이 길어보이지만, Raw packet으로 검색하면 많이 나오는 내용들이다.
왠지 또 쓰라고 할 것 같아서 이렇게 블로그에 적어두었다.
'정리글' 카테고리의 다른 글
| JAVA Maven 프로젝트에서 JNA 사용 (0) | 2020.09.16 |
|---|---|
| IIO - Linux Industrial I/O subsystem (0) | 2020.09.02 |
| LWM2M 했던 것들 정리 (0) | 2020.07.14 |
| mbed OS 에서 메모리 사용량 체크 mbed_stats.h (0) | 2019.12.27 |
| 시리얼 통신 (0) | 2019.07.03 |