Home PC Games Linux Windows Database Network Programming Server Mobile  
           
  Home \ Linux \ To achieve a two-way static NAT stateless available modules on Linux     - Xmanager Remote Desktop login CentOS 6.5 (Linux)

- Ubuntu 14.04 compile and install Apache (Server)

- MySQL fuzzy query: LIKE and REGEXP pattern mode (Database)

- CentOS7 virtual machine creation failed Solution (Linux)

- Shell Script: Bulk add users, and set the random character password (Programming)

- Recent Consolidation Using Linux security module (Linux)

- 14 useful example Linux Sort command (Linux)

- Gitolite how to import other Git repositories (Server)

- CentOS Linux build SVN server (Server)

- Error: Unable to establish connection with FTP SFTP server (Server)

- Why did not Oracle privileges can also log in with sysdba (Database)

- Network security system (Network)

- Linux system boot process ARM platforms (Linux)

- Linux Creating a new user error Creating mailbox file: File exists (Linux)

- PLSQL Developer synchronization table tools (Database)

- Hadoop 2.2.0 installation development environment (standalone pseudo-distributed mode) (Server)

- Ubuntu 14.04 and derivative versions of the user install Pantheon Photos 0.1 (Linux)

- Vim useful plugin: EasyGrep (Linux)

- Echo Command Examples (Linux)

- After Oracle 11g dataguard failover rebuild the archive logs are not applied to be NO problem (Database)

 
         
  To achieve a two-way static NAT stateless available modules on Linux
     
  Add Date : 2018-11-21      
         
         
         
  Information on how to configure NAT on Linux has many, can be described as overwhelming! This article has nothing to do with this. This article provides a way of iptables outside.

iptables? Do not! why? Because iptables is stateful NAT configuration, its implementation depends called conntrack module, what is conntrack? Oh, NO! This is my specialty, but I do not want to say it in this article, people who know me know that I can pull this topic I have something to do 12 hours ... also pulled finish. Maybe you do not know what is stateful NAT, but if you are a heart, or is a fairly sophisticated technology Linux network administrator or lover, you must configure the NAT when encountered this kind of problem, such as " when a connection has been established then why can not configure NAT timely entry into force "," Why after iptables NAT configuration data can only be sent to the initiative from one direction to another, "and the like. This is the state in trouble, you know, IP is no state, but NAT added after the fourth layer of logic have a state, which is stateful NAT, iptables -t nat .. it is out of the NAT configuration inherent nature, you can not change. At least I see in iptables latest version of NAT or stateful. sometimes..

Sometimes, you may be, you have to ...

You must configure a stateless for NAT, two-way, static. The problem, alas ..

I toss this question six months 2013 first nine months, and one that makes me happy let me worry about three quarters, almost all of my energies flutter in one thing, the high temperature from winter to 40+ degrees Celsius, from 6:30 am starting to work more than 10 points to the middle of the night to stay in the room ... but for also before that when packed bookshelves had not yet found a $ 120 reimbursement out routine work overtime to fight the ticket, I did not want to write this module a. 120 nothing, but took the opportunity to reminisce, make up incomplete way that part, be reimbursed for himself, and is much larger than the value of $ 120. I have to admit, that three quarters stateless NAT does not seem the most important reason why I am a year later to take it out, because other problems have been overcome and I was, no matter how long it took, there was Cry over 72 hours conntrack confirm solve the problem, there have been due to the confusion and impatience strange woman eat barbecue is fraud ... but the truth his wife on this stateless NAT has not been resolved, not resolved, which is why?

What I do is a product rather than an individual test, where I was a company team rather than do private job, all the techniques used must be technical pre-research to ensure the feasibility, more importantly, to ensure that everyone in the same rhythm, perhaps in parallel, but it is always a big one-melody, which is playing Canon ah. I can add some personal touch, such as a personal whim (in the future I confess, that I do not get!), If you have to join, then such a process must have the following:

