int main(int argc, char *argv[]) { char opt; int ret; int option_index; while ((opt = getopt_long(argc, argv, "d:f:i:lrs", long_options, &option_index)) >= 0) { switch (opt) { case 'f': case 'd': case 'i': flow_cmd = opt; flow_index = strtoul(optarg, NULL, 0); break; case 'l': list = 1; break; case 'r': rate = 1; break; case 's': stats = 1; break; case 0: parse_long_opts(option_index, optarg); break; default: Usage(); } } validate_options(); ret = flow_table_setup(); if (ret < 0) return ret; ret = flow_table_get(); if (ret < 0) return ret; if (list) flow_list(); else if (rate) flow_rate(); else if (stats) flow_stats(); else flow_validate(flow_index, flow_cmd); return 0; }
/* Handle linearized sk_buff post_routing */ static unsigned int post_routing_process(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out) { char* ip_pkt; char* nip_pkt; int ip_pkt_len, nip_pkt_len; int eth_vlan_hdr_len, full_pkt_len, ip_hdr_len; int err; struct sk_buff *nskb; struct ethhdr *eth_hdr; struct flow_keys flow_key; struct iphdr *ip_hdr; struct iphdr *nip_hdr; struct stack stk; void *saddr; void *daddr; __be16 proto; u32 hash; __wsum nskb_csum = 0; unsigned char dst[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; /* if(skb_is_nonlinear(skb)){ pr_debug("Non-linear skb.. linearizing...\n"); if(skb_linearize(skb)){ pr_debug("Failed to serialize!\n"); } } */ if (skb_is_nonlinear(skb)){ pr_debug("Proces_pkt: Still non-linear skb.\n"); return NF_ACCEPT; } proto = ntohs(skb->protocol); pr_debug("Proto: %04x\n", proto); switch (proto) { case ETH_P_IP: eth_hdr = (struct ethhdr *) skb_mac_header(skb); // need to set ip_hdr = (struct iphdr *) skb_network_header(skb); ip_hdr_len = ip_hdrlen(skb); ip_pkt = (char *) ip_hdr; ip_pkt_len = ntohs(ip_hdr->tot_len); pr_debug("IP pkt_len = %d IP hdr len = %d \n", ip_pkt_len, ip_hdr_len); if(skb_flow_dissect(skb, &flow_key)){ print_ip(flow_key.src); print_ip(flow_key.dst); pr_debug("Ports %d %d\n", ntohs(flow_key.port16[0]), ntohs(flow_key.port16[1])); hash = flow_keys_hash(flow_key); pr_debug("Hash: %x\n", hash); } else{ pr_debug("Failed to dissect flow\n"); return NF_ACCEPT; } //stats_entry_inc(be32_to_cpu(flow_key.dst), ip_pkt_len); pr_debug("Proto: IP pkt\nGetting stk from flow_table for %u\n", be32_to_cpu(flow_key.dst)); stk = flow_table_get(flow_table, flow_key, routing_table, be32_to_cpu(flow_key.dst)); if(stk.num_tags == -1) { // no_stack pr_debug("flow_table miss! consulting rt_table\n"); stk = get_random_stack_for_dst(be32_to_cpu(flow_key.dst), routing_table); flow_table_set(flow_table, flow_key, stk); } if(stk.num_tags < 0) { stk.num_tags=0; } eth_vlan_hdr_len = ETH_HLEN + stk.num_tags * sizeof(vlan_label); full_pkt_len = eth_vlan_hdr_len + ip_pkt_len; pr_debug("Full length: %d", full_pkt_len); // Allocate new skb nskb = alloc_skb(full_pkt_len, GFP_ATOMIC); if (nskb == NULL) { return NF_ACCEPT; } if (skb->sk != NULL) { skb_set_owner_w(nskb, skb->sk); } else { kfree_skb(nskb); return NF_ACCEPT; } pr_debug("mod_vlan: nskb - Reserving header\n"); // Reserve space for eth and vlan headers skb_reserve(nskb, eth_vlan_hdr_len); // Copy IP packet pr_debug("mod_vlan: copying IP pkt.\n"); if (!(nip_pkt = skb_put(nskb, ip_pkt_len))) { pr_debug("skb_put failed!\n"); kfree_skb(nskb); return NF_ACCEPT; } skb_reset_network_header(nskb); memcpy(nip_pkt, ip_pkt, ip_pkt_len); nip_hdr = (struct iphdr *) nip_pkt; nip_pkt_len = ntohs(nip_hdr->tot_len); nskb_csum = fix_csum(nip_hdr); // Set VLAN stack if (set_vlan_stack(nskb, &stk)) { proto = ETH_P_8021Q; } // Get outgoing interface nskb->dev = dev_get_by_name(&init_net, out->name); if (!nskb->dev) { pr_debug("mod_vlan dev_get_by_name (%s) FAILED.", out->name); kfree_skb(nskb); return NF_ACCEPT; } /* // Reduce MTU, if needed if (nskb->dev->mtu > 1500 - (4 * stk.num_tags)) { pr_debug("Setting MTU: (%s) %u", out->name, 1500 - (4 * stk.num_tags)); nskb->dev->mtu = 1500 - (4 * stk.num_tags); } pr_debug("mod_vlan dev_get_by_name success, nskb->dev->name='%s'", nskb->dev->name); */ saddr = nskb->dev->dev_addr; daddr = dst; // ARP Lookup if (get_dst_haddr(daddr, flow_key.dst, nskb->dev) != 0){ pr_debug("ARP lookup - FAILED!\n"); kfree_skb(nskb); return NF_ACCEPT; } // Set DL header print_mac(saddr); print_mac(daddr); pr_debug("calling dev_hard_header\n"); if (!dev_hard_header(nskb, nskb->dev, proto, daddr, saddr, nskb->dev->addr_len)) { pr_debug("mod_vlan dev_hard_header FAILED.\n"); kfree_skb(nskb); return NF_ACCEPT; } skb_reset_mac_header(nskb); // Set skb checksum nskb->csum = nskb_csum; // Send out packet - dev_queue_xmit will consume nskb pr_debug("mod_vlan: sending nskb....\n"); if ((err = dev_queue_xmit(nskb)) != NET_XMIT_SUCCESS) { pr_debug("mod_vlan dev_queue_xmit failed. %d\n", err); return NF_ACCEPT; } // Consume original skb consume_skb(skb); pr_debug("------ success - returning ------\n"); return NF_STOLEN; break; default: pr_debug("Proto: Non-IP pkt\n"); break; } // default: if we didn't send a new skb, then accept the original return NF_ACCEPT; }