The interface between the kernel and the user state is simply too much, and sometimes it is inappropriate to divide them into a ranked, such as the infamous IOCTL, which, once it stinks, does not say well. Sometimes it is not as bad as it is imagined, most of it is because people misuse them, and then a master says it is not good, and since then people have gone with the master ... For the IOCTL, corresponding to the socket type file descriptor, is get/setsockopt two interface functions, in fact, I do not understand the distinction between the operation type from the function name and the difference between the command type, Why would a single IOCTL for UNIX file descriptors derive two functions on a socket, which is really not supposed to happen, such as when I invoke a getxxx command on a setsockopt? Of course it's going to go wrong, but I don't think that's the answer to the whole idea that this API should not be designed at all. Of course I am not a master, and no one will follow my thoughts.
I said the IOCTL is not good at the beginning is heard, but later found that the system call hierarchy design is too messy, the basic idea is "I try to deal with, if I can not handle the words down the layer pass", ultimately no one can guarantee that a command will not be processed, the key is who is not responsible for this, The only thing that can be identified is a return value.
I suddenly found that I was tired of long-winded, and no longer casting pearls before swine, but also do not want to and poisoning too deep between the existence or provoke a violent conflict or simple misunderstanding, perhaps more is I found that time is too valuable, and write purely self-view of the most time, these things even if not written out is entirely mine myself, Therefore, two pages of paper are omitted here.
Socket option, one of my favorite, that is nf_sockopt_ops. may have been playing conntrack recently, so everything as far as possible to conntrack as the core, then I hope that in addition to netfilter flexible framework to conntrack huge stage, but also rich interface, so only enough chewy. NetFilter flexibility I will not repeat, because I have written a lot, I would build a group, can be discussed at any time. Master the NetFilter you should be able to drag skb from anywhere, completely in your palm. As for the user interface, the existing CONNTRACK,CONNTRACKD, as well as the procfs/net in the Nf_conntrack file ... If this doesn't meet the requirements, then you need to find something new. In fact, for a person who is programmed to live, will not like conntrack-tools such an administrator tool, if you are using a "real language" rather than a script like bash, you will not like procfs such interface, so to speak, to tell the truth, if you use a " Real language, such as C, you would definitely want to do the simplest thing in the most complex way, such as creating a socket, then ..., and finally calling a set/getsocketopt. If you can't do this, you'll find a way to do it, a day has passed, two days passed, ... That's how much work is going on, and it's all about being busy, because it's a "real language," not a script that can see the text.
Indeed, if you are in the C program, parsing the files in Procfs is really troublesome, so_original_dst This command is to get redirect to the local SKB of the original destination address tuple, which is implemented using Nf_sockopt_ops, The author adds a small tip to the front of the Get function:
/* Fast function for those who don ' t want to parse/proc (and I don ' t blame them). */
In fact, the author does not know, he should go to Parse/proc/net/ip_conntrack to try. If you call Conntrack-tools and then intercept the output more cumbersome, so you really need a C API level interface, then set/getsockopt is better. These two sockopt system call interfaces are almost identical to the IOCTL system invocation interface and are also ambiguous chained attempts to execute, meaning that if you define the implementation somewhere and hang it in the execution path, it can be found and executed.
Recently, due to the need to add a feature on the TCP socket, need to get the information stored on the conntrack, my initial solution is actually working on the workload, how to do it? The answer is a cliché, that is, add a field to the SKB, and then copy the information in the Conntrack to the new field on the Prerouting hook, and then add the same field in sock, passing the fields in SKB to sock at the transport layer. Then it's make kernel-image, wait, error, rework, wait ... loop and loop ... Does this have to be self-inflicted in fact? What about defining a nf_sockopt_ops? The Get method is as follows:
static intgetxxxyyyzzz (struct sock *sk, int optval, void __user *user, int *len) { const struct inet_sock * Inet = inet_sk (SK); const struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; memset (&tuple, 0, sizeof (tuple)); tuple.src.u3.ip = inet->rcv_saddr; tuple.src.u.tcp.port = inet->sport; tuple.dst.u3.ip = inet->daddr; tuple.dst.u.tcp.port = inet->dport; tuple.src.l3num = PF_INET; tuple.dst.protonum = sk->sk_protocol;...//How to imagine h = nf_conntrack_find_get (Sock_net (SK), &tuple);//Sky high any Fly}
Let me tell you the benefits of using set/getsockopt or IOCTL, and I say that I admit, "although it's really not very well designed in terms of APIs, the benefits are elsewhere." Compared to PROCFS file IO, the IOCTL can achieve direct memory copy, the cost of using PROCFS is that the data must first be converted into a string, then written to the kernel, and in the kernel again according to "related rules" to the data back to the bare format, which means "one data exchange", The encoding and decoding rules of the interchange must be known to both the data exchange parties (that is, the PROCFS operator and the kernel), which means, for binary data, that at least one BASE64 encoding must be performed and then BASE64 decoded in the kernel, the fact that the kernel and user-state reader must be Writer also knows. All this is just because on the command line, it's hard to "define and transfer the struct", and at the bottom of the system, it's essentially using pointers to directly address the data between each struct or the inside. Therefore, to make the data and coding irrelevant, you must support direct memory copy operations.
All right, here's what I want to say. Using the IOCTL is better than using PROCFS. But, without noticing, the better is not "how do you use it", and for me who does not love programming, the better thing is how it can be used. This is not really a point. The fact that you invoke the set/getsockopt command on a socket descriptor does not mean that what you are doing must be related to this socket, and for me and other non-standard programmers it simply means that the execution stream is taken into the kernel space, and that, if you can bring in some data, That would be even better, to be honest, it would be nice to write a getsockopt (SD, SO_IP, REBOOT, NULL, NULL) to implement a system restart.
For the data processing preferences, I believe most people prefer to point the decimal string to the IP address, rather than the IP address represented by uint32_t, why? There is no deep reason to deal with the different levels. Ordinary users like the domain name and hate dot decimal, the same truth, but even the domain name, is also a string, we can enter the computer from the keyboard, is actually a string, we usually see the text, is also a string, the basic unit of our brain recognition information is the symbol, is actually a string (please do not mention the color, Sound, smell, etc.), if I give a number 123, is it a number? No! It is a 3-character string! Therefore, I believe many people can not blind to write the socket program because the reason is not proficient in the structure of SOCKADDR. So a lot of people are very fond of a function is inet_addr, the tedious work to the computer! Someone asked, how to use inet_addr in the kernel? The answer is not to use, so many programmers may start to write their own, of course, as a kind of practice is not possible, and many companies in the interview is really likely to let you use a pen to write inet_addr on paper. However, if you want to solve the problem efficiently, it is better to reuse the existing implementation in the programming process.
However, the premise of reuse is that you need to be able to find what you want to reuse. For kernel-State inet_addr This function, there is no ready-made implementation, this time you want to think of a clue, along this clue you can find the corresponding implementation. Is there any kernel interface that directly receives a dotted decimal string IP address? Of course! Consider when you use the bonding module, is there a/sys/class/net/bond0/bonding/arp_ip_target it? Along this clue, you can find the Bonding_store_arp_targets function, oh, the original is In_aton, it comes from a common component net/core/utils.c, annotated as follows:
/* * Convert an ASCII string to binary IP. * This is outside of Net/ipv4/because various code, uses IP addresses * is otherwise not dependent on the TCP/IP Stac K. * *
This is often required for the guy who often toss the Linux kernel network protocol stack.
Csdn again in the book, the book is very full, the content is good, first-come first-served, it is conceivable, can smoothly get their favorite book will be how difficult. But I'm not afraid, I want a book about the Cisco firewall that is irrelevant to the program, see if it stays there, and no one wants it, it's pathetic, now the temperature has dropped sharply, the recent low temperature, the programming book long presenting illegal weapons, and the programmer night Conversation, look at the Cisco Firewall book has no one, of course, I mean
The nf_sockopt_ops of Nf_conntrack can be operated arbitrarily