Agora estou usando um serviço escrito em C para gerenciar a interface sozinho. É basicamente um wrapper para dhclient e ip . Este é o código que estou usando para gerenciar minha interface:
#include <stdio.h>
#include <string.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <stdlib.h>
#include <stdbool.h>
#define ENTRY(x) {x, #x}
struct {
unsigned flag;
const char *name;
} ifi_flag_map[] = {
ENTRY(IFF_UP),
ENTRY(IFF_BROADCAST),
ENTRY(IFF_DEBUG),
ENTRY(IFF_LOOPBACK),
ENTRY(IFF_POINTOPOINT),
ENTRY(IFF_NOTRAILERS),
ENTRY(IFF_RUNNING),
ENTRY(IFF_NOARP),
ENTRY(IFF_PROMISC),
ENTRY(IFF_ALLMULTI),
ENTRY(IFF_MASTER),
ENTRY(IFF_SLAVE),
ENTRY(IFF_MULTICAST),
ENTRY(IFF_PORTSEL),
ENTRY(IFF_AUTOMEDIA),
ENTRY(IFF_DYNAMIC),
ENTRY(IFF_LOWER_UP),
ENTRY(IFF_DORMANT),
ENTRY(IFF_ECHO),
};
int InterfaceIndex;
char InterfaceName[32];
char FlushCommand[64];
char DHCPCommand[64];
void check_flags(unsigned flags)
{
size_t i;
bool hasFlagLowerUp = false;
for (i = 0; i < sizeof ifi_flag_map/sizeof ifi_flag_map[0]; i++) {
if (flags & ifi_flag_map[i].flag) {
if (ifi_flag_map[i].name == "IFF_LOWER_UP"){
hasFlagLowerUp = true;
}
}
}
if (!hasFlagLowerUp){
printf("Cable removed. Going to flush IPs now...\n");
system(FlushCommand);
} else {
printf("Flag IFF_LOWER_UP present. Going to call %s.\n", DHCPCommand);
system(DHCPCommand);
}
}
void read_msg(int fd)
{
int len;
char buf[4096];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl sa;
struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
struct nlmsghdr *nh;
len = recvmsg(fd, &msg, 0);
if(len == -1) {
perror("recvmsg");
return;
}
for (nh = (struct nlmsghdr *) buf; NLMSG_OK (nh, len);
nh = NLMSG_NEXT (nh, len)) {
struct ifinfomsg *ifimsg;
if (nh->nlmsg_type == NLMSG_DONE)
return;
if (nh->nlmsg_type == NLMSG_ERROR) {
continue;
}
ifimsg = NLMSG_DATA(nh);
printf("Noticed event on interface with id %u\n", ifimsg->ifi_index);
if (ifimsg->ifi_index == InterfaceIndex) {
printf("Interface is supervised interface %s. Going to check if cable was removed...\n",InterfaceName);
check_flags(ifimsg->ifi_flags);
}
}
}
int main(int argc, char *argv[])
{
if (argc < 3){
printf("Please provide interface id as first argument\n");
printf("Please provide interface name as second argument\n\n");
printf("Example: %s 2 eth0\n", argv[0]);
return 1;
}
if (sscanf (argv[1], "%i", &InterfaceIndex) != 1) {
fprintf(stderr, "Interface index must be integer\n");
return 1;
}
strcpy(InterfaceName,argv[2]);
sprintf(FlushCommand, "ip addr flush dev %s", InterfaceName);
sprintf(DHCPCommand, "dhclient -r %s && dhclient %s", InterfaceName, InterfaceName);
printf("Watching interface %s with id %u for events.\n", InterfaceName, InterfaceIndex);
printf("Will flush IPs from interface %s when cable is removed.\n", InterfaceName);
struct sockaddr_nl sa;
int fd;
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK;
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(fd == -1) {
perror("socket");
return 1;
}
if(bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("bind");
return 1;
}
for(;;) {
read_msg(fd);
}
return 0;
}