C에서 TUN 인터페이스의 IP 주소 및 피어 IP 주소를 설정하는 방법

C에서 TUN 인터페이스의 IP 주소 및 피어 IP 주소를 설정하는 방법

저는 CMU용 달 탐사선을 개발하는 학생이고 달 탐사선에 있는 두 장치 간의 TUN 인터페이스 통신을 사용해야 합니다. TUN 인터페이스를 생성할 수 있지만 C에서 해당 IP 주소를 할당할 수 없습니다.

TUN 디바이스 제작 후 현재 상태는 다음과 같습니다.

41: tun11: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500
link/none

원하는 상태는 다음과 같습니다.

14: tun71: <POINTOPOINT,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 500
link/none 
inet 192.168.0.29 peer 192.168.0.23/32 scope global tun71
   valid_lft forever preferred_lft forever

ifreq에 대해 dstaddr 설정을 시도했지만 아무 소용이 없습니다.

int fd;
int dst_fd;
struct ifreq ifr;
struct sockaddr_in* addr;
struct sockaddr_in* dst_addr;

fd = socket(AF_INET, SOCK_DGRAM, 0);
dst_fd = socket(AF_INET, SOCK_DGRAM, 0);

ifr.ifr_addr.sa_family = AF_INET;

memcpy(ifr.ifr_name, "tun11", IFNAMSIZ - 1);
addr = (struct sockaddr_in*)&ifr.ifr_addr;
dst_addr = (struct sockaddr_in*)&ifr.ifr_dstaddr;

inet_pton(AF_INET, ip_address, &addr->sin_addr);
inet_pton(AF_INET, ip_address, &dst_addr->sin_addr);
int err;
if ( (err = ioctl(fd, SIOCSIFADDR, &ifr)) == -1 ) {
    perror("ioctl SIOCSIFFLAGS");close(fd);exit(1);
}

나는 무엇을 더 해야할지 모르겠습니다. 명령을 내린 후 IP를 디버깅하려고 하는데 알 수 없습니다.

답변1

아직 안 해보셨다면,테스트 튜닝 만들기:

# ip tuntap add mode tun dev tun0
# ip address show dev tun0
5: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500
    link/none

이것은 질문의 내용과 매우 유사해 보입니다. 지금 도착어떤 코드가 필요한지 확인하세요...

// uptun.c - set an IP address and UP a tun
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>             /* offsetof */
#include <net/if.h>
#include <net/if.h>
#include <linux/sockios.h>
#include <netinet/in.h>
#if __GLIBC__ >=2 && __GLIBC_MINOR >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h>
#else
#include <asm/types.h>
#include <linux/if_ether.h>
#endif

// TWEAK
#define IFNAME "tun0"
#define HOST "192.168.0.29"

#define ifreq_offsetof(x) offsetof(struct ifreq, x)

int main(int argc, char **argv) {
    struct ifreq ifr;
    struct sockaddr_in sai;
    int sockfd; /* socket fd we use to manipulate stuff with */
    int selector;
    unsigned char mask;

    char *p;

    /* Create a channel to the NET kernel. */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    /* get interface name */
    strncpy(ifr.ifr_name, IFNAME, IFNAMSIZ);

    memset(&sai, 0, sizeof(struct sockaddr));
    sai.sin_family = AF_INET;
    sai.sin_port   = 0;

    sai.sin_addr.s_addr = inet_addr(HOST);

    p = (char *) &sai;
    memcpy((((char *) &ifr + ifreq_offsetof(ifr_addr))), p,
           sizeof(struct sockaddr));

    ioctl(sockfd, SIOCSIFADDR, &ifr);
    ioctl(sockfd, SIOCGIFFLAGS, &ifr);

    ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
    // ifr.ifr_flags &= ~selector;  // unset something

    ioctl(sockfd, SIOCSIFFLAGS, &ifr);
    close(sockfd);
    return 0;
}

이는 우리에게 다음을 제공합니다.

# make uptun
cc     uptun.c   -o uptun
# ./uptun
# ip address show dev tun0
5: tun0: <NO-CARRIER,POINTOPOINT,MULTICAST,NOARP,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 500
    link/none
    inet 192.168.0.29/32 scope global tun0
       valid_lft forever preferred_lft forever

피어 주소만 누락되었습니다. 일부 altagoobingleduckgoing은 tun에 SIOCSIFDSTADDR(설정된 목적지, duh)가 추가로 있음을 나타냅니다 SIOCSIFADDR. 이 줄 다음에 스크립트에 넣어 봅시다 SIOCGIFFLAGS...

        // KLUGE copypasta in the destination address
        sai.sin_addr.s_addr = inet_addr("192.168.0.23");
        p = (char *) &sai;
        memcpy((((char *) &ifr + ifreq_offsetof(ifr_addr))), p,
               sizeof(struct sockaddr));
        ioctl(sockfd, SIOCSIFDSTADDR, &ifr);

컴파일하고 다시 실행하면 다음과 같은 결과 uptun가 나타납니다.

# ip address show dev tun0
5: tun0: <NO-CARRIER,POINTOPOINT,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 500
    link/none
    inet 192.168.0.29 peer 192.168.0.23/32 scope global tun0
       valid_lft forever preferred_lft forever

관련 정보