Skip to content

Commit

Permalink
refact 1/2
Browse files Browse the repository at this point in the history
  • Loading branch information
beraldoleal committed Jun 2, 2013
1 parent bfedf30 commit 157a17b
Showing 1 changed file with 138 additions and 118 deletions.
256 changes: 138 additions & 118 deletions proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,171 +23,191 @@

struct netsfs_skb_info {
struct work_struct my_work;
char mac_name[8];
char network_name[6];
int len;
struct sk_buff *skb;
};


/* Return the Ethernet Packet "Type" field in string.
*/
const char *get_ether_type(struct sk_buff *skb) {
switch (ntohs(eth_hdr(skb)->h_proto))
{
case ETH_P_IP:
return "ipv4";
break;
case ETH_P_IPV6:
return "ipv6";
break;
default:
return "unknow";
break;
}
}


const char *get_ipv4_protocol(struct sk_buff *skb) {
switch (ip_hdr(skb)->protocol)
{
case IPPROTO_IP:
return "ip";
break;
case IPPROTO_ICMP:
return "icmp";
break;
case IPPROTO_IGMP:
return "igmp";
break;
case IPPROTO_IPIP:
return "ipip";
break;
case IPPROTO_TCP:
return "tcp";
break;
case IPPROTO_UDP:
return "udp";
break;
case IPPROTO_IPV6:
return "ipv6"; /* ipv6 over ipv4 */
break;
case IPPROTO_SCTP:
return "sctp";
break;
case IPPROTO_RAW:
return "raw";
break;
default:
return "unknow";
break;
}
}

const char *get_ipv6_protocol(struct sk_buff *skb) {
switch (ipv6_hdr(skb)->nexthdr)
{
case NEXTHDR_HOP:
return "hop";
break;
case NEXTHDR_TCP:
return "tcp";
break;
case NEXTHDR_UDP:
return "udp";
break;
case NEXTHDR_IPV6:
return "ipv6";
break;
case NEXTHDR_ICMP:
return "icmp";
break;
default:
return "unknow";
break;
}
}

/* Return the IP "protocol" field in string.
*/
const char *get_ip_protocol(struct sk_buff *skb) {

switch (ntohs(eth_hdr(skb)->h_proto))
{
case ETH_P_IP:
return get_ipv4_protocol(skb);
case ETH_P_IPV6:
return get_ipv6_protocol(skb);
default:
return NULL;
break;
}
}

/* Return skb len.
*/
unsigned int get_skb_len(struct sk_buff *skb) {
return skb->len;
}

/* Top Halve.
* Work scheduled earlier is done now, here.
*/
// TODO: REFACT
static void netsfs_go(struct work_struct *work)
{
struct netsfs_skb_info *netsfsinfo;
struct dentry *mac_dentry, *network_dentry, *network_stats_dentry;
struct dentry *mac_dentry, *network_dentry, *stats_dentry;
unsigned int len;

netsfsinfo = container_of(work, struct netsfs_skb_info, my_work);

//printk("Worker: %s %s %d\n", netsfsinfo->mac_name, netsfsinfo->network_name, netsfsinfo->len);

/* Create mac dir */
netsfs_create_by_name(netsfsinfo->mac_name, S_IFDIR, NULL, &mac_dentry, NULL, NETSFS_DIR);
/* Create top level stats and stream files */
netsfs_create_by_name("stats", S_IFREG, NULL, &network_stats_dentry, NULL, NETSFS_STATS);
netsfs_create_by_name("stream", S_IFREG, NULL, &network_stats_dentry, NULL, NETSFS_STREAM);
netsfs_create_by_name(get_ether_type(netsfsinfo->skb), S_IFDIR, NULL, &mac_dentry, NULL, NETSFS_DIR);
netsfs_create_by_name("stats", S_IFREG, NULL, &stats_dentry, NULL, NETSFS_STATS);
netsfs_create_by_name("stream", S_IFREG, NULL, &stats_dentry, NULL, NETSFS_STREAM);

if (mac_dentry) {
netsfs_create_by_name("stats", S_IFREG, mac_dentry, &network_stats_dentry, NULL, NETSFS_STATS);
netsfs_create_by_name("stream", S_IFREG, mac_dentry, &network_stats_dentry, NULL, NETSFS_STREAM);
netsfs_create_by_name(netsfsinfo->network_name, S_IFDIR, mac_dentry, &network_dentry, NULL, NETSFS_DIR);
netsfs_create_by_name("stats", S_IFREG, mac_dentry, &stats_dentry, NULL, NETSFS_STATS);
netsfs_create_by_name("stream", S_IFREG, mac_dentry, &stats_dentry, NULL, NETSFS_STREAM);
netsfs_create_by_name(get_ip_protocol(netsfsinfo->skb), S_IFDIR, mac_dentry, &network_dentry, NULL, NETSFS_DIR);
if (network_dentry) {
netsfs_create_by_name("stats", S_IFREG, network_dentry, &network_stats_dentry, NULL, NETSFS_STATS);
netsfs_create_by_name("stream", S_IFREG, network_dentry, &network_stats_dentry, NULL, NETSFS_STREAM);
netsfs_create_by_name("stats", S_IFREG, network_dentry, &stats_dentry, NULL, NETSFS_STATS);
netsfs_create_by_name("stream", S_IFREG, network_dentry, &stats_dentry, NULL, NETSFS_STREAM);
}
}

/* Increment size of inode */
netsfs_inc_inode_size(mac_dentry->d_parent->d_inode, netsfsinfo->len);
netsfs_inc_inode_size(mac_dentry->d_inode, netsfsinfo->len);
netsfs_inc_inode_size(network_dentry->d_inode, netsfsinfo->len);
len = get_skb_len(netsfsinfo->skb);

netsfs_inc_inode_size(mac_dentry->d_parent->d_inode, len);
netsfs_inc_inode_size(mac_dentry->d_inode, len);
netsfs_inc_inode_size(network_dentry->d_inode, len);

/* Free stuff */
dev_kfree_skb(netsfsinfo->skb);
kfree( (void *) work);
}

