[ENC28J60] Bài 6: Giao thức ARP

arp

Như mình đã nói lần trước, để một gói tin được gửi tới chính xác thiết bị trong mạng LAN, nó cần có địa chỉ MAC của thiết bị đó. Giao thức ARP được sử dụng để từ 1 địa chỉ IP có thể tìm ra địa chỉ MAC của thiết bị đích hay nói cách khác là phân giải địa chỉ IP sang địa chỉ máy

Mình sẻ làm thử 1 demo gửi 1 gói tin ARP nhé !

Chúng ta mở project đã làm ở bài 5

Trong file code main, mình khai báo 1 gói tin arp như sau:

Chú ý: Kiểm tra ip của bạn thuộc dạng 192.168.1.xxx hay 192.168.0.xxx để đổi 2 cái bên trên ip tương ứng nhé

Trong hàm main, vòng lặp while(1) mình sẽ gửi gói tin đi liên tục bằng hàm ENC28J60_send_packet

Chạy thử chương trình và mình thấy led vàng nhấp nháy liên tục, có nghĩa là đã có dữ liệu được gửi đi. Để có thể dubug được gói dữ liệu này mình sẽ sử dụng 1 phần mềm chuyên bắt gói tin trên máy tính

Giới thiệu phần mềm Wireshark

Wireshark là phần mềm chuyên bắt mọi gói dữ liệu ra vào máy tính thông qua Ethernet, wifi, usb. Do chúng ta sử dụng mô phỏng để chạy chíp ENC28J60 nên tất cả gói dữ liệu ra vào con chip này cũng sẽ được phần mềm Wireshark bắt lại. Đây là công cụ mà hacker rất hay dùng

Chúng ta sẽ sử dụng phần mềm này để debug các gói tin trong suốt toàn bộ khóa học

Các bạn tải và cài đặt Wireshark nhé !

Sau khi cài phần mềm xong, mở lên, giao diện nó như vầy

Nếu bạn dùng wifi thì click chọn vào wifi, nếu dùng mạng dây thì chọn mạng dây tương ứng nhé !

Sau khi chọn wifi hoặc mạng dây thì màn hình real time sẽ hiện ra, ở đây sẽ liên tục hiện các gói tin vào ra máy tính theo thời gian thực

Do có rất nhiều gói tin gửi nên mình sẽ dùng chức năng lọc để lọc lấy các gói tin arp

Các bạn thấy đấy, phần mềm đã bắt được gói tin mà mình đã gửi đi, như vậy hàm ENC28J60_send_packet đã gửi thành công gói tin vào môi trường mạng LAN rồi !

Lan màn vậy đủ rồi, chúng ta sẽ vào chủ đề chính ngày hôm nay

Cấu trúc chung của 1 gói tin

Do chung ta đang làm việc với chip enc29j60 sử dụng giao thức mạng ethernet, tất các các gói tin truyền nhận đều phải tuân thủ quy tắc của Ethernet Frame Type II

Chúng ta cần quan tâm 14 byte đầu tiên :
Với 6 byte đầu tiên luôn luôn là địa chỉ MAC của thằng nhận
6 byte tiếp theo là địa chỉ MAC của thằng gửi
2 byte tiếp theo sẽ nói lên giao thức phía sau của nó thuộc loại gì ? IP hay ARP …. ????

Giao thức ARP (Ether Type =0x0806)

giao thức arp

Như đã nói bên trên, giao thức ARP dùng để lấy địa chỉ MAC của 1 thiết bị từ địa chỉ IP

Ví dụ ENC28J60 có ip 192.168.197 muốn gửi một tin nhắn cho máy tính có ip 192.168.1.4, trước tiên nó sẽ gửi 1 gói tin ARP request ( boardcast) tới toàn bộ thiết bị trong mạng, gói tin ARP request đó có nội dung như sau:
Tao là 192.168.1.197 đây, MAC của tao là xxx , thằng nào là 192.168.1.4 xưng danh

Toàn bộ thiết bị trong mạng đó sẽ nhận được tin nhắn này, những thằng nào không phải 192.168.1.4 sẽ ngó lơ bản tin này, chỉ riêng máy tính có địa chỉ 192.168.1.4 sẽ gửi 1 gói tin trả lời trực tiếp cho ENC28J60 có ip 192.168.1.197 do nó đã biết MAC của 192.168.1.197 (ARP reponse)
Tao là 192.168.1.4 đây, địa chỉ MAC của tao là AA:BB:CC:DD:EE:FF

