Я написал ловушку netfilter для изменения некоторых данных на прикладном уровне. Я пытаюсь получить начало и конец данных приложения:
sturct iphdr* iph = ip_hdr(skb);
struct tcphdr* tcph;
char *data_start, *data_end;
if(iph -> protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcph = tcp_hdr(skb);
data_start = (char *)tcph + tcph -> doff * 4;
data_end = (char *)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;
А затем, например, вывести первый символ:
if(data_end - data_start >= 1)
printk("%x\n", *data_start);
Но я обнаружил, что код не всегда работают хорошо, так как иногда данные приложения, кажется, не помещаются точно за заголовок TCP.
Я нашел решение: используйте skb_ensure_writable
(или skb_make_writable
в старом ядре) перед чтением данных приложения и повторно -get заголовки и указатели символов:
sturct iphdr* iph = ip_hdr(skb);
struct tcphdr* tcph;
char *data_start, *data_end;
if(iph -> protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcph = tcp_hdr(skb);
data_end = (char *)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;
skb_ensure_writable(skb, (char*)data_end - (char*)skb -> data);
iph = ip_hdr(skb);
tcph = tcp_hdr(skb);
data_start = (char *)tcph + tcph -> doff * 4;
data_end = (char *)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;
Но у меня все еще есть несколько вопросов:
- Почему данные приложения не предназначены для того, чтобы лежать позади заголовка TCP?
- Может ли заголовок TCP также не находиться за заголовком IP? Если да, как я могу получить второй параметр для
skb_ensure_writable
? - Что именно
skb_ensure_writable
или skb_make_writeable
делает? Я едва мог найти какой-либо документ.