aboutsummaryrefslogtreecommitdiffstats
path: root/if-linux.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:20 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:20 -0800
commitd97c47cad830d00c9da685cc4ea157d6185f6c97 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /if-linux.c
parent4c5a5fb53bccceff331bae70f748bf9b4609fe0a (diff)
downloadexternal_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.zip
external_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.tar.gz
external_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'if-linux.c')
-rw-r--r--if-linux.c379
1 files changed, 0 insertions, 379 deletions
diff --git a/if-linux.c b/if-linux.c
deleted file mode 100644
index 1009270..0000000
--- a/if-linux.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
- * All rights reserved
-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <asm/types.h> /* Needed for 2.4 kernels */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-
-#include <arpa/inet.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <netinet/ether.h>
-#include <netpacket/packet.h>
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/* Support older kernels */
-#ifndef IFLA_WIRELESS
-# define IFLA_WIRELSSS (IFLFA_MASTER + 1)
-#endif
-
-#include "config.h"
-#include "common.h"
-#include "dhcp.h"
-#include "net.h"
-
-#define BUFFERLEN 256
-
-int
-open_link_socket(struct interface *iface)
-{
- int fd;
- struct sockaddr_nl nl;
-
- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
- return -1;
- memset(&nl, 0, sizeof(nl));
- nl.nl_family = AF_NETLINK;
- nl.nl_groups = RTMGRP_LINK;
- if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1)
- return -1;
- set_cloexec(fd);
- if (iface->link_fd != -1)
- close(iface->link_fd);
- iface->link_fd = fd;
- return 0;
-}
-
-static int
-get_netlink(int fd, int flags,
- int (*callback)(struct nlmsghdr *, const char *),
- const char *ifname)
-{
- char *buffer = NULL;
- ssize_t bytes;
- struct nlmsghdr *nlm;
- int r = -1;
-
- buffer = xzalloc(sizeof(char) * BUFFERLEN);
- for (;;) {
- bytes = recv(fd, buffer, BUFFERLEN, flags);
- if (bytes == -1) {
- if (errno == EAGAIN) {
- r = 0;
- goto eexit;
- }
- if (errno == EINTR)
- continue;
- goto eexit;
- }
- for (nlm = (struct nlmsghdr *)buffer;
- NLMSG_OK(nlm, (size_t)bytes);
- nlm = NLMSG_NEXT(nlm, bytes))
- {
- r = callback(nlm, ifname);
- if (r != 0)
- goto eexit;
- }
- }
-
-eexit:
- free(buffer);
- return r;
-}
-
-static int
-err_netlink(struct nlmsghdr *nlm, _unused const char *ifname)
-{
- struct nlmsgerr *err;
- int l;
-
- if (nlm->nlmsg_type != NLMSG_ERROR)
- return 0;
- l = nlm->nlmsg_len - sizeof(*nlm);
- if ((size_t)l < sizeof(*err)) {
- errno = EBADMSG;
- return -1;
- }
- err = (struct nlmsgerr *)NLMSG_DATA(nlm);
- if (err->error == 0)
- return l;
- errno = -err->error;
- return -1;
-}
-
-static int
-link_netlink(struct nlmsghdr *nlm, const char *ifname)
-{
- int len;
- struct rtattr *rta;
- struct ifinfomsg *ifi;
- char ifn[IF_NAMESIZE + 1];
-
- if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
- return 0;
- len = nlm->nlmsg_len - sizeof(*nlm);
- if ((size_t)len < sizeof(*ifi)) {
- errno = EBADMSG;
- return -1;
- }
- ifi = NLMSG_DATA(nlm);
- if (ifi->ifi_flags & IFF_LOOPBACK)
- return 0;
- rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi)));
- len = NLMSG_PAYLOAD(nlm, sizeof(*ifi));
- *ifn = '\0';
- while (RTA_OK(rta, len)) {
- switch (rta->rta_type) {
- case IFLA_WIRELESS:
- /* Ignore wireless messages */
- if (nlm->nlmsg_type == RTM_NEWLINK &&
- ifi->ifi_change == 0)
- return 0;
- break;
- case IFLA_IFNAME:
- strlcpy(ifn, RTA_DATA(rta), sizeof(ifn));
- break;
- }
- rta = RTA_NEXT(rta, len);
- }
-
- if (strncmp(ifname, ifn, sizeof(ifn)) == 0)
- return 1;
- return 0;
-}
-
-int
-link_changed(struct interface *iface)
-{
- return get_netlink(iface->link_fd, MSG_DONTWAIT,
- &link_netlink, iface->name);
-}
-
-static int
-send_netlink(struct nlmsghdr *hdr)
-{
- int fd, r;
- struct sockaddr_nl nl;
- struct iovec iov;
- struct msghdr msg;
- static unsigned int seq;
-
- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
- return -1;
- memset(&nl, 0, sizeof(nl));
- nl.nl_family = AF_NETLINK;
- if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1) {
- close(fd);
- return -1;
- }
- memset(&iov, 0, sizeof(iov));
- iov.iov_base = hdr;
- iov.iov_len = hdr->nlmsg_len;
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = &nl;
- msg.msg_namelen = sizeof(nl);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- /* Request a reply */
- hdr->nlmsg_flags |= NLM_F_ACK;
- hdr->nlmsg_seq = ++seq;
-
- if (sendmsg(fd, &msg, 0) != -1)
- r = get_netlink(fd, 0, &err_netlink, NULL);
- else
- r = -1;
- close(fd);
- return r;
-}
-
-#define NLMSG_TAIL(nmsg) \
- ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len)))
-
-static int
-add_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
- const void *data, int alen)
-{
- int len = RTA_LENGTH(alen);
- struct rtattr *rta;
-
- if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
- errno = ENOBUFS;
- return -1;
- }
-
- rta = NLMSG_TAIL(n);
- rta->rta_type = type;
- rta->rta_len = len;
- memcpy(RTA_DATA(rta), data, alen);
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
-
- return 0;
-}
-
-static int
-add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, uint32_t data)
-{
- int len = RTA_LENGTH(sizeof(data));
- struct rtattr *rta;
-
- if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
- errno = ENOBUFS;
- return -1;
- }
-
- rta = NLMSG_TAIL(n);
- rta->rta_type = type;
- rta->rta_len = len;
- memcpy(RTA_DATA(rta), &data, sizeof(data));
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
-
- return 0;
-}
-
-struct nlma
-{
- struct nlmsghdr hdr;
- struct ifaddrmsg ifa;
- char buffer[64];
-};
-
-struct nlmr
-{
- struct nlmsghdr hdr;
- struct rtmsg rt;
- char buffer[256];
-};
-
-int
-if_address(const char *ifname,
- const struct in_addr *address, const struct in_addr *netmask,
- const struct in_addr *broadcast, int action)
-{
- struct nlma *nlm;
- int retval = 0;
-
- nlm = xzalloc(sizeof(*nlm));
- nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
- if (action >= 0) {
- nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
- nlm->hdr.nlmsg_type = RTM_NEWADDR;
- } else
- nlm->hdr.nlmsg_type = RTM_DELADDR;
- if (!(nlm->ifa.ifa_index = if_nametoindex(ifname))) {
- free(nlm);
- errno = ENODEV;
- return -1;
- }
- nlm->ifa.ifa_family = AF_INET;
- nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask);
- /* This creates the aliased interface */
- add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL,
- ifname, strlen(ifname) + 1);
- add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL,
- &address->s_addr, sizeof(address->s_addr));
- if (action >= 0)
- add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST,
- &broadcast->s_addr, sizeof(broadcast->s_addr));
-
- if (send_netlink(&nlm->hdr) == -1)
- retval = -1;
- free(nlm);
- return retval;
-}
-
-int
-if_route(const char *ifname,
- const struct in_addr *destination, const struct in_addr *netmask,
- const struct in_addr *gateway, int metric, int action)
-{
- struct nlmr *nlm;
- unsigned int ifindex;
- int retval = 0;
-
-
- if (!(ifindex = if_nametoindex(ifname))) {
- errno = ENODEV;
- return -1;
- }
-
- nlm = xzalloc(sizeof(*nlm));
- nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- nlm->hdr.nlmsg_type = RTM_NEWROUTE;
- if (action == 0)
- nlm->hdr.nlmsg_flags = NLM_F_REPLACE;
- else if (action > 0)
- /*
- * ers@google:
- * commented out NLM_F_EXCL here and below. We
- * sometimes keep one interface up while we are
- * configuring the other one, and this flag
- * causes route addition to fail.
- */
- nlm->hdr.nlmsg_flags = NLM_F_CREATE /* | NLM_F_EXCL */;
- else
- nlm->hdr.nlmsg_type = RTM_DELROUTE;
- nlm->hdr.nlmsg_flags |= NLM_F_REQUEST;
- nlm->rt.rtm_family = AF_INET;
- nlm->rt.rtm_table = RT_TABLE_MAIN;
-
- if (action < 0)
- nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
- else {
- nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/;
- nlm->rt.rtm_protocol = RTPROT_BOOT;
- if (gateway->s_addr == INADDR_ANY)
- nlm->rt.rtm_scope = RT_SCOPE_LINK;
- else
- nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE;
- nlm->rt.rtm_type = RTN_UNICAST;
- }
-
- nlm->rt.rtm_dst_len = inet_ntocidr(*netmask);
- add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST,
- &destination->s_addr, sizeof(destination->s_addr));
- add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY,
- &gateway->s_addr, sizeof(gateway->s_addr));
-
- add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex);
- add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, metric);
-
- if (send_netlink(&nlm->hdr) == -1)
- retval = -1;
- free(nlm);
- return retval;
-}