1 #include <sys/socket.h>
4 #include <linux/rtnetlink.h>
5 #include <linux/sockios.h>
6 #include <linux/if_vlan.h>
13 #include <netlink/msg.h>
19 static int sock_ioctl
= -1;
20 static struct nl_sock
*sock_rtnl
= NULL
;
24 sock_ioctl
= socket(AF_LOCAL
, SOCK_DGRAM
, 0);
25 fcntl(sock_ioctl
, F_SETFD
, fcntl(sock_ioctl
, F_GETFD
) | FD_CLOEXEC
);
27 if ((sock_rtnl
= nl_socket_alloc())) {
28 if (nl_connect(sock_rtnl
, NETLINK_ROUTE
)) {
29 nl_socket_free(sock_rtnl
);
34 return -(sock_ioctl
< 0 || !sock_rtnl
);
37 static int system_rtnl_call(struct nl_msg
*msg
)
39 int s
= -(nl_send_auto_complete(sock_rtnl
, msg
)
40 || nl_wait_for_ack(sock_rtnl
));
45 int system_bridge_addbr(struct device
*bridge
)
47 return ioctl(sock_ioctl
, SIOCBRADDBR
, bridge
->ifname
);
50 int system_bridge_delbr(struct device
*bridge
)
52 return ioctl(sock_ioctl
, SIOCBRDELBR
, bridge
->ifname
);
55 static int system_bridge_if(struct device
*bridge
, struct device
*dev
, int cmd
)
58 ifr
.ifr_ifindex
= dev
->ifindex
;
59 strncpy(ifr
.ifr_name
, bridge
->ifname
, sizeof(ifr
.ifr_name
));
60 return ioctl(sock_ioctl
, cmd
, &ifr
);
63 int system_bridge_addif(struct device
*bridge
, struct device
*dev
)
65 return system_bridge_if(bridge
, dev
, SIOCBRADDIF
);
68 int system_bridge_delif(struct device
*bridge
, struct device
*dev
)
70 return system_bridge_if(bridge
, dev
, SIOCBRDELIF
);
73 static int system_vlan(struct device
*dev
, int id
)
75 struct vlan_ioctl_args ifr
= {
76 .cmd
= (id
== 0) ? DEL_VLAN_CMD
: ADD_VLAN_CMD
,
79 strncpy(ifr
.device1
, dev
->ifname
, sizeof(ifr
.device1
));
80 return ioctl(sock_ioctl
, SIOCSIFVLAN
, &ifr
);
83 int system_vlan_add(struct device
*dev
, int id
)
85 return system_vlan(dev
, id
);
88 int system_vlan_del(struct device
*dev
)
90 return system_vlan(dev
, 0);
93 static int system_if_flags(struct device
*dev
, unsigned add
, unsigned rem
)
96 strncpy(ifr
.ifr_name
, dev
->ifname
, sizeof(ifr
.ifr_name
));
97 ioctl(sock_ioctl
, SIOCGIFFLAGS
, &ifr
);
99 ifr
.ifr_flags
&= ~rem
;
100 return ioctl(sock_ioctl
, SIOCSIFFLAGS
, &ifr
);
103 int system_if_up(struct device
*dev
)
105 return system_if_flags(dev
, IFF_UP
, 0);
108 int system_if_down(struct device
*dev
)
110 return system_if_flags(dev
, 0, IFF_UP
);
113 int system_if_check(struct device
*dev
)
116 strncpy(ifr
.ifr_name
, dev
->ifname
, sizeof(ifr
.ifr_name
));
117 if (ioctl(sock_ioctl
, SIOCGIFINDEX
, &ifr
))
120 dev
->ifindex
= ifr
.ifr_ifindex
;
122 /* if (!strcmp(dev->ifname, "eth0"))
123 device_set_present(dev, true); */
127 static int system_addr(struct device
*dev
, struct device_addr
*addr
, int cmd
)
129 int alen
= ((addr
->flags
& DEVADDR_FAMILY
) == DEVADDR_INET4
) ? 4 : 16;
130 struct ifaddrmsg ifa
= {
131 .ifa_family
= (alen
== 4) ? AF_INET
: AF_INET6
,
132 .ifa_prefixlen
= addr
->mask
,
133 .ifa_index
= dev
->ifindex
,
136 struct nl_msg
*msg
= nlmsg_alloc_simple(cmd
, 0);
140 nlmsg_append(msg
, &ifa
, sizeof(ifa
), 0);
141 nla_put(msg
, IFA_ADDRESS
, alen
, &addr
->addr
);
142 return system_rtnl_call(msg
);
145 int system_add_address(struct device
*dev
, struct device_addr
*addr
)
147 return system_addr(dev
, addr
, RTM_NEWADDR
);
150 int system_del_address(struct device
*dev
, struct device_addr
*addr
)
152 return system_addr(dev
, addr
, RTM_DELADDR
);
155 static int system_rt(struct device
*dev
, struct device_route
*route
, int cmd
)
157 int alen
= ((route
->flags
& DEVADDR_FAMILY
) == DEVADDR_INET4
) ? 4 : 16;
161 have_gw
= !!route
->nexthop
.in
.s_addr
;
163 have_gw
= route
->nexthop
.in6
.s6_addr32
[0] ||
164 route
->nexthop
.in6
.s6_addr32
[1] ||
165 route
->nexthop
.in6
.s6_addr32
[2] ||
166 route
->nexthop
.in6
.s6_addr32
[3];
168 unsigned char scope
= (cmd
== RTM_DELROUTE
) ? RT_SCOPE_NOWHERE
:
169 (have_gw
) ? RT_SCOPE_UNIVERSE
: RT_SCOPE_LINK
;
172 .rtm_family
= (alen
== 4) ? AF_INET
: AF_INET6
,
173 .rtm_dst_len
= route
->mask
,
174 .rtm_table
= RT_TABLE_MAIN
,
175 .rtm_protocol
= RTPROT_BOOT
,
177 .rtm_type
= (cmd
== RTM_DELROUTE
) ? 0: RTN_UNICAST
,
180 struct nl_msg
*msg
= nlmsg_alloc_simple(cmd
, 0);
184 nlmsg_append(msg
, &rtm
, sizeof(rtm
), 0);
187 nla_put(msg
, RTA_DST
, alen
, &route
->addr
);
190 nla_put(msg
, RTA_GATEWAY
, alen
, &route
->nexthop
);
192 if (route
->flags
& DEVADDR_DEVICE
)
193 nla_put_u32(msg
, RTA_OIF
, dev
->ifindex
);
195 return system_rtnl_call(msg
);
198 int system_add_route(struct device
*dev
, struct device_route
*route
)
200 return system_rt(dev
, route
, RTM_NEWROUTE
);
203 int system_del_route(struct device
*dev
, struct device_route
*route
)
205 return system_rt(dev
, route
, RTM_DELROUTE
);