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