The leadership, team owners pull in meetings, training, research and development and to ensure that any technical responsible people are well aware of the use of technology does not stay dead.

But how can this time? ! Human nature is fragile, no matter how strong life. Anyone can hang up suddenly one day, due to force majeure reasons other city or country, and familiar colleagues and do not take water since the departure of a fight ... if you do something and thus also leaving , and for a company, that you simply never been. ...... A little pull away.

So, even though I was already able to achieve stateless NAT (I was using a routing target way, maybe I have written a blog before), I can not make use of them, I can only look for opportunities to find a spare afternoon, a no urgent tasks in the afternoon, so that all who are associated with this understanding of this technology, and then is not a demand problem, the best way in addition to the code or the code, the programmer, the characters are saying 1G in vain, do not run up code is crap, even if the code ruthless bad it does not matter, because of this realism of the character, I like this job, no angry words, no wide long on, do not fight, do not incite, as long as the code can run, nothing more.

Yes, stateless NAT in Linux 2.4 has a good implementation, is the use of tc / policy routing to complete, but the 2.6 kernel has been difficult to do. Study on decoupled consider this module left really want to achieve it, maybe I count as one. The reason I did so many others seem pointless thing, because I want to express an idea, that is, "the development of operation and maintenance" and "the development of operation and maintenance" concept, these people must be the future of the hottest people. When I faced numerous accusations Cisco certified engineers, my first thought is not scold them or beat them (people not rich vocabulary and [Note: This can not 'or' use 'and'] beat people embarrassing, and even these are not a problem, there is no legal right ...), my first thought was, on Linux can not perform the same function, their purpose is not to burst chrysanthemum, but let he felt that I could blast him. Fortunately, I have done it, whenever the moment, I will return home to write a few test module, however, just as the company's technical pre-research. And then presented to the friends who are interested can go to test this thing profitable, but also not sure, it's useless to git, nor is God horse GPL open source is a special circle of friends to share, I very much dislike classification, I really like casually. Then, then, just a little, I code, write a bunch of bad code, based on the Linux Netfilter to achieve a two-way, static, stateless NAT, the code is not complicated, only a few hundred lines, but ....

However, the problem is twofold:

1. The primary module, but is available, this is my self-affirmation of one side;

2. This module has a lot of room for improvement suspicious, I self-denial.

Code is as follows:

/ *
 *
 * Usage:
 * Target address of the packet destination address 1.2.1.2 to do the conversion, goal into 192.168.1.8
 * Echo +1.2.1.2 192.168.1.8 dst> / proc / net / static_nat
 * The above command will also add a reverse of SNAT mappings
 *
 * please explain:
 * Echo +192.168.184.250 192.168.184.154 src> / proc / net / static_nat
 *
 * /
  
#include < linux / module.h>
#include < linux / skbuff.h>
#include < net / ip.h>
#include < net / netfilter / nf_conntrack.h>
  
#define DIRMASK 0x11
#define BUCKETS 1024
  
  
#define NAT_OPT_DEL 0x01
#define NAT_OPT_FIND 0x04
  
#define NAT_OPT_ACCT_BIT 0x02
  
  
enum nat_dir {
    DIR_SNAT,
    DIR_DNAT,
    DIR_NUM
};
  
/ *
 * Record statistics
 * /
struct nat_account {
    u32 nat_packets;
    u32 nat_bytes;
};
  
struct static_nat_entry {
    __be32 addr [DIR_NUM];
    enum nat_dir type;
    struct nat_account acct [DIR_NUM];
    struct hlist_node node [DIR_NUM];
};
  
static DEFINE_SPINLOCK (nat_lock);
  
/ * Save SNAT mapping * /
struct hlist_head * src_list;
  
/ * Save DNAT map * /
struct hlist_head * dst_list;
  
/ *
 * With a single IP address (for PREROUTING is daddr, for POSTROUTING is saddr) as a key to get the value.
 * /
