2009-02-25 15 views
10

Tôi đang viết mô-đun hạt nhân đăng ký móc nối netfilter. Tôi đang cố gắng để có được địa chỉ ip của người gọi bằng cách sử dụng sk_buff-> saddr thành viên. Có cách nào tôi có thể nhận IP ở định dạng i.xe.x.x.x.x có thể đọc được không?Địa chỉ IP từ sk_buff

Tôi đã tìm thấy hàm inet_ntop() nhưng dường như nó không có sẵn trong các tiêu đề hạt nhân. Làm cách nào để chuyển đổi \ xC0 \ xA8 \ x00 \ x01 thành 192.168.0.1?

+0

inet_ntop() và anh trai inet_pton() của nó thực sự nằm trong arpa/inet.h, tôi đang tìm kiếm triển khai hạt nhân ngay bây giờ. –

+0

ummm, mục tiêu nhật ký của netfilter phải làm điều này ... Tôi sẽ xem xét ở đó. – derobert

+0

& Rohit: thành thật mà nói, nếu bạn không biết cách định dạng byte trong chuỗi như vậy, có thể bạn không nên viết mô-đun hạt nhân. Hãy thử một số công cụ không gian người dùng trước tiên. –

Trả lời

12

có hai macro quy định tại bao gồm/linux/kernel.h

NIPQUAD cho các địa chỉ ipv4 và NIP6 cho các địa chỉ ipv6.

#define NIPQUAD(addr) \ 
    ((unsigned char *)&addr)[0], \ 
    ((unsigned char *)&addr)[1], \ 
    ((unsigned char *)&addr)[2], \ 
    ((unsigned char *)&addr)[3] 

#define NIP6(addr) \ 
    ntohs((addr).s6_addr16[0]), \ 
    ntohs((addr).s6_addr16[1]), \ 
    ntohs((addr).s6_addr16[2]), \ 
    ntohs((addr).s6_addr16[3]), \ 
    ntohs((addr).s6_addr16[4]), \ 
    ntohs((addr).s6_addr16[5]), \ 
    ntohs((addr).s6_addr16[6]), \ 
    ntohs((addr).s6_addr16[7]) 

Có nhiều ví dụ phong phú trong nguồn hạt nhân sử dụng chúng để in địa chỉ IP ở định dạng có thể đọc được. Ví dụ:

printk(KERN_DEBUG "Received packet from source address: %d.%d.%d.%d!\n",NIPQUAD(iph->saddr)); 

Hy vọng điều này sẽ hữu ích.

+9

Tôi đã chạy qua điều này ngay bây giờ. Vì lợi ích của những người khác có thể vấp phải điều này, 'NIPQUAD' đã bị xóa bỏ sau 2.6.38. Sử dụng '% pI4' thay vì – pratikm

+0

Đến sau này. Bây giờ có 'in4_pton()' trong /net/core/utils.c – BonBon

+0

@BonBon: 'in4_pton()' làm ngược lại. –

0

Bạn có thể sử dụng strtol để chuyển đổi từng phần thành dạng số nguyên của nó.

+0

Tôi gần như tích cực rằng một macro tồn tại mà chỉ có điều đó, tôi chỉ không thể tìm thấy nó ATM. –

2

Đơn giản. Địa chỉ IP ở định dạng "x.x.x.x" được gọi là chấm-quad vì một lý do. Mỗi số đại diện cho một byte, với tổng số 4 byte trong địa chỉ của bạn.

Vì vậy, với địa chỉ 4 byte, bạn chỉ cần in giá trị thập phân của mỗi byte.

Nhanh chóng và bẩn ví dụ (thay thế printf với chức năng đầu ra của bạn lựa chọn):

unsigned char *addr = (unsigned char*)sk_buff->addr; 
printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); 
+2

điều này đã bị lỗi hạt nhân – Rohit

0
/* Convinience union to __be32 to ip address */ 
union ip_address { 
    u8 a[4]; 
    __be32 saddr; 
}; 

Địa chỉ IP có thể thu được một [0] .a [1] .a [2] .a [3]

11

Bạn nên sử dụng% pI4 định dạng mở rộng specifiers cung cấp bởi printk():

printk(KERN_DEBUG "IP addres = %pI4\n", &local_ip); 
0

printk có thể xử lý này trực tiếp:

địa chỉ IPv4: địa chỉ

%pI4 1.2.3.4 
%pi4 001.002.003.004 
%p[Ii]4[hnbl] 

For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4' 
specifiers result in a printed address with ('i4') or without ('I4') 
leading zeros. 

The additional 'h', 'n', 'b', and 'l' specifiers are used to specify 
host, network, big or little endian order addresses respectively. Where 
no specifier is provided the default network/big endian order is used. 

Passed by reference. 

IPv6:

%pI6 0001:0002:0003:0004:0005:0006:0007:0008 
%pi6 00010002000300040005000600070008 
%pI6c 1:2:3:4:5:6:7:8 

For printing IPv6 network-order 16-bit hex addresses. The 'I6' and 'i6' 
specifiers result in a printed address with ('I6') or without ('i6') 
colon-separators. Leading zeros are always used. 

The additional 'c' specifier can be used with the 'I' specifier to 
print a compressed IPv6 address as described by 
http://tools.ietf.org/html/rfc5952 

Passed by reference. 

Tham chiếu: https://www.kernel.org/doc/Documentation/printk-formats.txt