[pso] [Tema4][Linux]NU incepeti tema inainte sa cititi ASTA
Andrei Popa
ca at i-neo.ro
Wed May 30 00:05:06 EEST 2007
On Sun, 2007-05-20 at 18:30 +0300, Razvan Deaconescu wrote:
> sorin gsmcreation wrote:
> > Salutare!
> >
> > Dupa ceva timp am reusit sa descoperim (Razvan de
> > fapt) motivul comportarii ciudate a hook-ului de
> > input.
> > Problema era ca in acest hook, cand citeam portul
> > sursa si destinatie al oricarui pachet, fie el
> > TCP/UDP, valorile acestor porturi erau corupte.
> >
> > Asta pentru ca nu obtineam ok pointerii catre
> > headerele tcp si udp (foloseam metoda initiala din
> > laboratorul de networking). Partea ciudata e ca in
> > hook-ul de output mergea sa obtinem headerele ca in
> > laborator; doar la input se comporta ciudat.
> >
> > Solutia care merge este:
> > struct iphdr *iph = (*skb)->nh.iph;
> > struct tcphdr *tcph = (struct tcphdr *) ((*skb)->data
> > + iph->ihl * 4);
> > struct udphdr *udph = (struct udphdr *) ((*skb)->data
> > + iph->ihl * 4);
>
> se pare ca pe hook-ul de in (NF_LOCAL_IN), subsistemul de networking nu
> "dezasambleaza" antetul TCP/UDP in campurile (*skb)->h.th, respectiv
> (*skb)->h.uh
>
> la hook-ul de out (NF_LOCAL_OUT), dezasamblarea este realizata corect si
> totul merge OK daca se folosesc (*skb)->h.th/(*skb)->h.uh
>
pachetul cand vine, prima oara este trecut prin ip_input.c si se
apeleaza functiile de hooking NF_IP_LOCAL_IN si dupa asta este pasat
layer-ului TCP/UDP.
din aceasta cauza campurile pt. TCP/UDP din skb nu sunt setate bine in hooking-ul NF_IP_LOCAL_IN.
cand un pachet pleaca, pleaca din layerele TCP/UDP unde i se seteaza campurile pt. TCP/UDP din skb
si dupa asta este trimis la ip_output.c care apeleaza functiile de hooking pt. NF_IP_LOCAL_OUT si astfel
campurile sunt setate bine.
explicatia mai tehnica:
filtrele NF_IP_LOCAL_IN si NF_IP_LOCAL_OUT sunt apelate in ip_input.c si
ip_output.c
INPUT( cand un pachet vine):
http://lxr.linux.no/source/net/ipv4/ip_input.c#L263
//hook-ul pt. NF_IP_LOCAL_IN este apelat in ip_local_deliver()
return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL, ip_local_deliver_finish);
//dupa care este apelata functia ip_local_deliver_finish()
http://lxr.linux.no/source/net/ipv4/ip_input.c#L199
//unde
http://lxr.linux.no/source/net/ipv4/ip_input.c#L214
struct net_protocol *ipprot;
if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
ret = ipprot->handler(skb); //se apeleaza defapt functia tcp_v4_rcv()
http://lxr.linux.no/source/net/ipv4/af_inet.c#L1289
//se inregistreaza functia care sa fie apelata pt. acest protocol
static struct net_protocol tcp_protocol = {
.handler = tcp_v4_rcv,
.err_handler = tcp_v4_err,
.gso_send_check = tcp_v4_gso_send_check,
.gso_segment = tcp_tso_segment,
.no_policy = 1,
};
// se vede ca .handler = tcp_v4_rcv,
//functia tcp_v4_rcv este definita in
http://lxr.linux.no/source/net/ipv4/tcp_ipv4.c#L1611
deci pachetul este trimis layerului TCP/UDP abia dupa ce au fost aplicate functiile
de filtrare din NF_IP_LOCAL_IN si din cauza asta nu are campurile skb->h.th si
skb->h.uh setate bine (aceste campuri le seteaza TCP/UDP-ul)
OUTPUT( cand un pachet pleaca):
in functia tcp_transmit_skb() se creeaza pachetul TCP/IP pt. a fi transmis,
fiindui setata si portul sursa si portul destinatie:
http://lxr.linux.no/source/net/ipv4/tcp_output.c#L468
http://lxr.linux.no/source/net/ipv4/tcp_output.c#L544
err = icsk->icsk_af_ops->queue_xmit(skb, 0); //se apeleaza aceasta functie
http://lxr.linux.no/source/net/ipv4/tcp_ipv4.c#L1807
.queue_xmit = ip_queue_xmit, //defapt este apelata functia ip_queue_xmit
http://lxr.linux.no/source/net/ipv4/ip_output.c#L284
este definita functia int ip_queue_xmit(struct sk_buff *skb, int ipfragok){}
care deja este in ip_output.c si care apeleaza hook-ul pt. NF_IP_LOCAL_OUT
return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);
deci pachetul cand pleaca prima oara este creat de layer-ul TCP/UDP care ii seteaza
campurile kb->h.th si skb->h.uh si abia dupa asta este filtrat de NF_IP_LOCAL_OUT.
--
Andrei Popa - 341C3
More information about the pso
mailing list