static __be32 get_address_from_map (struct sk_buff * skb, unsigned int dir, __be32 addr_key, unsigned int opt)
{
    __be32 ret = 0, cmp_key, ret_value;
    u32 hash;
    struct hlist_head * list;
    struct hlist_node * iter, * tmp;
    struct static_nat_entry * ent;
  
    hash = jhash_1word (addr_key, 1);
    hash = hash% BUCKETS;
  
    spin_lock (& nat_lock);
    if (dir == DIR_DNAT) {
        list = & dst_list [hash];
    } Else if (dir == DIR_SNAT) {
        list = & src_list [hash];
    } Else {
        spin_unlock (& nat_lock);
        goto out;
    }
  
    hlist_for_each_safe (iter, tmp, list) {
        ent = hlist_entry (iter, struct static_nat_entry, node [dir]);
        / * Reverse * Note /
        cmp_key = (ent-> type == dir)?
                            ent-> addr [0]: ent-> addr [1];
        ret_value = (ent-> type == dir)?
                            ent-> addr [1]: ent-> addr [0];
        if (addr_key == cmp_key) {
            ret = ret_value;
            if (opt == NAT_OPT_DEL) {
                if (dir == ent-> type) {
                    hlist_del (& ent-> node [0]);
                    hlist_del (& ent-> node [1]);
                    kfree (ent);
                } Else {
                    ret = 0;
                }
            }
            if (opt & NAT_OPT_ACCT_BIT) {
                ent-> acct [dir] .nat_packets ++;
                ent-> acct [dir] .nat_bytes + = skb == NULL 1: skb-> len;?
            }
            break;
        }
    }
    spin_unlock (& nat_lock);
out:
    return ret;
}
  
/ *
 * Update the fourth layer checksum information
 * /
static void nat4_update_l4 (struct sk_buff * skb, __be32 oldip, __be32 newip)
{
    struct iphdr * iph = ip_hdr (skb);
    void * transport_hdr = (void *) iph + ip_hdrlen (skb);
    struct tcphdr * tcph;
    struct udphdr * udph;
    bool cond;
  
    switch (iph-> protocol) {
    case IPPROTO_TCP:
        tcph = transport_hdr;
        inet_proto_csum_replace4 (& tcph-> check, skb, oldip, newip, true);
        break;
    case IPPROTO_UDP:
    case IPPROTO_UDPLITE:
        udph = transport_hdr;
        ! Cond = udph-> check = 0;
        cond | = skb-> ip_summed == CHECKSUM_PARTIAL;
        if (cond) {
            inet_proto_csum_replace4 (& udph-> check, skb, oldip, newip, true);
            if (udph-> check == 0) {
                udph-> check = CSUM_MANGLED_0;
            }
        }
        break;
    }
}
  
/ *
 * On POSTROUTING perform source address translation:
 * 1. Forward source address translation;
 * Reverse source address destination address translation 2. Conversion
 * /
static unsigned int ipv4_nat_out (unsigned int hooknum,
                struct sk_buff * skb,
                const struct net_device * in,
                const struct net_device * out,
                int (* okfn) (struct sk_buff *))
{
    unsigned int ret = NF_ACCEPT;
    __be32 to_trans = 0;
  
    struct iphdr * hdr = ip_hdr (skb);
      
    to_trans = get_address_from_map (skb, DIR_SNAT, hdr-> saddr, NAT_OPT_FIND | NAT_OPT_ACCT_BIT);
    if (! to_trans) {
        goto out;
    }
  
    if (hdr-> saddr == to_trans) {
        goto out;
    }
  
    / * Perform SNAT * /
    csum_replace4 (& hdr-> check, hdr-> saddr, to_trans);
    nat4_update_l4 (skb, hdr-> saddr, to_trans);
    hdr-> saddr = to_trans;
out:
    return ret;
}
  
/ *
 * On the PREROUTING execution target address translation:
 * 1. Forward destination address translation;
 * Reverse source address destination address 2. Conversion
 * /