ENC28J60 nhận được tin nhắn phải hồi và lưu địa chỉ MAC lại, bây giờ nó có thể gửi tin nhắn tới cho máy tính qua địa chỉ MAC

Bản tin ARP Request

Chúng ta sẽ ngâm cứu kĩ hơn cấu trúc của 1 ARP request

Giải thích cấu trúc :

  • 6 byte đầu mặc định: 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
  • 6 byte tiếp theo là địa chỉ MAC của nguồn – tức là của chính thằng gửi request
  • 2 byte 0x08 0x06 thể hiện đây là bản tin ARP (Ethernet Type)
  • 2 byte 0x00 0x01 thể hiện htype
  • 2 byte 0x80 0x00 thể hiện Protocol type, ở đây là IPv4
  • Tiếp đến là 0x06 và 0x04 là trường length
  • 2 byte 0x00 và 0x01 là opcode báo bản tin ARP này là request
  • Sender MAC và SenderIP của thiết bị request
  • Trường Taget MAC là của đích ( tức thiết bị nhận request) mặc định là 6 byte 0x00 do ta chưa biết MAC của nó
  • 4 byte cuối là IP của đích

Nói chung, chúng ta chỉ cần quan tâm tới SourceMAC SenderMAC SenderIP và TargetIP

Bản tin ARP Reponse

Bản tin ARP reponse có cấu trúc tương tự như các Request, chỉ khác nhau là Opcode sẽ là 0x0002 để thể hiện đây là reponse và Destination MAC và Target MAC sẽ không phải là 6 byte mặc định nữa mà là MAC của thiết bị đã gửi request

Dưới đây là ảnh chụp của 1 ARP reponse được bắt bởi WireShark

Các bạn có thể thấy, sau khi mình cho ENC28J60 gửi 1 boardcast (arp request) tới cho IP của máy tính thì máy tính đã trả lời lại MAC của nó ( 192.168.1.15 is at 00:26:5E:3D:74:66)

Thời gian ARP

Khi 1 thiết bị đã lấy được MAC của thiết bị khác từ IP, nó sẽ lưu trữ lại vào bảng để lần gửi sau chỉ việc lấy ra dùng chứ không cần phải hỏi lại nữa. Tuy nhiên trong mạng LAN, IP của các thiết bị là IP động, nó thường hay thay đổi mỗi khi thiết bị khởi động lại. Vì vậy các gói tin ARP vẫn thường xuyên được gửi để cập nhật lại MAC cho chính xác. Tránh việc sử dụng các địa chỉ đã lỗi thời

Thông thường, các bảng lưu ARP được cập nhật từ 30 đến 60s 1 lần

Tạo thư viện ARP

Trước khi viết thư viện ARP, mình sẽ tạo ra thư viện trung gian có tên là NET để làm trung gian giao tiếp giữa thư viện ENC28J60 với thư viện ARP và các thư viện khác nữa !

Chúng ta tạo 2 tệp là net.cnet.h và add vào project tương tự như hướng dẫn ở các bài trước

Các bạn copy nội dung khởi tạo cho file net.h

Tương tự, copy nội dung khởi tạo cho file net.c

Chú ý: Các này đáng lẽ mình phải nhắc từ đâu, tất cả các file .h .c các bạn phải có 1 dòng trống ở cuối file nhé, không thì trình dịch sẽ báo lỗi

Nhiệm vụ của thư viện NET

  • Phân tích gói tin tới xem nó thuộc loại gì, tùy vào loại của gói tin để gọi thư viện xử lí tương ứng. Ví dụ thư viện NET sẽ đọc truòng Ethernet Type của gói tin. Nếu nó là 0x0806 thì đây là gói ARP => gọi thư viện ARP và ném gói này cho nó xử lí. Nếu là gói tin chưa được hỗ trợ thì bỏ qua hoặc thông báo lỗi gì đó tùy ứng dụng …
  • Tính toán checksum
  • Gửi nhận gói tin
  • Kiểm tra liên tục xem có gói tin mới nào không
Mô hình hệ thống

Để có thể xử lí, phân tích các gói tin, mình sẻ khởi tạo trên ram của chip vi điều khiển 1 bộ đệm dài 512 byte

Thêm định #define cho BUFFER_LENGTH

Hàm NET_SendFrame sẽ gọi lại hàm ENC28J60_send_packet

Hàm NET_loop có nhiệm vụ check có gói tin nào không để gửi gói tin cho hàm NET_read xử lí gói tin

Các bạn nhớ thêm nguyên mẫu hàm vào file net.h

