You can perform any operation on nf_sockopt_ops of nf_conntrack.
There are too many interfaces for the kernel to communicate with the user State. Sometimes it is not appropriate to divide them into three, six, and nine. For example, the notorious ioctl will be exhausted once it stinks, nobody said it was good. Sometimes it is not as bad as imagined. The vast majority of it is because people misuse them. Which of the following Masters has said that it is not good? Since then, people will go with the masters... for ioctl, it corresponds to the socket type file descriptor, that is, the get/setsockopt interface functions. In fact, I don't know how to distinguish the operation type from the command type from the function name, why does ioctl, which has a uniform UNIX file descriptor, generate two functions on the socket? This is really not necessary. For example, what if I call a GETxxx command on a setsockopt? Of course there will be errors, but I don't think that this answer is equivalent to understanding all of them, and this API should not be designed in this way. Of course, I am not a master, and no one will follow my thoughts.
/* Fast function for those who don't want to parse/proc (and I don't blame them ).*/As a matter of fact, I don't know. He should try parse/proc/net/ip_conntrack on his own. If you call conntrack-tools and intercept the output, it is more troublesome, so you really need a c api-level interface, then set/getsockopt will be better. These two sockopt System Call interfaces are almost the same as the ioctl System Call interfaces, and they are also chain-based execution with unclear responsibilities. That is to say, as long as you define the implementation somewhere and mount it to the execution path, then it can be found and executed.
Static intgetXXXYYYZZZ (struct sock * sk, int optval, void _ user * user, int * len) {const struct inet_sock * inet = inet_sk (sk); const struct limit * 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 ;... // imagine h = nf_conntrack_find_get (sock_net (sk), & tuple );... // flying on a daily basis}Let me tell you the benefits of using set/getsockopt or ioctl. I say this shows that I admit that "although it is really not well designed in terms of API, the benefits are elsewhere ". Compared with procfs file IO, ioctl can implement direct memory copy. The cost of using procfs is that data must be converted to a string and then written to the kernel, in the kernel, convert the data back to the bare format according to the relevant rules, which means "one data exchange" is required ", the encoding/decoding rules of the switch must be known to both parties (namely, the operator of procfs and the kernel). For binary data, this means that at least one BASE64 encoding is required, then BASE64 decoding is performed in the kernel. This fact must be known to both the kernel and user-mode Reader. All of this is because on the command line, it is difficult for you to "define the struct and transmit it", and at the underlying layer of the system, essentially, the pointer is used to directly address data between or within each struct. Therefore, to make the data irrelevant to the encoding, you must support direct memory copy operations.
/** Convert an ASCII string to binary IP. * This is outside of net/ipv4/because various code that uses IP addresses * is otherwise not dependent on the TCP/IP stack. */This is often required for Linux kernel network protocol stacks.