2009-09-26 28 views
18

Các UDP tiêu đề struct quy định tại /usr/include/netinet/udp.h như sauUDP tính checksum

struct udphdr 
{ 
    u_int16_t source; 
    u_int16_t dest; 
    u_int16_t len; 
    u_int16_t check; 
}; 

giá trị gì được lưu trữ trong các lĩnh vực kiểm tra của tiêu đề? Làm cách nào để xác minh xem tổng kiểm tra có đúng không? Tôi có nghĩa là trên những dữ liệu được kiểm tra tính toán? (Có phải chỉ là tiêu đề udp hoặc tiêu đề udp cộng với trọng tải theo sau không?)

Cảm ơn.

Trả lời

27

Kiểm tra UDP được thực hiện trên toàn bộ tải trọng, các trường khác trong tiêu đề, một số trường từ tiêu đề IP. Một tiêu đề giả được xây dựng từ tiêu đề IP để thực hiện phép tính (được thực hiện trên tiêu đề giả này, tiêu đề UDP và tải trọng). Lý do tiêu đề giả được đưa vào là bắt các gói tin đã được định tuyến đến địa chỉ IP sai. Về cơ bản, ở đầu nhận, tất cả các từ 16 bit của các tiêu đề cộng với vùng dữ liệu được thêm vào với nhau (gói 16 bit) và kết quả được kiểm tra với 0xffff.

Về phía gửi, nó phức tạp hơn một chút. Một phần bù của một người được thực hiện trên tất cả các giá trị 16 bit sau đó bổ sung của một người (tức là đảo ngược tất cả các bit) được lấy giá trị đó để điền vào trường tổng kiểm tra (với điều kiện bổ sung là tổng kiểm tra được tính bằng không sẽ được thay đổi thành tất cả một bit).

Tổng chi phí của một người là không phải chỉ là tổng của tất cả các giá trị bổ sung của một người. Nó phức tạp hơn một chút.

Về cơ bản, bạn có bộ tích lũy 16 bit đang chạy bắt đầu từ 0 và bạn thêm mọi giá trị 16 bit vào đó. Bất cứ khi nào một trong những bổ sung đó dẫn đến việc mang theo, giá trị được bao quanh và bạn thêm một giá trị vào giá trị một lần nữa. Điều này có hiệu quả mất bit thực hiện của việc bổ sung 16-bit và thêm nó vào giá trị.


Là một sang một bên, và đây là phỏng đoán tinh khiết trên một phần của tôi, nhưng điều này có lẽ có thể được thực hiện một cách hiệu quả bằng cách sử dụng các ADC (thêm với carry) hướng dẫn chứ không phải là ADD (đáng ngạc nhiên đủ, thêm), hoặc bất kỳ hướng dẫn tương đương nào cũng có sẵn trên CPU của bạn vào thời điểm đó.

Nếu không mang theo, ADC sẽ chỉ thêm bit không từ carry. Trong những ngày khi công cụ này được thực hiện (và có, thật không may, tôi am cũ), bộ nhớ còn nhiều hạn chế hơn tốc độ, không quá nhiều trường hợp ngày nay, vì vậy, hãy tiết kiệm một vài byte trong mã của bạn. bạn đến mức độ demi-thần-hoàng đế-of-the-vũ trụ :-)


Lưu ý rằng bạn không bao giờ phải lo lắng về việc thực hiện lần thứ hai xung quanh (hoặc một carry hai với tiếp theo ADC nếu bạn đang sử dụng phương pháp được đề cập trong đoạn trước) vì hai giá trị 16 bit lớn nhất, khi tổng hợp, sản xuất (cắt ngắn từ 0x1fffe) 0xfffe - thêm một vào đó sẽ không bao giờ gây ra một lần mang khác.

Khi tính tổng bổ sung được tính toán, bit của nó được đảo ngược và được chèn vào gói, điều này sẽ dẫn đến việc tính toán ở đầu nhận để tạo ra 0xffff, giả sử không có lỗi trong quá trình truyền.

Cần lưu ý rằng tải trọng luôn được đệm để đảm bảo có một số tích phân các từ 16 bit. Nếu nó đệm, trường độ dài cho bạn biết độ dài thực tế.

RFC768 là đặc điểm kỹ thuật chi tiết thông tin này.

+0

Cảm ơn vì điều đó. Tôi hơi bối rối về phần Pseudo-Header .. nhưng sau đó RFC đã xóa không khí. – Deepak

+1

"Tất cả các từ 16 bit của các tiêu đề (trong đó UDP tổng kiểm tra là số không) được thêm vào và bổ sung của một người (tức là, đảo ngược tất cả các bit) là những gì được đưa vào trường kiểm tra." Không, những gì RFC nói sẽ dẫn đến "Tất cả các bổ sung của một người (tức là đảo ngược tất cả các bit) của các từ 16 bit của các tiêu đề (trong đó UDP checksum là số không) được thêm vào và bổ sung của nó là vào trường kiểm tra. " Nếu không, câu trả lời hoàn hảo +1. – Joren

+1

Điều này không đúng. "Phần bù trừ của một người" không có nghĩa là lấy phần bổ sung của mỗi từ và thêm chúng lại với nhau. Nó có nghĩa là bạn thêm các từ với nhau, và khi một bit mang được tạo ra, bạn thêm 1 vào tổng số đang chạy. Xem http://mathforum.org/library/drmath/view/54379.html. –

1

Một tốt đẹp và dễ hiểu ví dụ về tính toán checksum UDP được thực hiện bởi Gerd Hoffmann .

Bạn có thể google cho "net-checksum.c Gerd Hoffmann" hoặc nhìn vào các tập tin ở đây:

https://gist.github.com/fxlv/81209bbd150abfeaceb1f85ff076c9f3

Bạn có thể sử dụng chức năng net_checksum_tcpudp, nuôi nó payload length UDP, proto, src và các IP đầu tiên và sau đó là tải trọng UDP và nó sẽ làm điều đúng.

Cuối cùng, bạn phải gọi htons() trên tổng kiểm tra và bạn tốt.