Hàm NET_loop sẽ được gọi trọng vòng lặp while(1) của hàm main để liên tục thăm dò gói tin

Bây giờ chúng ta sẽ viết nội dung cho hàm NET_read cho nó mở gói tin và xử lí xem bên trong gói tin có gì

Khi 1 gói tin được gửi tới, chúng ta sẽ ngay lập tức biết nó có phải là gói tin ARP không bằng cách check trường Ethernet Type

  • Nếu Ethernet Type = 0x0806 -> Đây là gói tin ARP
  • Ngược lại nếu Ethernet Type = 0x0800 -> Đây là gói tin IP
  • Ngược lại đây là 1 gói tin lạ, chúng ta sẽ bỏ qua

Chúng ta sẽ tạm thời chưa quan tâm gói tin IP vội, mình sẽ xử lí nó sau, trước mắt sẽ viết code để xử lí gói tin ARP

Cước bước kiểm tra

  1. Một bản tin ARP phải có ít nhất 42 byte, nếu không đủ 42 byte -> loại
  2. Check Ethernet Type tại byte thứ 12 và 13 xem có phải 0x0806 không, nếu không phải -> loại
  3. Tới đây, đã có thể chắc chắn đây là 1 gói tin ARP rồi, chúng ta sẽ lại gửi gói tin cho thư viện ARP xử lí

Đương nhiên hàm ARP_read_packet mình chưua viết nên sẽ tạm comment nó chúng ta sẽ viết nó ngay, nhưng sẽ viết trong thư viện arp.c chứ không viết ở file net.c

Test thử

Code nhiều rồi mà không test thì cũng chán nhỉ ! Chúng ta sẻ test thử bằng cách cho điện thoại gửi thử các bản tin ARP để xem chương trình của chúng ta có nhận được các gói ARP này không nhé !

Để gửi được các boardcast (ARP request) đi, mình sẽ sử dụng 1 phần mềm Scan IP bất kì. Ví dụ ở điện thoại android mình sẽ xài Network IP Scan

Các bạn có thể dùng phần mềm sacn bất kì

Bản chất của phần mềm scan IP là nó sẽ gửi các boardcast ( tức ARP request) đến toàn mạng. Thiết bị nào có IP tương ứng sẽ trả lời lại cho nó

Bây giờ, mình chạy mô phỏng proteus và mở phần mềm scan lên cho nó scan và xem kết quả ( mình cũng mở đồng thời WireShark lên nữa)

Các bạn thấy đó, chúng ta đã bắt được rất nhiều gói tin ARP request của phần mềm scan ( toàn bộ thiết bị trong mạng wifi đều nhận được nha)

Đồng thời thì wireshark nó cũng bắt được rất nhiều gói tin ARP

Như vậy chúng ta đã bắt được các gói tin ARP. Trong phần tiếp theo của bài ARP, chúng ta sẽ tiếp tục hoàn thành thư viện xử lí gói tin ARP và viết hàm trả lời các bản tin ARP request nhé !

Các bạn có thể tải code cho bài học hôm nay tại đây !

Bài tiếp theo

 

Từ tác giả:

Nếu có bất kì thắc mắc nào trong bài viết, vui lòng để lại comment dưới mỗi bài ! Mình sẽ không trả lời thắc mắc của các bạn ở facebook hay email !

Nếu trong phần code bạn nhìn thấy nhưng thứ kiểu như &amp; thì đó là lỗi hiển thị, cụ thể 3 kí tự < > & bị biến đổi thành như thế
&amp; là &
&lt;  là <
&gt; là >

Giới thiệu Đào Nguyện 80 bài viết
DIY,chế cháo, viết blog chia sẽ kiến thức về lập trình,điện tử - IoT. Rất mong được giao lưu, kết bạn với các bạn cùng đam mê. Địa chỉ Facebook: https://www.facebook.com/nguyendao207

11 bình luận

  1. chào bạn. Trước hết cảm ơn bạn đã viết tut chia sẽ cũng như hướng dẫn về 28j60.
    Mình làm tới tút này thì gặp vấn đề như sau. debug bằng Wireshark thì ko có capture được gói tin từ enc28j60 trong proteus. Bạn giúp mình chỗ này với. . Cảm ơn bạn nhiều

  2. Mình có một thắc mắc, đó là tại sao MAC addr khi set cho module khác với Source MAC trong bản tin ARP_request mà khi máy tính gửi bản tin ARP_reply vẫn có thể nhận được gói tin đó nhỉ?

Đã đóng bình luận.