/* Bottom Halve.
* Grab the packet in Interrupt Context, we need be fast here.
* Only filter some packet types and sends to a work queue do the job.
*/
int netsfs_packet_handler(struct sk_buff *skb, struct net_device *dev, struct packet_type *pkt,
struct net_device *dev2)
{
int len, err;
unsigned int len;
struct netsfs_skb_info *netsfsinfo;
char mac_name[8], network_name[10];

len = skb->len;
len = get_skb_len(skb);

/* IEEE 802.3 Ethernet magic. */
if (len > ETH_DATA_LEN) {
err = -ENOMEM;
goto free;
dev_kfree_skb(skb);
return -ENOMEM;
}

printk("** BEGIN: 0x%.2x, 0x%.2x\n", ntohs(eth_hdr(skb)->h_proto), ip_hdr(skb)->protocol);

/* check for ip header, in this case never will get nothing different of ETH_P_IP, but this switch
* is here just in case you change netsfs_pseudo_proto.type
/* Currently we are only watching ETH_P_IP and ETH_P_IPV6.
*/
switch (ntohs(eth_hdr(skb)->h_proto))
{
case ETH_P_IP:
//sprintf(mac_name, "0x%.4x", ntohs(eth_hdr(skb)->h_proto));
sprintf(mac_name, "ipv4");
// TODO: FIX this switch
switch (ip_hdr(skb)->protocol)
{
case IPPROTO_IP:
sprintf(network_name, "ip");
break;
case IPPROTO_ICMP:
sprintf(network_name, "icmp");
break;
case IPPROTO_IGMP:
sprintf(network_name, "igmp");
break;
case IPPROTO_IPIP:
sprintf(network_name, "ipip");
break;
case IPPROTO_TCP:
sprintf(network_name, "tcp");
break;
case IPPROTO_EGP:
sprintf(network_name, "egp");
break;
case IPPROTO_PUP:
sprintf(network_name, "pup");
break;
case IPPROTO_UDP:
sprintf(network_name, "udp");
break;
case IPPROTO_IPV6:
sprintf(network_name, "ipv6");
break;
case IPPROTO_SCTP:
sprintf(network_name, "sctp");
break;
case IPPROTO_RAW:
sprintf(network_name, "raw");
break;
default:
sprintf(network_name, "0x%.2x", ip_hdr(skb)->protocol);
break;
}
break;
case ETH_P_IPV6:
//sprintf(mac_name, "0x%.4x", ntohs(eth_hdr(skb)->h_proto));
sprintf(mac_name, "ipv6");
switch (ipv6_hdr(skb)->nexthdr)
{
case NEXTHDR_HOP:
sprintf(network_name, "hop");
break;
case NEXTHDR_TCP:
sprintf(network_name, "tcp");
break;
case NEXTHDR_UDP:
sprintf(network_name, "udp");
break;
case NEXTHDR_IPV6:
sprintf(network_name, "ipv6");
break;
case NEXTHDR_ICMP:
sprintf(network_name, "icmp");
break;
default:
sprintf(network_name, "0x%.2x", ipv6_hdr(skb)->nexthdr);
break;
/* Put a work in a shared workqueue provided by the kernel */
netsfsinfo = kzalloc(sizeof(struct netsfs_skb_info), GFP_ATOMIC);
if (!netsfsinfo) {
dev_kfree_skb(skb);
return -ENOMEM;
}
break;
case ETH_P_ARP:
sprintf(mac_name, "arp");
sprintf(network_name, "0x%.2x", ip_hdr(skb)->protocol);

netsfsinfo->skb = skb;
INIT_WORK(&netsfsinfo->my_work, netsfs_go);
schedule_work(&netsfsinfo->my_work);

break;
default:
printk(KERN_INFO "%s: Unknow packet (0x%.4X, 0x%.4X)\n",
THIS_MODULE->name,
ntohs(pkt->type),
ntohs(eth_hdr(skb)->h_proto));
err = -ENOMEM;
goto free;
break;
dev_kfree_skb(skb);
return -ENOMEM;
}

/* Put a work in a shared workqueue provided by the kernel */
netsfsinfo = kzalloc(sizeof(struct netsfs_skb_info), GFP_ATOMIC);
if (!netsfsinfo) {
err = -ENOMEM;
goto free;
}

netsfsinfo->len = len;
strncpy(netsfsinfo->mac_name, mac_name, strlen(mac_name));
strncpy(netsfsinfo->network_name, network_name, strlen(mac_name));
INIT_WORK(&netsfsinfo->my_work, netsfs_go);
schedule_work(&netsfsinfo->my_work);

free:
dev_kfree_skb(skb);
printk("** END\n");
return err;
return 0;
}

0 comments on commit 157a17b

Please sign in to comment.