From bd7a40f5a9bacb569c21e22ce7db20e7e44655f3 Mon Sep 17 00:00:00 2001 From: bol-van Date: Sat, 7 Feb 2026 13:31:10 +0300 Subject: [PATCH] nfqws2: handling of incoming frag, AI fixes --- docs/changes.txt | 4 + lua/zapret-antidpi.lua | 2 +- lua/zapret-lib.lua | 6 +- nfq2/darkmagic.c | 79 +++++++----- nfq2/darkmagic.h | 6 +- nfq2/desync.c | 46 +++---- nfq2/helpers.h | 2 +- nfq2/lua.c | 279 +++++++++++++++++++++++------------------ nfq2/sec.c | 52 +++++--- 9 files changed, 276 insertions(+), 200 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 69ef17e..aa1d288 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -228,3 +228,7 @@ nfqws2: bt and utp_bt protocol detectors nfqws2: localtime,gmtime,timelocal,timegm luacalls winws2: load wlanapi.dll dynamically only if needed winws2: fixed lost windivert deinit on logical network disappear + +0.9.3 + +nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload) diff --git a/lua/zapret-antidpi.lua b/lua/zapret-antidpi.lua index 3000f51..19ec66c 100644 --- a/lua/zapret-antidpi.lua +++ b/lua/zapret-antidpi.lua @@ -54,7 +54,7 @@ standard rawsend : 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 : diff --git a/lua/zapret-lib.lua b/lua/zapret-lib.lua index 1c6f917..c7588f0 100644 --- a/lua/zapret-lib.lua +++ b/lua/zapret-lib.lua @@ -932,11 +932,11 @@ function apply_fooling(desync, dis, fooling_options) local bin if fooling_options.ip6_hopbyhop then 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 if fooling_options.ip6_hopbyhop2 then 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 -- for possible unfragmentable part if fooling_options.ip6_destopt then @@ -1094,7 +1094,7 @@ end -- option : ipfrag.ipfrag_disorder - send fragments from last to first 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 if type(_G[frag_func]) ~= "function" then error("rawsend_dissect_ipfrag: ipfrag function '"..tostring(frag_func).."' does not exist") diff --git a/nfq2/darkmagic.c b/nfq2/darkmagic.c index 60882c2..310f7f8 100644 --- a/nfq2/darkmagic.c +++ b/nfq2/darkmagic.c @@ -383,9 +383,11 @@ bool proto_check_ipv4_payload(const uint8_t *data, size_t len) return len >= ntohs(((struct ip*)data)->ip_len); } // 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; + 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; *len -= off; } @@ -434,21 +436,25 @@ bool proto_check_ipv6_payload(const uint8_t *data, size_t len) } // move to transport protocol // 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; - uint8_t HeaderType; - uint16_t plen; 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 (frag) *frag = false; + if (frag_off) *frag_off = 0; HeaderType = ip6->ip6_nxt; if (proto_type) *proto_type = HeaderType; plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); *data += sizeof(struct ip6_hdr); *len -= sizeof(struct ip6_hdr); // skip ipv6 base header 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) { @@ -463,6 +469,11 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type) break; case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved 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; case IPPROTO_AH: // 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) { size_t hdrlen; - uint8_t HeaderType, last_proto, *data; uint16_t plen; + uint8_t HeaderType, last_proto, *data; + bool fr=false; + uint16_t fr_off=0; if (lenip6_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); len -= sizeof(struct ip6_hdr); 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 switch (last_proto) @@ -513,6 +526,8 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto) break; case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved 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; case IPPROTO_AH: // 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->proto = dis->ip->ip_p; p = data; - proto_skip_ipv4(&data, &len); + proto_skip_ipv4(&data, &len, &dis->frag, &dis->frag_off); dis->len_l3 = data-p; } else if (proto_check_ipv6(data, len) && (no_payload_check || proto_check_ipv6_payload(data, len))) { dis->ip6 = (const struct ip6_hdr *) 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; } 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->len_l4 = 0; - if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len)) + if (!dis->frag) { - dis->tcp = (const struct tcphdr *) data; - p = data; - proto_skip_tcp(&data, &len); - dis->len_l4 = data-p; - } - else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len))) - { - dis->udp = (const struct udphdr *) data; - p = data; - proto_skip_udp(&data, &len); - dis->len_l4 = data-p; - } - else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len)) - { - dis->icmp = (const struct icmp46 *) data; - p = data; - proto_skip_icmp(&data, &len); - dis->len_l4 = data-p; - } - else - { - dis->len_l4 = 0; + if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len)) + { + dis->tcp = (const struct tcphdr *) data; + p = data; + proto_skip_tcp(&data, &len); + dis->len_l4 = data-p; + } + else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len))) + { + dis->udp = (const struct udphdr *) data; + p = data; + proto_skip_udp(&data, &len); + dis->len_l4 = data-p; + } + else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len)) + { + dis->icmp = (const struct icmp46 *) data; + p = data; + proto_skip_icmp(&data, &len); + dis->len_l4 = data-p; + } } dis->data_payload = data; diff --git a/nfq2/darkmagic.h b/nfq2/darkmagic.h index ff9de31..6fca51d 100644 --- a/nfq2/darkmagic.h +++ b/nfq2/darkmagic.h @@ -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_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_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); bool proto_check_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; const uint8_t *data_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 reverse_ip(struct ip *ip, struct ip6_hdr *ip6); diff --git a/nfq2/desync.c b/nfq2/desync.c index b0ad6c8..a348307 100644 --- a/nfq2/desync.c +++ b/nfq2/desync.c @@ -188,7 +188,10 @@ static void packet_debug(bool replay, const struct dissect *dis) { char s_proto[16]; 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); DLOG("\n"); } @@ -2099,36 +2102,27 @@ static uint8_t dpi_desync_packet_play( if (!!dis.ip != !!dis.ip6) { packet_debug(!!replay_piece_count, &dis); + // 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 // 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: - if (dis.tcp) - { - 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); + 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); } + 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 DLOG("invalid packet - neither ipv4 or ipv6\n"); diff --git a/nfq2/helpers.h b/nfq2/helpers.h index 01fc78b..ac49e65 100644 --- a/nfq2/helpers.h +++ b/nfq2/helpers.h @@ -114,7 +114,7 @@ const struct in6_addr *mask_from_bitcount6(uint32_t zct); #elif defined(CLOCK_UPTIME) #define CLOCK_BOOT_OR_UPTIME CLOCK_UPTIME #else -#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTINIC +#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTONIC #endif time_t boottime(void); diff --git a/nfq2/lua.c b/nfq2/lua.c index 74acd57..6707509 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -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 size_t hdrlen; + lua_Integer idx = 1; uint8_t HeaderType, *data; uint16_t plen; - lua_Integer idx = 1; + uint16_t fr_off=0; + bool fr=false; lua_pushliteral(L, "exthdr"); 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); plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_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) { @@ -1536,6 +1538,8 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len) break; case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved 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; case IPPROTO_AH: // 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) { - lua_createtable(L, 0, 10); - 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_createtable(L, 0, 10+dis->frag); lua_pushf_int(L,"l4proto",dis->proto); lua_pushf_int(L,"transport_len",dis->transport_len); lua_pushf_int(L,"l3_len",dis->len_l3); lua_pushf_int(L,"l4_len",dis->len_l4); 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 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 icmp46 *icmp=NULL; const char *p; + bool frag; LUA_STACK_GUARD_ENTER(L) 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"); l = left; 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; lua_pop(L, 1); - lua_getfield(L,idx,"tcp"); - l=0; - if (lua_type(L,-1)==LUA_TTABLE) + if (frag) { - l = left; - tcp = (struct tcphdr*)data; - if (!lua_reconstruct_tcphdr(L, -1, tcp, &l)) + lua_getfield(L,idx,"payload"); + p = lua_tolstring(L,-1,&lpayload); + if (p) { - DLOG_ERR("reconstruct_dissect: bad tcp\n"); - goto err; + if (lpayload>0xFFFF) + { + DLOG_ERR("reconstruct_dissect: invalid payload length\n"); + goto err; + } + if (left0xFFFF) + lua_getfield(L,idx,"payload"); + p = lua_tolstring(L,-1,&lpayload); + if (p) { - DLOG_ERR("reconstruct_dissect: invalid payload length\n"); - goto err; - } - if (leftth_sum ^= 1 + (random() % 0xFFFF); - } - else if (udp) - { - sz = (uint16_t)(lpayload+sizeof(struct udphdr)); - if (sz>0xFFFF) + if (lpayload>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); + if (lefticmp_cksum ^= 1 + (random() % 0xFFFF); + 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"); + 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 (iplenl) + { + 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 (iplenl) - { - 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; LUA_STACK_GUARD_LEAVE(L, 0) return true; diff --git a/nfq2/sec.c b/nfq2/sec.c index 506625f..3a01cab 100644 --- a/nfq2/sec.c +++ b/nfq2/sec.c @@ -327,37 +327,57 @@ void daemonize(void) int pid; char cwd[PATH_MAX]; - if (!getcwd(cwd, sizeof(cwd))) *cwd=0; + if (!getcwd(cwd, sizeof(cwd))) + { + DLOG_PERROR("getcwd"); + *cwd=0; + } pid = fork(); if (pid == -1) { DLOG_PERROR("fork"); - exit(2); + exit(20); } else if (pid != 0) exit(0); - if (*cwd) - { - int res = chdir(cwd); - } + if (*cwd && chdir(cwd)<0) + DLOG_PERROR("chdir"); if (setsid() == -1) - exit(2); - if (chdir("/") == -1) - exit(2); - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); + { + DLOG_PERROR("setsid"); + exit(21); + } + if (close(STDIN_FILENO)<0 || close(STDOUT_FILENO)<0 || close(STDERR_FILENO)<0) + { + // will work only if debug not to console + DLOG_PERROR("close"); + exit(22); + } /* redirect fd's 0,1,2 to /dev/null */ - open("/dev/null", O_RDWR); - int fd; /* 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 */ - fd = dup(0); + if (dup(0)<0) + { + // will work only if debug not to console + DLOG_PERROR("dup(stdout)"); + exit(24); + } /* stderror */ + if (dup(0)<0) + { + // will work only if debug not to console + DLOG_PERROR("dup(stderr)"); + exit(25); + } } bool writepid(const char *filename)