From 157a17b9fce5b6934b392b78ea785f801d713855 Mon Sep 17 00:00:00 2001 From: Beraldo Leal Date: Sun, 2 Jun 2013 02:00:33 -0400 Subject: [PATCH] refact 1/2 --- proto.c | 256 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 138 insertions(+), 118 deletions(-) diff --git a/proto.c b/proto.c index ac4508b..87f31fc 100644 --- a/proto.c +++ b/proto.c @@ -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; }