mirror of
https://github.com/bol-van/zapret2.git
synced 2026-06-17 12:50:04 +04:00
nfqws2: handling of incoming frag, AI fixes
This commit is contained in:
@@ -228,3 +228,7 @@ nfqws2: bt and utp_bt protocol detectors
|
|||||||
nfqws2: localtime,gmtime,timelocal,timegm luacalls
|
nfqws2: localtime,gmtime,timelocal,timegm luacalls
|
||||||
winws2: load wlanapi.dll dynamically only if needed
|
winws2: load wlanapi.dll dynamically only if needed
|
||||||
winws2: fixed lost windivert deinit on logical network disappear
|
winws2: fixed lost windivert deinit on logical network disappear
|
||||||
|
|
||||||
|
0.9.3
|
||||||
|
|
||||||
|
nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ standard rawsend :
|
|||||||
|
|
||||||
standard payload :
|
standard payload :
|
||||||
|
|
||||||
* payload - comma separarated list of allowed payload types. if not present - allow non-empty known payloads.
|
* payload - comma separated list of allowed payload types. if not present - allow non-empty known payloads.
|
||||||
|
|
||||||
standard ip_id :
|
standard ip_id :
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -932,11 +932,11 @@ function apply_fooling(desync, dis, fooling_options)
|
|||||||
local bin
|
local bin
|
||||||
if fooling_options.ip6_hopbyhop then
|
if fooling_options.ip6_hopbyhop then
|
||||||
bin = prepare_bin(fooling_options.ip6_hopbyhop,"\x00\x00\x00\x00\x00\x00")
|
bin = prepare_bin(fooling_options.ip6_hopbyhop,"\x00\x00\x00\x00\x00\x00")
|
||||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
|
||||||
end
|
end
|
||||||
if fooling_options.ip6_hopbyhop2 then
|
if fooling_options.ip6_hopbyhop2 then
|
||||||
bin = prepare_bin(fooling_options.ip6_hopbyhop2,"\x00\x00\x00\x00\x00\x00")
|
bin = prepare_bin(fooling_options.ip6_hopbyhop2,"\x00\x00\x00\x00\x00\x00")
|
||||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
|
||||||
end
|
end
|
||||||
-- for possible unfragmentable part
|
-- for possible unfragmentable part
|
||||||
if fooling_options.ip6_destopt then
|
if fooling_options.ip6_destopt then
|
||||||
@@ -1094,7 +1094,7 @@ end
|
|||||||
|
|
||||||
-- option : ipfrag.ipfrag_disorder - send fragments from last to first
|
-- option : ipfrag.ipfrag_disorder - send fragments from last to first
|
||||||
function rawsend_dissect_ipfrag(dis, options)
|
function rawsend_dissect_ipfrag(dis, options)
|
||||||
if options and options.ipfrag and options.ipfrag.ipfrag then
|
if options and options.ipfrag and options.ipfrag.ipfrag and not dis.frag then
|
||||||
local frag_func = options.ipfrag.ipfrag=="" and "ipfrag2" or options.ipfrag.ipfrag
|
local frag_func = options.ipfrag.ipfrag=="" and "ipfrag2" or options.ipfrag.ipfrag
|
||||||
if type(_G[frag_func]) ~= "function" then
|
if type(_G[frag_func]) ~= "function" then
|
||||||
error("rawsend_dissect_ipfrag: ipfrag function '"..tostring(frag_func).."' does not exist")
|
error("rawsend_dissect_ipfrag: ipfrag function '"..tostring(frag_func).."' does not exist")
|
||||||
|
|||||||
+47
-32
@@ -383,9 +383,11 @@ bool proto_check_ipv4_payload(const uint8_t *data, size_t len)
|
|||||||
return len >= ntohs(((struct ip*)data)->ip_len);
|
return len >= ntohs(((struct ip*)data)->ip_len);
|
||||||
}
|
}
|
||||||
// move to transport protocol
|
// move to transport protocol
|
||||||
void proto_skip_ipv4(const uint8_t **data, size_t *len)
|
void proto_skip_ipv4(const uint8_t **data, size_t *len, bool *frag, uint16_t *frag_off)
|
||||||
{
|
{
|
||||||
uint8_t off = ((struct ip*)*data)->ip_hl << 2;
|
uint8_t off = ((struct ip*)*data)->ip_hl << 2;
|
||||||
|
if (frag_off) *frag_off = (ntohs(((struct ip*)*data)->ip_off) & IP_OFFMASK) << 3;
|
||||||
|
if (frag) *frag = ntohs(((struct ip*)*data)->ip_off) & (IP_OFFMASK|IP_MF);
|
||||||
*data += off;
|
*data += off;
|
||||||
*len -= off;
|
*len -= off;
|
||||||
}
|
}
|
||||||
@@ -434,21 +436,25 @@ bool proto_check_ipv6_payload(const uint8_t *data, size_t len)
|
|||||||
}
|
}
|
||||||
// move to transport protocol
|
// move to transport protocol
|
||||||
// proto_type = 0 => error
|
// proto_type = 0 => error
|
||||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
|
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, bool *frag, uint16_t *frag_off)
|
||||||
{
|
{
|
||||||
size_t hdrlen;
|
size_t hdrlen;
|
||||||
uint8_t HeaderType;
|
|
||||||
uint16_t plen;
|
|
||||||
struct ip6_hdr *ip6 = (struct ip6_hdr*)*data;
|
struct ip6_hdr *ip6 = (struct ip6_hdr*)*data;
|
||||||
|
uint16_t plen;
|
||||||
|
uint16_t fr_off=0;
|
||||||
|
bool fr=false;
|
||||||
|
uint8_t HeaderType;
|
||||||
|
|
||||||
if (proto_type) *proto_type = 0; // put error in advance
|
if (proto_type) *proto_type = 0; // put error in advance
|
||||||
|
if (frag) *frag = false;
|
||||||
|
if (frag_off) *frag_off = 0;
|
||||||
|
|
||||||
HeaderType = ip6->ip6_nxt;
|
HeaderType = ip6->ip6_nxt;
|
||||||
if (proto_type) *proto_type = HeaderType;
|
if (proto_type) *proto_type = HeaderType;
|
||||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||||
*data += sizeof(struct ip6_hdr); *len -= sizeof(struct ip6_hdr); // skip ipv6 base header
|
*data += sizeof(struct ip6_hdr); *len -= sizeof(struct ip6_hdr); // skip ipv6 base header
|
||||||
if (plen < *len) *len = plen;
|
if (plen < *len) *len = plen;
|
||||||
while (*len) // need at least one byte for NextHeader field
|
while (*len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
|
||||||
{
|
{
|
||||||
switch (HeaderType)
|
switch (HeaderType)
|
||||||
{
|
{
|
||||||
@@ -463,6 +469,11 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
|
|||||||
break;
|
break;
|
||||||
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
||||||
hdrlen = 8;
|
hdrlen = 8;
|
||||||
|
if (*len < hdrlen) return; // error
|
||||||
|
fr_off = ntohs(((struct ip6_frag*)*data)->ip6f_offlg & IP6F_OFF_MASK);
|
||||||
|
fr = ((struct ip6_frag*)*data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
|
||||||
|
if (frag_off) *frag_off = fr_off;
|
||||||
|
if (frag) *frag = fr;
|
||||||
break;
|
break;
|
||||||
case IPPROTO_AH:
|
case IPPROTO_AH:
|
||||||
// special case. length in ah header is in 32-bit words minus 2
|
// special case. length in ah header is in 32-bit words minus 2
|
||||||
@@ -488,8 +499,10 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
|
|||||||
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
||||||
{
|
{
|
||||||
size_t hdrlen;
|
size_t hdrlen;
|
||||||
uint8_t HeaderType, last_proto, *data;
|
|
||||||
uint16_t plen;
|
uint16_t plen;
|
||||||
|
uint8_t HeaderType, last_proto, *data;
|
||||||
|
bool fr=false;
|
||||||
|
uint16_t fr_off=0;
|
||||||
|
|
||||||
if (len<sizeof(struct ip6_hdr)) return false;
|
if (len<sizeof(struct ip6_hdr)) return false;
|
||||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||||
@@ -497,7 +510,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
|||||||
data = (uint8_t*)(ip6+1);
|
data = (uint8_t*)(ip6+1);
|
||||||
len -= sizeof(struct ip6_hdr);
|
len -= sizeof(struct ip6_hdr);
|
||||||
if (plen < len) len = plen;
|
if (plen < len) len = plen;
|
||||||
while (len) // need at least one byte for NextHeader field
|
while (len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
|
||||||
{
|
{
|
||||||
if (last_proto==proto) return data; // found
|
if (last_proto==proto) return data; // found
|
||||||
switch (last_proto)
|
switch (last_proto)
|
||||||
@@ -513,6 +526,8 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
|||||||
break;
|
break;
|
||||||
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
||||||
hdrlen = 8;
|
hdrlen = 8;
|
||||||
|
fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK);
|
||||||
|
fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
|
||||||
break;
|
break;
|
||||||
case IPPROTO_AH:
|
case IPPROTO_AH:
|
||||||
// special case. length in ah header is in 32-bit words minus 2
|
// special case. length in ah header is in 32-bit words minus 2
|
||||||
@@ -546,14 +561,14 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
|
|||||||
dis->ip = (const struct ip *) data;
|
dis->ip = (const struct ip *) data;
|
||||||
dis->proto = dis->ip->ip_p;
|
dis->proto = dis->ip->ip_p;
|
||||||
p = data;
|
p = data;
|
||||||
proto_skip_ipv4(&data, &len);
|
proto_skip_ipv4(&data, &len, &dis->frag, &dis->frag_off);
|
||||||
dis->len_l3 = data-p;
|
dis->len_l3 = data-p;
|
||||||
}
|
}
|
||||||
else if (proto_check_ipv6(data, len) && (no_payload_check || proto_check_ipv6_payload(data, len)))
|
else if (proto_check_ipv6(data, len) && (no_payload_check || proto_check_ipv6_payload(data, len)))
|
||||||
{
|
{
|
||||||
dis->ip6 = (const struct ip6_hdr *) data;
|
dis->ip6 = (const struct ip6_hdr *) data;
|
||||||
p = data;
|
p = data;
|
||||||
proto_skip_ipv6(&data, &len, &dis->proto);
|
proto_skip_ipv6(&data, &len, &dis->proto, &dis->frag, &dis->frag_off);
|
||||||
dis->len_l3 = data-p;
|
dis->len_l3 = data-p;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -562,31 +577,31 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
dis->transport_len = len;
|
dis->transport_len = len;
|
||||||
|
dis->len_l4 = 0;
|
||||||
|
|
||||||
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
if (!dis->frag)
|
||||||
{
|
{
|
||||||
dis->tcp = (const struct tcphdr *) data;
|
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
||||||
p = data;
|
{
|
||||||
proto_skip_tcp(&data, &len);
|
dis->tcp = (const struct tcphdr *) data;
|
||||||
dis->len_l4 = data-p;
|
p = data;
|
||||||
}
|
proto_skip_tcp(&data, &len);
|
||||||
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len)))
|
dis->len_l4 = data-p;
|
||||||
{
|
}
|
||||||
dis->udp = (const struct udphdr *) data;
|
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len)))
|
||||||
p = data;
|
{
|
||||||
proto_skip_udp(&data, &len);
|
dis->udp = (const struct udphdr *) data;
|
||||||
dis->len_l4 = data-p;
|
p = data;
|
||||||
}
|
proto_skip_udp(&data, &len);
|
||||||
else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len))
|
dis->len_l4 = data-p;
|
||||||
{
|
}
|
||||||
dis->icmp = (const struct icmp46 *) data;
|
else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len))
|
||||||
p = data;
|
{
|
||||||
proto_skip_icmp(&data, &len);
|
dis->icmp = (const struct icmp46 *) data;
|
||||||
dis->len_l4 = data-p;
|
p = data;
|
||||||
}
|
proto_skip_icmp(&data, &len);
|
||||||
else
|
dis->len_l4 = data-p;
|
||||||
{
|
}
|
||||||
dis->len_l4 = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dis->data_payload = data;
|
dis->data_payload = data;
|
||||||
|
|||||||
+4
-2
@@ -175,10 +175,10 @@ void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp);
|
|||||||
|
|
||||||
bool proto_check_ipv4(const uint8_t *data, size_t len);
|
bool proto_check_ipv4(const uint8_t *data, size_t len);
|
||||||
bool proto_check_ipv4_payload(const uint8_t *data, size_t len);
|
bool proto_check_ipv4_payload(const uint8_t *data, size_t len);
|
||||||
void proto_skip_ipv4(const uint8_t **data, size_t *len);
|
void proto_skip_ipv4(const uint8_t **data, size_t *len, bool *frag, uint16_t *frag_off);
|
||||||
bool proto_check_ipv6(const uint8_t *data, size_t len);
|
bool proto_check_ipv6(const uint8_t *data, size_t len);
|
||||||
bool proto_check_ipv6_payload(const uint8_t *data, size_t len);
|
bool proto_check_ipv6_payload(const uint8_t *data, size_t len);
|
||||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type);
|
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, bool *frag, uint16_t *frag_off);
|
||||||
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto);
|
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto);
|
||||||
bool proto_check_tcp(const uint8_t *data, size_t len);
|
bool proto_check_tcp(const uint8_t *data, size_t len);
|
||||||
void proto_skip_tcp(const uint8_t **data, size_t *len);
|
void proto_skip_tcp(const uint8_t **data, size_t *len);
|
||||||
@@ -203,6 +203,8 @@ struct dissect
|
|||||||
size_t transport_len;
|
size_t transport_len;
|
||||||
const uint8_t *data_payload;
|
const uint8_t *data_payload;
|
||||||
size_t len_payload;
|
size_t len_payload;
|
||||||
|
bool frag;
|
||||||
|
uint16_t frag_off;
|
||||||
};
|
};
|
||||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bool no_payload_check);
|
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bool no_payload_check);
|
||||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
|
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
|
||||||
|
|||||||
+20
-26
@@ -188,7 +188,10 @@ static void packet_debug(bool replay, const struct dissect *dis)
|
|||||||
{
|
{
|
||||||
char s_proto[16];
|
char s_proto[16];
|
||||||
str_proto_name(s_proto,sizeof(s_proto),dis->proto);
|
str_proto_name(s_proto,sizeof(s_proto),dis->proto);
|
||||||
DLOG("\nIP PROTO %s: len=%zu : ", s_proto, dis->len_payload);
|
if (dis->frag)
|
||||||
|
DLOG("\nIP FRAG off=%u PROTO %s: len=%zu : ", dis->frag_off, s_proto, dis->len_payload);
|
||||||
|
else
|
||||||
|
DLOG("\nIP PROTO %s: len=%zu : ", s_proto, dis->len_payload);
|
||||||
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
|
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
|
||||||
DLOG("\n");
|
DLOG("\n");
|
||||||
}
|
}
|
||||||
@@ -2099,36 +2102,27 @@ static uint8_t dpi_desync_packet_play(
|
|||||||
if (!!dis.ip != !!dis.ip6)
|
if (!!dis.ip != !!dis.ip6)
|
||||||
{
|
{
|
||||||
packet_debug(!!replay_piece_count, &dis);
|
packet_debug(!!replay_piece_count, &dis);
|
||||||
|
|
||||||
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
|
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
|
||||||
// modified means we have already fixed the checksum or made it invalid intentionally
|
// modified means we have already fixed the checksum or made it invalid intentionally
|
||||||
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
|
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
|
||||||
switch (dis.proto)
|
if (dis.tcp)
|
||||||
{
|
{
|
||||||
case IPPROTO_TCP:
|
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||||
if (dis.tcp)
|
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||||
{
|
|
||||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
|
||||||
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IPPROTO_UDP:
|
|
||||||
if (dis.udp)
|
|
||||||
{
|
|
||||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
|
||||||
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IPPROTO_ICMP:
|
|
||||||
case IPPROTO_ICMPV6:
|
|
||||||
if (dis.icmp)
|
|
||||||
{
|
|
||||||
verdict = dpi_desync_icmp_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
|
||||||
verdict_icmp_csum_fix(verdict, (struct icmp46 *)dis.icmp, dis.transport_len, dis.ip6);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
|
||||||
}
|
}
|
||||||
|
else if (dis.udp)
|
||||||
|
{
|
||||||
|
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||||
|
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||||
|
}
|
||||||
|
else if (dis.icmp)
|
||||||
|
{
|
||||||
|
verdict = dpi_desync_icmp_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||||
|
verdict_icmp_csum_fix(verdict, (struct icmp46 *)dis.icmp, dis.transport_len, dis.ip6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DLOG("invalid packet - neither ipv4 or ipv6\n");
|
DLOG("invalid packet - neither ipv4 or ipv6\n");
|
||||||
|
|||||||
+1
-1
@@ -114,7 +114,7 @@ const struct in6_addr *mask_from_bitcount6(uint32_t zct);
|
|||||||
#elif defined(CLOCK_UPTIME)
|
#elif defined(CLOCK_UPTIME)
|
||||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_UPTIME
|
#define CLOCK_BOOT_OR_UPTIME CLOCK_UPTIME
|
||||||
#else
|
#else
|
||||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTINIC
|
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTONIC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
time_t boottime(void);
|
time_t boottime(void);
|
||||||
|
|||||||
+160
-119
@@ -1508,9 +1508,11 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
|||||||
|
|
||||||
// assume ipv6 packet structure was already checked for validity
|
// assume ipv6 packet structure was already checked for validity
|
||||||
size_t hdrlen;
|
size_t hdrlen;
|
||||||
|
lua_Integer idx = 1;
|
||||||
uint8_t HeaderType, *data;
|
uint8_t HeaderType, *data;
|
||||||
uint16_t plen;
|
uint16_t plen;
|
||||||
lua_Integer idx = 1;
|
uint16_t fr_off=0;
|
||||||
|
bool fr=false;
|
||||||
|
|
||||||
lua_pushliteral(L, "exthdr");
|
lua_pushliteral(L, "exthdr");
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
@@ -1521,7 +1523,7 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
|||||||
len-=sizeof(struct ip6_hdr);
|
len-=sizeof(struct ip6_hdr);
|
||||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||||
if (plen < len) len = plen;
|
if (plen < len) len = plen;
|
||||||
while (len > 0) // need at least one byte for NextHeader field
|
while (len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
|
||||||
{
|
{
|
||||||
switch (HeaderType)
|
switch (HeaderType)
|
||||||
{
|
{
|
||||||
@@ -1536,6 +1538,8 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
|||||||
break;
|
break;
|
||||||
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
||||||
hdrlen = 8;
|
hdrlen = 8;
|
||||||
|
fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK);
|
||||||
|
fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
|
||||||
break;
|
break;
|
||||||
case IPPROTO_AH:
|
case IPPROTO_AH:
|
||||||
// special case. length in ah header is in 32-bit words minus 2
|
// special case. length in ah header is in 32-bit words minus 2
|
||||||
@@ -1618,17 +1622,18 @@ void lua_push_dissect(lua_State *L, const struct dissect *dis)
|
|||||||
|
|
||||||
if (dis)
|
if (dis)
|
||||||
{
|
{
|
||||||
lua_createtable(L, 0, 10);
|
lua_createtable(L, 0, 10+dis->frag);
|
||||||
lua_pushf_iphdr(L,dis->ip, dis->len_l3);
|
|
||||||
lua_pushf_ip6hdr(L,dis->ip6, dis->len_l3);
|
|
||||||
lua_pushf_tcphdr(L,dis->tcp, dis->len_l4);
|
|
||||||
lua_pushf_udphdr(L,dis->udp, dis->len_l4);
|
|
||||||
lua_pushf_icmphdr(L,dis->icmp, dis->len_l4);
|
|
||||||
lua_pushf_int(L,"l4proto",dis->proto);
|
lua_pushf_int(L,"l4proto",dis->proto);
|
||||||
lua_pushf_int(L,"transport_len",dis->transport_len);
|
lua_pushf_int(L,"transport_len",dis->transport_len);
|
||||||
lua_pushf_int(L,"l3_len",dis->len_l3);
|
lua_pushf_int(L,"l3_len",dis->len_l3);
|
||||||
lua_pushf_int(L,"l4_len",dis->len_l4);
|
lua_pushf_int(L,"l4_len",dis->len_l4);
|
||||||
lua_pushf_raw(L,"payload",dis->data_payload,dis->len_payload);
|
lua_pushf_raw(L,"payload",dis->data_payload,dis->len_payload);
|
||||||
|
if (dis->frag) lua_pushf_int(L,"frag_off",dis->frag_off);
|
||||||
|
lua_pushf_iphdr(L,dis->ip, dis->len_l3);
|
||||||
|
lua_pushf_ip6hdr(L,dis->ip6, dis->len_l3);
|
||||||
|
lua_pushf_tcphdr(L,dis->tcp, dis->len_l4);
|
||||||
|
lua_pushf_udphdr(L,dis->udp, dis->len_l4);
|
||||||
|
lua_pushf_icmphdr(L,dis->icmp, dis->len_l4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
@@ -2383,11 +2388,24 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
|||||||
struct udphdr *udp=NULL;
|
struct udphdr *udp=NULL;
|
||||||
struct icmp46 *icmp=NULL;
|
struct icmp46 *icmp=NULL;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
bool frag;
|
||||||
|
|
||||||
LUA_STACK_GUARD_ENTER(L)
|
LUA_STACK_GUARD_ENTER(L)
|
||||||
|
|
||||||
idx = lua_absindex(L, idx);
|
idx = lua_absindex(L, idx);
|
||||||
|
|
||||||
|
lua_getfield(L,idx,"frag_off");
|
||||||
|
if (lua_type(L,-1)!=LUA_TNIL)
|
||||||
|
{
|
||||||
|
luaL_checkinteger(L,-1); // verify type
|
||||||
|
frag = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
frag = false;
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
if (frag) ip6_preserve_next = true; // there's no other source of next. no tcp, no udp, no icmp headers. just raw ip payload
|
||||||
|
|
||||||
lua_getfield(L,idx,"ip");
|
lua_getfield(L,idx,"ip");
|
||||||
l = left;
|
l = left;
|
||||||
if (lua_type(L,-1)==LUA_TTABLE)
|
if (lua_type(L,-1)==LUA_TTABLE)
|
||||||
@@ -2416,150 +2434,173 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
|||||||
data+=l; left-=l;
|
data+=l; left-=l;
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_getfield(L,idx,"tcp");
|
if (frag)
|
||||||
l=0;
|
|
||||||
if (lua_type(L,-1)==LUA_TTABLE)
|
|
||||||
{
|
{
|
||||||
l = left;
|
lua_getfield(L,idx,"payload");
|
||||||
tcp = (struct tcphdr*)data;
|
p = lua_tolstring(L,-1,&lpayload);
|
||||||
if (!lua_reconstruct_tcphdr(L, -1, tcp, &l))
|
if (p)
|
||||||
{
|
{
|
||||||
DLOG_ERR("reconstruct_dissect: bad tcp\n");
|
if (lpayload>0xFFFF)
|
||||||
goto err;
|
{
|
||||||
|
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (left<lpayload) goto err;
|
||||||
|
memcpy(data,p,lpayload);
|
||||||
|
data+=lpayload; left-=lpayload;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
lpayload = 0;
|
||||||
|
lua_pop(L, 1);
|
||||||
|
l = data-buf;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lua_pop(L, 1);
|
lua_getfield(L,idx,"tcp");
|
||||||
lua_getfield(L,idx,"udp");
|
l=0;
|
||||||
if (lua_type(L,-1)==LUA_TTABLE)
|
if (lua_type(L,-1)==LUA_TTABLE)
|
||||||
{
|
{
|
||||||
l = sizeof(struct udphdr);
|
l = left;
|
||||||
udp = (struct udphdr*)data;
|
tcp = (struct tcphdr*)data;
|
||||||
if (!lua_reconstruct_udphdr(L, -1, udp))
|
if (!lua_reconstruct_tcphdr(L, -1, tcp, &l))
|
||||||
{
|
{
|
||||||
DLOG_ERR("reconstruct_dissect: bad udp\n");
|
DLOG_ERR("reconstruct_dissect: bad tcp\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
lua_getfield(L,idx,"icmp");
|
lua_getfield(L,idx,"udp");
|
||||||
if (lua_type(L,-1)==LUA_TTABLE)
|
if (lua_type(L,-1)==LUA_TTABLE)
|
||||||
{
|
{
|
||||||
l = sizeof(struct icmp46);
|
l = sizeof(struct udphdr);
|
||||||
icmp = (struct icmp46*)data;
|
udp = (struct udphdr*)data;
|
||||||
if (!lua_reconstruct_icmphdr(L, -1, icmp))
|
if (!lua_reconstruct_udphdr(L, -1, udp))
|
||||||
{
|
{
|
||||||
DLOG_ERR("reconstruct_dissect: bad icmp\n");
|
DLOG_ERR("reconstruct_dissect: bad udp\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lua_getfield(L,idx,"icmp");
|
||||||
|
if (lua_type(L,-1)==LUA_TTABLE)
|
||||||
|
{
|
||||||
|
l = sizeof(struct icmp46);
|
||||||
|
icmp = (struct icmp46*)data;
|
||||||
|
if (!lua_reconstruct_icmphdr(L, -1, icmp))
|
||||||
|
{
|
||||||
|
DLOG_ERR("reconstruct_dissect: bad icmp\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
data+=l; left-=l;
|
||||||
data+=l; left-=l;
|
lua_pop(L, 1);
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
lua_getfield(L,idx,"payload");
|
lua_getfield(L,idx,"payload");
|
||||||
p = lua_tolstring(L,-1,&lpayload);
|
p = lua_tolstring(L,-1,&lpayload);
|
||||||
if (p)
|
if (p)
|
||||||
{
|
|
||||||
if (lpayload>0xFFFF)
|
|
||||||
{
|
{
|
||||||
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
if (lpayload>0xFFFF)
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (left<lpayload) goto err;
|
|
||||||
memcpy(data,p,lpayload);
|
|
||||||
data+=lpayload; left-=lpayload;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lpayload = 0;
|
|
||||||
lua_pop(L, 1);
|
|
||||||
|
|
||||||
l = data-buf;
|
|
||||||
|
|
||||||
if (!keepsum)
|
|
||||||
{
|
|
||||||
if (tcp)
|
|
||||||
{
|
|
||||||
tcp_fix_checksum(tcp,l-l3,ip,ip6);
|
|
||||||
if (badsum) tcp->th_sum ^= 1 + (random() % 0xFFFF);
|
|
||||||
}
|
|
||||||
else if (udp)
|
|
||||||
{
|
|
||||||
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
|
|
||||||
if (sz>0xFFFF)
|
|
||||||
{
|
{
|
||||||
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
udp->uh_ulen = htons((uint16_t)sz);
|
if (left<lpayload) goto err;
|
||||||
udp_fix_checksum(udp,l-l3,ip,ip6);
|
memcpy(data,p,lpayload);
|
||||||
if (badsum) udp->uh_sum ^= 1 + (random() % 0xFFFF);
|
data+=lpayload; left-=lpayload;
|
||||||
}
|
}
|
||||||
else if (icmp)
|
else
|
||||||
|
lpayload = 0;
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
l = data-buf;
|
||||||
|
|
||||||
|
if (!keepsum)
|
||||||
{
|
{
|
||||||
icmp_fix_checksum(icmp,l-l3,ip6);
|
if (tcp)
|
||||||
if (badsum) icmp->icmp_cksum ^= 1 + (random() % 0xFFFF);
|
{
|
||||||
|
tcp_fix_checksum(tcp,l-l3,ip,ip6);
|
||||||
|
if (badsum) tcp->th_sum ^= 1 + (random() % 0xFFFF);
|
||||||
|
}
|
||||||
|
else if (udp)
|
||||||
|
{
|
||||||
|
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
|
||||||
|
if (sz>0xFFFF)
|
||||||
|
{
|
||||||
|
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
udp->uh_ulen = htons((uint16_t)sz);
|
||||||
|
udp_fix_checksum(udp,l-l3,ip,ip6);
|
||||||
|
if (badsum) udp->uh_sum ^= 1 + (random() % 0xFFFF);
|
||||||
|
}
|
||||||
|
else if (icmp)
|
||||||
|
{
|
||||||
|
icmp_fix_checksum(icmp,l-l3,ip6);
|
||||||
|
if (badsum) icmp->icmp_cksum ^= 1 + (random() % 0xFFFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ip)
|
||||||
|
{
|
||||||
|
if (ntohs(ip->ip_off) & (IP_OFFMASK|IP_MF))
|
||||||
|
{
|
||||||
|
// fragmentation. caller should set ip_len, ip_off and IP_MF correctly. C code moves and shrinks constructed ip payload
|
||||||
|
uint16_t iplen = ntohs(ip->ip_len);
|
||||||
|
uint16_t off = (ntohs(ip->ip_off) & IP_OFFMASK)<<3;
|
||||||
|
size_t frag_start = l3 + off;
|
||||||
|
if (iplen<l3 || iplen>l)
|
||||||
|
{
|
||||||
|
DLOG_ERR("ipv4 frag : invalid ip_len\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (frag_start>l)
|
||||||
|
{
|
||||||
|
DLOG_ERR("ipv4 frag : fragment offset is outside of the packet\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (off) memmove(buf+l3,buf+l3+off,iplen-l3);
|
||||||
|
l = iplen; // shrink packet to iplen
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ip->ip_len = htons((uint16_t)l);
|
||||||
|
ip4_fix_checksum(ip);
|
||||||
|
}
|
||||||
|
else if (ip6)
|
||||||
|
{
|
||||||
|
// data points to reconstructed packet's end
|
||||||
|
uint8_t *frag = proto_find_ip6_exthdr(ip6, l, IPPROTO_FRAGMENT);
|
||||||
|
if (frag)
|
||||||
|
{
|
||||||
|
uint16_t plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); // without ipv6 base header
|
||||||
|
uint16_t off = ntohs(((struct ip6_frag *)frag)->ip6f_offlg) & 0xFFF8;
|
||||||
|
uint8_t *endfrag = frag + 8;
|
||||||
|
size_t size_unfragmentable = endfrag - (uint8_t*)ip6 - sizeof(struct ip6_hdr);
|
||||||
|
|
||||||
|
if (size_unfragmentable > plen)
|
||||||
|
{
|
||||||
|
DLOG_ERR("ipv6 frag : invalid ip6_plen\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
size_t size_fragmentable = plen - size_unfragmentable;
|
||||||
|
if ((endfrag + off + size_fragmentable) > data)
|
||||||
|
{
|
||||||
|
DLOG_ERR("ipv6 frag : fragmentable part is outside of the packet\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (off) memmove(endfrag, endfrag + off, size_fragmentable);
|
||||||
|
l = sizeof(struct ip6_hdr) + plen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons((uint16_t)(l-sizeof(struct ip6_hdr)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip)
|
|
||||||
{
|
|
||||||
if (ntohs(ip->ip_off) & (IP_OFFMASK|IP_MF))
|
|
||||||
{
|
|
||||||
// fragmentation. caller should set ip_len, ip_off and IP_MF correctly. C code moves and shrinks constructed ip payload
|
|
||||||
uint16_t iplen = ntohs(ip->ip_len);
|
|
||||||
uint16_t off = (ntohs(ip->ip_off) & IP_OFFMASK)<<3;
|
|
||||||
size_t frag_start = l3 + off;
|
|
||||||
if (iplen<l3 || iplen>l)
|
|
||||||
{
|
|
||||||
DLOG_ERR("ipv4 frag : invalid ip_len\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (frag_start>l)
|
|
||||||
{
|
|
||||||
DLOG_ERR("ipv4 frag : fragment offset is outside of the packet\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (off) memmove(buf+l3,buf+l3+off,iplen-l3);
|
|
||||||
l = iplen; // shrink packet to iplen
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ip->ip_len = htons((uint16_t)l);
|
|
||||||
ip4_fix_checksum(ip);
|
|
||||||
}
|
|
||||||
else if (ip6)
|
|
||||||
{
|
|
||||||
// data points to reconstructed packet's end
|
|
||||||
uint8_t *frag = proto_find_ip6_exthdr(ip6, l, IPPROTO_FRAGMENT);
|
|
||||||
if (frag)
|
|
||||||
{
|
|
||||||
uint16_t plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); // without ipv6 base header
|
|
||||||
uint16_t off = ntohs(((struct ip6_frag *)frag)->ip6f_offlg) & 0xFFF8;
|
|
||||||
uint8_t *endfrag = frag + 8;
|
|
||||||
size_t size_unfragmentable = endfrag - (uint8_t*)ip6 - sizeof(struct ip6_hdr);
|
|
||||||
|
|
||||||
if (size_unfragmentable > plen)
|
|
||||||
{
|
|
||||||
DLOG_ERR("ipv6 frag : invalid ip6_plen\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
size_t size_fragmentable = plen - size_unfragmentable;
|
|
||||||
if ((endfrag + off + size_fragmentable) > data)
|
|
||||||
{
|
|
||||||
DLOG_ERR("ipv6 frag : fragmentable part is outside of the packet\n");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (off) memmove(endfrag, endfrag + off, size_fragmentable);
|
|
||||||
l = sizeof(struct ip6_hdr) + plen;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons((uint16_t)(l-sizeof(struct ip6_hdr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
*len = l;
|
*len = l;
|
||||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+36
-16
@@ -327,37 +327,57 @@ void daemonize(void)
|
|||||||
int pid;
|
int pid;
|
||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
|
|
||||||
if (!getcwd(cwd, sizeof(cwd))) *cwd=0;
|
if (!getcwd(cwd, sizeof(cwd)))
|
||||||
|
{
|
||||||
|
DLOG_PERROR("getcwd");
|
||||||
|
*cwd=0;
|
||||||
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
{
|
{
|
||||||
DLOG_PERROR("fork");
|
DLOG_PERROR("fork");
|
||||||
exit(2);
|
exit(20);
|
||||||
}
|
}
|
||||||
else if (pid != 0)
|
else if (pid != 0)
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
if (*cwd)
|
if (*cwd && chdir(cwd)<0)
|
||||||
{
|
DLOG_PERROR("chdir");
|
||||||
int res = chdir(cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setsid() == -1)
|
if (setsid() == -1)
|
||||||
exit(2);
|
{
|
||||||
if (chdir("/") == -1)
|
DLOG_PERROR("setsid");
|
||||||
exit(2);
|
exit(21);
|
||||||
close(STDIN_FILENO);
|
}
|
||||||
close(STDOUT_FILENO);
|
if (close(STDIN_FILENO)<0 || close(STDOUT_FILENO)<0 || close(STDERR_FILENO)<0)
|
||||||
close(STDERR_FILENO);
|
{
|
||||||
|
// will work only if debug not to console
|
||||||
|
DLOG_PERROR("close");
|
||||||
|
exit(22);
|
||||||
|
}
|
||||||
/* redirect fd's 0,1,2 to /dev/null */
|
/* redirect fd's 0,1,2 to /dev/null */
|
||||||
open("/dev/null", O_RDWR);
|
|
||||||
int fd;
|
|
||||||
/* stdin */
|
/* stdin */
|
||||||
fd = dup(0);
|
if (open("/dev/null", O_RDWR)<0)
|
||||||
|
{
|
||||||
|
// will work only if debug not to console
|
||||||
|
DLOG_PERROR("open(stdin)");
|
||||||
|
exit(23);
|
||||||
|
}
|
||||||
/* stdout */
|
/* stdout */
|
||||||
fd = dup(0);
|
if (dup(0)<0)
|
||||||
|
{
|
||||||
|
// will work only if debug not to console
|
||||||
|
DLOG_PERROR("dup(stdout)");
|
||||||
|
exit(24);
|
||||||
|
}
|
||||||
/* stderror */
|
/* stderror */
|
||||||
|
if (dup(0)<0)
|
||||||
|
{
|
||||||
|
// will work only if debug not to console
|
||||||
|
DLOG_PERROR("dup(stderr)");
|
||||||
|
exit(25);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool writepid(const char *filename)
|
bool writepid(const char *filename)
|
||||||
|
|||||||
Reference in New Issue
Block a user