Re: How to re-send out the packets captured by my hook function at NF_IP_PRE_ROUTING

From: Jiangbo Li
Date: Sun Apr 30 2006 - 03:24:08 EST


Hello, Real Oneone

I wrote some code which swap the src and dst address/port and send out
the packet for 2.6 kernel. The packets are captured from PRE_ROUTINT
point. I steal some code from the ipt_MIRROR.c in 2.5.* kernels. I
don't know why this is not in the 2.6 kernel.

My code works on 2.6.10 kernel. Please start read my code from the
very end handle_reflect(). Even I can not understand all the code
now. damn.

Jiangbo


314 /***********************************************************************
315 * Reflect the packet to the sender.
316 * The code here is almost the same as what
317 * net/ipv4/netfilter/ipt_MIRROR.c did.
318 ***********************************************************************/
319 static int route_mirror(struct sk_buff *skb)
320 {
321 struct iphdr *iph = skb->nh.iph;
322 struct flowi fl = {
323 .nl_u = {
324 .ip4_u = {
325 .daddr = iph->saddr,
326 .saddr = iph->daddr,
327 .tos = RT_TOS(iph->tos) | RTO_CONN
328 }
329 }
330 };
331 struct rtable *rt;
332
333 /* Query the routing table */
334 if (ip_route_output_key(&rt, &fl)) {
335 printk("ip_route_output_key failed\n");
336 return 0;
337 }
338
339 /* check if the interface we are leaving by is the same as the
340 one we arrived on */
341 if (skb->dev != rt->u.dst.dev) {
342 printk(" check dev stuff failed\n");
343 //return 0; Seems this do happens sometimes.
344 }
345
346 /* Drop old route. */
347 dst_release(skb->dst);
348 skb->dst = &rt->u.dst;
349 return 1;
350 }
351
352 static int ip_rewrite(struct sk_buff **pskb)
353 {
354 u32 odaddr, osaddr;
355 struct sk_buff* skb=*pskb;
356
357 if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
358 return 0;
359
360 odaddr = skb->nh.iph->saddr;
361 osaddr = skb->nh.iph->daddr;
362
363 skb->nfcache |= NFC_ALTERED;
364
365 /* Rewrite IP header */
366 skb->nh.iph->daddr = odaddr;
367 skb->nh.iph->saddr = osaddr;
368
369 /* Switch the ports for some transport protocols*/
370 if ( skb->nh.iph->protocol == 6 || //6: TCP
371 skb->nh.iph->protocol == 17 || //17: UDP
372 skb->nh.iph->protocol == 113 ){ //113: PGM
373 uint16_t port; 374 port = skb->h.uh->dest;
375 skb->h.uh->dest = skb->h.uh->source;
376 skb->h.uh->source = port;
377 dbgout(DBG_MODULE, DBG_VERBOSE, ("reflect
piggybacket packet:"
378 "protocol=%d\n",skb->nh.iph->protocol ));
379 }
380 return 1;
381 }
382
383 /* Stolen from ip_finish_output2 */
384 static void ip_direct_send(struct sk_buff *skb)
385 {
386 struct dst_entry *dst = skb->dst;
387 struct hh_cache *hh = dst->hh;
388
389 if (hh) {
390 int hh_alen;
391
392 read_lock_bh(&hh->hh_lock);
393 hh_alen = HH_DATA_ALIGN(hh->hh_len);
394 memcpy(skb->data - hh_alen,
hh->hh_data, hh_alen);
395 read_unlock_bh(&hh->hh_lock);
396 skb_push(skb, hh->hh_len);
397 hh->hh_output(skb);
398 } else if (dst->neighbour)
399 dst->neighbour->output(skb);
400 else {
401 printk(KERN_DEBUG "khm in MIRROR\n");
402 kfree_skb(skb);
403 }
404 }
405
406 static unsigned int handle_reflect(struct sk_buff **pskb,
407 unsigned int hooknum)
408 {
409 struct sk_buff* skb = *pskb;
410 struct iphdr *iph = skb->nh.iph;
411
412 dbgout(DBG_MODULE, DBG_VERBOSE, ("begin the reflection\n"));
413 if ( inet_addr_type(iph->saddr) == RTN_LOCAL ){
414 //The packet will be reflected to local application.
415 //Stolen from ip_rcv_finish();
416
417 struct net_device *dev = skb->dev;
418 struct iphdr *iph = skb->nh.iph;
419
420 dbgout(DBG_RB, DBG_VERBOSE, ("Reflect to local!"
421 "skb->dev=0x%X\n",(unsigned int)dev));
422
423 if (!ip_rewrite(pskb))
424 return NF_DROP;
425
426 dst_release(skb->dst);
427 skb->dst = NULL;
428 if (ip_route_input(skb, iph->daddr,
iph->saddr, iph->tos, dev))
429 return NF_DROP;
430
431 dst_input(skb);
432 dbgout(DBG_RB, DBG_VERBOSE, ("Reflect to local
seems OK\n"));
433 return NF_STOLEN;
434
435 }else if ( route_mirror(skb) ) {
436 if (!ip_rewrite(pskb))

437 return NF_DROP;
438
439 /* If we are not at FORWARD hook (INPUT/PREROUTING),
440 * the TTL isn't decreased by the IP stack */
441 if (hooknum != NF_IP_FORWARD) {
442 if (skb->nh.iph->ttl <= 1) {
443 /* this will traverse normal stack, and
444 * thus call conntrack on the
icmp packet */
445 icmp_send(skb, ICMP_TIME_EXCEEDED,
446 ICMP_EXC_TTL, 0);
447 return NF_DROP;
448 }
449 /* Made writable by ip_rewrite */
450 ip_decrease_ttl(skb->nh.iph);
451 }
452
453 /* Don't let conntrack code see this packet:
454 it will think we are starting a new
455 connection! --RR */
456 dbgout(DBG_RB, DBG_VERBOSE, ("ip direct send
the reflection\n"));
457 ip_direct_send(skb);
458
459 return NF_STOLEN;
460 }
461 return NF_DROP;
462 }



On 4/26/06, Real Oneone <realoneone@xxxxxxxxx> wrote:
Hi, I plugged a callback function into netfilter at the hook point of
NF_IP_PRE_ROUTING, tring to capture all the packets, make
some changes to some of them, and invoke skb->dev->hard_start_xmit to
send them out directly. However, the kernel crashed before I could get
any printked information.

If you have any idea of how to send the received packets out, please tell me.

Thank you in advance.

Best regards,
Gu, Xinxing
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html

-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html