강좌 & 팁
안녕하세요.
유형석입니다.
이번시간에는 이더넷 패킷에 어떻게 데이터를 넣어야 되는지 알아 봅시다.
1. 주의
일단 저는 회사 보드의 부트로더에서 작업을 했습니다.
커널로 진입한뒤 어플로 실행하면 여러가지 간섭도 발생하기 때문에
부트로더에서 테스트를 하는게 더 좋을 것이라고 생각되네요.
그리고 참고 하실점은 이더넷 디바이스 드라이버로 쓰는 인터페이스 함수가 필요한데요.
이건 디바이스 드라이버 작성한 사람에 따라 틀려질수 있으니 유의하시길 바랍니다.
뭐 그렇다고 해도 왠만하면 가능하다고 봅니다.
일단 상황은 fd_eth_main 이라는 변수가 디바이스 드라이버에 등록되 있는 상태를 가정으로 진행 합니다.
2. 진행
일단 이더넷 헤더와 ARP 헤더를 같이 보내기 위해서 아래와 같이 만들어 줬습니다.
struct _eth_test_packet { ETH_HDR eth_hdr; ETHARP_HDR etharp_hdr; }__attribute__((packed)); typedef struct _eth_test_packet ETH_TEST_PACKET;
일단 풀 소스 먼저 보여드리겠습니다.
char buff[2048]; ETH_TEST_PACKET *test_packet = NULL; test_packet = (ETH_TEST_PACKET *)buff; int tx_size; u8 test_dest_mac[6] = { 0x00, 0xFA, 0x01, 0xA2, 0x04, 0x49 }; u8 test_src_mac[6] = { 0x00, 0xFA, 0x01, 0xA2, 0x04, 0x41 }; u16 test_dest_ip[2] = { 0xC0A8, 0x0431 }; u16 test_src_ip[2] = { 0xC0A8, 0x0429 }; test_packet->eth_hdr.dest[0] = 0x00; test_packet->eth_hdr.dest[1] = 0xFA; test_packet->eth_hdr.dest[2] = 0x01; test_packet->eth_hdr.dest[3] = 0xA2; test_packet->eth_hdr.dest[4] = 0x04; test_packet->eth_hdr.dest[5] = 0x49; test_packet->eth_hdr.src[0] = 0x00; test_packet->eth_hdr.src[1] = 0xFA; test_packet->eth_hdr.src[2] = 0x01; test_packet->eth_hdr.src[3] = 0xA2; test_packet->eth_hdr.src[4] = 0x04; test_packet->eth_hdr.src[5] = 0x41; test_packet->eth_hdr.type = 0x0608; test_packet->etharp_hdr.hwtype = 0x0001; test_packet->etharp_hdr.proto = 0x0800; test_packet->etharp_hdr.hwlen = 0x06; test_packet->etharp_hdr.protolen = 0x04; test_packet->etharp_hdr.opcode = 0x0001; memcpy(&test_packet->etharp_hdr.shwaddr, &test_src_mac , 6); memcpy(&test_packet->etharp_hdr.dhwaddr, &test_dest_mac, 6); memcpy(&test_packet->etharp_hdr.sipaddr, &test_src_ip , 2); memcpy(&test_packet->etharp_hdr.dipaddr, &test_dest_ip , 2); tx_size = write(fd_eth_main, test_packet, sizeof( test_packet )); printf("tx_size = %d\n", tx_size);
주소를 넣기 위해서는 두가지 방법이 있습니다.
배열 주소 하나마다 넣을 수도 있고
test_packet->eth_hdr.dest[0] = 0xFF; test_packet->eth_hdr.dest[1] = 0xFF; test_packet->eth_hdr.dest[2] = 0xFF; test_packet->eth_hdr.dest[3] = 0xFF; test_packet->eth_hdr.dest[4] = 0xFF; test_packet->eth_hdr.dest[5] = 0xFF;
따로 배열 변수를 두고 미리 넣어둔 다음 memcpy 로 복사 하는 방법이 있습니다.
u8 test_dest_mac[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; memcpy(&test_packet->etharp_hdr.shwaddr, &test_src_mac , 6);
test_packet->eth_hdr.type = 0x0608;
ARP 타입은 원래 0806 이지만 엔디안의 차이로 인해서 0608로 적어 주셔야 됩니다.
tx_size = write(fd_eth_main, test_packet, sizeof( test_packet ));
fd_eth_main 변수가 이더넷 디바이스 드라이버와 연결 되어 있기 때문에
write함수를 사용해서 fd_eth_main에 구조체의 값을 전달하여 전송 합니다.
원래 ARP는 타겟 IP는 알고 있는데 MAC주소를 모를때 MAC주소를 얻기 위해서 전송합니다.
그렇기 때문에 이더넷 헤더의 목적지 주소(dest)는 FF로 하여 브로드케스트 형식으로 보내는게 일반적입니다.
IP값은 헥사값으로 변경 시켰을뿐 변환하면
목적지IP는 192.168.4.49
송신IP는 192.168.4.41
이 되겠습니다.
이 부분은 윈도우 계산기로도 간편하게 값을 얻을수 있으니 이용하시면 되겠습니다.
일단 나머지 값들에 대해서는 일단 저렇게 넣는 다고만 알고 계시면 되겠습니다~
그 부분에 대해서는 수신쪽을 끝 마치고 따로 정리해서 적을 예정입니다.
짧은 글 읽어 주셔서 감사합니다!
이미지 출처 : 위키피디아