1a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/*
2a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * Copyright 2012 Daniel Drown <dan-android@drown.org>
3a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown *
4a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * Licensed under the Apache License, Version 2.0 (the "License");
5a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * you may not use this file except in compliance with the License.
6a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * You may obtain a copy of the License at
7a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown *
8a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * http://www.apache.org/licenses/LICENSE-2.0
9a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown *
10a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * Unless required by applicable law or agreed to in writing, software
11a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * distributed under the License is distributed on an "AS IS" BASIS,
12a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * See the License for the specific language governing permissions and
14a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * limitations under the License.
15a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown *
16a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * setif.c - network interface configuration
17a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */
18a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <errno.h>
19a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <netinet/in.h>
20a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <net/if.h>
21a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
22a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <linux/rtnetlink.h>
23a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <netlink/handlers.h>
24a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include <netlink/msg.h>
25a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
26a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown#include "netlink_msg.h"
27a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
28a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: add_address
29a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * adds an IP address to/from an interface, returns 0 on success and <0 on failure
30a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * ifname    - name of interface to change
31a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * family    - address family (AF_INET, AF_INET6)
32a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * address   - pointer to a struct in_addr or in6_addr
33a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * prefixlen - bitlength of network (example: 24 for AF_INET's 255.255.255.0)
34a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * broadcast - broadcast address (only for AF_INET, ignored for AF_INET6)
35a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */
36a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownint add_address(const char *ifname, int family, const void *address, int prefixlen, const void *broadcast) {
37a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  int retval;
38a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  size_t addr_size;
39a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  struct ifaddrmsg ifa;
40a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  struct nl_msg *msg = NULL;
41a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
42a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  addr_size = inet_family_size(family);
43a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(addr_size == 0) {
44a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -EAFNOSUPPORT;
45a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
46a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
47a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
48a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  memset(&ifa, 0, sizeof(ifa));
49a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if (!(ifa.ifa_index = if_nametoindex(ifname))) {
50a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -ENODEV;
51a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
52a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
53a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  ifa.ifa_family = family;
54a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  ifa.ifa_prefixlen = prefixlen;
55a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  ifa.ifa_scope = RT_SCOPE_UNIVERSE;
56a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
57a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  msg = nlmsg_alloc_ifaddr(RTM_NEWADDR, NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE, &ifa);
58a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(!msg) {
59a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -ENOMEM;
60a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
61a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
62a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
63a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(nla_put(msg, IFA_LOCAL, addr_size, address) < 0) {
64a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -ENOMEM;
65a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
66a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
67a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(family == AF_INET6) {
68a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    // AF_INET6 gets IFA_LOCAL + IFA_ADDRESS
69a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    if(nla_put(msg, IFA_ADDRESS, addr_size, address) < 0) {
70a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown      retval = -ENOMEM;
71a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown      goto cleanup;
72a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    }
73a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  } else if(family == AF_INET) {
74a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    // AF_INET gets IFA_LOCAL + IFA_BROADCAST
75a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    if(nla_put(msg, IFA_BROADCAST, addr_size, broadcast) < 0) {
76a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown      retval = -ENOMEM;
77a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown      goto cleanup;
78a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    }
79a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  } else {
80a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -EAFNOSUPPORT;
81a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
82a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
83a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
84a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  retval = netlink_sendrecv(msg);
85a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
86a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drowncleanup:
87a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(msg)
88a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    nlmsg_free(msg);
89a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
90a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  return retval;
91a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown}
92a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
93a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown/* function: if_up
94a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * sets interface link state to up and sets mtu, returns 0 on success and <0 on failure
95a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * ifname - interface name to change
96a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown * mtu    - new mtu
97a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown */
98a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drownint if_up(const char *ifname, int mtu) {
99a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  int retval = -1;
100a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  struct ifinfomsg ifi;
101a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  struct nl_msg *msg = NULL;
102a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
103a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  memset(&ifi, 0, sizeof(ifi));
104a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if (!(ifi.ifi_index = if_nametoindex(ifname))) {
105a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -ENODEV;
106a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
107a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
108a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  ifi.ifi_change = IFF_UP;
109a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  ifi.ifi_flags = IFF_UP;
110a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
111a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  msg = nlmsg_alloc_ifinfo(RTM_SETLINK, NLM_F_ACK | NLM_F_REQUEST | NLM_F_ROOT, &ifi);
112a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(!msg) {
113a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -ENOMEM;
114a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
115a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
116a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
117a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(nla_put(msg, IFLA_MTU, 4, &mtu) < 0) {
118a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    retval = -ENOMEM;
119a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    goto cleanup;
120a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  }
121a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
122a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  retval = netlink_sendrecv(msg);
123a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
124a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drowncleanup:
125a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  if(msg)
126a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown    nlmsg_free(msg);
127a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown
128a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown  return retval;
129a45056e35c1af2a0f0a6eed258fd5fdf4846a79fDaniel Drown}
130