tunctl1.5.1源代碼分析
file address: https://files.cnblogs.com/files/blogs/773707/tunctl.zip?t=1699629591&download=true
strtol 是 C 語言標準庫中的一個函數,用于將字符串轉換為長整型數(long)。
long strtol(const char *str, char **endptr, int base);
str:要轉換的字符串。endptr:指向字符指針的指針,用于存儲轉換結束后剩余的字符串的地址。如果這個參數為NULL,則忽略這個信息。base:表示數字的進制,可以是 2 到 36 之間的任何值,或者是 0。如果為 0,則根據字符串的前綴來確定進制(0x 或 0X 表示十六進制,0 表示八進制,其它為十進制)。
strtol 返回轉換后的長整型數。如果發生錯誤,返回 0 并設置 errno。
下面是一個簡單的示例,演示如何使用 strtol:
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[] = "12345";
char *endptr;
long num = strtol(str, &endptr, 10);
if (*endptr != '\0') {
printf("Conversion failed. Remaining string: %s\n", endptr);
} else {
printf("Converted number: %ld\n", num);
}
return 0;
}
此示例將字符串 "12345" 轉換為長整型數 12345,并打印轉換結果。如果轉換失敗,它會打印剩余的字符串。
getgrnam 是 C 語言標準庫中的一個函數,用于通過組名獲取對應的組結構。該函數的聲明如下:
#include <grp.h>
struct group *getgrnam(const char *name);
name:要查找的組名。
getgrnam 函數返回一個指向 group 結構體的指針,該結構體包含了有關組的信息,包括組名、組 ID、組的用戶列表等。如果未找到對應的組,返回 NULL。
下面是一個簡單的示例,演示如何使用 getgrnam 函數:
#include <stdio.h>
#include <grp.h>
int main() {
const char *group_name = "users";
struct group *grp = getgrnam(group_name);
if (grp != NULL) {
printf("Group information for %s:\n", group_name);
printf("Group name: %s\n", grp->gr_name);
printf("Group ID: %d\n", grp->gr_gid);
// Print user list
printf("Group members:\n");
for (int i = 0; grp->gr_mem[i] != NULL; i++) {
printf(" %s\n", grp->gr_mem[i]);
}
} else {
printf("Group %s not found.\n", group_name);
}
return 0;
}
此示例通過組名 "users" 獲取組的信息,并打印組名、組 ID 以及組成員的列表。如果未找到組,它會打印相應的消息。
這里的 "bd:f:npt:u:g:h" 是 getopt 函數的第三個參數,即期望的選項字符串。它定義了你的程序可以接受的命令行選項,并指明哪些選項需要參數。
解釋一下這個字符串:
b:表示一個短選項-b,沒有參數。d::表示一個短選項-d,后面需要一個參數。f::表示一個短選項-f,后面需要一個參數。n:表示一個短選項-n,沒有參數。p:表示一個短選項-p,沒有參數。t::表示一個短選項-t,后面需要一個參數。u::表示一個短選項-u,后面需要一個參數。g::表示一個短選項-g,后面需要一個參數。h:表示一個短選項-h,沒有參數。
這個字符串告訴 getopt 函數你的程序支持哪些短選項,以及這些選項是否需要參數。在代碼中,getopt 會根據這個字符串解析命令行參數,并將下一個選項字符返回給 opt 變量。
例如,如果你的命令行參數是 -d some_device -u some_user -g some_group,那么在 while 循環中,getopt 會逐個返回 d、u、g,然后你可以通過 optarg 獲取相應的參數值。
getpwnam 函數是用于通過用戶名獲取用戶信息的函數。該函數的聲明如下:
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwnam(const char *name);
函數接受一個用戶名作為參數,返回一個指向 struct passwd 結構的指針。struct passwd 結構包含了有關用戶的信息,例如用戶名、用戶 ID、組 ID、用戶的主目錄等。
下面是一個簡單的例子,演示如何使用 getpwnam 函數:
#include <stdio.h>
#include <pwd.h>
int main() {
const char *username = "your_username";
struct passwd *pwd = getpwnam(username);
if (pwd != NULL) {
printf("User Information:\n");
printf("Username: %s\n", pwd->pw_name);
printf("User ID: %d\n", (int)pwd->pw_uid);
printf("Group ID: %d\n", (int)pwd->pw_gid);
printf("Home Directory: %s\n", pwd->pw_dir);
} else {
printf("User not found.\n");
}
return 0;
}
請將 "your_username" 替換為你想要查詢的實際用戶名。在實際應用中,你可能需要檢查返回的指針是否為 NULL,以確定用戶是否存在。
argv += optind;
argc -= optind;
這兩行代碼用于更新命令行參數,以便忽略已經被處理的選項。optind 是 getopt 函數的全局變量,表示下一個要處理的參數的索引。argv 是一個指向命令行參數數組的指針,而 argc 是命令行參數的個數。
在處理命令行參數時,getopt 會逐個獲取選項,并將 optind 更新為下一個要處理的參數的索引。optind 的初值通常為 1。optind 之前的參數是程序名,通常不包含選項。
argv += optind; 將 argv 向后移動,指向下一個要處理的參數。argc -= optind; 則減去已經處理的參數個數,以保持 argc 的正確值。這兩行代碼的目的是調整 argv 和 argc,以便后續的代碼只處理用戶輸入的實際參數,而不包括程序名和已經處理過的選項。
ioctl 是一個用于設備 I/O 控制的系統調用,它可以在不同類型的設備上執行各種操作。在C語言中,ioctl 函數的原型如下:
int ioctl(int fd, unsigned long request, ...);
fd是指向打開設備的文件描述符。request是控制命令的整數,用于指定要執行的操作。...是一個可選的參數列表,用于傳遞命令所需的任何參數。
ioctl 的使用通常涉及到與具體設備相關的命令和參數。在你提供的代碼中,ioctl 主要用于配置 TUN/TAP 設備的屬性,例如設置設備的所有者、組、持久性等。
在你的代碼中的一些 ioctl 使用示例:
ioctl(tap_fd, TUNSETIFF, (void *) &ifr); // 設置 TUN/TAP 設備的接口
ioctl(tap_fd, TUNSETOWNER, owner); // 設置 TUN/TAP 設備的所有者
ioctl(tap_fd, TUNSETGROUP, group); // 設置 TUN/TAP 設備的組
ioctl(tap_fd, TUNSETPERSIST, 1); // 設置 TUN/TAP 設備為持久性
這些調用通過 ioctl 來與 TUN/TAP 設備進行通信,執行相應的配置和控制操作。





浙公網安備 33010602011771號