Generating a packet from IPvw
f.invernizzi at libero.it
f.invernizzi at libero.it
Wed Mar 9 14:47:45 UTC 2011
Hi all
i am trying to do something quite odd with the IPfw (FreeSD 8.1 at AMD64) for a
particular system i am trying to build.
The idea is that whenever a dynamic rule is UNLINKED from the IPfw linked
list, i want a fake packet to be generated and sent by the firewall.
In a quite simple configuration I had sucesfully done, using ip_output to send
a on-the-fly generated packet, and added a call to my function in the
UNLINK_DYN_RULE macro (ip_fw_dynamic.c ).
It looks something like:
#define UNLINK_DYN_RULE(prev, head, q) { \
ipfw_dyn_rule *old_q = q; \
/* Fabrizio */ \
ipfw_send_sv_pkt(q); \
where ipfw_send_sv_pkt(q) is
ipfw_send_sv_pkt(struct _ipfw_dyn_rule *rule)
{
#ifndef __FreeBSD__
return ;
#else
struct mbuf *m;
int len;
struct ip *h = NULL;
struct tcphdr *th = NULL;
char *payload = NULL; /* Payload */
char buf[DATI_SV_MAX_PAYLOAD]=""; /* payload */
struct ipfw_flow_id *id = &(rule->id); /* Flow id */
// Payload
sprintf(buf,"%4s%4s%12li%12li",DATI_MAGIC_STRING,DATI_SV_VERSION,rule->pcnt,
rule->bcnt);
/* Alloca un Mbuf, non aspetta se no c'e' spazio, di tipo dati dinamici */
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL)
return ;
M_SETFIB(m, id->fib);
len = sizeof(struct ip) + sizeof(struct tcphdr) + sizeof(buf);
// To be sure it fits in mbuf data space
if (len > DATI_SV_MAX_PAYLOAD){
m_freem(m);
return;
}
m->m_data += max_linkhdr;
m->m_flags |= M_SKIP_FIREWALL;
m->m_pkthdr.len = m->m_len = len;
m->m_pkthdr.rcvif = NULL;
bzero(m->m_data, len);
h = mtod(m, struct ip *);
/* prepare for checksum */
h->ip_p = IPPROTO_TCP;
h->ip_ttl = 1; /* per sicurezza, nel caso per errore uscisse */
h->ip_len = htons(sizeof(struct tcphdr));
h->ip_src.s_addr = htonl(id->src_ip);
//h->ip_dst.s_addr = htonl(id->dst_ip);
struct in_addr addr;
inet_aton("10.2.2.3", &addr);
h->ip_dst.s_addr = addr.s_addr;
th = (struct tcphdr *)(h + 1);
th->th_sport = htons(id->src_port);
th->th_dport = htons(id->dst_port);
th->th_off = sizeof(struct tcphdr) >> 2;
th->th_seq = htonl(0);
th->th_ack = htonl(0);
th->th_flags = TH_ACK; /* ??? */
th->th_sum = in_cksum(m, len);
/* finish the ip header */
h->ip_v = 4;
h->ip_hl = sizeof(*h) >> 2;
h->ip_tos = IPTOS_LOWDELAY;
h->ip_off = 0;
/* ip_len must be in host format for ip_output */
h->ip_len = len;
h->ip_ttl = V_ip_defttl;
h->ip_sum = 0;
payload = (char *)(th + 1);
strcpy(payload,buf);
/* Invia il pacchetto */
ip_output(m, NULL, NULL, 0, NULL, NULL);
#endif /* __FreeBSD__ */
}
/* end of file */
As you can see it is quite bad in some assumption and a lot controls still to
put in place, but the fact is: it does the work. I can see the packet coming
out on the first system
Now. If i try on a system with ng_ipfw and VIMAGE enabled (working on a
specific jailed workspace) the code apparently does not do anything. I have
done a lot of debugging, but with no luck.
Can someoune help me?
Thanks in advance
Fabrizio
More information about the freebsd-ipfw
mailing list