anaconda.spec | 2 -
command-stubs/dhcpclient-stub | 116 ----
isys/Makefile | 9 -
isys/iface.c | 1153 +++++++++++++++++++++++++++++++++++++++--
isys/iface.h | 191 +++++++-
isys/isys.c | 193 ++++----
isys/wireless.c | 34 +-
isys/wireless.h | 4 +-
loader2/Makefile | 12 +-
loader2/linuxrc.s390 | 1 -
loader2/loader.c | 57 ++-
loader2/net.c | 1148 +++++++++++++++++++++--------------------
loader2/net.h | 68 +--
loader2/nfsinstall.c | 34 +-
loader2/telnetd.c | 179 ++++----
loader2/urlinstall.c | 6 +-
loader2/urls.c | 2 +-
scripts/mk-images | 11 +-
scripts/upd-instroot | 13 +-
19 files changed, 2187 insertions(+), 1046 deletions(-)
diff --git a/anaconda.spec b/anaconda.spec
index 19dc803..5840cd7 100644
--- a/anaconda.spec
+++ b/anaconda.spec
@@ -17,7 +17,6 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%define dmver 1.02.17-6
%define gettextver 0.11
%define intltoolver 0.31.2-3
-%define libdhcpver 1.99.8-1
%define libnlver 1.0
%define libselinuxver 1.6
%define mkinitrdver 5.1.2-1
@@ -46,7 +45,6 @@ BuildRequires: isomd5sum-devel
BuildRequires: libX11-devel
BuildRequires: libXt-devel
BuildRequires: libXxf86misc-devel
-BuildRequires: libdhcp-devel >= %{libdhcpver}
BuildRequires: libnl-devel >= %{libnlver}
BuildRequires: libselinux-devel >= %{libselinuxver}
BuildRequires: libsepol-devel
diff --git a/command-stubs/dhcpclient-stub b/command-stubs/dhcpclient-stub
deleted file mode 100755
index b5ffdc7..0000000
--- a/command-stubs/dhcpclient-stub
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/python
-#
-# dhcpclient-stub
-#
-# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-
-import os
-import sys
-import getopt
-
-# for testing
-if (os.path.exists('isys')):
- sys.path.append('isys')
-
-sys.path.append('/usr/lib/anaconda')
-
-import isys
-from sys import argv
-
-import network
-from network import NetworkDevice
-
-def showusage():
- print "Usage: dhcpclient [-4] [-6] [-a] [-i device] [-c class]"
-
-def showhelp():
- showusage()
- print "Options:"
- print " -4 Configure IPv4 stack via DHCP"
- print " -6 Configure IPv6 stack (DHCPv6 unless -a given)"
- print " -a Use IPv6 auto neighbor discovery"
- print " -i device Device to configure (e.g., eth0)"
- print " -c class Optional DHCP class name"
- print "Defaults:"
- print " dhcpclient -4 -6 -a -i eth0"
-
-if __name__ == "__main__":
- dev = NetworkDevice('eth0')
- dev.set(('bootproto', 'dhcp'))
-
- auto = False
- stacks = 0
-
- help = False
- unknown = False
-
- try:
- opts, args = getopt.getopt(sys.argv[1:], '46ai:c:',
- ['ipv4', 'ipv6', 'auto', 'interface',
- 'class', 'help'])
- except getopt.GetoptError:
- help = True
-
- for o, a in opts:
- if o in ('-4', '--ipv4'):
- stacks += 4
- elif o in ('-6', '--ipv6'):
- stacks += 6
- elif o in ('-a', '--auto'):
- auto = True
- elif o in ('-i', '--interface'):
- dev.set(('device', a))
- elif o in ('-c', '--class'):
- dev.set(('dhcpclass', a))
- elif o in ('--help'):
- help = True
- else:
- unknown = True
-
- if help:
- showhelp()
- sys.exit(0)
-
- if unknown:
- showusage()
- sys.exit(1)
-
- if auto:
- dev.set(('ipv6_autoconf', 'yes'))
- else:
- dev.set(('ipv6_autoconf', 'no'))
-
- if stacks == 10:
- dev.set(('useipv4', True))
- dev.set(('useipv6', True))
- elif stacks == 6:
- dev.set(('useipv4', False))
- dev.set(('useipv6', True))
- elif stacks == 4:
- dev.set(('useipv4', True))
- dev.set(('useipv6', False))
-
- try:
- ns = isys.dhcpNetDevice(dev)
- if ns:
- f = open('/etc/resolv.conf', 'w')
- f.write("nameserver %s\n" % ns)
- f.close()
- except:
- print "Error configuring device %s." % (dev.get('device'),)
-
- sys.exit(0)
diff --git a/isys/Makefile b/isys/Makefile
index 5935277..690beaf 100644
--- a/isys/Makefile
+++ b/isys/Makefile
@@ -38,10 +38,6 @@ SUBDIRS =
LOADLIBES += $(shell pkg-config --libs libnl-1)
CFLAGS += $(shell pkg-config --cflags libnl-1)
-# libdhcp
-LOADLIBES += $(shell pkg-config --libs libdhcp)
-CFLAGS += $(shell pkg-config --cflags libdhcp)
-
ifeq ($(ARCH),sparc)
PYMODULES += _silo.so
SOURCES += silo.c
@@ -79,7 +75,6 @@ clean:
rm -f *.o *.so *.lo *.a *.pyc $(TARGET) $(SOBJECTS)
rm -f $(OBJECTS)
rm -f .depend
- rm -f nl
for d in $(SUBDIRS); do make -C $$d clean; done
install: all
@@ -89,10 +84,6 @@ install: all
subdirs:
for d in $(SUBDIRS); do make -C $$d; done
-nltest: str.o nl.c nl.h
- $(CC) -c $(CFLAGS) -DTESTING nl.c -o nl.o
- $(CC) -DTESTING nl.o -o nl $(LOADLIBES) str.o
-
depend:
$(CPP) -M $(CFLAGS) $(SOURCES) > .depend
diff --git a/isys/iface.c b/isys/iface.c
index 51f923c..d46bedd 100644
--- a/isys/iface.c
+++ b/isys/iface.c
@@ -1,7 +1,7 @@
/*
- * iface.c - Network interface control functions
+ * iface.c - Network interface configuration API
*
- * Copyright (C) 2006, 2007, 2008 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,34 +21,79 @@
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
#include
+#include
+#include
#include
#include
#include "iface.h"
#include "str.h"
+/* Internal-only function prototypes. */
+static struct nl_handle *_iface_get_handle(void);
+static struct nl_cache *_iface_get_link_cache(struct nl_handle **);
+static int _iface_name_to_index(char *);
+static int _iface_up_or_down(char *, int);
+static int _iface_autoconf_on_or_off(char *, int);
+static int _iface_is_autoconf(char *);
+static struct nl_addr *_iface_in_addr2nl_addr(struct in_addr *,
+ struct in_addr *);
+static struct nl_addr *_iface_in6_addr2nl_addr(struct in6_addr *, int);
+static int _iface_kill_client_daemon(pid_t);
+static int _iface_set_hostname(iface_t *);
+static int _iface_have_valid_addr(void *addr, int family, int length);
+static int _iface_set_gateway(void *gw, int family);
+static int _iface_redirect_io(char *device, int fd, int mode);
+static int _iface_kill_clients(char *ifname);
+
+/* IPv6 autoconfiguration flags in /proc/sys/net/ipv6/conf/ethX */
+static char *flags[] = {"accept_ra", "accept_redirects", "autoconf", NULL};
+
/*
- * Return an NETLINK_ROUTE cache.
+ * Return a libnl handle for NETLINK_ROUTE.
*/
-struct nl_cache *iface_get_link_cache(struct nl_handle **handle) {
- struct nl_cache *cache = NULL;
+static struct nl_handle *_iface_get_handle(void) {
+ struct nl_handle *handle = NULL;
- if ((*handle = nl_handle_alloc()) == NULL) {
- perror("nl_handle_alloc() failure in iface_get_link_cache()");
+ if ((handle = nl_handle_alloc()) == NULL) {
return NULL;
}
- if (nl_connect(*handle, NETLINK_ROUTE)) {
- perror("nl_connect() failure in iface_get_link_cache()");
- nl_handle_destroy(*handle);
+ if (nl_connect(handle, NETLINK_ROUTE)) {
+ nl_handle_destroy(handle);
+ return NULL;
+ }
+
+ return handle;
+}
+
+/*
+ * Return an NETLINK_ROUTE cache.
+ */
+static struct nl_cache *_iface_get_link_cache(struct nl_handle **handle) {
+ struct nl_cache *cache = NULL;
+
+ if ((*handle = _iface_get_handle()) == NULL) {
return NULL;
}
if ((cache = rtnl_link_alloc_cache(*handle)) == NULL) {
- perror("rtnl_link_alloc_cache() failure in iface_get_link_cache()");
nl_close(*handle);
nl_handle_destroy(*handle);
return NULL;
@@ -58,6 +103,533 @@ struct nl_cache *iface_get_link_cache(struct nl_handle **handle) {
}
/*
+ * Convert an interface name to index number.
+ */
+static int _iface_name_to_index(char *ifname) {
+ struct nl_handle *handle = NULL;
+ struct nl_cache *cache = NULL;
+
+ if (ifname == NULL) {
+ return -1;
+ }
+
+ if ((cache = _iface_get_link_cache(&handle)) == NULL) {
+ return -1;
+ }
+
+ return rtnl_link_name2i(cache, ifname);
+}
+
+/*
+ * Set or clear IFF_UP and IFF_RUNNING flags.
+ */
+static int _iface_up_or_down(char *ifname, int toggle) {
+ struct nl_handle *handle = NULL;
+ struct nl_cache *cache = NULL;
+ struct rtnl_link *request = NULL;
+ struct rtnl_link *link = NULL;
+
+ if (ifname == NULL) {
+ return 1;
+ }
+
+ /* set IFF_UP and IFF_RUNNING */
+ if ((cache = _iface_get_link_cache(&handle)) == NULL) {
+ return 2;
+ }
+
+ if ((request = rtnl_link_alloc()) == NULL) {
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ return 3;
+ }
+
+ if ((link = rtnl_link_get_by_name(cache, ifname)) == NULL) {
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ return 4;
+ }
+
+ if (toggle) {
+ rtnl_link_set_flags(request, rtnl_link_str2flags("up"));
+ rtnl_link_set_flags(request, rtnl_link_str2flags("running"));
+ } else if (!toggle) {
+ rtnl_link_unset_flags(request, rtnl_link_str2flags("up"));
+ rtnl_link_unset_flags(request, rtnl_link_str2flags("running"));
+ }
+
+ if (rtnl_link_change(handle, link, request, 0)) {
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ return 5;
+ }
+
+ rtnl_link_put(link);
+ nl_close(handle);
+ nl_handle_destroy(handle);
+
+ return 0;
+}
+
+/*
+ * Enable or disable IPv6 autoconfiguration on the specified interface.
+ */
+static int _iface_autoconf_on_or_off(char *ifname, int toggle) {
+ int i = 0, fd;
+ char *flagpath = NULL;
+ char val[2];
+
+ if (ifname == NULL) {
+ return 1;
+ }
+
+ if (toggle != 0 || toggle != 1) {
+ return 2;
+ }
+
+ val[0] = toggle + 48;
+ val[1] = '\0';
+
+ while (flags[i] != NULL) {
+ if (flagpath != NULL) {
+ free(flagpath);
+ flagpath = NULL;
+ }
+
+ if (asprintf(&flagpath, "/proc/sys/net/ipv6/conf/%s/%s",
+ ifname, flags[i]) == -1) {
+ return 3;
+ }
+
+ fd = open(flagpath, O_RDWR);
+ if (fd >= 0) {
+ if (write(fd, val, 1) == -1) {
+ close(fd);
+ return 4;
+ }
+
+ close(fd);
+ }
+
+ i++;
+ }
+
+ return 0;
+}
+
+/*
+ * Returns 1 if IPv6 autoconfiguration is enabled, 0 if it disabled.
+ * A return value of -1 indicates error.
+ */
+static int _iface_is_autoconf(char *ifname) {
+ int i = 0, ret = 0, fd = -1;
+ long int conv = 0;
+ char *flagpath = NULL;
+ char buf[2];
+ char *tmp = NULL;
+
+ if (ifname == NULL) {
+ return 0;
+ }
+
+ while (flags[i] != NULL) {
+ if (flagpath != NULL) {
+ free(flagpath);
+ flagpath = NULL;
+ }
+
+ if (asprintf(&flagpath, "/proc/sys/net/ipv6/conf/%s/%s",
+ ifname, flags[i]) == -1) {
+ return -1;
+ }
+
+ fd = open(flagpath, O_RDONLY);
+ if (fd >= 0) {
+ if (read(fd, &buf, sizeof(buf) - 1) == -1) {
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ buf[1] = '\0';
+ conv = strtol(buf, &tmp, 10);
+
+ if ((conv == LONG_MIN || conv == LONG_MAX) && errno == ERANGE) {
+ return -1;
+ }
+
+ ret += conv;
+ }
+
+ i++;
+ }
+
+ if (ret == i) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * Convert an IPv4 address and accompanying netmask from struct in_addr to
+ * a struct nl_addr. The netmask is optional. Pass NULL for netmask if you
+ * just want to convert an arbitrary in_addr to nl_addr. Return NULL on
+ * failure.
+ */
+static struct nl_addr *_iface_in_addr2nl_addr(struct in_addr *ipaddr,
+ struct in_addr *netmask) {
+ int prefix = -1;
+ char ipbuf[INET_ADDRSTRLEN+1];
+ char *tmpbuf = NULL;
+ struct nl_addr *addr = NULL;
+
+ if (ipaddr == NULL) {
+ return NULL;
+ }
+
+ memset(&ipbuf, '\0', INET_ADDRSTRLEN+1);
+
+ /* convert ip address to dotted-quad representation with prefix */
+ if (inet_ntop(AF_INET, ipaddr, ipbuf, INET_ADDRSTRLEN) == NULL) {
+ return NULL;
+ }
+
+ if (netmask != NULL) {
+ if ((prefix = iface_netmask2prefix(netmask)) == -1) {
+ return NULL;
+ }
+
+ if (asprintf(&tmpbuf, "%s/%d", ipbuf, prefix) == -1) {
+ return NULL;
+ }
+ } else {
+ if (asprintf(&tmpbuf, "%s", ipbuf) == -1) {
+ return NULL;
+ }
+ }
+
+ /* build our nl_addr */
+ if ((addr = nl_addr_parse(tmpbuf, AF_INET)) == NULL) {
+ return NULL;
+ }
+
+ return addr;
+}
+
+/*
+ * Convert an IPv6 address and accompanying prefix from struct in6_addr to
+ * an nl_addr. Return NULL on failure.
+ */
+struct nl_addr *_iface_in6_addr2nl_addr(struct in6_addr *ip6addr,
+ int ip6prefix) {
+ struct nl_addr *addr = NULL;
+ char *tmpbuf = NULL;
+ char ip6buf[INET6_ADDRSTRLEN+1];
+
+ if (ip6addr == NULL || (ip6prefix < 0 || ip6prefix > 128)) {
+ return NULL;
+ }
+
+ memset(&ip6buf, '\0', INET6_ADDRSTRLEN+1);
+
+ /* convert ip address to hex+colon representation with prefix */
+ if (inet_ntop(AF_INET6, ip6addr, ip6buf, INET6_ADDRSTRLEN) == NULL) {
+ return NULL;
+ }
+
+ if (asprintf(&tmpbuf, "%s/%d", ip6buf, ip6prefix) == -1) {
+ return NULL;
+ }
+
+ /* build our nl_addr */
+ if ((addr = nl_addr_parse(tmpbuf, AF_INET6)) == NULL) {
+ return NULL;
+ }
+
+ return addr;
+}
+
+/*
+ * Kill the specified client daemon process (DHCP or DHCPv6). Return 0 on
+ * success or non-negative on failure.
+ */
+static int _iface_kill_client_daemon(pid_t pid) {
+ int sig;
+ char *pidpath = NULL;
+
+ if (pid == 0 || pid == -1) {
+ return 0;
+ }
+
+ if (asprintf(&pidpath, "/proc/%d/exe", pid) == -1) {
+ return 1;
+ }
+
+ for (sig = SIGTERM; sig >= SIGKILL; sig -= (SIGTERM - SIGKILL)) {
+ if (access(pidpath, R_OK)) {
+ pid = 0;
+ break;
+ } else {
+ if (kill(pid, sig) == -1) {
+ continue;
+ }
+ }
+ }
+
+ if ((pid != 0) || (!access(pidpath, R_OK))) {
+ return 2;
+ }
+
+ return 0;
+}
+
+/*
+ * Try to set the system hostname if we have one. Return 0 on success,
+ * non-negative on failure.
+ */
+static int _iface_set_hostname(iface_t *iface) {
+ if (iface == NULL) {
+ return 1;
+ }
+
+ if (iface->hostname) {
+ if (sethostname(iface->hostname, strlen(iface->hostname))) {
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Determine if a struct in_addr or struct in6_addr contains a valid address.
+ */
+static int _iface_have_valid_addr(void *addr, int family, int length) {
+ char buf[length+1];
+
+ if ((addr == NULL) || (family != AF_INET && family != AF_INET6)) {
+ return 0;
+ }
+
+ memset(buf, '\0', sizeof(buf));
+
+ if (inet_ntop(family, addr, buf, length) == NULL) {
+ return 0;
+ } else {
+ /* check for unknown addresses */
+ if (family == AF_INET) {
+ if (!strncmp(buf, "0.0.0.0", 7)) {
+ return 0;
+ }
+ } else if (family == AF_INET6) {
+ if (!strncmp(buf, "::", 2)) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Set the specified address as the default gateway for the given addr family.
+ */
+int _iface_set_gateway(void *gw, int family) {
+ struct in_addr *gateway = NULL;
+ struct in6_addr *gateway6 = NULL;
+ struct {
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[1024];
+ } req;
+
+ if (family == AF_INET) {
+ gateway = (struct in_addr *) gw;
+ } else if (family == AF_INET6) {
+ gateway6 = (struct in6_addr *) gw;
+ } else {
+ return 1;
+ }
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
+ req.n.nlmsg_type = RTM_NEWROUTE;
+ req.r.rtm_family = family;
+ /* req.r.rtm_table = RTM_TABLE_MAIN; */
+ req.r.rtm_scope = RT_SCOPE_NOWHERE;
+ req.r.rtm_protocol = RTPROT_BOOT;
+ req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+ req.r.rtm_type = RTN_UNICAST;
+
+/* FIXME: libnl currently has trouble setting IPv4 and IPv6 gateways, working
+ * upstream to help fix that
+ */
+
+ return 0;
+}
+
+/*
+ * Redirect I/O to another device (e.g., stdout to /dev/tty5)
+ */
+int _iface_redirect_io(char *device, int fd, int mode) {
+ int io = -1;
+
+ if ((io = open(device, mode)) == -1) {
+ return 1;
+ }
+
+ if (close(fd) == -1) {
+ return 2;
+ }
+
+ if (dup2(io, fd) == -1) {
+ return 3;
+ }
+
+ if (close(io) == -1) {
+ return 4;
+ }
+
+ return 0;
+}
+
+/*
+ * Search the /proc filesystem for any matching DHCP or DHCPv6 processes
+ * for the specified interface...and kill them. Kill them dead.
+ */
+int _iface_kill_clients(char *ifname) {
+ char *procpath = NULL;
+ char exepath[PATH_MAX];
+ DIR *dp = NULL;
+ struct dirent *de = NULL;
+ FILE *fp = NULL;
+ ssize_t rdsz = 0;
+ char buf[2];
+ char *arg = NULL;
+ int match = 0;
+ char *tmp = NULL;
+ pid_t pid = 0;
+
+ if (ifname == NULL) {
+ return 1;
+ }
+
+ memset(exepath, '\0', sizeof(exepath));
+
+ /* loop over all running processes */
+ if ((dp = opendir("/proc")) == NULL) {
+ return 2;
+ }
+
+ while ((de = readdir(dp)) != NULL) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
+ continue;
+ }
+
+ if (procpath != NULL) {
+ free(procpath);
+ procpath = NULL;
+ }
+
+ if (asprintf(&procpath, "/proc/%s/exe", de->d_name) == -1) {
+ return 3;
+ }
+
+ if (realpath(procpath, exepath) == NULL) {
+ /* on failure here, just keep reading the directory */
+ continue;
+ }
+
+ if (!strcmp(DHCP_CLIENT, exepath) || !strcmp(DHCPV6_CLIENT, exepath)) {
+ /* found a DHCP or DHCPv6 client process, check for iface */
+ if (procpath != NULL) {
+ free(procpath);
+ procpath = NULL;
+ }
+
+ if (asprintf(&procpath, "/proc/%s/cmdline", de->d_name) == -1) {
+ return 4;
+ }
+
+ if ((fp = fopen(procpath, "r")) == NULL) {
+ free(procpath);
+ procpath = NULL;
+ return 5;
+ }
+
+ /* read args (these are NULL delimited in /proc) */
+ while (!feof(fp) && !ferror(fp)) {
+ rdsz = fread(buf, sizeof(char), 1, fp);
+
+ if (buf[0] == '\0') {
+ if (arg != NULL) {
+ if (!strcmp(ifname, arg)) {
+ match = 1;
+ break;
+ }
+
+ free(arg);
+ arg = NULL;
+ }
+ } else {
+ if (arg == NULL) {
+ if (asprintf(&arg, "%s", buf) == -1) {
+ return 6;
+ }
+ } else {
+ arg = realloc(arg, strlen(arg) + strlen(buf) + 1);
+
+ if (arg == NULL) {
+ return 7;
+ }
+
+ arg = strcat(arg, buf);
+ }
+ }
+ }
+
+ if (ferror(fp)) {
+ return 8;
+ }
+
+ if (fclose(fp) == EOF) {
+ return 9;
+ }
+
+ if (arg != NULL) {
+ free(arg);
+ arg = NULL;
+ }
+
+ /* if match is set, we need to kill the process */
+ if (match) {
+ pid = strtol(de->d_name, &tmp, 10);
+
+ if ((pid == LONG_MIN || pid == LONG_MAX) && errno == ERANGE) {
+ return 10;
+ }
+
+ if (_iface_kill_client_daemon(pid)) {
+ return 11;
+ }
+
+ match = 0;
+ }
+ }
+ }
+
+ if (closedir(dp)) {
+ return 12;
+ }
+
+ return 0;
+}
+
+/*
* Given an interface name (e.g., eth0), return the IP address in human
* readable format (i.e., the output from inet_ntop()). Return NULL for
* no match. NOTE: This function will check for IPv6 and IPv4
@@ -74,26 +646,16 @@ char *iface_ip2str(char *ifname) {
struct rtnl_addr *raddr = NULL;
struct nl_addr *addr = NULL;
- if (ifname == NULL) {
- perror("Missing ifname in iface_ip2str()");
- return NULL;
- }
-
- if ((cache = iface_get_link_cache(&handle)) == NULL) {
- perror("iface_get_link_cache() failure in iface_ip2str()");
- return NULL;
+ if ((ifindex = _iface_name_to_index(ifname)) == -1) {
+ goto ip2str_error;
}
- ifindex = rtnl_link_name2i(cache, ifname);
-
if ((cache = rtnl_addr_alloc_cache(handle)) == NULL) {
- perror("rtnl_addr_alloc_cache() failure in iface_ip2str()");
goto ip2str_error;
}
/* find the IPv4 and IPv6 addresses for this interface */
if ((obj = nl_cache_get_first(cache)) == NULL) {
- perror("nl_cache_get_first() failure in iface_ip2str()");
goto ip2str_error;
}
@@ -128,8 +690,7 @@ char *iface_ip2str(char *ifname) {
buflen += 1;
- if ((buf = malloc(buflen)) == NULL) {
- perror("malloc() failure on buf in iface_ip2str()");
+ if ((buf = calloc(sizeof(char *), buflen)) == NULL) {
nl_addr_destroy(addr);
goto ip2str_error;
}
@@ -141,7 +702,6 @@ char *iface_ip2str(char *ifname) {
if ((pos = index(buf, '/')) != NULL) {
*pos = '\0';
if ((buf = realloc(buf, strlen(buf) + 1)) == NULL) {
- perror("realloc() failure on buf in iface_ip2str()");
nl_addr_destroy(addr);
goto ip2str_error;
}
@@ -180,7 +740,7 @@ ip2str_error:
}
}
-/**
+/*
* Given an interface name (e.g., eth0), return the MAC address in human
* readable format (e.g., 00:11:52:12:D9:A0). Return NULL for no match.
*/
@@ -193,27 +753,22 @@ char *iface_mac2str(char *ifname) {
struct nl_addr *addr = NULL;
if (ifname == NULL) {
- perror("Missing ifname in iface_mac2str()");
return NULL;
}
- if ((cache = iface_get_link_cache(&handle)) == NULL) {
- perror("iface_get_link_cache() failure in iface_mac2str()");
+ if ((cache = _iface_get_link_cache(&handle)) == NULL) {
return NULL;
}
if ((link = rtnl_link_get_by_name(cache, ifname)) == NULL) {
- perror("rtnl_link_get_by_name() failure in iface_mac2str()");
goto mac2str_error2;
}
if ((addr = rtnl_link_get_addr(link)) == NULL) {
- perror("rtnl_link_get_addr() failure in iface_mac2str()");
goto mac2str_error3;
}
- if ((buf = malloc(buflen)) == NULL) {
- perror("malloc() failure on buf in iface_mac2str()");
+ if ((buf = calloc(sizeof(char *), buflen)) == NULL) {
goto mac2str_error4;
}
@@ -231,3 +786,533 @@ mac2str_error2:
return buf;
}
+
+/*
+ * Bring up an interface using the specified configuration information.
+ */
+int iface_config(iface_t *iface) {
+ int ifindex = -1;
+ struct nl_handle *handle = NULL;
+ struct rtnl_addr *addr = NULL;
+ struct nl_addr *nla = NULL;
+
+ if (iface == NULL) {
+ return 1;
+ }
+
+ /* do not configure the interface if we are given static info and a client
+ * daemon is already running, return failure.
+ */
+ if (iface->dhcp_pid != -1 && iface_have_in_addr(&iface->ipaddr)) {
+ return 2;
+ }
+
+ if (iface->dhcpv6_pid != -1 && iface_have_in6_addr(&iface->ip6addr)) {
+ return 3;
+ }
+
+ /* if IPv6 autoconf is enabled and we have static IPv6 addr, fail */
+ if (iface_have_in6_addr(&iface->ip6addr) &&
+ _iface_is_autoconf(iface->device)) {
+ return 4;
+ }
+
+ /* we need the interface index number */
+ if ((ifindex = _iface_name_to_index(iface->device)) == -1) {
+ return 5;
+ }
+
+ /* get a netlink handle */
+ if ((handle = _iface_get_handle()) == NULL) {
+ return 6;
+ }
+
+ /* add IPv4 address if we have that */
+ if (iface_have_in_addr(&iface->ipaddr) &&
+ iface_have_in_addr(&iface->netmask)) {
+ if ((addr = rtnl_addr_alloc()) == NULL) {
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ return 7;
+ }
+
+ rtnl_addr_set_ifindex(addr, ifindex);
+ rtnl_addr_set_family(addr, AF_INET);
+
+ nla = _iface_in_addr2nl_addr(&iface->ipaddr, &iface->netmask);
+ if (nla == NULL) {
+ return 8;
+ }
+
+ rtnl_addr_set_local(addr, nla);
+
+ nla = _iface_in_addr2nl_addr(&iface->broadcast, NULL);
+ if (nla == NULL) {
+ return 9;
+ }
+
+ rtnl_addr_set_broadcast(addr, nla);
+
+ if (rtnl_addr_add(handle, addr, 0)) {
+ rtnl_addr_put(addr);
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ return 10;
+ }
+ }
+
+ /* add IPv6 address if we have that */
+ if (iface_have_in6_addr(&iface->ip6addr) &&
+ ((iface->ip6prefix >= 0) && (iface->ip6prefix <= 128))) {
+ if ((addr = rtnl_addr_alloc()) == NULL) {
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ return 11;
+ }
+
+ rtnl_addr_set_ifindex(addr, ifindex);
+ rtnl_addr_set_family(addr, AF_INET6);
+
+ nla = _iface_in6_addr2nl_addr(&iface->ip6addr, iface->ip6prefix);
+ if (nla == NULL) {
+ return 12;
+ }
+
+ rtnl_addr_set_local(addr, nla);
+
+ if (rtnl_addr_add(handle, addr, 0)) {
+ rtnl_addr_put(addr);
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ return 13;
+ }
+ }
+
+ nl_close(handle);
+ nl_handle_destroy(handle);
+
+ if (nla != NULL) {
+ nl_addr_destroy(nla);
+ }
+
+ /* add IPv4 default gateway */
+ /* FIXME: libnl's rtnl_route_add() function does not currently work, so
+ * we have to talk to netlink by hand for this part. Version 1.2 of libnl
+ * should have rtnl_route_add() working correctly.
+ */
+ if (iface_have_in_addr(&iface->gateway)) {
+ if (_iface_set_gateway(&iface->gateway, AF_INET)) {
+ return 14;
+ }
+ }
+
+ /* set default IPv6 gateway */
+ if (iface_have_in6_addr(&iface->gateway6)) {
+ if (_iface_set_gateway(&iface->gateway6, AF_INET6)) {
+ return 15;
+ }
+ }
+
+ /* set hostname */
+ if (_iface_set_hostname(iface)) {
+ return 16;
+ }
+
+ /* bring interface up */
+ if (iface_up(iface->device)) {
+ return 17;
+ }
+
+ return 0;
+}
+
+/*
+ * Run the DHCP client on the specified interface. Output from the client
+ * is redirected to another tty.
+ */
+int iface_dhcp(iface_t *iface) {
+ int status;
+ char *timeout = NULL;
+ struct utsname kv;
+
+ if (iface == NULL) {
+ return 1;
+ }
+
+ if (iface->device == NULL) {
+ return 1;
+ }
+
+ /* kill existing DHCP client process */
+ if (_iface_kill_client_daemon(iface->dhcp_pid)) {
+ return 2;
+ }
+
+ /* build options */
+ if (iface->dhcptimeout < 0) {
+ iface->dhcptimeout = 45;
+ }
+
+ if (asprintf(&timeout, "%d", iface->dhcptimeout) == -1) {
+ timeout = strdup("45");
+ }
+
+ if (iface->vendorclass == NULL) {
+ if (uname(&kv) == -1) {
+ iface->vendorclass = strdup("anaconda");
+ } else {
+ if (asprintf(&iface->vendorclass, "anaconda-%s %s %s",
+ kv.sysname, kv.release, kv.machine) == -1) {
+ iface->vendorclass = strdup("anaconda");
+ }
+ }
+ }
+
+ /* run the client */
+ iface->dhcp_pid = fork();
+ if (iface->dhcp_pid == 0) {
+ if (_iface_redirect_io("/dev/null", STDIN_FILENO, O_RDONLY) ||
+ _iface_redirect_io(OUTPUT_TERMINAL, STDOUT_FILENO, O_WRONLY) ||
+ _iface_redirect_io(OUTPUT_TERMINAL, STDERR_FILENO, O_WRONLY)) {
+ exit(1);
+ }
+
+ printf("cmd: |%s -q -1 -T %s -V %s %s|\n", DHCP_CLIENT, timeout, iface->vendorclass, iface->device);
+
+ if (execl(DHCP_CLIENT, DHCP_CLIENT, "-q", "-1", "-T", timeout,
+ "-V", iface->vendorclass, iface->device, NULL) == -1) {
+ exit(2);
+ } else {
+ exit(0);
+ }
+ } else if (iface->dhcp_pid == -1) {
+ return 4;
+ }
+
+ if (waitpid(iface->dhcp_pid, &status, 0) == -1) {
+ return 5;
+ }
+
+ return 0;
+}
+
+/*
+ * Run the DHCPv6 client on the specified interface. Return 0 on success,
+ * non-negative on failure. Output from the client is redirected to another
+ * tty.
+ */
+int iface_dhcpv6(iface_t *iface) {
+ int status;
+ FILE *fp = NULL;
+
+ if (iface == NULL) {
+ return 1;
+ }
+
+ if (iface->device == NULL) {
+ return 1;
+ }
+
+ /* kill existing DHCPv6 client process */
+ if (_iface_kill_client_daemon(iface->dhcpv6_pid)) {
+ return 2;
+ }
+
+ /* write out a new configuration file for this client */
+ if ((fp = fopen(DHCPV6_CLIENT_CONF_FILE, "w")) == NULL) {
+ return 3;
+ }
+
+ fprintf(fp, "interface %s {\n", iface->device);
+ fprintf(fp, " request domain-name-servers;\n");
+ fprintf(fp, " request domain-search-list;\n");
+ fprintf(fp, " request prefix-delegation;\n");
+ fprintf(fp, "};");
+
+ fclose(fp);
+
+ /* run the client */
+ iface->dhcpv6_pid = fork();
+ if (iface->dhcpv6_pid == 0) {
+ if (_iface_redirect_io("/dev/null", STDIN_FILENO, O_RDONLY) ||
+ _iface_redirect_io(OUTPUT_TERMINAL, STDOUT_FILENO, O_WRONLY) ||
+ _iface_redirect_io(OUTPUT_TERMINAL, STDERR_FILENO, O_WRONLY)) {
+ exit(1);
+ }
+
+ if (execl(DHCPV6_CLIENT, DHCPV6_CLIENT, "-c",
+ DHCPV6_CLIENT_CONF_FILE, iface->device, NULL) == -1) {
+ exit(2);
+ } else {
+ exit(0);
+ }
+ } else if (iface->dhcpv6_pid == -1) {
+ return 4;
+ }
+
+ if (waitpid(iface->dhcpv6_pid, &status, 0) == -1) {
+ return 5;
+ }
+
+ return 0;
+}
+
+/*
+ * Enable IPv6 autoconfiguration on the specified interface.
+ */
+int iface_autoconf(iface_t *iface) {
+ return _iface_autoconf_on_or_off(iface->device, 1);
+}
+
+/*
+ * Clear all addresses on the specified interface.
+ */
+int iface_clear_addrs(char *ifname) {
+ int ifindex = -1;
+ struct nl_cache *cache = NULL;
+ struct nl_handle *handle = NULL;
+ struct nl_object *obj = NULL;
+ struct rtnl_addr *raddr = NULL;
+
+ if ((ifindex = _iface_name_to_index(ifname)) == -1) {
+ return 1;
+ }
+
+ if ((cache = rtnl_addr_alloc_cache(handle)) == NULL) {
+ if (handle != NULL) {
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ }
+
+ return 2;
+ }
+
+ if ((obj = nl_cache_get_first(cache)) == NULL) {
+ if (handle != NULL) {
+ nl_close(handle);
+ nl_handle_destroy(handle);
+ }
+
+ return 3;
+ }
+
+ do {
+ raddr = (struct rtnl_addr *) obj;
+
+ if (rtnl_addr_get_ifindex(raddr) == ifindex) {
+ rtnl_addr_delete(handle, raddr, 0);
+ rtnl_addr_put(raddr);
+ }
+ } while ((obj = nl_cache_get_next(obj)) != NULL);
+
+ nl_close(handle);
+ nl_handle_destroy(handle);
+
+ return 0;
+}
+
+/*
+ * Down an interface, which (for our purposes) includes removing all addresses,
+ * stopping any client daemons, and setting IFF_DOWN. Returns 0 on success,
+ * non-zero on failure.
+ */
+int iface_down(char *ifname) {
+ if (ifname == NULL) {
+ return 1;
+ }
+
+ /* stop running client daemons */
+ if (_iface_kill_clients(ifname)) {
+ return 2;
+ }
+
+ /* Disable IPv6 autoconfiguration */
+ if (_iface_autoconf_on_or_off(ifname, 0)) {
+ return 3;
+ }
+
+ /* remove all addresses on this interface (don't care if this fails) */
+ if (iface_clear_addrs(ifname)) {
+ return 4;
+ }
+
+ /* clear IFF_UP and IFF_RUNNING */
+ if (_iface_up_or_down(ifname, 0)) {
+ return 5;
+ }
+
+ return 0;
+}
+
+/*
+ * Up an interface, which means just set IFF_UP and IFF_RUNNING.
+ */
+int iface_up(char *ifname) {
+ return _iface_up_or_down(ifname, 1);
+}
+
+/*
+ * Convert an IPv4 CIDR prefix to a dotted-quad netmask. Return NULL on
+ * failure.
+ */
+struct in_addr *iface_prefix2netmask(int prefix) {
+ int mask = 0;
+ char *buf = NULL;
+ struct in_addr *ret;
+
+ if ((buf = calloc(sizeof(char *), INET_ADDRSTRLEN + 1)) == NULL) {
+ return NULL;
+ }
+
+ mask = htonl(~((1 << (32 - prefix)) - 1));
+
+ if (inet_ntop(AF_INET, (struct in_addr *) &mask, buf,
+ INET_ADDRSTRLEN) == NULL) {
+ return NULL;
+ }
+
+ if ((ret = calloc(sizeof(struct in_addr), 1)) == NULL) {
+ return NULL;
+ }
+
+ memcpy(ret, (struct in_addr *) &mask, sizeof(struct in_addr));
+ return ret;
+}
+
+/*
+ * Convert an IPv4 netmask to an IPv4 CIDR prefix. Return -1 on failure.
+ */
+int iface_netmask2prefix(struct in_addr *netmask) {
+ int ret = -1;
+ struct in_addr mask;
+
+ if (netmask == NULL) {
+ return -1;
+ }
+
+ memcpy(&mask, netmask, sizeof(struct in_addr));
+
+ while (mask.s_addr != 0) {
+ mask.s_addr = mask.s_addr >> 1;
+ ret++;
+ }
+
+ return ret;
+}
+
+/*
+ * Look up the hostname and domain for our assigned IP address. Tries IPv4
+ * first, then IPv6. Returns 0 on success, non-negative on failure.
+ */
+int iface_dns_lookup(iface_t *iface) {
+ char *ch = NULL;
+ struct sockaddr_in sa;
+ struct sockaddr_in6 sa6;
+
+ if ((iface->hostname != NULL) && (iface->domain != NULL)) {
+ return 0;
+ }
+
+ /* make sure our hostname buffer is large enough */
+ if ((iface->hostname = calloc('\0', NI_MAXHOST+1)) == NULL) {
+ return 1;
+ }
+
+ /* try an IPv4 lookup first */
+ if (iface_have_in_addr(&iface->ipaddr)) {
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = iface->ipaddr.s_addr;
+
+ if (getnameinfo((struct sockaddr *) &sa, sizeof(sa), iface->hostname,
+ NI_MAXHOST, NULL, 0, NI_NAMEREQD)) {
+ free(iface->hostname);
+ iface->hostname = NULL;
+ }
+ }
+
+ /* try IPv6 lookup if IPv4 failed */
+ if ((iface->hostname == NULL) && iface_have_in6_addr(&iface->ip6addr)) {
+ memset(&sa6, 0, sizeof(sa6));
+ sa6.sin6_family = AF_INET6;
+ memcpy(&sa6.sin6_addr, &iface->ip6addr, sizeof(iface->ip6addr));
+
+ if (getnameinfo((struct sockaddr *) &sa6, sizeof(sa6), iface->hostname,
+ NI_MAXHOST, NULL, 0, NI_NAMEREQD)) {
+ free(iface->hostname);
+ iface->hostname = NULL;
+ }
+ }
+
+ /* fill in the domain */
+ if ((iface->domain == NULL) && (iface->hostname != NULL)) {
+ for (ch = iface->hostname; *ch && (*ch != '.'); ch++);
+
+ if (*ch == '.') {
+ iface->domain = strdup(ch + 1);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Initialize a new iface_t structure to default values.
+ */
+void iface_init_iface_t(iface_t *iface) {
+ int i;
+
+ memset(&iface->device, '\0', sizeof(iface->device));
+ memset(&iface->ipaddr, 0, sizeof(iface->ipaddr));
+ memset(&iface->netmask, 0, sizeof(iface->netmask));
+ memset(&iface->broadcast, 0, sizeof(iface->broadcast));
+ memset(&iface->ip6addr, 0, sizeof(iface->ip6addr));
+ memset(&iface->gateway, 0, sizeof(iface->gateway));
+ memset(&iface->gateway6, 0, sizeof(iface->gateway6));
+
+ for (i = 0; i < MAXNS; i++) {
+ iface->dns[i] = NULL;
+ }
+
+ iface->macaddr = NULL;
+ iface->ip6prefix = 0;
+ iface->nextserver = NULL;
+ iface->bootfile = NULL;
+ iface->numdns = 0;
+ iface->hostname = NULL;
+ iface->domain = NULL;
+ iface->search = NULL;
+ iface->dhcptimeout = 0;
+ iface->vendorclass = NULL;
+ iface->ssid = NULL;
+ iface->wepkey = NULL;
+ iface->mtu = 0;
+ iface->subchannels = NULL;
+ iface->portname = NULL;
+ iface->peerid = NULL;
+ iface->nettype = NULL;
+ iface->ctcprot = NULL;
+ iface->dhcp_pid = -1;
+ iface->dhcpv6_pid = -1;
+ iface->flags = 0;
+ iface->ipv4method = IPV4_UNUSED_METHOD;
+ iface->ipv6method = IPV6_UNUSED_METHOD;
+
+ return;
+}
+
+/*
+ * Given a pointer to a struct in_addr, return 1 if it contains a valid
+ * address, 0 otherwise.
+ */
+int iface_have_in_addr(struct in_addr *addr) {
+ return _iface_have_valid_addr(addr, AF_INET, INET_ADDRSTRLEN);
+}
+
+/*
+ * Given a pointer to a struct in6_addr, return 1 if it contains a valid
+ * address, 0 otherwise.
+ */
+int iface_have_in6_addr(struct in6_addr *addr6) {
+ return _iface_have_valid_addr(addr6, AF_INET6, INET6_ADDRSTRLEN);
+}
diff --git a/isys/iface.h b/isys/iface.h
index cc1f813..5e1ce02 100644
--- a/isys/iface.h
+++ b/isys/iface.h
@@ -1,7 +1,7 @@
/*
- * iface.h
+ * iface.h - Network interface configuration API
*
- * Copyright (C) 2006, 2007, 2008 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,10 +19,191 @@
* Author(s): David Cantrell
*/
+#ifndef ISYSIFACE_H
+#define ISYSIFACE_H
+
+#include
+#include
#include
#include
+/* Enumerated types used in iface.c as well as loader's network code */
+enum { IPV4, IPV6 };
+
+enum { IPV4_UNUSED_METHOD, IPV4_DHCP_METHOD, IPV4_MANUAL_METHOD };
+enum { IPV6_UNUSED_METHOD, IPV6_AUTO_METHOD, IPV6_DHCP_METHOD,
+ IPV6_MANUAL_METHOD };
+
+#define IPV4_FIRST_METHOD IPV4_DHCP_METHOD
+#define IPV4_LAST_METHOD IPV4_MANUAL_METHOD
+
+#define IPV6_FIRST_METHOD IPV6_AUTO_METHOD
+#define IPV6_LAST_METHOD IPV6_MANUAL_METHOD
+
+/* Flags for the iface_t */
+#define IFACE_FLAGS_NO_WRITE_RESOLV_CONF (((uint64_t) 1) << 0)
+/* FIXME: do we need these? */
+#define IFACE_FLAGS_IS_PRESET (((uint64_t) 1) << 1)
+#define IFACE_FLAGS_IS_DYNAMIC (((uint64_t) 1) << 2)
+
+#define IFACE_NO_WRITE_RESOLV_CONF(a) ((a) & IFACE_FLAGS_NO_WRITE_RESOLV_CONF)
+#define IFACE_IS_PRESET(a) ((a) & IFACE_FLAGS_IS_PRESET)
+#define IFACE_IS_DYNAMIC(a) ((a) & IFACE_FLAGS_IS_DYNAMIC)
+
+/* DHCP and DHCPv6 clients */
+#define DHCP_CLIENT "/sbin/dhclient"
+#define DHCPV6_CLIENT "/sbin/dhcp6c"
+#define DHCPV6_CLIENT_CONF_FILE "/tmp/dhcp6c.conf"
+#define OUTPUT_TERMINAL "/dev/tty5"
+
+/* Per-interface configuration information */
+typedef struct _iface_t {
+ /* device name (e.g., eth0) */
+ char device[IF_NAMESIZE];
+
+ /* MAC address as xx:xx:xx:xx:xx:xx */
+ char *macaddr;
+
+ /* IPv4 (store addresses in in_addr format, use inet_pton() to display) */
+ struct in_addr ipaddr;
+ struct in_addr netmask;
+ struct in_addr broadcast;
+
+ /* IPv6 (store addresses in in6_addr format, prefix is just an int) */
+ struct in6_addr ip6addr;
+ int ip6prefix;
+
+ /* Gateway settings */
+ struct in_addr gateway;
+ struct in6_addr gateway6;
+
+ /* BOOTP (these can be IPv4 or IPv6, store human-readable version as str) */
+ char *nextserver;
+ char *bootfile;
+
+ /* DNS (these can be IPv4 or IPv6, store human-readable version as str) */
+ char *dns[MAXNS];
+ int numdns;
+ char *hostname;
+ char *domain;
+ char *search;
+
+ /* Misc DHCP settings */
+ int dhcptimeout;
+ char *vendorclass;
+
+ /* Wireless settings */
+ char *ssid;
+ char *wepkey;
+
+ /* s390 specifics */
+ int mtu;
+ char *subchannels;
+ char *portname;
+ char *peerid;
+ char *nettype;
+ char *ctcprot;
+
+ /* DHCP and DHCPv6 process control */
+ pid_t dhcp_pid;
+ pid_t dhcpv6_pid;
+
+ /* flags */
+ uint64_t flags;
+ int ipv4method;
+ int ipv6method;
+} iface_t;
+
/* Function prototypes */
-struct nl_cache *iface_get_link_cache(struct nl_handle **handle);
-char *iface_mac2str(char *ifname);
-char *iface_ip2str(char *ifname);
+
+/*
+ * Given an interface name (e.g., eth0), return the IP address in human
+ * readable format (i.e., the output from inet_ntop()). Return NULL for
+ * no match. NOTE: This function will check for IPv6 and IPv4
+ * addresses. In the case where the interface has both, the IPv4 address
+ * is returned. The only way you will get an IPv6 address from this function
+ * is if that's the only address configured for the interface.
+ */
+char *iface_ip2str(char *);
+
+/*
+ * Given an interface name (e.g., eth0), return the MAC address in human
+ * readable format (e.g., 00:11:52:12:D9:A0). Return NULL for no match.
+ */
+char *iface_mac2str(char *);
+
+/*
+ * Bring up an interface using the specified configuration information.
+ */
+int iface_config(iface_t *);
+
+/*
+ * Run the DHCP client on the specified interface. Output from the client
+ * is redirected to another tty.
+ */
+int iface_dhcp(iface_t *);
+
+/*
+ * Run the DHCPv6 client on the specified interface. Return 0 on success,
+ * non-negative on failure. Output from the client is redirected to another
+ * tty.
+ */
+int iface_dhcpv6(iface_t *);
+
+/*
+ * Enable IPv6 autoconfiguration on the specified interface.
+ */
+int iface_autoconf(iface_t *);
+
+/*
+ * Clear all addresses on the specified interface.
+ */
+int iface_clear_addrs(char *);
+
+/*
+ * Down an interface, which (for our purposes) includes removing all addresses,
+ * stopping any client daemons, and setting IFF_DOWN. Returns 0 on success,
+ * non-zero on failure.
+ */
+int iface_down(char *);
+
+/*
+ * Up an interface, which means just set IFF_UP and IFF_RUNNING.
+ */
+int iface_up(char *);
+
+/*
+ * Convert an IPv4 CIDR prefix to a dotted-quad netmask. Return NULL on
+ * failure.
+ */
+struct in_addr *iface_prefix2netmask(int);
+
+/*
+ * Convert an IPv4 netmask to an IPv4 CIDR prefix. Return -1 on failure.
+ */
+int iface_netmask2prefix(struct in_addr *);
+
+/*
+ * Look up the hostname and domain for our assigned IP address. Tries IPv4
+ * first, then IPv6. Returns 0 on success, non-negative on failure.
+ */
+int iface_dns_lookup(iface_t *);
+
+/*
+ * Initialize a new iface_t structure to default values.
+ */
+void iface_init_iface_t(iface_t *);
+
+/*
+ * Given a pointer to a struct in_addr, return 1 if it contains a valid
+ * address, 0 otherwise.
+ */
+int iface_have_in_addr(struct in_addr *addr);
+
+/*
+ * Given a pointer to a struct in6_addr, return 1 if it contains a valid
+ * address, 0 otherwise.
+ */
+int iface_have_in6_addr(struct in6_addr *addr6);
+
+#endif /* ISYSIFACE_H */
diff --git a/isys/isys.c b/isys/isys.c
index 32ae1d9..41a4e9d 100644
--- a/isys/isys.c
+++ b/isys/isys.c
@@ -53,6 +53,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#ifdef USESELINUX
@@ -65,9 +67,6 @@
#include
#include
-#include
-#include
-
#include
#include "iface.h"
@@ -79,6 +78,7 @@
#include "wireless.h"
#include "eddsupport.h"
#include "auditd.h"
+#include "imount.h"
#ifndef CDROMEJECT
#define CDROMEJECT 0x5309
@@ -517,52 +517,54 @@ void init_isys(void) {
static PyObject * doConfigNetDevice(PyObject * s, PyObject * args) {
int i = 0;
- char *dev, *ipv4, *netmask, *ipv6, *prefix, *gateway;
- struct pumpNetIntf cfg;
- struct in_addr addr, nm, nw;
- struct in6_addr addr6;
+ char *dev, *ipv4, *netmask, *ipv6, *prefix, *gateway, *gateway6, *ep;
+ iface_t iface;
+ struct in_addr tmpaddr;
if (!PyArg_ParseTuple(args, "ssssss", &dev, &ipv4, &netmask,
- &ipv6, &prefix, &gateway))
+ &ipv6, &prefix, &gateway, &gateway6))
return NULL;
- memset(&cfg, '\0', sizeof(struct pumpNetIntf));
- strncpy(cfg.device, dev, sizeof(cfg.device) - 1);
+ memset(&iface, '\0', sizeof(iface_t));
+ strncpy(iface.device, dev, sizeof(iface.device) - 1);
/* IPv4 */
- if (inet_pton(AF_INET, ipv4, &addr) >= 1) {
- cfg.ipv4 = ip_addr_in(&addr);
-
- if (inet_pton(AF_INET, netmask, &nm) >= 1) {
- cfg.netmask = ip_addr_in(&nm);
-
- /* we have IP and netmask, calculate network and broadcast */
- cfg.network = ip_addr_v4(ntohl((addr.s_addr) & nm.s_addr));
- nw = ip_in_addr(&cfg.network);
- cfg.broadcast = ip_addr_v4(ntohl(nw.s_addr | ~nm.s_addr));
+ if (inet_pton(AF_INET, ipv4, &iface.ipaddr) >= 1) {
+ if (inet_pton(AF_INET, netmask, &iface.netmask) >= 1) {
+ /* we have IP and netmask, calculate broadcast */
+ memset(&tmpaddr, 0, sizeof(tmpaddr));
+ tmpaddr.s_addr = iface.ipaddr.s_addr & iface.netmask.s_addr;
+ iface.broadcast.s_addr = tmpaddr.s_addr | ~iface.netmask.s_addr;
}
}
/* IPv6 */
- if (inet_pton(AF_INET6, ipv6, &addr6) >= 1) {
- cfg.ipv6 = ip_addr_in6(&addr6);
-
- if (strlen(prefix))
- i = atoi(prefix);
- if (i > 0 && i <= 128)
- cfg.ipv6_prefixlen = i;
+ if (inet_pton(AF_INET6, ipv6, &iface.ip6addr) >= 1) {
+ if (strlen(prefix)) {
+ i = strtol(prefix, &ep, 10);
+ if (i > 0 && i <= 128) {
+ iface.ip6prefix = i;
+ }
+ }
}
- /* Global */
+ /* Gateways */
if (strlen(gateway)) {
- if (inet_pton(AF_INET, gateway, &addr) >= 1) {
- cfg.gateway = ip_addr_in(&addr);
- } else if (inet_pton(AF_INET6, gateway, &addr6) >= 1) {
- cfg.gateway = ip_addr_in6(&addr6);
+ if (inet_pton(AF_INET, gateway, &iface.gateway) <= 0) {
+ PyErr_SetFromErrno(PyExc_SystemError);
+ return NULL;
}
}
- if (pumpSetupInterface(&cfg)) {
+ if (strlen(gateway6)) {
+ if (inet_pton(AF_INET6, gateway6, &iface.gateway6) <= 0) {
+ PyErr_SetFromErrno(PyExc_SystemError);
+ return NULL;
+ }
+ }
+
+ /* Bring up the interface */
+ if (iface_config(&iface)) {
PyErr_SetFromErrno(PyExc_SystemError);
return NULL;
}
@@ -571,21 +573,17 @@ static PyObject * doConfigNetDevice(PyObject * s, PyObject * args) {
return Py_None;
}
-void pumplogger(void *arg, int priority, char *fmt, va_list va) {
- libdhcp_syslogger(0, priority, fmt, va);
-}
-
static PyObject * doDhcpNetDevice(PyObject * s, PyObject * args) {
- char *device = NULL, *r = NULL;
+ char *device = NULL;
+// char *r = NULL;
char *ipv4method = NULL, *ipv6method = NULL, *dhcpclass = NULL;
int useipv4, useipv6;
- char buf[47];
- time_t timeout = 45;
- struct pumpNetIntf cfg;
+// char buf[47];
+// time_t timeout = 45;
+ iface_t cfg;
struct utsname kv;
- DHCP_Preference pref = 0;
- ip_addr_t *tip;
- PyObject * rc;
+// DHCP_Preference pref = 0;
+// PyObject * rc;
if (!PyArg_ParseTuple(args, "sisis|s", &device, &useipv4, &ipv4method, &useipv6, &ipv6method, &dhcpclass))
return NULL;
@@ -604,62 +602,67 @@ static PyObject * doDhcpNetDevice(PyObject * s, PyObject * args) {
memset(&cfg, '\0', sizeof(cfg));
strcpy(cfg.device, device);
- /* disable DHCPv4 is user selected manual IPv4 or didn't select IPv4 */
- if (useipv4 && strlen(ipv4method) > 0) {
- if (!strncmp(ipv4method, "manual", 6)) {
- /* IPv4 disabled entirely -or- manual IPv4 config selected */
- pref |= DHCPv4_DISABLE;
- }
- } else if (!useipv4 && strlen(ipv4method) == 0) {
- pref |= DHCPv4_DISABLE;
- }
-
- /* set appropriate IPv6 configuration method */
- if (strlen(ipv6method) > 0) {
- if ((!useipv6 && !strncmp(ipv6method, "auto", 4)) ||
- (useipv6 && !strncmp(ipv6method, "manual", 6))) {
- pref |= DHCPv6_DISABLE | DHCPv6_DISABLE_ADDRESSES;
- }
- } else if (strlen(ipv6method) == 0 && !useipv6) {
- pref |= DHCPv6_DISABLE | DHCPv6_DISABLE_ADDRESSES;
- }
-
- pref |= DHCPv6_DISABLE_RESOLVER | DHCPv4_DISABLE_HOSTNAME_SET;
-
- if (!(pref & DHCPv4_DISABLE) || !(pref & DHCPv6_DISABLE)) {
- r = pumpDhcpClassRun(&cfg, NULL, dhcpclass, pref, 0, timeout,
- pumplogger, LOG_ERR);
- if (r) {
- Py_INCREF(Py_None);
- return Py_None;
- } else {
- if (pumpSetupInterface(&cfg)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- }
- }
-
- if (cfg.numDns) {
- tip = &(cfg.dnsServers[0]);
- inet_ntop(tip->sa_family, IP_ADDR(tip), buf, IP_STRLEN(tip));
- rc = PyString_FromString(buf);
- } else {
- rc = PyString_FromString("");
- }
-
- return rc;
+// /* disable DHCPv4 is user selected manual IPv4 or didn't select IPv4 */
+// if (useipv4 && strlen(ipv4method) > 0) {
+// if (!strncmp(ipv4method, "manual", 6)) {
+// /* IPv4 disabled entirely -or- manual IPv4 config selected */
+// pref |= DHCPv4_DISABLE;
+// }
+// } else if (!useipv4 && strlen(ipv4method) == 0) {
+// pref |= DHCPv4_DISABLE;
+// }
+//
+// /* set appropriate IPv6 configuration method */
+// if (strlen(ipv6method) > 0) {
+// if ((!useipv6 && !strncmp(ipv6method, "auto", 4)) ||
+// (useipv6 && !strncmp(ipv6method, "manual", 6))) {
+// pref |= DHCPv6_DISABLE | DHCPv6_DISABLE_ADDRESSES;
+// }
+// } else if (strlen(ipv6method) == 0 && !useipv6) {
+// pref |= DHCPv6_DISABLE | DHCPv6_DISABLE_ADDRESSES;
+// }
+//
+// pref |= DHCPv6_DISABLE_RESOLVER | DHCPv4_DISABLE_HOSTNAME_SET;
+//
+// if (!(pref & DHCPv4_DISABLE) || !(pref & DHCPv6_DISABLE)) {
+// r = pumpDhcpClassRun(&cfg, NULL, dhcpclass, pref, 0, timeout,
+// pumplogger, LOG_ERR);
+// if (r) {
+// Py_INCREF(Py_None);
+// return Py_None;
+// } else {
+// if (pumpSetupInterface(&cfg)) {
+// Py_INCREF(Py_None);
+// return Py_None;
+// }
+// }
+// }
+//
+// if (cfg.numDns) {
+// tip = &(cfg.dnsServers[0]);
+// inet_ntop(tip->sa_family, IP_ADDR(tip), buf, IP_STRLEN(tip));
+// rc = PyString_FromString(buf);
+// } else {
+// rc = PyString_FromString("");
+// }
+
+ return PyString_FromString("");
+ //return rc;
}
static PyObject * doPrefixToNetmask (PyObject * s, PyObject * args) {
- int prefix = 0;
- int mask = 0;
- char dst[INET_ADDRSTRLEN];
+ int prefix = 0;
+ struct in_addr *mask = NULL;
+ char dst[INET_ADDRSTRLEN+1];
- if (!PyArg_ParseTuple(args, "i", &prefix)) return NULL;
+ if (!PyArg_ParseTuple(args, "i", &prefix))
+ return NULL;
- mask = htonl(~((1 << (32 - prefix)) - 1));
- inet_ntop(AF_INET, (struct in_addr *) &mask, dst, INET_ADDRSTRLEN);
+ if ((mask = iface_prefix2netmask(prefix)) == NULL)
+ return NULL;
+
+ if (inet_ntop(AF_INET, mask, dst, INET_ADDRSTRLEN) == NULL)
+ return NULL;
return Py_BuildValue("s", dst);
}
diff --git a/isys/wireless.c b/isys/wireless.c
index aa13b11..6c17577 100644
--- a/isys/wireless.c
+++ b/isys/wireless.c
@@ -70,14 +70,14 @@ int is_wireless_interface(char * ifname) {
return 1;
}
-/* set the essid for ifname to essid. if essid is NULL, do automatically */
-int set_essid(char * ifname, char * essid) {
- int sock;
+/* set the ssid for ifname to ssid. if essid is NULL, do automatically */
+int set_ssid(char * ifname, char * ssid) {
+ int sock;
struct iwreq wreq;
memset(&wreq, 0, sizeof (wreq));
- if (strlen(essid) > IW_ESSID_MAX_SIZE) {
+ if (strlen(ssid) > IW_ESSID_MAX_SIZE) {
fprintf(stderr, "essid too long\n");
return -1;
}
@@ -85,10 +85,10 @@ int set_essid(char * ifname, char * essid) {
sock = get_socket();
wreq = get_wreq(ifname);
- if (essid) {
+ if (ssid) {
wreq.u.essid.flags = 1;
- wreq.u.essid.pointer = (caddr_t) essid;
- wreq.u.essid.length = strlen(essid) + 1;
+ wreq.u.essid.pointer = (caddr_t) ssid;
+ wreq.u.essid.length = strlen(ssid) + 1;
} else {
wreq.u.essid.flags = 0;
wreq.u.essid.pointer = (caddr_t) NULL;
@@ -106,9 +106,9 @@ int set_essid(char * ifname, char * essid) {
return 0;
}
-char * get_essid(char * ifname) {
- int sock;
- struct iwreq wreq;
+char * get_ssid(char * ifname) {
+ int sock;
+ struct iwreq wreq;
memset(&wreq, 0, sizeof (wreq));
@@ -137,7 +137,7 @@ static int parse_wep_key(char * in, unsigned char * key) {
if (!strncmp(in, "s:", 2)) {
/* the key is a string */
len = strlen(in + 2);
- memmove(key, in + 2, len);
+ memmove(key, in + 2, len);
} else {
char *buff, *hex, *out, *p;
@@ -185,10 +185,10 @@ static int parse_wep_key(char * in, unsigned char * key) {
}
int set_wep_key(char * ifname, char * key) {
- int sock;
- struct iwreq wreq;
+ int sock;
+ struct iwreq wreq;
unsigned char thekey[IW_ENCODING_TOKEN_MAX];
-
+
if (strlen(key) > IW_ENCODING_TOKEN_MAX) {
fprintf(stderr, "wep key too long\n");
return -1;
@@ -252,13 +252,13 @@ int main(int argc, char **argv) {
exit(2);
}
- /* if (set_essid(argv[1], NULL) < 0) {
- fprintf(stderr, "Unable to set essid to %s\n", argv[2]);
+ /* if (set_ssid(argv[1], NULL) < 0) {
+ fprintf(stderr, "Unable to set ssid to %s\n", argv[2]);
exit(3);
}
exit(0);*/
- if (set_essid(argv[1], argv[2]) < 0) {
+ if (set_ssid(argv[1], argv[2]) < 0) {
fprintf(stderr, "Unable to set essid to %s\n", argv[2]);
exit(3);
}
diff --git a/isys/wireless.h b/isys/wireless.h
index 82cb4d4..9f683d9 100644
--- a/isys/wireless.h
+++ b/isys/wireless.h
@@ -21,8 +21,8 @@
#define WIRELESS_H
int is_wireless_interface(char * ifname);
-int set_essid(char * ifname, char * essid);
-char * get_essid(char * ifname);
+int set_ssid(char * ifname, char * ssid);
+char * get_ssid(char * ifname);
int set_wep_key(char * ifname, char * key);
int set_managed(char * ifname);
diff --git a/loader2/Makefile b/loader2/Makefile
index 9e1361b..103709d 100644
--- a/loader2/Makefile
+++ b/loader2/Makefile
@@ -28,13 +28,13 @@ endif
LIBS = -lnewt -lslang -lz -lpopt ../isys/libisys.a -lcheckisomd5
-# dhcp library flags
-LIBS += $(shell pkg-config --libs libdhcp)
-CFLAGS += $(shell pkg-config --cflags libdhcp)
-
# devmapper
-LIBS += $(shell pkg-config --libs devmapper)
-CFLAGS += $(shell pkg-config --cflags devmapper)
+LIBS += $(shell pkg-config --libs devmapper)
+CFLAGS += $(shell pkg-config --cflags devmapper)
+
+# libnl
+LIBS += $(shell pkg-config --libs libnl-1)
+CFLAGS += $(shell pkg-config --cflags libnl-1)
ifeq (1, $(USESELINUX))
LIBS += -lselinux -lsepol
diff --git a/loader2/linuxrc.s390 b/loader2/linuxrc.s390
index f9e1de9..210f83e 100644
--- a/loader2/linuxrc.s390
+++ b/loader2/linuxrc.s390
@@ -370,7 +370,6 @@ if [ "$NETTYPE" = "qeth" ] || [ "$NETTYPE" = "lcs" ]; then
else # ctc0, iucv0
if [ -z "$NETMASK" ]; then
# If the user did not supply netmask, we add the right one.
- # Netmask MUST be present, or pumpSetupInterface() blows routes.
NETMASK="255.255.255.255"
fi
while [ -z "$GATEWAY" ]; do
diff --git a/loader2/loader.c b/loader2/loader.c
index 56b227d..5f944f4 100644
--- a/loader2/loader.c
+++ b/loader2/loader.c
@@ -45,9 +45,12 @@
#include
#include
+#include
#include
#include
+#include
+
#include
#include
#include
@@ -150,7 +153,7 @@ void doShell(void) {
void doGdbserver(struct loaderData_s *loaderData) {
int child, rc, fd;
char *pid;
- struct networkDeviceConfig netCfg;
+ iface_t iface;
/* If gdbserver is found, go ahead and run it on the loader process now
* before anything bad happens.
@@ -158,7 +161,7 @@ void doGdbserver(struct loaderData_s *loaderData) {
if (loaderData->gdbServer && !access("/usr/bin/gdbserver", X_OK)) {
pid_t loaderPid = getpid();
- if (kickstartNetworkUp(loaderData, &netCfg)) {
+ if (kickstartNetworkUp(loaderData, &iface)) {
logMessage(ERROR, "can't run gdbserver due to no network");
return;
}
@@ -1077,7 +1080,7 @@ static char *doLoaderMain(char * location,
int rhcdfnd = 0;
char * devName = NULL;
- static struct networkDeviceConfig netDev;
+ static iface_t iface;
char * kbdtype = NULL;
@@ -1284,8 +1287,8 @@ static char *doLoaderMain(char * location,
logMessage(INFO, "need to set up networking");
initLoopback();
- memset(&netDev, 0, sizeof(netDev));
- netDev.isDynamic = 1;
+ memset(&iface, 0, sizeof(iface));
+ iface.flags |= IFACE_FLAGS_IS_DYNAMIC;
/* fall through to interface selection */
case STEP_IFACE:
@@ -1312,7 +1315,7 @@ static char *doLoaderMain(char * location,
}
devName = loaderData->netDev;
- strcpy(netDev.dev.device, devName);
+ strcpy(iface.device, devName);
/* continue to ip config */
step = STEP_IP;
@@ -1324,7 +1327,7 @@ static char *doLoaderMain(char * location,
break;
}
- if ((ret = malloc(48)) == NULL) {
+ if ((ret = malloc(INET6_ADDRSTRLEN+1)) == NULL) {
logMessage(ERROR, "malloc failure for ret in STEP_IP");
exit(EXIT_FAILURE);
}
@@ -1339,25 +1342,26 @@ static char *doLoaderMain(char * location,
/* populate netDev based on any kickstart data */
if (loaderData->ipinfo_set) {
- netDev.preset = 1;
+ iface.flags |= IFACE_FLAGS_IS_PRESET;
}
- setupNetworkDeviceConfig(&netDev, loaderData);
+ setupNetworkDeviceConfig(&iface, loaderData);
- rc = readNetConfig(devName, &netDev, loaderData->netCls, methodNum);
+ rc = readNetConfig(devName, &iface, loaderData->netCls, methodNum);
if (FL_NOIPV4(flags)) {
loaderData->ipinfo_set = 0;
} else {
if (loaderData->ipv4 == NULL) {
- if (strcmp((char *) &(netDev.dev.ip), "")) {
- ret = (char *) inet_ntop(AF_INET,
- IP_ADDR(&(netDev.dev.ip)), ret,
- IP_STRLEN(&(netDev.dev.ip)));
+ if (iface_have_in_addr(&iface.ipaddr)) {
+ if (inet_ntop(AF_INET, &iface.ipaddr, ret,
+ INET_ADDRSTRLEN) == NULL) {
+ ret = NULL;
+ }
} else {
ret = NULL;
- netDev.isDynamic = 1;
+ iface.flags |= IFACE_FLAGS_IS_DYNAMIC;
}
- if (netDev.isDynamic || ret == NULL) {
+ if (IFACE_IS_DYNAMIC(iface.flags) || ret == NULL) {
loaderData->ipv4 = strdup("dhcp");
} else {
loaderData->ipv4 = strdup(ret);
@@ -1371,16 +1375,17 @@ static char *doLoaderMain(char * location,
loaderData->ipv6info_set = 0;
} else {
if (loaderData->ipv6 == NULL) {
- if (strcmp((char *) &(netDev.dev.ip), "")) {
- ret = (char *) inet_ntop(AF_INET6,
- IP_ADDR(&(netDev.dev.ip)), ret,
- IP_STRLEN(&(netDev.dev.ip)));
+ if (iface_have_in6_addr(&iface.ip6addr)) {
+ if (inet_ntop(AF_INET6, &iface.ip6addr, ret,
+ INET6_ADDRSTRLEN) == NULL) {
+ ret = NULL;
+ }
} else {
ret = NULL;
- netDev.isDynamic = 1;
+ iface.flags |= IFACE_FLAGS_IS_DYNAMIC;
}
- if (netDev.isDynamic || ret == NULL) {
+ if (IFACE_IS_DYNAMIC(iface.flags) || ret == NULL) {
loaderData->ipv6 = strdup("dhcpv6");
} else {
loaderData->ipv6 = strdup(ret);
@@ -1399,8 +1404,10 @@ static char *doLoaderMain(char * location,
}
}
- free(ret);
- ret = NULL;
+ if (ret) {
+ free(ret);
+ ret = NULL;
+ }
if ((rc == LOADER_BACK) || (rc == LOADER_ERROR) ||
((dir == -1) && (rc == LOADER_NOOP))) {
@@ -1409,7 +1416,7 @@ static char *doLoaderMain(char * location,
break;
}
- writeNetInfo("/tmp/netinfo", &netDev);
+ writeNetInfo("/tmp/netinfo", &iface);
step = STEP_URL;
dir = 1;
break;
diff --git a/loader2/net.c b/loader2/net.c
index c468b67..8f12c66 100644
--- a/loader2/net.c
+++ b/loader2/net.c
@@ -1,8 +1,8 @@
/*
* net.c
*
- * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
- * All rights reserved.
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
+ * 2006, 2007, 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -65,6 +65,7 @@ static void cidrCallback(newtComponent co, void * dptr) {
struct intfconfig_s * data = dptr;
int cidr, upper = 0;
struct in_addr addr;
+ char *ep = NULL;
if (co == data->cidr4Entry) {
if (data->cidr4 == NULL && data->ipv4 == NULL)
@@ -73,7 +74,7 @@ static void cidrCallback(newtComponent co, void * dptr) {
if (inet_pton(AF_INET, data->cidr4, &addr) >= 1)
return;
- cidr = atoi(data->cidr4);
+ cidr = strtol(data->cidr4, &ep, 10);
if (strcmp(data->ipv4, ""))
upper = 32;
@@ -81,7 +82,7 @@ static void cidrCallback(newtComponent co, void * dptr) {
if (data->cidr6 == NULL && data->ipv6 == NULL)
return;
- cidr = atoi(data->cidr6);
+ cidr = strtol(data->cidr6, &ep, 10);
if (strcmp(data->ipv6, ""))
upper = 128;
@@ -99,7 +100,7 @@ static void cidrCallback(newtComponent co, void * dptr) {
static void ipCallback(newtComponent co, void * dptr) {
int i;
- char *buf, *octet;
+ char *buf, *octet, *ep;
struct intfconfig_s * data = dptr;
if (co == data->ipv4Entry) {
@@ -107,7 +108,7 @@ static void ipCallback(newtComponent co, void * dptr) {
if (data->cidr4 == NULL && data->ipv4 != NULL) {
buf = strdup(data->ipv4);
octet = strtok(buf, ".");
- i = atoi(octet);
+ i = strtol(octet, &ep, 10);
free(buf);
free(octet);
@@ -229,7 +230,7 @@ void initLoopback(void) {
strcpy(req.ifr_name, "lo");
if (ioctl(s, SIOCGIFFLAGS, &req)) {
- logMessage(LOG_ERR, "ioctl SIOCGIFFLAGS failed: %d %s\n", errno,
+ logMessage(ERROR, "ioctl SIOCGIFFLAGS failed: %d %s\n", errno,
strerror(errno));
close(s);
return;
@@ -237,7 +238,7 @@ void initLoopback(void) {
req.ifr_flags |= (IFF_UP | IFF_RUNNING);
if (ioctl(s, SIOCSIFFLAGS, &req)) {
- logMessage(LOG_ERR, "ioctl SIOCSIFFLAGS failed: %d %s\n", errno,
+ logMessage(ERROR, "ioctl SIOCSIFFLAGS failed: %d %s\n", errno,
strerror(errno));
close(s);
return;
@@ -248,19 +249,19 @@ void initLoopback(void) {
return;
}
-static int getWirelessConfig(struct networkDeviceConfig *cfg, char * ifname) {
+static int getWirelessConfig(iface_t * iface, char * ifname) {
char * wepkey = "";
- char * essid = "";
+ char * ssid = "";
int rc = 0;
char * buf;
- if (cfg->wepkey != NULL) {
- wepkey = strdup(cfg->wepkey);
+ if (iface->wepkey != NULL) {
+ wepkey = strdup(iface->wepkey);
}
- if (cfg->essid != NULL) {
- essid = strdup(cfg->essid);
+ if (iface->ssid != NULL) {
+ ssid = strdup(iface->ssid);
} else {
- essid = get_essid(ifname);
+ ssid = get_ssid(ifname);
}
rc = asprintf(&buf, _("%s is a wireless network adapter. Please "
@@ -268,8 +269,14 @@ static int getWirelessConfig(struct networkDeviceConfig *cfg, char * ifname) {
"to access your wireless network. If no key "
"is needed, leave this field blank and the "
"install will continue."), ifname);
+
+ if (rc == -1) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, strerror(errno));
+ abort();
+ }
+
do {
- struct newtWinEntry entry[] = { { N_("ESSID"), &essid, 0 },
+ struct newtWinEntry entry[] = { { N_("SSID"), &ssid, 0 },
{ N_("Encryption Key"), &wepkey, 0 },
{ NULL, NULL, 0 } };
@@ -284,26 +291,26 @@ static int getWirelessConfig(struct networkDeviceConfig *cfg, char * ifname) {
} while (rc == 2);
free(buf);
- if (cfg->wepkey != NULL)
- free(cfg->wepkey);
+ if (iface->wepkey != NULL)
+ free(iface->wepkey);
if (wepkey && (strlen(wepkey) > 0))
- cfg->wepkey = strdup(wepkey);
+ iface->wepkey = strdup(wepkey);
else
- cfg->wepkey = NULL;
+ iface->wepkey = NULL;
- if (cfg->essid != NULL)
- free(cfg->essid);
+ if (iface->ssid != NULL)
+ free(iface->ssid);
- if (essid && (strlen(essid) > 0))
- cfg->essid = strdup(essid);
+ if (ssid && (strlen(ssid) > 0))
+ iface->ssid = strdup(ssid);
else
- cfg->essid = NULL;
+ iface->ssid = NULL;
return LOADER_OK;
}
-static int getDnsServers(struct networkDeviceConfig * cfg) {
+static int getDnsServers(iface_t * iface) {
int rc;
struct in_addr addr;
struct in6_addr addr6;
@@ -323,23 +330,22 @@ static int getDnsServers(struct networkDeviceConfig * cfg) {
rc = 0;
if (!ns || !*ns) {
- cfg->dev.numDns = 0;
+ iface->numdns = 0;
break;
} else {
- if (inet_pton(AF_INET, ns, &addr) >= 1)
- cfg->dev.dnsServers[0] = ip_addr_in(&addr);
- else if (inet_pton(AF_INET6, ns, &addr6) >= 1)
- cfg->dev.dnsServers[0] = ip_addr_in6(&addr6);
- else
+ if ((inet_pton(AF_INET, ns, &addr) >= 1) ||
+ (inet_pton(AF_INET6, ns, &addr6) >= 1)) {
+ iface->dns[0] = strdup(ns);
+ } else {
rc = 2;
+ }
}
if (rc) {
newtWinMessage(_("Invalid IP Information"), _("Retry"),
_("You entered an invalid IP address."));
} else {
- cfg->dev.set |= PUMP_NETINFO_HAS_DNS;
- cfg->dev.numDns = 1;
+ iface->numdns = 1;
}
} while (rc == 2);
@@ -364,7 +370,7 @@ void printLoaderDataIPINFO(struct loaderData_s *loaderData) {
}
/* given loader data from kickstart, populate network configuration struct */
-void setupNetworkDeviceConfig(struct networkDeviceConfig * cfg,
+void setupNetworkDeviceConfig(iface_t * iface,
struct loaderData_s * loaderData) {
struct in_addr addr;
struct in6_addr addr6;
@@ -380,9 +386,9 @@ void setupNetworkDeviceConfig(struct networkDeviceConfig * cfg,
}
if (loaderData->netCls_set) {
- cfg->vendor_class = loaderData->netCls;
+ iface->vendorclass = loaderData->netCls;
} else {
- cfg->vendor_class = NULL;
+ iface->vendorclass = NULL;
}
if (loaderData->ipinfo_set) {
@@ -390,20 +396,20 @@ void setupNetworkDeviceConfig(struct networkDeviceConfig * cfg,
if (loaderData->essid) {
logMessage(INFO, "setting specified essid of %s",
loaderData->essid);
- cfg->essid = strdup(loaderData->essid);
+ iface->ssid = strdup(loaderData->essid);
}
if (loaderData->wepkey) {
logMessage(INFO, "setting specified wepkey");
- cfg->wepkey = strdup(loaderData->wepkey);
+ iface->wepkey = strdup(loaderData->wepkey);
}
/* go ahead and set up the wireless interface in case
* we're using dhcp */
- setupWireless(cfg);
+ setupWireless(iface);
}
/* this is how we specify dhcp */
if (!strncmp(loaderData->ipv4, "dhcp", 4)) {
- char *ret = NULL;
+ int ret = 0;
/* JKFIXME: this soooo doesn't belong here. and it needs to
* be broken out into a function too */
@@ -422,180 +428,169 @@ void setupNetworkDeviceConfig(struct networkDeviceConfig * cfg,
if (!FL_TESTING(flags)) {
waitForLink(loaderData->netDev);
- cfg->noDns = loaderData->noDns;
- cfg->dhcpTimeout = loaderData->dhcpTimeout;
- ret = doDhcp(cfg);
+
+ if (loaderData->noDns) {
+ iface->flags |= IFACE_FLAGS_NO_WRITE_RESOLV_CONF;
+ }
+
+ iface->dhcptimeout = loaderData->dhcpTimeout;
+ ret = doDhcp(iface);
}
if (!FL_CMDLINE(flags))
newtPopWindow();
- if (ret != NULL) {
- logMessage(DEBUGLVL, "dhcp: %s", ret);
+ if (ret) {
+ logMessage(DEBUGLVL, "dhcp: %d", ret);
return;
}
- cfg->isDynamic = 1;
- cfg->preset = 1;
+ iface->flags |= IFACE_FLAGS_IS_DYNAMIC | IFACE_FLAGS_IS_PRESET;
} else if (loaderData->ipv4) {
if (inet_pton(AF_INET, loaderData->ipv4, &addr) >= 1) {
- cfg->dev.ip = ip_addr_in(&addr);
- cfg->dev.ipv4 = ip_addr_in(&addr);
- cfg->dev.set |= PUMP_INTFINFO_HAS_IP|PUMP_INTFINFO_HAS_IPV4_IP;
- cfg->isDynamic = 0;
- cfg->preset = 1;
+ iface->ipaddr = addr;
+ iface->flags &= ~IFACE_FLAGS_IS_DYNAMIC;
+ iface->flags |= IFACE_FLAGS_IS_PRESET;
}
} else if (loaderData->ipv6) {
if (inet_pton(AF_INET6, loaderData->ipv6, &addr6) >= 1) {
- cfg->dev.ip = ip_addr_in6(&addr6);
- cfg->dev.ipv6 = ip_addr_in6(&addr6);
- cfg->dev.set |= PUMP_INTFINFO_HAS_IP|PUMP_INTFINFO_HAS_IPV6_IP;
- cfg->isDynamic = 0;
- cfg->preset = 1;
+ memcpy(&iface->ip6addr, &addr6, sizeof(struct in6_addr));
+ iface->flags &= ~IFACE_FLAGS_IS_DYNAMIC;
+ iface->flags |= IFACE_FLAGS_IS_PRESET;
}
} else { /* invalid ip information, disable the setting of ip info */
loaderData->ipinfo_set = 0;
- cfg->isDynamic = 0;
+ iface->flags &= ~IFACE_FLAGS_IS_DYNAMIC;
loaderData->ipv4 = NULL;
loaderData->ipv6 = NULL;
}
}
- if (loaderData->netmask && (inet_pton(AF_INET, loaderData->netmask, &addr) >= 1)) {
- cfg->dev.netmask = ip_addr_in(&addr);
- cfg->dev.set |= PUMP_INTFINFO_HAS_NETMASK;
+ if (loaderData->netmask) {
+ if (inet_pton(AF_INET, loaderData->netmask, &iface->netmask) <= 0) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
}
- if (loaderData->gateway && (inet_pton(AF_INET, loaderData->gateway, &addr) >= 1)) {
- cfg->dev.gateway = ip_addr_in(&addr);
- cfg->dev.set |= PUMP_NETINFO_HAS_GATEWAY;
+ if (loaderData->gateway) {
+ if (inet_pton(AF_INET, loaderData->gateway, &iface->gateway) <= 0) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
}
- if (loaderData->gateway && (inet_pton(AF_INET6, loaderData->gateway, &addr6) >= 1)) {
- cfg->dev.gateway = ip_addr_in6(&addr6);
- cfg->dev.set |= PUMP_NETINFO_HAS_GATEWAY;
- }
+ /* FIXME: add support for loaderData->gateway6 */
if (loaderData->dns) {
char * buf;
- char ret[48];
+ char ret[INET6_ADDRSTRLEN+1];
buf = strdup(loaderData->dns);
/* Scan the dns parameter for multiple comma-separated IP addresses */
- c = strtok(buf, ",");
- while ((cfg->dev.numDns < MAXNS) && (c != NULL)) {
+ c = strtok(buf, ",");
+ while ((iface->numdns < MAXNS) && (c != NULL)) {
if (inet_pton(AF_INET, c, &addr) >= 1) {
- cfg->dev.dnsServers[cfg->dev.numDns] = ip_addr_in(&addr);
- cfg->dev.numDns++;
- inet_ntop(AF_INET, &addr, ret, INET_ADDRSTRLEN);
- logMessage(DEBUGLVL, "adding dns4 %s", ret);
- c = strtok(NULL, ",");
+ iface->dns[iface->numdns] = strdup(c);
+ iface->numdns++;
+
+ if (inet_ntop(AF_INET, &addr, ret, INET_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, strerror(errno));
+ } else {
+ logMessage(DEBUGLVL, "adding dns4 %s", ret);
+ c = strtok(NULL, ",");
+ }
} else if (inet_pton(AF_INET6, c, &addr6) >= 1) {
- cfg->dev.dnsServers[cfg->dev.numDns] = ip_addr_in6(&addr6);
- cfg->dev.numDns++;
- inet_ntop(AF_INET6, &addr6, ret, INET6_ADDRSTRLEN);
- logMessage(DEBUGLVL, "adding dns6 %s", ret);
- c = strtok(NULL, ",");
+ iface->dns[iface->numdns] = strdup(c);
+ iface->numdns++;
+
+ if (inet_ntop(AF_INET6, &addr6, ret, INET6_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, strerror(errno));
+ } else {
+ logMessage(DEBUGLVL, "adding dns6 %s", ret);
+ c = strtok(NULL, ",");
+ }
}
}
+
logMessage(INFO, "dnsservers is %s", loaderData->dns);
- if (cfg->dev.numDns)
- cfg->dev.set |= PUMP_NETINFO_HAS_DNS;
}
if (loaderData->hostname) {
logMessage(INFO, "setting specified hostname of %s",
loaderData->hostname);
- cfg->dev.hostname = strdup(loaderData->hostname);
- cfg->dev.set |= PUMP_NETINFO_HAS_HOSTNAME;
+ iface->hostname = strdup(loaderData->hostname);
}
if (loaderData->mtu) {
- cfg->mtu = loaderData->mtu;
- cfg->dev.mtu = loaderData->mtu;
- cfg->dev.set |= PUMP_INTFINFO_HAS_MTU;
+ iface->mtu = loaderData->mtu;
}
if (loaderData->peerid) {
- cfg->peerid = strdup(loaderData->peerid);
+ iface->peerid = strdup(loaderData->peerid);
}
if (loaderData->subchannels) {
- cfg->subchannels = strdup(loaderData->subchannels);
+ iface->subchannels = strdup(loaderData->subchannels);
}
if (loaderData->ctcprot) {
- cfg->ctcprot = strdup(loaderData->ctcprot);
+ iface->ctcprot = strdup(loaderData->ctcprot);
}
if (loaderData->portname) {
- cfg->portname = strdup(loaderData->portname);
+ iface->portname = strdup(loaderData->portname);
}
if (loaderData->nettype) {
- cfg->nettype = strdup(loaderData->nettype);
+ iface->nettype = strdup(loaderData->nettype);
}
if (loaderData->ethtool) {
parseEthtoolSettings(loaderData);
}
- cfg->noDns = loaderData->noDns;
- cfg->dhcpTimeout = loaderData->dhcpTimeout;
+ if (loaderData->noDns) {
+ iface->flags |= IFACE_FLAGS_NO_WRITE_RESOLV_CONF;
+ }
+
+ iface->dhcptimeout = loaderData->dhcpTimeout;
}
-int readNetConfig(char * device, struct networkDeviceConfig * cfg,
+int readNetConfig(char * device, iface_t * iface,
char * dhcpclass, int methodNum) {
- struct networkDeviceConfig newCfg;
int ret;
int i = 0;
struct netconfopts opts;
- struct in_addr addr, nm, nw;
- struct in6_addr addr6;
+ struct in_addr addr;
struct intfconfig_s ipcomps;
- memset(&ipcomps, '\0', sizeof(ipcomps));
+ /* ipcomps contains the user interface components */
ipcomps.ipv4 = NULL;
ipcomps.ipv6 = NULL;
ipcomps.cidr4 = NULL;
ipcomps.cidr6 = NULL;
ipcomps.gw = NULL;
+ ipcomps.gw6 = NULL;
ipcomps.ns = NULL;
-
- /* init opts */
opts.ipv4Choice = 0;
opts.ipv6Choice = 0;
- /* init newCfg */
- memset(&newCfg, '\0', sizeof(newCfg));
- strcpy(newCfg.dev.device, device);
- newCfg.essid = NULL;
- newCfg.wepkey = NULL;
- newCfg.isDynamic = cfg->isDynamic;
- newCfg.noDns = cfg->noDns;
- newCfg.dhcpTimeout = cfg->dhcpTimeout;
- newCfg.preset = cfg->preset;
- if (dhcpclass) {
- newCfg.vendor_class = strdup(dhcpclass);
- } else {
- newCfg.vendor_class = NULL;
- }
-
/* JKFIXME: we really need a way to override this and be able to change
* our network config */
- if (!FL_TESTING(flags) && cfg->preset) {
+ if (!FL_TESTING(flags) && IFACE_IS_PRESET(iface->flags)) {
logMessage(INFO, "doing kickstart... setting it up");
- if (configureNetwork(cfg)) {
+ if (configureNetwork(iface)) {
newtWinMessage(_("Network Error"), _("Retry"),
_("There was an error configuring your network "
"interface."));
return LOADER_BACK;
}
- findHostAndDomain(cfg);
+ findHostAndDomain(iface);
- if (!cfg->noDns)
- writeResolvConf(cfg);
+ if (!IFACE_NO_WRITE_RESOLV_CONF(iface->flags))
+ writeResolvConf(iface);
return LOADER_NOOP;
}
@@ -603,15 +598,9 @@ int readNetConfig(char * device, struct networkDeviceConfig * cfg,
/* handle wireless device configuration */
if (is_wireless_interface(device)) {
logMessage(INFO, "%s is a wireless adapter", device);
- if (getWirelessConfig(cfg, device) == LOADER_BACK) {
+ if (getWirelessConfig(iface, device) == LOADER_BACK) {
return LOADER_BACK;
}
-
- if (cfg->essid != NULL)
- newCfg.essid = strdup(cfg->essid);
-
- if (cfg->wepkey != NULL)
- newCfg.wepkey = strdup(cfg->wepkey);
} else {
logMessage(INFO, "%s is not a wireless adapter", device);
}
@@ -619,14 +608,14 @@ int readNetConfig(char * device, struct networkDeviceConfig * cfg,
/* dhcp/manual network configuration loop */
i = 1;
while (i == 1) {
- ret = configureTCPIP(device, cfg, &newCfg, &opts, methodNum);
+ ret = configureTCPIP(device, iface, &opts, methodNum);
if (ret == LOADER_NOOP) {
/* dhcp selected, proceed */
i = 0;
} else if (ret == LOADER_OK) {
/* do manual configuration */
- ret = manualNetConfig(device, cfg, &newCfg, &ipcomps, &opts);
+ ret = manualNetConfig(device, iface, &ipcomps, &opts);
if (ret == LOADER_BACK) {
continue;
@@ -638,87 +627,54 @@ int readNetConfig(char * device, struct networkDeviceConfig * cfg,
}
}
- cfg->ipv4method = newCfg.ipv4method;
- cfg->ipv6method = newCfg.ipv6method;
-
- /* preserve extra dns servers for the sake of being nice */
- if (cfg->dev.numDns > newCfg.dev.numDns) {
- for (i = newCfg.dev.numDns; i < cfg->dev.numDns; i++) {
- memcpy(&newCfg.dev.dnsServers[i], &cfg->dev.dnsServers[i],
- sizeof (newCfg.dev.dnsServers[i]));
- }
- newCfg.dev.numDns = cfg->dev.numDns;
- }
-
- cfg->isDynamic = newCfg.isDynamic;
- memcpy(&cfg->dev, &newCfg.dev, sizeof(newCfg.dev));
-
- if (!(cfg->dev.set & PUMP_NETINFO_HAS_GATEWAY)) {
- if (ipcomps.gw != NULL) {
- if (inet_pton(AF_INET, ipcomps.gw, &addr) >= 1) {
- cfg->dev.gateway = ip_addr_in(&addr);
- cfg->dev.set |= PUMP_NETINFO_HAS_GATEWAY;
- } else if (inet_pton(AF_INET6, ipcomps.gw, &addr6) >= 1) {
- cfg->dev.gateway = ip_addr_in6(&addr6);
- cfg->dev.set |= PUMP_NETINFO_HAS_GATEWAY;
- }
+/*
+ if (ipcomps.gw && *ipcomps.gw) {
+ if (inet_pton(AF_INET, ipcomps.gw, &iface->gateway) <= 0) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else if (inet_pton(AF_INET6, ipcomps.gw, &iface->gateway6) <= 0) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
}
}
+*/
/* calculate any missing IPv4 pieces */
if (opts.ipv4Choice == '*') {
- addr = ip_in_addr(&cfg->dev.ipv4);
- nm = ip_in_addr(&cfg->dev.netmask);
+ memset(&addr, 0, sizeof(addr));
+ addr.s_addr = (iface->ipaddr.s_addr) & (iface->netmask.s_addr);
- if (!(cfg->dev.set & PUMP_INTFINFO_HAS_NETWORK)) {
- cfg->dev.network = ip_addr_v4(ntohl((addr.s_addr) & nm.s_addr));
- cfg->dev.set |= PUMP_INTFINFO_HAS_NETWORK;
+ if (iface->broadcast.s_addr == 0) {
+ iface->broadcast.s_addr = addr.s_addr | ~(iface->netmask.s_addr);
}
-
- if (!(cfg->dev.set & PUMP_INTFINFO_HAS_BROADCAST)) {
- nw = ip_in_addr(&cfg->dev.network);
- cfg->dev.broadcast = ip_addr_v4(ntohl(nw.s_addr | ~nm.s_addr));
- cfg->dev.set |= PUMP_INTFINFO_HAS_BROADCAST;
- }
- }
-
- /* make sure we don't have a dhcp_nic handle for static */
- if ((cfg->isDynamic == 0) && (cfg->dev.dhcp_nic != NULL)) {
- dhcp_nic_free(cfg->dev.dhcp_nic);
- cfg->dev.dhcp_nic = NULL;
}
/* dump some network debugging info */
- debugNetworkInfo(cfg);
+ debugNetworkInfo(iface);
/* bring up the interface */
if (!FL_TESTING(flags)) {
- if (configureNetwork(cfg)) {
+ if (configureNetwork(iface)) {
newtWinMessage(_("Network Error"), _("Retry"),
_("There was an error configuring your network "
"interface."));
return LOADER_BACK;
}
- findHostAndDomain(cfg);
- writeResolvConf(cfg);
+ findHostAndDomain(iface);
+ writeResolvConf(iface);
}
return LOADER_OK;
}
-int configureTCPIP(char * device, struct networkDeviceConfig * cfg,
- struct networkDeviceConfig * newCfg,
+int configureTCPIP(char * device, iface_t * iface,
struct netconfopts * opts, int methodNum) {
- int i = 0, z = 0, skipForm = 0;
- char *dret = NULL;
+ int i = 0, z = 0, skipForm = 0, dret = 0;
newtComponent f, okay, back, answer;
newtComponent ipv4Checkbox, ipv6Checkbox, v4Method[2], v6Method[3];
newtGrid grid, checkgrid, buttons;
- newCfg->ipv4method = -1;
- newCfg->ipv6method = -1;
-
/* UI WINDOW 1: ask for ipv4 choice, ipv6 choice, and conf methods */
/* IPv4 checkbox */
@@ -836,39 +792,39 @@ int configureTCPIP(char * device, struct networkDeviceConfig * cfg,
/* what TCP/IP stacks do we use? what conf methods? */
if (opts->ipv4Choice == '*') {
flags &= ~LOADER_FLAGS_NOIPV4;
- for (z = 0; z < 2; z++)
- if (newtRadioGetCurrent(v4Method[0]) == v4Method[z])
- newCfg->ipv4method = z;
+ for (z = IPV4_FIRST_METHOD; z <= IPV4_LAST_METHOD; z++)
+ if (newtRadioGetCurrent(v4Method[0]) == v4Method[z-1])
+ iface->ipv4method = z;
} else {
flags |= LOADER_FLAGS_NOIPV4;
}
if (opts->ipv6Choice == '*') {
flags &= ~LOADER_FLAGS_NOIPV6;
- for (z = 0; z < 3; z++)
- if (newtRadioGetCurrent(v6Method[0]) == v6Method[z])
- newCfg->ipv6method = z;
+ for (z = IPV6_FIRST_METHOD; z <- IPV6_LAST_METHOD; z++)
+ if (newtRadioGetCurrent(v6Method[0]) == v6Method[z-1])
+ iface->ipv6method = z;
} else {
flags |= LOADER_FLAGS_NOIPV6;
}
/* do interface configuration (call DHCP here, or return for manual) */
- if ((!FL_NOIPV4(flags) && newCfg->ipv4method == IPV4_DHCP_METHOD) ||
- (!FL_NOIPV6(flags) && (newCfg->ipv6method == IPV6_AUTO_METHOD ||
- newCfg->ipv6method == IPV6_DHCP_METHOD))) {
+ if ((!FL_NOIPV4(flags) && iface->ipv4method == IPV4_DHCP_METHOD) ||
+ (!FL_NOIPV6(flags) && (iface->ipv6method == IPV6_AUTO_METHOD ||
+ iface->ipv6method == IPV6_DHCP_METHOD))) {
/* do DHCP if selected */
if (!FL_TESTING(flags)) {
winStatus(55, 3, NULL,
_("Sending request for IP information for %s..."),
device, 0);
waitForLink(device);
- dret = doDhcp(newCfg);
+ dret = doDhcp(iface);
newtPopWindow();
}
- if (dret == NULL) {
- newCfg->isDynamic = 1;
- if (!(newCfg->dev.set & PUMP_NETINFO_HAS_DNS)) {
+ if (!dret) {
+ iface->flags |= IFACE_FLAGS_IS_DYNAMIC;
+ if (iface->numdns == 0) {
logMessage(WARNING,
"dhcp worked, but did not return a DNS server");
@@ -878,15 +834,15 @@ int configureTCPIP(char * device, struct networkDeviceConfig * cfg,
* - IPv4 disabled and DHCP/AUTO for IPv6
* - IPv6 disabled and DHCP for IPv4
*/
- if ((newCfg->ipv4method == IPV4_DHCP_METHOD
- && (newCfg->ipv6method == IPV6_AUTO_METHOD ||
- newCfg->ipv6method == IPV6_DHCP_METHOD))
- || (newCfg->ipv4method == IPV4_DHCP_METHOD
+ if ((iface->ipv4method == IPV4_DHCP_METHOD
+ && (iface->ipv6method == IPV6_AUTO_METHOD ||
+ iface->ipv6method == IPV6_DHCP_METHOD))
+ || (iface->ipv4method == IPV4_DHCP_METHOD
&& FL_NOIPV6(flags))
|| (FL_NOIPV4(flags)
- && (newCfg->ipv6method == IPV6_AUTO_METHOD ||
- newCfg->ipv6method == IPV6_DHCP_METHOD))) {
- i = getDnsServers(newCfg);
+ && (iface->ipv6method == IPV6_AUTO_METHOD ||
+ iface->ipv6method == IPV6_DHCP_METHOD))) {
+ i = getDnsServers(iface);
i = i ? 0 : 1;
} else {
i = 1;
@@ -895,7 +851,7 @@ int configureTCPIP(char * device, struct networkDeviceConfig * cfg,
i = 1;
}
} else {
- logMessage(DEBUGLVL, "dhcp: %s", dret);
+ logMessage(DEBUGLVL, "dhcp: %d", dret);
i = 0;
}
} else {
@@ -909,22 +865,21 @@ int configureTCPIP(char * device, struct networkDeviceConfig * cfg,
newtFormDestroy(f);
newtPopWindow();
- if ((!FL_NOIPV4(flags) && newCfg->ipv4method == IPV4_MANUAL_METHOD) ||
- (!FL_NOIPV6(flags) && newCfg->ipv6method == IPV6_MANUAL_METHOD))
+ if ((!FL_NOIPV4(flags) && iface->ipv4method == IPV4_MANUAL_METHOD) ||
+ (!FL_NOIPV6(flags) && iface->ipv6method == IPV6_MANUAL_METHOD))
return LOADER_OK;
else
return LOADER_NOOP;
}
-int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
- struct networkDeviceConfig * newCfg,
+int manualNetConfig(char * device, iface_t * iface,
struct intfconfig_s * ipcomps, struct netconfopts * opts) {
- int i, rows, pos, prefix, cidr, q, have[2], stack[2];
- char *buf = NULL;
- char ret[48];
- ip_addr_t *tip;
+ int i, rows, pos, prefix, cidr, have[2], stack[2];
+ char *buf = NULL, *ep;
+ char ret[INET6_ADDRSTRLEN+1];
struct in_addr addr;
struct in6_addr addr6;
+ struct in_addr *tmpaddr = NULL;
newtComponent f, okay, back, answer;
newtGrid egrid = NULL;
newtGrid qgrid = NULL;
@@ -932,16 +887,21 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
newtGrid buttons, grid;
newtComponent text = NULL;
+ memset(ret, '\0', INET6_ADDRSTRLEN+1);
+
/* so we don't perform this test over and over */
- stack[IPV4] = opts->ipv4Choice == '*'
- && newCfg->ipv4method == IPV4_MANUAL_METHOD;
- stack[IPV6] = opts->ipv6Choice == '*'
- && newCfg->ipv6method == IPV6_MANUAL_METHOD;
+ stack[IPV4] = opts->ipv4Choice == '*' &&
+ iface->ipv4method == IPV4_MANUAL_METHOD;
+ stack[IPV6] = opts->ipv6Choice == '*' &&
+ iface->ipv6method == IPV6_MANUAL_METHOD;
/* UI WINDOW 2 (optional): manual IP config for non-DHCP installs */
rows = 2;
- for (i = 0; i < 2; i++)
- if (stack[i]) rows++;
+ for (i = 0; i < 2; i++) {
+ if (stack[i]) {
+ rows++;
+ }
+ }
egrid = newtCreateGrid(4, rows);
pos = 0;
@@ -973,25 +933,39 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
newtComponentAddCallback(ipcomps->cidr4Entry, cidrCallback, ipcomps);
/* populate fields if we have data already */
- tip = NULL;
- if (cfg->dev.set & PUMP_INTFINFO_HAS_IPV4_IP)
- tip = &(cfg->dev.ipv4);
- else if (newCfg->dev.set & PUMP_INTFINFO_HAS_IPV4_IP)
- tip = &(newCfg->dev.ipv4);
-
- if (tip) {
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
+ if (iface_have_in_addr(&iface->ipaddr)) {
+ if (inet_ntop(AF_INET, &iface->ipaddr, ret,
+ INET_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
+ } else if (iface_have_in_addr(&iface->ipaddr)) {
+ if (inet_ntop(AF_INET, &iface->ipaddr, ret,
+ INET_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
+ }
+
+ if (*ret) {
newtEntrySet(ipcomps->ipv4Entry, ret, 1);
}
- tip = NULL;
- if (cfg->dev.set & PUMP_INTFINFO_HAS_NETMASK)
- tip = &(cfg->dev.netmask);
- else if (newCfg->dev.set & PUMP_INTFINFO_HAS_NETMASK)
- tip = &(newCfg->dev.netmask);
+ if (iface_have_in_addr(&iface->netmask)) {
+ if (inet_ntop(AF_INET, &iface->netmask, ret,
+ INET_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
+ } else if (iface_have_in_addr(&iface->netmask)) {
+ if (inet_ntop(AF_INET, &iface->netmask, ret,
+ INET_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
+ }
- if (tip) {
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
+ if (*ret) {
newtEntrySet(ipcomps->cidr4Entry, ret, 1);
}
@@ -1025,23 +999,35 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
newtComponentAddCallback(ipcomps->cidr6Entry, cidrCallback, ipcomps);
/* populate fields if we have data already */
- tip = NULL;
- if (cfg->dev.set & PUMP_INTFINFO_HAS_IPV6_IP)
- tip = &(cfg->dev.ipv6);
- else if (newCfg->dev.set & PUMP_INTFINFO_HAS_IPV6_IP)
- tip = &(newCfg->dev.ipv6);
-
- if (tip) {
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
+ if (iface_have_in6_addr(&iface->ip6addr)) {
+ if (inet_ntop(AF_INET6, &iface->ip6addr, ret,
+ INET6_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
+ } else if (iface_have_in6_addr(&iface->ip6addr)) {
+ if (inet_ntop(AF_INET6, &iface->ip6addr, ret,
+ INET6_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ }
+ }
+
+ if (*ret) {
newtEntrySet(ipcomps->ipv6Entry, ret, 1);
}
- if (cfg->dev.set & PUMP_INTFINFO_HAS_IPV6_PREFIX)
- q = asprintf(&buf, "%d", cfg->dev.ipv6_prefixlen);
- else if (newCfg->dev.set & PUMP_INTFINFO_HAS_IPV6_PREFIX)
- q = asprintf(&buf, "%d", newCfg->dev.ipv6_prefixlen);
+ if (iface->ip6prefix) {
+ if (asprintf(&buf, "%d", iface->ip6prefix) == -1) {
+ buf = NULL;
+ }
+ } else if (iface->ip6prefix) {
+ if (asprintf(&buf, "%d", iface->ip6prefix) == -1) {
+ buf = NULL;
+ }
+ }
- if (buf) {
+ if (buf != NULL) {
newtEntrySet(ipcomps->cidr6Entry, buf, 1);
free(buf);
}
@@ -1067,26 +1053,28 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
newtGridSetField(egrid, 1, pos, NEWT_GRID_COMPONENT,
ipcomps->nsEntry, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
- tip = NULL;
- if (cfg->dev.set & PUMP_NETINFO_HAS_GATEWAY)
- tip = &(cfg->dev.gateway);
- else if (newCfg->dev.set & PUMP_NETINFO_HAS_GATEWAY)
- tip = &(newCfg->dev.gateway);
-
- if (tip) {
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- newtEntrySet(ipcomps->gwEntry, ret, 1);
+ if (iface_have_in_addr(&iface->gateway)) {
+ if (inet_ntop(AF_INET, &iface->gateway, ret,
+ INET_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ newtEntrySet(ipcomps->gwEntry, ret, 1);
+ }
+ } else if (iface_have_in6_addr(&iface->gateway6)) {
+ if (inet_ntop(AF_INET6, &iface->gateway6, ret,
+ INET6_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ newtEntrySet(ipcomps->gwEntry, ret, 1);
+ }
}
- tip = NULL;
- if (cfg->dev.numDns)
- tip = &(cfg->dev.dnsServers[0]);
- else if (newCfg->dev.numDns)
- tip = &(newCfg->dev.dnsServers[0]);
-
- if (tip) {
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- newtEntrySet(ipcomps->nsEntry, ret, 1);
+ if (iface->numdns) {
+ newtEntrySet(ipcomps->nsEntry, iface->dns[0], 1);
+ } else if (iface->numdns) {
+ newtEntrySet(ipcomps->nsEntry, iface->dns[0], 1);
}
newtComponentAddCallback(ipcomps->gwEntry, ipCallback, ipcomps);
@@ -1103,6 +1091,12 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
"netmask or the CIDR-style prefix are acceptable. "
"The gateway and name server fields must be valid IPv4 "
"or IPv6 addresses."));
+
+ if (i == -1) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__, strerror(errno));
+ abort();
+ }
+
text = newtTextboxReflowed(-1, -1, buf, 52, 0, 10, 0);
newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
@@ -1126,31 +1120,31 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
if (!stack[i]) have[i] = 2;
answer = newtRunForm(f);
- /* memset(newCfg, 0, sizeof(*newCfg)); */
/* collect IPv4 data */
if (stack[IPV4]) {
if (ipcomps->ipv4) {
- if (inet_pton(AF_INET, ipcomps->ipv4, &addr) >= 1) {
- newCfg->dev.ipv4 = ip_addr_in(&addr);
- newCfg->dev.set |= PUMP_INTFINFO_HAS_IPV4_IP;
+ if (inet_pton(AF_INET, ipcomps->ipv4, &iface->ipaddr) <= 0) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
have[IPV4]++;
}
}
if (ipcomps->cidr4) {
- if (inet_pton(AF_INET, ipcomps->cidr4, &addr) >= 1) {
- newCfg->dev.netmask = ip_addr_in(&addr);
- newCfg->dev.set |= PUMP_INTFINFO_HAS_NETMASK;
+ if (inet_pton(AF_INET, ipcomps->cidr4, &iface->netmask)>=1) {
have[IPV4]++;
} else {
- cidr = atoi(ipcomps->cidr4);
+ cidr = strtol(ipcomps->cidr4, &ep, 10);
if (cidr >= 1 && cidr <= 32) {
- if (inet_pton(AF_INET, "255.255.255.255", &addr) >= 1) {
- addr.s_addr = htonl(ntohl(addr.s_addr) << (32 - cidr));
- newCfg->dev.netmask = ip_addr_in(&addr);
- newCfg->dev.set |= PUMP_INTFINFO_HAS_NETMASK;
+ tmpaddr = iface_prefix2netmask(cidr);
+ if (tmpaddr != NULL) {
+ memcpy(&iface->netmask, tmpaddr,
+ sizeof(struct in_addr));
have[IPV4]++;
+ } else {
+ iface->netmask.s_addr = 0;
}
}
}
@@ -1160,18 +1154,18 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
/* collect IPv6 data */
if (stack[IPV6]) {
if (ipcomps->ipv6) {
- if (inet_pton(AF_INET6, ipcomps->ipv6, &addr6) >= 1) {
- newCfg->dev.ipv6 = ip_addr_in6(&addr6);
- newCfg->dev.set |= PUMP_INTFINFO_HAS_IPV6_IP;
+ if (inet_pton(AF_INET6, ipcomps->ipv6, &iface->ip6addr) <= 0) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
have[IPV6]++;
}
}
if (ipcomps->cidr6) {
- prefix = atoi(ipcomps->cidr6);
+ prefix = strtol(ipcomps->cidr6, &ep, 10);
if (prefix > 0 || prefix <= 128) {
- newCfg->dev.ipv6_prefixlen = prefix;
- newCfg->dev.set |= PUMP_INTFINFO_HAS_IPV6_PREFIX;
+ iface->ip6prefix = prefix;
have[IPV6]++;
}
}
@@ -1179,37 +1173,24 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
/* collect common network settings */
if (ipcomps->gw) {
- if (inet_pton(AF_INET, ipcomps->gw, &addr) >= 1) {
- newCfg->dev.gateway = ip_addr_in(&addr);
- newCfg->dev.set |= PUMP_NETINFO_HAS_GATEWAY;
- } else if (inet_pton(AF_INET6, ipcomps->gw, &addr6) >= 1) {
- newCfg->dev.gateway = ip_addr_in6(&addr6);
- newCfg->dev.set |= PUMP_NETINFO_HAS_GATEWAY;
- }
- }
-
- /* The cfg->dev.ip field needs to store the IPv4 address if
- * there is one.
- */
- if (ipcomps->ipv4) {
- if (inet_pton(AF_INET, ipcomps->ipv4, &addr) >= 1) {
- newCfg->dev.ip = ip_addr_in(&addr);
- newCfg->dev.set |= PUMP_INTFINFO_HAS_IP;
+ if (inet_pton(AF_INET, ipcomps->gw, &iface->gateway) <= 0) {
+ memset(&iface->gateway, 0, sizeof(iface->gateway));
+
+ if (inet_pton(AF_INET6, ipcomps->gw, &iface->gateway6) <= 0) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ memset(&iface->gateway6, 0, sizeof(iface->gateway6));
+ }
}
}
/* gather nameservers */
if (ipcomps->ns) {
- if (inet_pton(AF_INET, ipcomps->ns, &addr) >= 1) {
- cfg->dev.dnsServers[0] = ip_addr_in(&addr);
- cfg->dev.set |= PUMP_NETINFO_HAS_DNS;
- if (cfg->dev.numDns < 1)
- cfg->dev.numDns = 1;
- } else if (inet_pton(AF_INET6, ipcomps->ns, &addr6) >= 1) {
- cfg->dev.dnsServers[0] = ip_addr_in6(&addr6);
- cfg->dev.set |= PUMP_NETINFO_HAS_DNS;
- if (cfg->dev.numDns < 1)
- cfg->dev.numDns = 1;
+ if ((inet_pton(AF_INET, ipcomps->ns, &addr) >= 1) ||
+ (inet_pton(AF_INET6, ipcomps->ns, &addr6) >= 1)) {
+ iface->dns[0] = strdup(ipcomps->ns);
+ if (iface->numdns < 1)
+ iface->numdns = 1;
}
}
@@ -1234,8 +1215,8 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
"CIDR prefix."));
}
- strcpy(newCfg->dev.device, device);
- newCfg->isDynamic = 0;
+ strcpy(iface->device, device);
+ iface->flags &= ~IFACE_FLAGS_IS_DYNAMIC;
}
free(buf);
@@ -1245,295 +1226,337 @@ int manualNetConfig(char * device, struct networkDeviceConfig * cfg,
return LOADER_OK;
}
-void debugNetworkInfo(struct networkDeviceConfig *cfg) {
+void debugNetworkInfo(iface_t * iface) {
int i;
- char *buf = NULL;
+ char buf[INET6_ADDRSTRLEN];
- logMessage(DEBUGLVL, "device = %s", cfg->dev.device);
+ logMessage(DEBUGLVL, "device = %s", iface->device);
- if (cfg->dev.set & PUMP_INTFINFO_HAS_IPV4_IP) {
- logMessage(DEBUGLVL, "ipv4 = %s", ip_text(cfg->dev.ipv4, buf, 0));
- free(buf);
- buf = NULL;
+ if (iface->macaddr != NULL) {
+ logMessage(DEBUGLVL, "MAC address = %s", iface->macaddr);
}
- if (cfg->dev.set & PUMP_INTFINFO_HAS_BROADCAST) {
- logMessage(DEBUGLVL,"broadcast = %s",ip_text(cfg->dev.broadcast,buf,0));
- free(buf);
- buf = NULL;
+ if (iface_have_in_addr(&iface->ipaddr)) {
+ if (inet_ntop(AF_INET, &iface->ipaddr, buf, INET_ADDRSTRLEN) == NULL) {
+ logMessage(DEBUGLVL, "IPv4 address = ");
+ } else {
+ logMessage(DEBUGLVL, "IPv4 address = %s", buf);
+ }
}
- if (cfg->dev.set & PUMP_INTFINFO_HAS_NETMASK) {
- logMessage(DEBUGLVL, "netmask = %s", ip_text(cfg->dev.netmask, buf, 0));
- free(buf);
- buf = NULL;
+ if (iface_have_in_addr(&iface->netmask)) {
+ if (inet_ntop(AF_INET, &iface->netmask, buf, INET_ADDRSTRLEN) == NULL) {
+ logMessage(DEBUGLVL, "IPv4 netmask = ");
+ } else {
+ logMessage(DEBUGLVL, "IPv4 netmask = %s", buf);
+ }
}
- if (cfg->dev.set & PUMP_INTFINFO_HAS_NETWORK) {
- logMessage(DEBUGLVL, "network = %s", ip_text(cfg->dev.network, buf, 0));
- free(buf);
- buf = NULL;
+ if (iface_have_in_addr(&iface->broadcast)) {
+ if (inet_ntop(AF_INET, &iface->broadcast, buf,
+ INET_ADDRSTRLEN) == NULL ) {
+ logMessage(DEBUGLVL, "IPv4 broadcast = ");
+ } else {
+ logMessage(DEBUGLVL, "IPv4 broadcast = %s", buf);
+ }
}
- if (cfg->dev.set & PUMP_INTFINFO_HAS_IPV6_IP) {
- logMessage(DEBUGLVL, "ipv6 = %s", ip_text(cfg->dev.ipv6, buf, 0));
- free(buf);
- buf = NULL;
+ if (iface_have_in_addr(&iface->gateway)) {
+ if (inet_ntop(AF_INET, &iface->gateway, buf, INET_ADDRSTRLEN) == NULL) {
+ logMessage(DEBUGLVL, "Gateway = ");
+ } else {
+ logMessage(DEBUGLVL, "Gateway = %s", buf);
+ }
}
- if (cfg->dev.set & PUMP_INTFINFO_HAS_IPV6_PREFIX) {
- logMessage(DEBUGLVL, "ipv6_prefixlen = %d", cfg->dev.ipv6_prefixlen);
- free(buf);
- buf = NULL;
+ if (iface_have_in6_addr(&iface->ip6addr)) {
+ if (inet_ntop(AF_INET6, &iface->ip6addr, buf,
+ INET6_ADDRSTRLEN) == NULL) {
+ logMessage(DEBUGLVL, "IPv6 address = ");
+ } else {
+ logMessage(DEBUGLVL, "IPv6 address = %s", buf);
+ }
}
- if (cfg->dev.set & PUMP_NETINFO_HAS_GATEWAY) {
- logMessage(DEBUGLVL, "gateway = %s", ip_text(cfg->dev.gateway, buf, 0));
- free(buf);
- buf = NULL;
+ if (iface->ip6prefix) {
+ logMessage(DEBUGLVL, "IPv6 prefix = %d", iface->ip6prefix);
}
- if (cfg->dev.set & PUMP_NETINFO_HAS_DNS) {
- for (i=0; i < cfg->dev.numDns; i++) {
- logMessage(DEBUGLVL, "dns[%d] = %s", i,
- ip_text(cfg->dev.dnsServers[i], buf, 0));
- free(buf);
- buf = NULL;
+ if (iface_have_in6_addr(&iface->gateway6)) {
+ if (inet_ntop(AF_INET6, &iface->gateway6, buf,
+ INET6_ADDRSTRLEN) == NULL) {
+ logMessage(DEBUGLVL, "IPv6 Gateway = ");
+ } else {
+ logMessage(DEBUGLVL, "IPv6 Gateway = %s", buf);
}
}
-}
-
-int setupWireless(struct networkDeviceConfig *dev) {
- /* wireless config needs to be set up before we can bring the interface
- * up */
- if (!is_wireless_interface(dev->dev.device))
- return 0;
-
- if (dev->essid) {
- logMessage(INFO, "setting essid for %s to %s", dev->dev.device,
- dev->essid);
- if (set_essid(dev->dev.device, dev->essid) < 0) {
- logMessage(ERROR, "failed to set essid: %s", strerror(errno));
- }
- if (dev->wepkey) {
- logMessage(INFO, "setting encryption key for %s", dev->dev.device);
- if (set_wep_key(dev->dev.device, dev->wepkey) < 0) {
- logMessage(ERROR, "failed to set wep key: %s", strerror(errno));
- }
+ if (iface->numdns > 0) {
+ for (i = 0; i < iface->numdns; i++) {
+ logMessage(DEBUGLVL, "DNS[%d] = %s", i, iface->dns[i]);
}
}
- return 0;
-}
+ if (iface->hostname) {
+ logMessage(DEBUGLVL, "hostname = %s", iface->hostname);
+ }
-void netlogger(void *arg, int priority, char *fmt, va_list va) {
- int p;
- char *buf = NULL;
-
- if (priority == LOG_ERR)
- p = ERROR;
- else if (priority == LOG_INFO)
- p = INFO;
- else if (priority == LOG_DEBUG)
- p = DEBUGLVL;
- else if (priority == LOG_FATAL)
- p = CRITICAL;
- else
- p = INFO;
+ if (iface->domain) {
+ logMessage(DEBUGLVL, "domain = %s", iface->domain);
+ }
- if (vasprintf(&buf, fmt, va) != -1) {
- logMessage(p, "%s", buf);
- free(buf);
- } else {
- logMessage(ERROR, "unable to log network message");
+ if (iface->dhcptimeout) {
+ logMessage(DEBUGLVL, "DHCP timeout = %d", iface->dhcptimeout);
}
- return;
-}
+ if (iface->vendorclass) {
+ logMessage(DEBUGLVL, "DHCP vendor class = %s", iface->vendorclass);
+ }
-char *doDhcp(struct networkDeviceConfig *dev) {
- struct pumpNetIntf *i;
- char *r = NULL, *class = NULL;
- time_t timeout;
- int loglevel;
- DHCP_Preference pref = 0;
- struct utsname kv;
+ if (iface->ssid) {
+ logMessage(DEBUGLVL, "SSID = %s", iface->ssid);
+ }
- i = &dev->dev;
+ if (iface->wepkey) {
+ logMessage(DEBUGLVL, "WEP key = %s", iface->wepkey);
+ }
- if (dev->dhcpTimeout < 0)
- timeout = 45;
- else
- timeout = dev->dhcpTimeout;
+#if defined(__s390__) || defined(__s390x__)
+ if (iface->mtu) {
+ logMessage(DEBUGLVL, "mtu = %d", iface->mtu);
+ }
- if (dev->vendor_class != NULL) {
- class = dev->vendor_class;
- } else {
- if (uname(&kv) == -1) {
- logMessage(ERROR, "failure running uname() in doDhcp()");
- class = "anaconda";
- } else {
- int ret;
+ if (iface->subchannels) {
+ logMessage(DEBUGLVL, "subchannels = %s", iface->subchannels);
+ }
- ret = asprintf(&class, "anaconda-%s %s %s",
- kv.sysname, kv.release, kv.machine);
- logMessage(DEBUGLVL, "sending %s as dhcp vendor-class", class);
- }
+ if (iface->portname) {
+ logMessage(DEBUGLVL, "portname = %s", iface->portname);
}
- if (getLogLevel() == DEBUGLVL)
- loglevel = LOG_DEBUG;
- else
- loglevel = LOG_INFO;
+ if (iface->peerid) {
+ logMessage(DEBUGLVL, "peerid = %s", iface->peerid);
+ }
- /* dhcp preferences are in /usr/include/libdhcp/dhcp_nic.h */
+ if (iface->nettype) {
+ logMessage(DEBUGLVL, "nettype = %s", iface->nettype);
+ }
- /* calling function should catch ipv4Choice & ipv6Choice both being ' ' */
- if (FL_NOIPV4(flags) || dev->ipv4method == IPV4_MANUAL_METHOD) {
- /* IPv4 disabled entirely -or- manual IPv4 config selected */
- pref |= DHCPv4_DISABLE;
+ if (iface->ctcprot) {
+ logMessage(DEBUGLVL, "ctcprot = %s", iface->ctcprot);
}
+#endif
+
+/* FIXME: print rest of iface structure */
+
+ return;
+}
- /* IPv6 enabled -and- auto neighbor discovery selected */
- /* IPv6 disabled entirely -or- manual IPv6 config selected */
- if ((!FL_NOIPV6(flags) && dev->ipv6method == IPV6_AUTO_METHOD) ||
- (FL_NOIPV6(flags) || dev->ipv6method == IPV6_MANUAL_METHOD)) {
- pref |= DHCPv6_DISABLE | DHCPv6_DISABLE_ADDRESSES;
+int setupWireless(iface_t * iface) {
+ /* wireless config needs to be set up before we can bring the interface
+ * up */
+ if (!is_wireless_interface(iface->device))
+ return 0;
+
+ if (iface->ssid) {
+ logMessage(INFO, "setting SSID for %s to %s", iface->device,
+ iface->ssid);
+
+ if (set_ssid(iface->device, iface->ssid) < 0) {
+ logMessage(ERROR, "failed to set SSID: %s", strerror(errno));
+ }
+
+ if (iface->wepkey) {
+ logMessage(INFO, "setting encryption key for %s", iface->device);
+
+ if (set_wep_key(iface->device, iface->wepkey) < 0) {
+ logMessage(ERROR, "failed to set WEP key: %s", strerror(errno));
+ }
+ }
}
- /* disable some things for this DHCP call */
- pref |= DHCPv6_DISABLE_RESOLVER | DHCPv4_DISABLE_HOSTNAME_SET;
+ return 0;
+}
- /* don't try to run the client if DHCPv4 and DHCPv6 are disabled */
- if (!(pref & DHCPv4_DISABLE) || !(pref & DHCPv6_DISABLE)){
- logMessage(loglevel, "requesting dhcp timeout %ld", (long)timeout);
- r = pumpDhcpClassRun(i,0L,class,pref,0,timeout,netlogger,loglevel);
+int doDhcp(iface_t * iface) {
+ int err = 0;
+
+ if (!FL_NOIPV6(flags)) {
+ if (iface->ipv6method == IPV6_AUTO_METHOD) {
+ if ((err = iface_autoconf(iface))) {
+ logMessage(ERROR, "IPv6 neighbor discovery failure on %s: %d",
+ iface->device, err);
+ }
+ } else if (iface->ipv6method == IPV6_DHCP_METHOD) {
+ if ((err = iface_dhcpv6(iface))) {
+ logMessage(ERROR, "DHCPv6 failure on %s: %d",
+ iface->device, err);
+ }
+ }
}
- /* set hostname if we have that */
- if (dev->dev.hostname) {
- if (sethostname(dev->dev.hostname, strlen(dev->dev.hostname))) {
- logMessage(ERROR,"error setting hostname to %s",dev->dev.hostname);
+ if (!FL_NOIPV4(flags) && (iface->ipv4method == IPV4_DHCP_METHOD)) {
+ if ((err = iface_dhcp(iface))) {
+ logMessage(ERROR, "DHCP failure on %s: %d", iface->device, err);
}
}
- return r;
+ return err;
}
-int configureNetwork(struct networkDeviceConfig * dev) {
- char *rc;
+int configureNetwork(iface_t * iface) {
+ int rc;
- setupWireless(dev);
- rc = pumpSetupInterface(&dev->dev);
- if (rc != NULL) {
- logMessage(INFO, "result of pumpSetupInterface is %s", rc);
+ setupWireless(iface);
+ rc = iface_config(iface);
+ if (rc) {
+ logMessage(INFO, "result of iface_config() is %d", rc);
return 1;
}
/* we need to wait for a link after setting up the interface as some
* switches decide to reconfigure themselves after that (#115825)
*/
- waitForLink((char *)&dev->dev.device);
+ waitForLink((char *) &iface->device);
return 0;
}
-int writeNetInfo(const char * fn, struct networkDeviceConfig * dev) {
+int writeNetInfo(const char * fn, iface_t * iface) {
FILE * f;
int i;
struct device ** devices;
- char ret[48];
- ip_addr_t *tip;
+ char ret[INET6_ADDRSTRLEN+1];
devices = getDevices(DEVICE_NETWORK);
if (!devices)
return 0;
for (i = 0; devices[i]; i++)
- if (!strcmp(devices[i]->device, dev->dev.device)) break;
-
- if (!(f = fopen(fn, "w"))) return -1;
+ if (!strcmp(devices[i]->device, iface->device))
+ break;
+
+ if (!(f = fopen(fn, "w")))
+ return -1;
- fprintf(f, "DEVICE=%s\n", dev->dev.device);
+ fprintf(f, "DEVICE=%s\n", iface->device);
fprintf(f, "ONBOOT=yes\n");
- if (dev->isDynamic) {
+ if (IFACE_IS_DYNAMIC(iface->flags)) {
fprintf(f, "BOOTPROTO=dhcp\n");
} else {
fprintf(f, "BOOTPROTO=static\n");
- tip = &(dev->dev.ipv4);
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- fprintf(f, "IPADDR=%s\n", ret);
+ if (iface_have_in_addr(&iface->ipaddr)) {
+ inet_ntop(AF_INET, &iface->ipaddr, ret, INET_ADDRSTRLEN);
+ if (ret == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ fprintf(f, "IPADDR=%s\n", ret);
+ }
+ }
- tip = &(dev->dev.netmask);
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- fprintf(f, "NETMASK=%s\n", ret);
+ if (iface_have_in_addr(&iface->netmask)) {
+ inet_ntop(AF_INET, &iface->netmask, ret, INET_ADDRSTRLEN);
+ if (ret == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ fprintf(f, "NETMASK=%s\n", ret);
+ }
+ }
- if (dev->dev.set & PUMP_NETINFO_HAS_GATEWAY) {
- tip = &(dev->dev.gateway);
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- fprintf(f, "GATEWAY=%s\n", ret);
+ if (iface_have_in_addr(&iface->broadcast)) {
+ inet_ntop(AF_INET, &iface->broadcast, ret, INET_ADDRSTRLEN);
+ if (ret == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ fprintf(f, "BROADCAST=%s\n", ret);
+ }
}
- if (dev->dev.set & PUMP_INTFINFO_HAS_BROADCAST) {
- tip = &(dev->dev.broadcast);
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- fprintf(f, "BROADCAST=%s\n", ret);
+ if (iface_have_in_addr(&iface->gateway)) {
+ inet_ntop(AF_INET, &iface->gateway, ret, INET_ADDRSTRLEN);
+ if (ret == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ fprintf(f, "GATEWAY=%s\n", ret);
+ }
}
}
if (!FL_NOIPV6(flags)) {
- if (dev->ipv6method == IPV6_AUTO_METHOD) {
+ if (iface->ipv6method == IPV6_AUTO_METHOD) {
fprintf(f, "IPV6_AUTOCONF=yes\n");
- } else if (dev->ipv6method == IPV6_DHCP_METHOD) {
+ } else if (iface->ipv6method == IPV6_DHCP_METHOD) {
fprintf(f, "IPV6ADDR=dhcp\n");
} else {
- tip = &(dev->dev.ipv6);
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- fprintf(f, "IPV6ADDR=%s/%d\n", ret, dev->dev.ipv6_prefixlen);
- }
- }
-
- if (dev->dev.set & PUMP_NETINFO_HAS_HOSTNAME)
- fprintf(f, "HOSTNAME=%s\n", dev->dev.hostname);
- if (dev->dev.set & PUMP_NETINFO_HAS_DOMAIN)
- fprintf(f, "DOMAIN=%s\n", dev->dev.domain);
- if (dev->mtu)
- fprintf(f, "MTU=%d\n", dev->mtu);
- if (dev->peerid)
- fprintf(f, "PEERID=%s\n", dev->peerid);
- if (dev->subchannels)
- fprintf(f, "SUBCHANNELS=%s\n", dev->subchannels);
- if (dev->portname)
- fprintf(f, "PORTNAME=%s\n", dev->portname);
- if (dev->nettype)
- fprintf(f, "NETTYPE=%s\n", dev->nettype);
- if (dev->ctcprot)
- fprintf(f, "CTCPROT=%s\n", dev->ctcprot);
-
- if (dev->essid)
- fprintf(f, "ESSID=%s\n", dev->essid);
- if (dev->wepkey)
- fprintf(f, "KEY=%s\n", dev->wepkey);
-
+ if (inet_ntop(AF_INET6, &iface->ip6addr, ret,
+ INET6_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ fprintf(f, "IPV6ADDR=%s/%d\n", ret, iface->ip6prefix);
+ }
+ }
+
+ if (iface_have_in6_addr(&iface->gateway6)) {
+ if (inet_ntop(AF_INET6, &iface->gateway6, ret,
+ INET6_ADDRSTRLEN) == NULL) {
+ logMessage(ERROR, "%s (%d): %s", __func__, __LINE__,
+ strerror(errno));
+ } else {
+ fprintf(f, "IPV6_DEFAULTGW=%s\n", ret);
+ }
+ }
+ }
+
+ if (iface->numdns > 0) {
+ for (i = 0; i < iface->numdns; i++) {
+ fprintf(f, "DNS%d=%s\n", i+1, iface->dns[i]);
+ }
+ }
+
+ if (iface->hostname)
+ fprintf(f, "HOSTNAME=%s\n", iface->hostname);
+ if (iface->domain)
+ fprintf(f, "DOMAIN=%s\n", iface->domain);
+ if (iface->mtu)
+ fprintf(f, "MTU=%d\n", iface->mtu);
+ if (iface->peerid)
+ fprintf(f, "PEERID=%s\n", iface->peerid);
+ if (iface->subchannels)
+ fprintf(f, "SUBCHANNELS=%s\n", iface->subchannels);
+ if (iface->portname)
+ fprintf(f, "PORTNAME=%s\n", iface->portname);
+ if (iface->nettype)
+ fprintf(f, "NETTYPE=%s\n", iface->nettype);
+ if (iface->ctcprot)
+ fprintf(f, "CTCPROT=%s\n", iface->ctcprot);
+
+ if (iface->ssid)
+ fprintf(f, "ESSID=%s\n", iface->ssid);
+ if (iface->wepkey)
+ fprintf(f, "KEY=%s\n", iface->wepkey);
+
fclose(f);
return 0;
}
-int writeResolvConf(struct networkDeviceConfig * net) {
+int writeResolvConf(iface_t * iface) {
char * filename = "/etc/resolv.conf";
FILE * f;
int i;
- char ret[48];
- ip_addr_t *tip;
+
#if defined(__s390__) || defined(__s390x__)
return 0;
#endif
- if (!(net->dev.set & PUMP_NETINFO_HAS_DOMAIN) && !net->dev.numDns)
+ if (iface->numdns == 0)
return LOADER_ERROR;
f = fopen(filename, "w");
@@ -1542,85 +1565,69 @@ int writeResolvConf(struct networkDeviceConfig * net) {
return LOADER_ERROR;
}
- if (net->dev.set & PUMP_NETINFO_HAS_DOMAIN)
- fprintf(f, "search %s\n", net->dev.domain);
+ if (iface->domain != NULL) {
+ fprintf(f, "search %s\n", iface->domain);
+ }
- for (i = 0; i < net->dev.numDns; i++) {
- tip = &(net->dev.dnsServers[i]);
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- fprintf(f, "nameserver %s\n", ret);
+ for (i = 0; i < iface->numdns; i++) {
+ fprintf(f, "nameserver %s\n", iface->dns[i]);
}
fclose(f);
- res_init(); /* reinit the resolver so DNS changes take affect */
+ /* reinit the resolver so DNS changes take affect */
+ res_init();
return 0;
}
-int findHostAndDomain(struct networkDeviceConfig * dev) {
- char * name, * chptr;
- char ret[48];
- ip_addr_t *tip;
- struct hostent *host;
-
- if (!FL_TESTING(flags)) {
- writeResolvConf(dev);
- }
+int findHostAndDomain(iface_t * iface) {
+ int err = 0;
- if (dev->dev.numDns == 0) {
+ if (iface->numdns == 0) {
logMessage(ERROR, "no DNS servers, can't look up hostname");
return 1;
}
- if (!(dev->dev.set & PUMP_NETINFO_HAS_HOSTNAME)) {
- if (!FL_CMDLINE(flags))
- winStatus(50, 3, NULL,
- _("Determining host name and domain..."));
- else
- printf("Determining host name and domain...\n");
-
- tip = &(dev->dev.ip);
- inet_ntop(tip->sa_family, IP_ADDR(tip), ret, IP_STRLEN(tip));
- host = gethostbyaddr(IP_ADDR(tip), IP_STRLEN(tip), tip->sa_family);
+ if (!FL_TESTING(flags)) {
+ writeResolvConf(iface);
+ }
- if (!FL_CMDLINE(flags))
- newtPopWindow();
+ if ((iface->hostname == NULL) || (iface->domain == NULL)) {
+ if (!FL_CMDLINE(flags)) {
+ winStatus(50, 3, NULL, _("Determining host name and domain..."));
+ } else {
+ printf("Determining host name and domain...\n");
+ }
- if (!host) {
- logMessage(WARNING, "reverse name lookup of %s failed", ret);
+ err = iface_dns_lookup(iface);
+ if (err) {
+ logMessage(WARNING, "reverse name lookup failed (%d)", err);
return 1;
+ } else {
+/*
+ logMessage(INFO, "reverse name lookup worked (hostname is %s)",
+ iface->hostname);
+*/
}
- name = strdup(host->h_name);
-
- logMessage(INFO, "reverse name lookup worked (hostname is %s)", name);
-
- dev->dev.hostname = strdup(name);
- dev->dev.set |= PUMP_NETINFO_HAS_HOSTNAME;
- } else {
- name = dev->dev.hostname;
- }
-
- if (!(dev->dev.set & PUMP_NETINFO_HAS_DOMAIN)) {
- for (chptr = name; *chptr && (*chptr != '.'); chptr++) ;
- if (*chptr == '.') {
- if (dev->dev.domain) free(dev->dev.domain);
- dev->dev.domain = strdup(chptr + 1);
- dev->dev.set |= PUMP_NETINFO_HAS_DOMAIN;
+ if (!FL_CMDLINE(flags)) {
+ newtPopWindow();
}
}
return 0;
}
-void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
+void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
char ** argv) {
- char * arg, * bootProto = NULL, * device = NULL, *ethtool = NULL, * class = NULL;
- char * essid = NULL, * wepkey = NULL, * onboot = NULL;
- int noDns = 0, noksdev = 0, rc, mtu = 0, noipv4 = 0, noipv6 = 0, dhcpTimeout = -1;
+ char *arg, *bootProto = NULL;
+ char *device = NULL, *ethtool = NULL, *class = NULL;
+ char *essid = NULL, *wepkey = NULL, *onboot = NULL;
+ int noDns = 0, noksdev = 0, rc, mtu = 0;
+ int noipv4 = 0, noipv6 = 0, dhcpTimeout = -1;
poptContext optCon;
- struct networkDeviceConfig cfg;
+ iface_t iface;
struct poptOption ksOptions[] = {
{ "bootproto", '\0', POPT_ARG_STRING, &bootProto, 0, NULL, NULL },
@@ -1643,7 +1650,9 @@ void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
{ "dhcptimeout", '\0', POPT_ARG_INT, &dhcpTimeout, 0, NULL, NULL },
{ 0, 0, 0, 0, 0, 0, 0 }
};
-
+
+ iface_init_iface_t(&iface);
+
optCon = poptGetContext(NULL, argc, (const char **) argv,
ksOptions, 0);
while ((rc = poptGetNextOpt(optCon)) >= 0) {
@@ -1669,7 +1678,7 @@ void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
break;
}
}
-
+
if (rc < -1) {
newtWinMessage(_("Kickstart Error"), _("OK"),
_("Bad argument to kickstart network command %s: %s"),
@@ -1697,7 +1706,7 @@ void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
newtWinMessage(_("Kickstart Error"), _("OK"),
_("Bad bootproto %s specified in network command"),
bootProto);
- }
+ }
if (!noksdev) {
if (device) {
@@ -1751,7 +1760,7 @@ void setKickstartNetwork(struct loaderData_s * loaderData, int argc,
*/
if (loaderData->method != METHOD_NFS && loaderData->method != METHOD_URL) {
initLoopback();
- if (kickstartNetworkUp(loaderData, &cfg))
+ if (kickstartNetworkUp(loaderData, &iface))
logMessage(ERROR, "unable to bring up network");
}
}
@@ -1884,10 +1893,10 @@ int chooseNetworkInterface(struct loaderData_s * loaderData) {
/* JKFIXME: should display link status */
deviceNum = 0;
rc = newtWinMenu(_("Networking Device"),
- _("You have multiple network devices on this system. "
- "Which would you like to install through?"), max, 10, 10,
- deviceNums < 6 ? deviceNums : 6, deviceNames,
- &deviceNum, _("OK"), _("Back"), NULL);
+ _("You have multiple network devices on this system. "
+ "Which would you like to install through?"), max, 10, 10,
+ deviceNums < 6 ? deviceNums : 6, deviceNames,
+ &deviceNum, _("OK"), _("Back"), NULL);
if (rc == 2)
return LOADER_BACK;
@@ -1899,7 +1908,7 @@ int chooseNetworkInterface(struct loaderData_s * loaderData) {
for (i = 0; devs[i]; i++) {
if (strcmp(loaderData->netDev, devices[i]))
if (!FL_TESTING(flags))
- pumpDisableInterface(devs[i]->device);
+ iface_down(devs[i]->device);
}
return LOADER_OK;
@@ -1908,8 +1917,7 @@ int chooseNetworkInterface(struct loaderD