4
* ioctl-based device configuration
7
#include <sys/socket.h>
14
#include <net/if_arp.h>
15
#include <netinet/in.h>
16
#include <linux/route.h>
22
static void copy_name(struct netdev *dev, struct ifreq *ifr)
24
strncpy(ifr->ifr_name, dev->name, sizeof(ifr->ifr_name));
25
ifr->ifr_name[sizeof(ifr->ifr_name) - 1] = '\0';
28
int netdev_getflags(struct netdev *dev, short *flags)
34
if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) {
35
perror("SIOCGIFFLAGS");
39
*flags = ifr.ifr_flags;
43
static int netdev_sif_addr(struct ifreq *ifr, int cmd, __u32 addr)
45
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr;
47
sin->sin_family = AF_INET;
48
sin->sin_addr.s_addr = addr;
50
return ioctl(cfd, cmd, ifr);
53
int netdev_setaddress(struct netdev *dev)
59
if (dev->ip_addr != INADDR_ANY &&
60
netdev_sif_addr(&ifr, SIOCSIFADDR, dev->ip_addr) == -1) {
61
perror("SIOCSIFADDR");
65
if (dev->ip_broadcast != INADDR_ANY &&
66
netdev_sif_addr(&ifr, SIOCSIFBRDADDR, dev->ip_broadcast) == -1) {
67
perror("SIOCSIFBRDADDR");
71
if (dev->ip_netmask != INADDR_ANY &&
72
netdev_sif_addr(&ifr, SIOCSIFNETMASK, dev->ip_netmask) == -1) {
73
perror("SIOCSIFNETMASK");
80
int netdev_setdefaultroute(struct netdev *dev)
84
if (dev->ip_gateway == INADDR_ANY)
87
memset(&r, 0, sizeof(r));
89
((struct sockaddr_in *)&r.rt_dst)->sin_family = AF_INET;
90
((struct sockaddr_in *)&r.rt_dst)->sin_addr.s_addr = INADDR_ANY;
91
((struct sockaddr_in *)&r.rt_gateway)->sin_family = AF_INET;
92
((struct sockaddr_in *)&r.rt_gateway)->sin_addr.s_addr = dev->ip_gateway;
93
((struct sockaddr_in *)&r.rt_genmask)->sin_family = AF_INET;
94
((struct sockaddr_in *)&r.rt_genmask)->sin_addr.s_addr = INADDR_ANY;
95
r.rt_flags = RTF_UP | RTF_GATEWAY;
97
if (ioctl(cfd, SIOCADDRT, &r) == -1 && errno != EEXIST) {
104
int netdev_setmtu(struct netdev *dev)
108
copy_name(dev, &ifr);
109
ifr.ifr_mtu = dev->mtu;
111
return ioctl(cfd, SIOCSIFMTU, &ifr);
114
static int netdev_gif_addr(struct ifreq *ifr, int cmd, __u32 *ptr)
116
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr;
118
if (ioctl(cfd, cmd, ifr) == -1)
121
*ptr = sin->sin_addr.s_addr;
126
int netdev_up(struct netdev *dev)
130
copy_name(dev, &ifr);
132
if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) {
133
perror("SIOCGIFFLAGS");
137
ifr.ifr_flags |= IFF_UP;
139
if (ioctl(cfd, SIOCSIFFLAGS, &ifr) == -1) {
140
perror("SIOCSIFFLAGS");
146
int netdev_down(struct netdev *dev)
150
copy_name(dev, &ifr);
152
if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) {
153
perror("SIOCGIFFLAGS");
157
ifr.ifr_flags &= ~IFF_UP;
159
if (ioctl(cfd, SIOCSIFFLAGS, &ifr) == -1) {
160
perror("SIOCSIFFLAGS");
166
int netdev_init_if(struct netdev *dev)
171
cfd = socket(AF_INET, SOCK_DGRAM, 0);
173
perror("socket(AF_INET)");
177
copy_name(dev, &ifr);
179
if (ioctl(cfd, SIOCGIFINDEX, &ifr) == -1) {
180
perror("SIOCGIFINDEX");
184
dev->ifindex = ifr.ifr_ifindex;
186
if (ioctl(cfd, SIOCGIFMTU, &ifr) == -1) {
187
perror("SIOCGIFMTU");
191
dev->mtu = ifr.ifr_mtu;
193
if (ioctl(cfd, SIOCGIFHWADDR, &ifr) == -1) {
194
perror("SIOCGIFHWADDR");
198
dev->hwtype = ifr.ifr_hwaddr.sa_family;
201
switch (dev->hwtype) {
208
case ARPHRD_LOOPBACK:
215
memcpy(dev->hwaddr, ifr.ifr_hwaddr.sa_data, dev->hwlen);
216
memset(dev->hwbrd, 0xff, dev->hwlen);
219
* Try to get the current interface information.
221
if (dev->ip_addr == INADDR_NONE &&
222
netdev_gif_addr(&ifr, SIOCGIFADDR, &dev->ip_addr) == -1) {
223
perror("SIOCGIFADDR");
225
dev->ip_broadcast = 0;
230
if (dev->ip_broadcast == INADDR_NONE &&
231
netdev_gif_addr(&ifr, SIOCGIFBRDADDR, &dev->ip_broadcast) == -1) {
232
perror("SIOCGIFBRDADDR");
233
dev->ip_broadcast = 0;
236
if (dev->ip_netmask == INADDR_NONE &&
237
netdev_gif_addr(&ifr, SIOCGIFNETMASK, &dev->ip_netmask) == -1) {
238
perror("SIOCGIFNETMASK");