static unsigned int ipv4_nat_in (unsigned int hooknum,
                      struct sk_buff * skb,
                      const struct net_device * in,
                      const struct net_device * out,
                      int (* okfn) (struct sk_buff *))
{
    unsigned int ret = NF_ACCEPT;
    __be32 to_trans = 0;
  
    struct iphdr * hdr = ip_hdr (skb);
  
    if (skb-> nfct && skb-> nfct! = & nf_conntrack_untracked.ct_general) {
        goto out;
    }
      
    to_trans = get_address_from_map (skb, DIR_DNAT, hdr-> daddr, NAT_OPT_FIND | NAT_OPT_ACCT_BIT);
    if (! to_trans) {
        goto out;
    }
  
    if (hdr-> daddr == to_trans) {
        goto out;
    }
      
    / * Perform DNAT * /
    csum_replace4 (& hdr-> check, hdr-> daddr, to_trans);
    nat4_update_l4 (skb, hdr-> daddr, to_trans);
    hdr-> daddr = to_trans;
      
    / *
    * Set a notrack prevent its track and nat.
    * It is absolutely right, because since it is static for stateless NAT
    * We do not want it to be about the state
    ** /
  
    / *
    * In fact, not primarily to avoid the NAT conntrack based on it, because
    * Conntrack tuple itself can not you be free to modify both directions
    * /
    if (! skb-> nfct) {
        skb-> nfct = & nf_conntrack_untracked.ct_general;
        skb-> nfctinfo = IP_CT_NEW;
        nf_conntrack_get (skb-> nfct);
    }
  
out:
    return ret;
}
  
static struct nf_hook_ops ipv4_nat_ops [] __read_mostly = {
    {
        .hook = ipv4_nat_in,
        .owner = THIS_MODULE,
        .pf = NFPROTO_IPV4,
        .hooknum = NF_INET_PRE_ROUTING,
        .priority = NF_IP_PRI_CONNTRACK-1,
    },
    {
        .hook = ipv4_nat_out,
        .owner = THIS_MODULE,
        .pf = NFPROTO_IPV4,
        .hooknum = NF_INET_POST_ROUTING,
        .priority = NF_IP_PRI_CONNTRACK + 1,
    },
};
  
static char * parse_addr (const char * input, __be32 * from, __be32 * to)
{
    char * p1, * p2;
    size_t length = strlen (input);
      
    if (! (p1 = memchr (input, '', length))) {
        return NULL;
    }
  
    if ((p2 = memchr (p1 + 1, '', length -! (p1 + 1 - input)))) {
        return NULL;
    }
  
    if ((in4_pton (input, p1 -! input, (u8 *) from, '', NULL))
            ||! (In4_pton (p1 + 1, p2 - p1 - 1, (u8 *) to, '', NULL))) {
        return NULL;
    }
  
    return ++ p2;
}
  
