blob: 2022d240bed1ba3d75485901460503dae6694e4c [file] [log] [blame]
Harald Weltef7365592020-04-15 21:48:45 +02001/* SPDX-License-Identifier: GPL-2.0 */
2#include <unistd.h>
3#include <stdint.h>
4#include <stdbool.h>
5#include <stdlib.h>
6#include <string.h>
7#include <stdio.h>
8#include <errno.h>
9#include <sys/types.h>
10#include <sys/socket.h>
11
12#include <netinet/ip.h>
13#include <netinet/ip6.h>
14
15#include <linux/if.h>
16#include <linux/if_tun.h>
17#include <sys/ioctl.h>
18
19#include <netlink/socket.h>
20#include <netlink/route/link.h>
21#include <netlink/route/addr.h>
22#include <netlink/route/route.h>
23#include <netlink/route/nexthop.h>
24
25#include <osmocom/core/utils.h>
26
27/***********************************************************************
28 * netlink helper functions
29 ***********************************************************************/
30
31static int _netdev_addr(struct nl_sock *nlsk, int ifindex, const struct sockaddr_storage *ss, bool add)
32{
33 const struct sockaddr_in6 *sin6;
34 const struct sockaddr_in *sin;
35 struct nl_addr *local = NULL;
36 struct rtnl_addr *addr;
37 int rc;
38
39 switch (ss->ss_family) {
40 case AF_INET:
41 sin = (struct sockaddr_in *) ss;
42 local = nl_addr_build(AF_INET, &sin->sin_addr, 4);
43 break;
44 case AF_INET6:
45 sin6 = (struct sockaddr_in6 *) ss;
46 local = nl_addr_build(AF_INET6, &sin6->sin6_addr, 16);
47 break;
48 }
49 OSMO_ASSERT(local);
50
51 addr = rtnl_addr_alloc();
52 OSMO_ASSERT(addr);
53 rtnl_addr_set_ifindex(addr, ifindex);
54 OSMO_ASSERT(rtnl_addr_set_local(addr, local) == 0);
55
56 if (add)
57 rc = rtnl_addr_add(nlsk, addr, 0);
58 else
59 rc = rtnl_addr_delete(nlsk, addr, 0);
60
61 rtnl_addr_put(addr);
62
63 return rc;
64}
65
66int netdev_add_addr(struct nl_sock *nlsk, int ifindex, const struct sockaddr_storage *ss)
67{
68 return _netdev_addr(nlsk, ifindex, ss, true);
69}
70
71int netdev_del_addr(struct nl_sock *nlsk, int ifindex, const struct sockaddr_storage *ss)
72{
73 return _netdev_addr(nlsk, ifindex, ss, false);
74}
75
76int netdev_set_link(struct nl_sock *nlsk, int ifindex, bool up)
77{
78 struct rtnl_link *link, *change;
79 int rc;
80
81 rc = rtnl_link_get_kernel(nlsk, ifindex, NULL, &link);
82 if (rc < 0)
83 return rc;
84
85 change = rtnl_link_alloc();
86 OSMO_ASSERT(change);
87
88 if (up)
89 rtnl_link_set_flags(change, IFF_UP);
90 else
91 rtnl_link_unset_flags(change, IFF_UP);
92
93 rc = rtnl_link_change(nlsk, link, change, 0);
94
95 rtnl_link_put(change);
96 rtnl_link_put(link);
97
98 return rc;
99}
100
101int netdev_add_defaultroute(struct nl_sock *nlsk, int ifindex, uint8_t family)
102{
103 struct rtnl_route *route = rtnl_route_alloc();
104 struct rtnl_nexthop *nhop = rtnl_route_nh_alloc();
105 struct nl_addr *dst, *gw;
106 uint8_t buf[16];
107 int rc;
108
109 OSMO_ASSERT(route);
110 OSMO_ASSERT(nhop);
111
112 /* destination address of route: all-zero */
113 memset(buf, 0, sizeof(buf));
114 dst = nl_addr_build(family, buf, family == AF_INET ? 4 : 16);
115 OSMO_ASSERT(dst);
116 nl_addr_set_prefixlen(dst, 0);
117
118 /* gateway address of route: also all-zero */
119 gw = nl_addr_clone(dst);
120 OSMO_ASSERT(gw);
121
122 /* nexthop for route */
123 rtnl_route_nh_set_ifindex(nhop, ifindex);
124 rtnl_route_nh_set_gateway(nhop, gw);
125
126 /* tie everything together in the route */
127 rtnl_route_set_dst(route, dst);
128 rtnl_route_set_family(route, family);
129 rtnl_route_add_nexthop(route, nhop);
130
131 rc = rtnl_route_add(nlsk, route, NLM_F_CREATE);
132
133 //rtnl_route_nh_free(nhop);
134 nl_addr_put(gw);
135 nl_addr_put(dst);
136 rtnl_route_put(route);
137
138 return rc;
139}