static int sc_data_fixup(const struct ip_ct_sc_expect *exp_sc_info, struct ip_conntrack *ct, unsigned int datalen, struct sk_buff **pskb, enum ip_conntrack_info ctinfo) { u_int32_t newip; struct iphdr *iph = (*pskb)->nh.iph; struct tcphdr *tcph = (void *)iph + iph->ihl*4; u_int16_t port, new_port; struct ip_conntrack_tuple tuple; struct sc_ip_port_data *list_t=sc_list; int ret=0; /* Don't care about source port */ const struct ip_conntrack_tuple mask = { { 0xFFFFFFFF, { 0xFFFFFFFF } }, { 0x0, { 0xFFFF }, 0xFFFF } }; memset(&tuple, 0, sizeof(tuple)); MUST_BE_LOCKED(&ip_sc_lock); #if 0 DEBUGP("SC_NAT: seq %u + %u in %u + %u\n", exp_sc_info->seq, exp_sc_info->len, ntohl(tcph->seq), datalen); #endif /* Change address inside packet to match way we're mapping this connection. */ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; DEBUGP("sc_data_fixup: %u.%u.%u.%u->%u.%u.%u.%u\n", NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip), NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip)); /* Expect something from server->client */ tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; tuple.dst.protonum = IPPROTO_UDP; jiq_task.routine = open_sc_socket; memset(task_data, 0, 64); sprintf(task_data,"IP:%u.%u.%u.%uPORT:%dEND",NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip), port); jiq_task.data = (void *)task_data; schedule_task(&jiq_task); if (!mangle_packet(pskb, newip, exp_sc_info->seq - ntohl(tcph->seq), exp_sc_info->len, ct, ctinfo)) return 0; return 1; }
static int mangle_packet(struct sk_buff **pskb, u_int32_t newip, unsigned int matchoff, unsigned int matchlen, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { unsigned char buffer[4]; MUST_BE_LOCKED(&ip_sc_lock); *((u_int32_t *)(buffer)) = htonl(newip); DEBUGP("calling ip_nat_mangle_tcp_packet\n"); return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, matchlen, buffer, 4); }
static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info, struct ip_conntrack *ct, struct sk_buff **pskb, enum ip_conntrack_info ctinfo, struct ip_conntrack_expect *expect) { u_int32_t newip; struct ip_conntrack_tuple t; struct iphdr *iph = (*pskb)->nh.iph; struct tcphdr *tcph = (void *) iph + iph->ihl * 4; int port; /* "4294967296 65635 " */ char buffer[18]; MUST_BE_LOCKED(&ip_irc_lock); DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n", expect->seq, ct_irc_info->len, ntohl(tcph->seq)); newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; /* Alter conntrack's expectations. */ /* We can read expect here without conntrack lock, since it's only set in ip_conntrack_irc, with ip_irc_lock held writable */ t = expect->tuple; t.dst.ip = newip; for (port = ct_irc_info->port; port != 0; port++) { t.dst.u.tcp.port = htons(port); if (ip_conntrack_change_expect(expect, &t) == 0) { DEBUGP("using port %d", port); break; } } if (port == 0) return 0; /* strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27 * strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28 * strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26 * strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26 * strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27 * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits, * 255.255.255.255==4294967296, 10 digits) * P: bound port (min 1 d, max 5d (65635)) * F: filename (min 1 d ) * S: size (min 1 d ) * 0x01, \n: terminators */ sprintf(buffer, "%u %u", ntohl(newip), port); DEBUGP("ip_nat_irc: Inserting '%s' == %u.%u.%u.%u, port %u\n", buffer, NIPQUAD(newip), port); return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, expect->seq - ntohl(tcph->seq), ct_irc_info->len, buffer, strlen(buffer)); }