static ssize_t static_nat_config_write (struct file * file, const char * buffer, size_t count, loff_t * unused)
{
    int ret = 0;
    size_t length = count;
    __be32 from, to;
    u32 normal, reverse;
    char * buf = NULL;
    char * p;
    struct static_nat_entry * ent;
  
    if (length) {
        char * pp = (char *) (buffer + (length - 1));
        for (; (* pp < (char) 32) || (* pp> (char) 126); pp--) {
            if (length < = 0) {
                ret = -EINVAL;
                goto out;
            }
            length--;
        }
    } Else {
        goto out;
    }
  
    buf = kzalloc ((length + 1), GFP_ATOMIC);
    if (! buf) {
        ret = -ENOMEM;
        goto out;
    }
    memcpy (buf, buffer, length);
    if (! (p = parse_addr (buf + 1, & from, & to))) {
        ret = -EINVAL;
        goto out;
    }
  
    if ( '+' == * buf) {
        ent = (struct static_nat_entry *) kzalloc (sizeof (struct static_nat_entry), GFP_KERNEL);
        if (! ent) {
            ret = -EFAULT;
            goto out;
        }
  
        / * Calculate the original item hash bucket position * /
        normal = jhash_1word (from, 1);
        normal = normal% BUCKETS;
  
        / * Calculate the hash bucket position reversing position * /
        reverse = jhash_1word (to, 1);
        reverse = reverse% BUCKETS;
  
        / *
        * Setting key / value pair
        * Note that the reverse type hnode its key / value should be reversed
        * /
        ent-> addr [0] = from;
        ent-> addr [1] = to;
  
        / * Initialize the list node * /
        INIT_HLIST_NODE (& ent-> node [DIR_SNAT]);
        INIT_HLIST_NODE (& ent-> node [DIR_DNAT]);
  
        if (strstr (p, "src")) {/ * Add SNAT entry automatically generates DNAT item * /
            / * First determines whether already exists * /
            if (get_address_from_map (NULL, DIR_SNAT, from, NAT_OPT_FIND) ||
                    get_address_from_map (NULL, DIR_SNAT, to, NAT_OPT_FIND)) {
                ret = -EEXIST;
                kfree (ent);
                goto out;
            }
  
            / * This is the entry's type, used to distinguish between two configuration items generated * /
            ent-> type = DIR_SNAT;
  
            / * Implement the linked list * /
            spin_lock (& nat_lock);
            hlist_add_head (& ent-> node [DIR_SNAT], & src_list [normal]);
            hlist_add_head (& ent-> node [DIR_DNAT], & dst_list [reverse]);
            spin_unlock (& nat_lock);
        } Else if (strstr (p, "dst")) {/ * add DNAT entries generated automatically SNAT item * /
            / * First determines whether already exists * /
            if (get_address_from_map (NULL, DIR_DNAT, from, NAT_OPT_FIND) ||
                    get_address_from_map (NULL, DIR_DNAT, to, NAT_OPT_FIND)) {
                ret = -EEXIST;
                kfree (ent);
                goto out;
            }
  
            / * This is the entry's type, used to distinguish between two configuration items generated * /
            ent-> type = DIR_DNAT;
  
            / * Implement the linked list * /
            spin_lock (& nat_lock);
            hlist_add_head (& ent-> node [DIR_DNAT], & dst_list [normal]);
            hlist_add_head (& ent-> node [DIR_SNAT], & src_list [reverse]);
            spin_unlock (& nat_lock);
        } Else {
            ret = -EFAULT;
            kfree (ent);
            goto out;
        }
  
    } Else if ( '-' == * buf) {
        u32 r1;
  
        if (strstr (p, "src")) {
            r1 = get_address_from_map (NULL, DIR_SNAT, from, NAT_OPT_DEL);
            if (r1 == 0) {
                ret = -ENOENT;
                goto out;
            }
        } Else if (strstr (p, "dst")) {
            r1 = get_address_from_map (NULL, DIR_DNAT, from, NAT_OPT_DEL);
            if (r1 == 0) {
                ret = -ENOENT;
                goto out;
            }
        } Else {
        }
  
    } Else {
        ret = -EINVAL;
        goto out;
    }
      
    ret = count;
out:
    kfree (buf);
    return ret;
}
  
