Bahasa pemrograman tingkat tinggi sangat populer, tetapi ada area di mana Anda perlu menggunakan implementasi pustaka yang tidak terkelola. Ini bisa berupa panggilan ke fungsi OS tertentu, akses level rendah ke perangkat, kebutuhan performa dalam algoritme, dan lainnya. Di bawah potongan, saya akan memberi tahu Anda apa yang dapat Anda temui saat bepergian dengan kode yang tidak dikelola dan apa yang harus Anda bawa.
Anda berdiri di depan pintu IDE Anda yang nyaman, dan Anda sama sekali tidak tergoda untuk pergi ke dunia kode sumber, di mana gelap dan tidak ada yang jelas. Untuk keberhasilan perusahaan, pertama-tama, Anda perlu mendapatkan peta - deskripsi tajuk perpustakaan akan turun, dan lebih baik memiliki dokumentasi lengkap. Biasanya terlihat seperti ini:
...
#include <linux/netfilter_ipv4/ip_tables.h>
#include <libiptc/xtcshared.h>
#ifdef __cplusplus
extern "C" {
#endif
#define iptc_handle xtc_handle
#define ipt_chainlabel xt_chainlabel
#define IPTC_LABEL_ACCEPT "ACCEPT"
#define IPTC_LABEL_DROP "DROP"
#define IPTC_LABEL_QUEUE "QUEUE"
#define IPTC_LABEL_RETURN "RETURN"
/* Does this chain exist? */
int iptc_is_chain(const char *chain, struct xtc_handle *const handle);
/* Take a snapshot of the rules. Returns NULL on error. */
struct xtc_handle *iptc_init(const char *tablename);
/* Cleanup after iptc_init(). */
void iptc_free(struct xtc_handle *h);
...
Katakanlah Anda beruntung dan dokumentasinya ada di sana. Ini menjelaskan tanda tangan fungsi, struktur yang digunakan, alias, dan referensi ke header lain yang digunakan. Quest pertama adalah menemukan library di OS. Namanya mungkin berbeda dari yang diharapkan:
~$ find /usr/lib/x86_64-linux-gnu/ -maxdepth 1 -name 'libip*'
/usr/lib/x86_64-linux-gnu/libip6tc.so.0.1.0
/usr/lib/x86_64-linux-gnu/libip4tc.so
/usr/lib/x86_64-linux-gnu/libiptc.so.0
/usr/lib/x86_64-linux-gnu/libip4tc.so.0.1.0
/usr/lib/x86_64-linux-gnu/libip6tc.so.0
/usr/lib/x86_64-linux-gnu/libiptc.so.0.0.0
/usr/lib/x86_64-linux-gnu/libip4tc.so.0
/usr/lib/x86_64-linux-gnu/libiptc.so
/usr/lib/x86_64-linux-gnu/libip6tc.so
Akhiran numerik berarti versi perpustakaan yang berbeda. Secara umum, kita membutuhkan libip4tc.so asli. Anda dapat melihat ke dalam dengan satu mata dan memastikan bahwa itu bermanfaat:
~$ nm -D /usr/lib/x86_64-linux-gnu/libip4tc.so ... 0000000000206230 D _edata 0000000000206240 B _end U __errno_location U fcntl 000000000000464c T _fini U __fprintf_chk U free U getsockopt w __gmon_start__ 0000000000001440 T _init 0000000000003c80 T iptc_append_entry 0000000000003700 T iptc_builtin 0000000000004640 T iptc_check_entry 0000000000003100 T iptc_commit 0000000000002ff0 T iptc_create_chain 00000000000043f0 T iptc_delete_chain ...
, , , . :
public static class Libiptc4
{
/* Prototype: iptc_handle_t iptc_init(const char *tablename) */
[DllImport("libip4tc.so")]
public static extern IntPtr iptc_init(string tablename);
}
/* Prototype: iptc_handle_t iptc_init(const char *tablename) */
[DllImport("libip4tc.so")]
public static extern IntPtr iptc_init(IntPtr tblPtr);
...
var tblPtr = Marshal.StringToHGlobalAnsi("filter");
var _handle = Libiptc4.iptc_init_ptr(tblPtr);
Marshal.FreeHGlobal(tblPtr);
.
, , , , .
, : . :
struct ipt_entry {
struct ipt_ip ip;
/* Mark with fields that we care about. */
unsigned int nfcache;
/* Size of ipt_entry + matches */
__u16 target_offset;
/* Size of ipt_entry + matches + target */
__u16 next_offset;
/* Back pointer */
unsigned int comefrom;
/* Packet and byte counters. */
struct xt_counters counters;
/* The matches (if any), then the target. */
unsigned char elems[0];
};
unsigned char elems[0]
. , , . :
*******************************************
* ip_entry *
* 112 bytes *
*******************************************
* matches *
* target_offset - 112 bytes *
*******************************************
* target *
* next_offset - target_offset - 112 bytes *
*******************************************
(matches
target
) ip_entry
. :
.
.
, , . ipt_entry
:
[StructLayout(LayoutKind.Sequential)]
public struct IptEntry
{
public IptIp ip;
public uint nfcache;
public ushort target_offset;
public ushort next_offset;
public uint comefrom;
public IptCounters counters;
};
Marshal.SizeOf<IptEntry>()
112 . matches
target
( ). : libiptc
8 ( long
), . , . :
static readonly int _WORDLEN = Marshal.SizeOf<long>();
public static int Align(int size)
{
return ((size + (_WORDLEN - 1)) & ~(_WORDLEN - 1));
}
, entry.target_offset
entry.next_offset
, :
IntPtr entryPtr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr<IptEntry>(entryPtr, entry, false);
Marshal.StructureToPtr<Match>(entryPtr + 112, match, false);
: , , :
var entry = Marshal.PtrToStructure<IptEntry>(point);
var match = Marshal.PtrToStructure<Match>(point + 112)
, union:
struct xt_entry_match {
union {
struct {
__u16 match_size;
/* Used by userspace */
char name[XT_EXTENSION_MAXNAMELEN];
__u8 revision;
} user;
struct {
__u16 match_size;
/* Used inside the kernel */
struct xt_match *match;
} kernel;
/* Total length */
__u16 match_size;
} u;
unsigned char data[0];
};
:
#define XT_EXTENSION_MAXNAMELEN 29
...
char name [XT_EXTENSION_MAXNAMELEN]
. header .
, . ushort, uint long , . . : , . . . :
byte [] convArray = BitConverter.GetBytes(value);
Array.Reverse(convArray);
ushort reverseEndian = BitConverter.ToUInt16(convArray,0);
ushort reverseEndian = (ushort)((value << 8) | (value >> 8));
. unmanaged code . /, errno. . , :
[DllImport("libip4tc.so", SetLastError = true)]
, , :
int errno = Marshal.GetLastWin32Error();
var errPtr = Libiptc4.iptc_strerror(errno);
string errStr = Marshal.PtrToStringAnsi(errPtr);
Linux c net.core (, /). : -, 32/64 , Windows . .
Ini mengakhiri perjalanan kita. Saya akan menambahkan bahwa menggunakan perpustakaan tingkat rendah tampaknya menjadi pendekatan yang sulit dan tidak dapat diprediksi dalam hal keberhasilan. Kurangnya dokumentasi dan interaksi yang kompleks bisa menakutkan. Namun, terkadang ini adalah satu-satunya cara untuk mencapai hasil yang diinginkan.