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