static ssize_t static_nat_config_read (struct file * file, char __user * buf, size_t count, loff_t * ppos)
{
    int len = 0;
    static int done = 0;
    int i;
    char from [15], to [15];
    char * kbuf_to_avoid_user_space_memory_page_fault = NULL;
  
/ * The maximum length of each line * /
#define MAX_LINE_CHARS 128
  
    if (done) {
        done = 0;
        goto out;
    }
      
    / *
    * Allocate a block of kernel memory, in order to avoid direct manipulation user memory and paging initiation,
    * Paging can cause sleep switch, and the content of our operations in the spin lock
    * Next, so you can not switch!
    * /
  
    / *
    * Question:
    * I'm just here to count the size of the allocated memory, because this version does not support multiple read,
    * Only one sitting. Maybe I should learn seq read method.
    * /
    kbuf_to_avoid_user_space_memory_page_fault = kzalloc (count, GFP_KERNEL);
    if (! kbuf_to_avoid_user_space_memory_page_fault) {
        len = -ENOMEM;
        done = 1;
        goto out;
    }
  
    spin_lock (& nat_lock);
    len + = sprintf (kbuf_to_avoid_user_space_memory_page_fault + len, "Source trans table: \ n");
    if (len + MAX_LINE_CHARS> count) {
        goto copy_now;
    }
    for (i = 0; i < BUCKETS; i ++) {
        struct hlist_node * iter, * tmp;
        struct static_nat_entry * ent;
        hlist_for_each_safe (iter, tmp, & src_list [i]) {
            ent = hlist_entry (iter, struct static_nat_entry, node [DIR_SNAT]);
            sprintf (from, "% pI4", (ent-> type == DIR_SNAT) & ent-> addr [0]: & ent-> addr [1]?);
            sprintf (? to, "% pI4", (ent-> type == DIR_SNAT) & ent-> addr [1]: & ent-> addr [0]);
            len + = sprintf (kbuf_to_avoid_user_space_memory_page_fault + len, "From:% - 15s To:% - 15s [% s] [Bytes:% u Packet:% u] \ n",
                        from,
                        to,
                        ? (Ent-> type == DIR_SNAT) "STATIC": "AUTO",
                        ent-> acct [DIR_SNAT] .nat_bytes,
                        ent-> acct [DIR_SNAT] .nat_packets);
  
            if (len + MAX_LINE_CHARS> count) {
                goto copy_now;
            }
        }
    }
    len + = sprintf (kbuf_to_avoid_user_space_memory_page_fault + len, "\ nDestination trans table: \ n");
    if (len + MAX_LINE_CHARS> count) {
        goto copy_now;
    }
    for (i = 0; i < BUCKETS; i ++) {
        struct hlist_node * iter, * tmp;
        struct static_nat_entry * ent;
        hlist_for_each_safe (iter, tmp, & dst_list [i]) {
            ent = hlist_entry (iter, struct static_nat_entry, node [DIR_DNAT]);
            sprintf (from, "% pI4", (ent-> type == DIR_DNAT) & ent-> addr [0]: & ent-> addr [1]?);
            sprintf (? to, "% pI4", (ent-> type == DIR_DNAT) & ent-> addr [1]: & ent-> addr [0]);
            len + = sprintf (kbuf_to_avoid_user_space_memory_page_fault + len, "From:% - 15s To:% - 15s [% s] [Bytes:% u Packet:% u] \ n",
                        from,
                        to,
                        ? (Ent-> type == DIR_DNAT) "STATIC": "AUTO",
                        ent-> acct [DIR_DNAT] .nat_bytes,
                        ent-> acct [DIR_DNAT] .nat_packets);
  
  
            if (len + MAX_LINE_CHARS> count) {
                goto copy_now;
            }
        }
    }
copy_now:
    spin_unlock (& nat_lock);
    done = 1;
    / * Spin lock has been lifted here * /
    if (copy_to_user (buf, kbuf_to_avoid_user_space_memory_page_fault, len)) {
        len = EFAULT;
        goto out;
    }
      
out:
    if (kbuf_to_avoid_user_space_memory_page_fault) {
        kfree (kbuf_to_avoid_user_space_memory_page_fault);
    }
    return len;
}
  
static const struct file_operations static_nat_file_ops = {
    .owner = THIS_MODULE,
    .read = static_nat_config_read,
    .write = static_nat_config_write,
};
  
