2016-08-27 1 views
1

Ich versuche, eine IPv6-Adresse zu einer Ethernet-Schnittstelle hinzufügen, mit libmnl. Nachdem ich eine Nachricht erstellt und zum Kernel gesendet hatte, sah ich, dass sie nicht zur Schnittstelle hinzugefügt wurde, obwohl die Rückkehrcodes für die Kernel-Antwort keinen Fehler enthielten. Freundlich kann jemand schauen, und helfen Sie mir, es zu korrigieren. Soll ich dem nlmsghdr oder etwas anderem mehr Attribute hinzufügen?Hinzufügen einer IPv6-Adresse zur Schnittstelle VERWENDUNG von libmnl und rtnetlink

#include <assert.h> 
#include <string.h> 
#include <inttypes.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <libmnl/libmnl.h> 
#include <linux/rtnetlink.h> 
#include <net/if.h> 
#include <time.h> 
static struct mnl_socket *nl; 
static unsigned int nlportid; 

int mnl_init(void); 
int mnl_init(){ 
    nl = mnl_socket_open(NETLINK_ROUTE); 
    if(nl == NULL){ 
     printf("Error: mnl_socket_open\n"); 
     return 0; 
    } 
    if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0){ 
     printf("Error: mnl_socket_bind\n"); 
     return 0; 
    } 
    nlportid = mnl_socket_get_portid(nl); 
    return 1; 
} 
int add_to_interface(const char* eip){ 
    char buf[MNL_SOCKET_BUFFER_SIZE]; 
    struct nlmsghdr *nlh; 
    struct ifaddrmsg *ifm; 
    int ret; 
    uint8_t seq; 

    nlh = mnl_nlmsg_put_header(buf); 

    nlh->nlmsg_type = RTM_NEWADDR; 
    nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; 
    nlh->nlmsg_seq = seq = time(NULL); 

    ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); 

    ifm->ifa_family = AF_INET6; 
    ifm->ifa_prefixlen = 64; 
    ifm->ifa_flags = IFA_F_PERMANENT; 
    ifm->ifa_scope = RT_SCOPE_UNIVERSE; 
    /* TODO get interaface name from user or configuration*/ 
    ifm->ifa_index = if_nametoindex("eth0"); 
    unsigned char eipn[16]; 
    inet_pton(AF_INET6, eip, eipn); 
    mnl_attr_put(nlh, IFA_ADDRESS, 16,eipn); 

    mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct ifaddrmsg)); 

    if(mnl_socket_sendto(nl,nlh, nlh->nlmsg_len) < 0){ 
     printf("Error: mnl_socket_sendto"); 
     return 0; 
    } 
    ret = mnl_socket_recvfrom(nl,buf, sizeof(buf)); 
    if(ret == -1){ 
     printf("Error: mnl_socket_recvfrom"); 
     return 0; 
    } 
    ret = mnl_cb_run(buf, ret, seq, nlportid, NULL, NULL); 
    return 0; 
} 

int main(int argc, char *argv[]){ 
    if(mnl_init()){ 
     add_to_interface("2001::20c:29ff:fe5f:13c7/64"); // for testing 
    } 
} 

Antwort

0

Ich weiß nicht wirklich etwas über libmnl, und die folgende Lösung ist nicht perfekt. Aber falls Sie immer noch stecken ...

Beachten Sie, dass Sie mehrere Fehlercodes löschen. Dieser, insbesondere:

inet_pton(AF_INET6, eip, eipn); 

Sollte etwas in den Zeilen dieses:

ret = inet_pton(AF_INET6, eip, eipn); 
if (ret != 1) { 
    printf("Bad address.\n"); 
    return -22; 
} 

Und ich nehme an, Sie sagen, wo ich mit diesem gehe. Dies:

add_to_interface("2001::20c:29ff:fe5f:13c7/64"); // for testing 

Sollte dies sein:

add_to_interface("2001::20c:29ff:fe5f:13c7"); // for testing 

, dass es für mich fixiert. Außer es hagelt bei mnl_socket_recvfrom(), weil der Kernel scheinbar nicht antwortet.

Aber seien Sie vorsichtig mit diesen Fehlercodes; diejenigen, die ich erwähnt habe, sind nicht die einzigen.

+0

Pablo hier antwortete http://www.spinics.net/lists/netfilter/msg56909.html und dass es gelöst. – Khawar

+0

Fügen Sie 'NLM_F_ACK' zu' nlh-> nlmsg_flags' hinzu, um eine Antwort vom Kernel zu erhalten. – user3637203

0

Lösung von Pablo Neira,

eipn sollte stattdessen 'struct in6_addr' sein.

mnl_attr_put(nlh, IFA_ADDRESS, 16,eipn); 

So sieht das so:

 mnl_attr_put(nlh, IFA_ADDRESS, sizeof(eipn), &eipn); 
Verwandte Themen