static int __init nf_static_nat_init (void)
{
    int ret = 0;
    int i;
  
    src_list = kzalloc (sizeof (struct hlist_head) * BUCKETS, GFP_KERNEL);
    if (! src_list) {
        ret = -ENOMEM;
        goto out;
    }
    dst_list = kzalloc (sizeof (struct hlist_head) * BUCKETS, GFP_KERNEL);
    if (! dst_list) {
        ret = -ENOMEM;
        goto out;
    }
  
    ret = nf_register_hooks (ipv4_nat_ops, ARRAY_SIZE (ipv4_nat_ops));
    if (ret < 0) {
        printk ( ". nf_nat_ipv4: can not register hooks \ n");
        goto out;
    }
  
    if (! proc_create ( "static_nat", 0644, init_net.proc_net, & static_nat_file_ops)) {
        ret = -ENOMEM;
        goto out;
    }
  
    for (i = 0; i < BUCKETS; i ++) {
        INIT_HLIST_HEAD (& src_list [i]);
        INIT_HLIST_HEAD (& dst_list [i]);
    }
    return ret;
out:
    if (src_list) {
        kfree (src_list);
    }
    if (dst_list) {
        kfree (dst_list);
    }
  
    return ret;
}
  
static void __exit nf_static_nat_fini (void)
{
    int i;
  
    remove_proc_entry ( "static_nat", init_net.proc_net);
    nf_unregister_hooks (ipv4_nat_ops, ARRAY_SIZE (ipv4_nat_ops));
  
    spin_lock (& nat_lock);
    for (i = 0; i < BUCKETS; i ++) {
        struct hlist_node * iter, * tmp;
        struct static_nat_entry * ent;
        hlist_for_each_safe (iter, tmp, & src_list [i]) {
            ent = hlist_entry (iter, struct static_nat_entry, node [0]);
            hlist_del (& ent-> node [DIR_SNAT]);
            hlist_del (& ent-> node [DIR_DNAT]);
            kfree (ent);
        }
    }
    spin_unlock (& nat_lock);
    if (src_list) {
        kfree (src_list);
    }
    if (dst_list) {
        kfree (dst_list);
    }
}
  
module_init (nf_static_nat_init);
module_exit (nf_static_nat_fini);
  
MODULE_DESCRIPTION ( "STATIC two-way NAT");
MODULE_AUTHOR ( "marywangran@126.com");
MODULE_LICENSE ( "GPL");

Makefile:

obj-m + = nf_rawnat.o
  
all:
    make -C / lib / modules / `uname -r` / build SUBDIRS =` pwd` modules
  
clean:
    rm -rf * .ko * .o .tmp_versions. *. mod.o. *. o.cmd * .mod.c. *. ko.cmd Module.symvers modules.order

I am not optimistic about private job-related applications does not mean I do not like it, does not mean I will not. After all the work has been very tired, why we should continue Leia. Outside of work, engage in something else, what else is it? stateless NAT ... This is what many people do not get involved, I sigh, I am sad, Micro man, who I go? ...
     
         
         
         
  More:      
 
- Use ARChon runtime environment to run Android apps on Ubuntu (Linux)
- Oracle View index and use indexes Precautions (Database)
- Linux software firewall ACL match point optimization (Linux)
- OpenNMS separate database (Server)
- Briefly explain the invasion of the four-level denial of service attack DoS Linux server (Linux)
- Hadoop new and old version of the difference in the size of the InputSplit (Server)
- Let CentOS perform PPPoE dial-up, ADSL can be used in a network environment! (Linux)
- Oracle in the add & split partition on the impact of global & local index (Database)
- Linux common commands MEMO (Linux)
- CentOS7 install MySQL5.6.22 (Linux)
- Ubuntu 14.10 Server configuration wireless Internet access (Server)
- RedHat Linux 9.0 under P4VP-MX motherboard graphics resolution of problems (Linux)
- iptraf: A Practical TCP / UDP network monitoring tools (Linux)
- Build your own Git server under Linux (Server)
- Python data types summary (Programming)
- Source code compiled by the installation program under Linux (Linux)
- CentOS How to mount the hard drive (Linux)
- Installation and management of Linux applications (Linux)
- Database start listening TNS-12537, TNS-12560 error (Database)
- Linux how to view the graphics models notebook (Linux)
     
           
     
  CopyRight 2002-2022 newfreesoft.com, All Rights Reserved.