move linuxrc.s390 out of harm's way
We still need linuxrc.s390 (that's a project for another year), so move
it out of loader/ while we warm up the orbital lasers. --- data/Makefile.am | 5 + data/linuxrc.s390 | 3079 ++++++++++++++++++++++++++++++++++++++++++++++++++ + loader/linuxrc.s390 | 3079 --------------------------------------------------- 3 files changed, 3084 insertions(+), 3079 deletions(-) create mode 100644 data/linuxrc.s390 delete mode 100644 loader/linuxrc.s390 diff --git a/data/Makefile.am b/data/Makefile.am index 6e5b5b9..cc82ae5 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -29,6 +29,11 @@ langdir = $(datadir)/$(PACKAGE_NAME) lang_DATA = lang-names dist_lang_DATA = lang-table +if IS_S390 +shareddir = $(datadir)/$(PACKAGE_NAME) +dist_shared_SCRIPTS = linuxrc.s390 +endif + MAINTAINERCLEANFILES = Makefile.in lang-names: lang-table diff --git a/data/linuxrc.s390 b/data/linuxrc.s390 new file mode 100644 index 0000000..3280498 --- /dev/null +++ b/data/linuxrc.s390 @@ -0,0 +1,3079 @@ +#! /bin/bash + +# linuxrc.s390: init process of Red Hat's installer initrd for s390(x) +# Copyright (C) 2000-2004 by +# Bernhard Rosenkraenzer <bero@redhat.com> +# Oliver Paukstadt <opaukstadt@millenux.com> +# Karsten Hopp <karsten@redhat.de> +# Florian La Roche <laroche@redhat.com> +# Nils Philippsen <nils@redhat.de> +# Helge Deller <hdeller@redhat.de> +# David Sainty <dsainty@redhat.com> +# Copyright (C) IBM Corp. 2008,2009 +# Author: Steffen Maier <maier@de.ibm.com> +# +# 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# prerequisites of this script to run inside the installer initrd: +# - udevadm and udevd need to be there +# - have /etc/udev/udev.conf with at least one comment line as content +# - if necessary, have udev rules +# - lsznet.raw and znetcontrolunits from s390utils-base in /lib/s390-tools +# - pack kernel modules and module-init-tools (no longer use busybox for that) +# - "multi on" in /etc/host.conf [RH bugs 486457,486461,483244] + +# TODOs: +# - make sure driver modules get loaded automatically +# - udev rule for lcs/ctcm vs. cu3088 + +# debug: set -x + +if [ "${0##*/}" = "reboot" ]; then + kill -USR2 1 + exit +elif [ "${0##*/}" = "halt" ]; then + kill -USR1 1 + exit +fi + +VERSION=1.2 + +export TEXTDOMAIN=s390installer +export TEXTDOMAINDIR=/usr/lib/locale + +# helper function to execute command in arguments and print command on stdout +function debug() { + # uncomment the following echo "$*" to enable debug output + #echo "$*" + $* +} + +# FIXME: maybe change to "$$" for production use, in case it wouldn't be init +declare -r INITPID="1" + +unset testing +[ "$$" != "$INITPID" ] && testing="1" +# uncomment the following test="1" to never execute sensitive commands +#testing="1" + +if [ "$RUNKS" = "0" ]; then + RUNKS="" +fi + +# ping command to use to test host availability (for gateway & dns servers) +PINGOPTS="-c 3 -w 30" +PING="ping $PINGOPTS" +PING6="ping6 $PINGOPTS" + +# helper function to disable commands while running outside the initrd +function tv() { + if [ -z "$testing" ]; then + $* + else + return 0 + fi +} + +function checkipv6() +{ + local ip=$1 + [ -z "$ip" ] && return 1 + /bin/ipcalc -c -6 "$ip" >/dev/null 2>&1 + return $? +} + +function checkipv4() +{ + local ip=$1 + [ -z "$ip" ] && return 1 + /bin/ipcalc -c -4 "$ip" >/dev/null 2>&1 + return $? +} + +function doshutdown() +{ + echo $"about to exec shutdown" + /sbin/umount -a -d -n >/dev/null 2>&1 + exec /sbin/shutdown + exit 0 +} + +function doreboot() +{ + if [ -e "/sys/firmware/reipl" ]; then + read REIPL_TYPE < /sys/firmware/reipl/reipl_type + echo "reipl_type=$REIPL_TYPE" + pushd /sys/firmware/reipl/$REIPL_TYPE >/dev/null 2>&1 + for i in *; do + echo "$i=`cat $i`" + done + popd >/dev/null 2>&1 + fi + + echo $"about to exec shutdown -r" + /sbin/umount -a -d -n >/dev/null 2>&1 + exec /sbin/shutdown -r + exit 0 +} + +function sysecho () { + file=$1 + shift + local i=1 + while [ $i -le 10 ] ; do + if [ ! -f "$file" ]; then + sleep 1 + i=$((i+1)) + else + break + fi + done + [ -f "$file" ] && echo $* > $file +} + +function dasd_settle() { + local dasd_status=/sys/bus/ccw/devices/$1/status + if [ ! -f $dasd_status ]; then + return 1 + fi + local i=1 + while [ $i -le 30 ] ; do + local status + read status < $dasd_status + case $status in + online|unformatted) + return 0 ;; + *) + sleep 0.1 + i=$((i+1)) ;; + esac + done + return 1 +} + +function dasd_settle_all() { + for dasdccw in $(cut -d '(' -f 1 /proc/dasd/devices) ; do + if ! dasd_settle $dasdccw ; then + echo $"Could not access DASD $dasdccw in time" + return 1 + fi + done + return 0 +} + +function startinetd() +{ + echo + echo $"Starting sshd to allow login over the network." + if [ -z "$testing" ]; then + echo $"Welcome to the anaconda install environment $VERSION for $S390ARCH" > /etc/issue.net + echo $"Welcome to the anaconda install environment $VERSION for $S390ARCH" > /etc/motd + echo >> /etc/motd + fi # testing + + /usr/sbin/sshd -f /etc/ssh/sshd_config.anaconda + if [ -z "$RUNKS" ]; then + echo + echo $"Connect now to $IPADDR and log in as user 'install' to start the installation." + echo $"E.g. using: ssh -x install@$IPADDR" + echo $"For VNC or text mode, disable X11 forwarding (recommended) with 'ssh -x'." + echo $"For X11, enable X11 forwarding with 'ssh -X'." + echo + echo $"You may log in as the root user to start an interactive shell." + read + while : ; do + /bin/sh --login + [ $? = 0 ] || break + done + fi +} + +# prints a canonocalized device bus ID for a given devno of any format +function canonicalize_devno() +{ + case ${#1} in + 3) echo "0.0.0${1}" ;; + 4) echo "0.0.${1}" ;; + *) echo "${1}" ;; + esac + return 0 +} + +# read file from CMS and write it to /tmp +function readcmsfile() # $1=dasdport $2=filename +{ + local dev + if [ $# -ne 2 ]; then return; fi + # precondition: udevd created dasda block device node + if ! dasd_cio_free -d $1 ; then + echo $"DASD $1 could not be cleared from device blacklist" + return 1 + fi + # precondition: dasd_eckd_mod driver incl. dependencies loaded, + # dasd_mod must be loaded without setting any DASD online + dev=$(canonicalize_devno $1) + if ! sysecho /sys/bus/ccw/devices/$dev/online 1; then + echo $"DASD $dev could not be set online" + return 1 + fi + udevadm settle + if ! dasd_settle $dev ; then + echo $"Could not access DASD $dev in time" + return 1 + fi + udevadm settle + if ! cmsfscat -d /dev/dasda -a $2 > /tmp/$2; then + echo $"Could not read conf file $2 on CMS DASD $1." + fi + if ! sysecho /sys/bus/ccw/devices/$dev/online 0; then + echo $"DASD $dev could not be set offline again" + return 1 + fi + udevadm settle + # consequences of no more module unload: loader can no longer + # use DASD module option to online DASDs and set other DASD parameters! +} + +# adaption of the same function in init.c (udevd gets started later) +function createDevices() +{ + awk '{ printf("mknod /dev/%s %s %s %s ", $1, $2, $3, $4); + printf("chmod %s /dev/%s ", $5, $1); + printf("chown %s /dev/%s ", $6, $1); + }' <<EOF | sh +console c 5 1 600 root:root +null c 1 3 666 root:root +zero c 1 5 666 root:root +mem c 1 1 600 root:root +ptmx c 5 2 666 root:root +tty c 5 0 666 root:root +tty0 c 4 0 600 root:tty +tty1 c 4 1 600 root:tty +random c 1 8 644 root:root +urandom c 1 9 644 root:root +rtc c 10 135 644 root:root +EOF + # tty handling is different from init.c since s390 does not have all + for i in 2 3 4 5 6 7 8 9 ; do + ln -s console /dev/tty$i + done + mkdir /dev/pts + ln -s /proc/self/fd /dev/fd +} + +# approximately the main() function of init.c +function init_main() { + S390ARCH=$(uname -m) + if [ "$S390ARCH" = "s390" ]; then + export S390ARCH="S/390" + else + export S390ARCH="zSeries" + fi + + echo + echo $"Starting the $S390ARCH initrd to configure networking. Version is $VERSION" + + # set up env vars as we do in init.c + if [ $(uname -m) = "s390x" ]; then + LD_LIBRARY_PATH=/lib64:/usr/lib64:/usr/X11R6/lib64:/usr/kerberos/lib64:/lib:/usr/lib:/usr/X11R6/lib:/usr/kerberos/lib + else + LD_LIBRARY_PATH=/lib:/usr/lib:/usr/X11R6/lib:/usr/kerberos/lib + fi + export LD_LIBRARY_PATH + + PATH="$PATH:/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin:/mnt/sysimage/usr/sbin:/mnt/sysimage/sbin:/mnt/sysimage/usr/X11R6/bin" + export PATH + HOME=/ + export HOME + PYTHONPATH=/tmp/updates + export PYTHONPATH + + if [ -z "$testing" ]; then + + mount -t proc none /proc + + mount -t tmpfs none /dev + createDevices + # udevd req'd by udevadm settle (/dev/.udev/queue) + # in readcmsfile, dialog_network_table, semantic_check_subchannels. + # (important: start udevd at the right time, e.g. after setup of /dev) + echo $"Starting udev..." + udevd --daemon + # debug: udevadm control --log-priority=debug + + udevadm control --env=ANACONDA=1 + + mount -t devpts /dev/pts /dev/pts + mount -t sysfs none /sys + + # remount root fs rw + mount /dev/root / -o remount,rw + + # limit output on 3270 console + # (console_loglevel of 4 is just right to not get driver info, + # e.g. from qeth, since that would mix up with the user dialog) + echo "4 4 1 7" > /proc/sys/kernel/printk + + # make /tmp/ramfs + mount -t ramfs none /tmp + + # start rsyslogd after mount of /tmp ramfs since it logs to /tmp/syslog + echo $"Starting rsyslogd..." + rsyslogd -c 4 + + ifconfig lo 127.0.0.1 netmask 255.0.0.0 + route add -host 127.0.0.1 dev lo + + echo -e "127.0.0.1 localhost.localdomain localhost localhost4 localhost4.localdomain4" > /etc/hosts + echo -e "::1 localhost.localdomain localhost localhost6 localhost6.localdomain6" >> /etc/hosts + + /bin/dbus-uuidgen --ensure & + [ $? != 0 ] && echo "error on calling /bin/dbus-uuidgen --ensure" + /bin/dbus-daemon --system & + [ $? != 0 ] && echo "error on calling /bin/dbus-daemon --system" + + fi # testing +} + +# trigger udev to automatically load device drivers +function udev_setup() { + if [ -z "$testing" ]; then + # debug: udevadm monitor & + udevadm trigger + udevadm settle + fi # testing +} + +# from here on accesses to sysfs try to follow +# linux/Documentation/sysfs-rules.txt + +### lsznet.raw integration + +declare -a nettable + +function read_lsznet_output() { + count=0 + local line + while read line; do + nettable[$count]="$line" + count=$((count + 1)) + # using the more sophisticated process substitution instead of temp file + # requires the symlink /dev/fd -> /proc/self/fd => createDevices + done < <(/lib/s390-tools/lsznet.raw) +} + +function print_nettable() { + local fmtstring="%3s %-14s %-7s %-5s %-4s %-6s %-7s %s " + printf "$fmtstring" + "NUM" "CARD" "CU" "CHPID" "TYPE" "DRIVER" "IF" "DEVICES" + local i + for ((i=0; i < count; i++)); do + local item cutype chp chpidtype devdrv devname chlist cardtype + read item cutype chp chpidtype devdrv devname chlist cardtype <<< ${nettable[$i]} + printf "$fmtstring" + $item "$cardtype" $cutype $chp "$chpidtype" $devdrv $devname $chlist + done +} + +function clear_screen() { + # FIXME: find a way to clear screen despite 3215 line mode terminal + echo +} + +function dialog_network_table() { + while : ; do + echo $"Scanning for available network devices..." + # This may take a long time so we show "progress": + #( while true; do echo -n "."; sleep 1; done ) & + #local childpid=$! + read_lsznet_output + #kill $childpid + #echo + echo $"Autodetection found ${count} devices." + # count==0: there might still be a blacklist the user wants to clear. + # do not flood user with long list if there are many devices + if [ "$count" -le 15 ]; then + # Show list + answer=s + else # [ $count -gt 15 ] + echo + while : ; do + echo $"s) show all, m) manual config:" + local answer + read answer + case $answer in + s|m) break ;; + esac + done + fi + [ "$answer" = "m" ] && break + # show network table to select network hardware configuration from + if [ "$count" -gt 0 ]; then + clear_screen + print_nettable + echo + fi + # account for possibly ignored common I/O devices + # cio_wc_bytes is NOT local so it can be re-used outside this function + cio_wc_bytes=0 + local cio_wc_filename cio_wc_foo + if [ -f /proc/cio_ignore ]; then + local cio_wc=$(wc -c /proc/cio_ignore) + read cio_wc_bytes cio_wc_filename cio_wc_foo <<< "$cio_wc" + if [ "$cio_wc_bytes" != "0" ]; then + echo $"Note: There is a device blacklist active! (Clearing might take long)" + #cat /proc/cio_ignore | tr ' ' ',' + #echo + else + if [ "$count" -eq 0 ]; then + # count==0 AND no device blacklist => manual mode + echo $"Entering manual configuration mode." + break + fi + fi + fi + # selection dialog + while : ; do + [ "$count" -gt 0 ] && echo -n $"<num>) use config, " + [ "$cio_wc_bytes" != "0" ] && echo -n $"c) clear blacklist, " + echo $"m) manual config, r) rescan, s) shell:" + local choice + read choice + [ -z "$choice" ] && continue + if [ "$choice" = "s" ]; then + echo $"Enter 'exit' at the shell prompt to get back to the installation dialog." + /bin/bash + continue 2 + fi + [ "$choice" = "m" ] && break + [ "$choice" = "r" ] && continue 2 + [ "$cio_wc_bytes" != "0" -a "$choice" = "c" ] && break + [[ "$choice" =~ ^[[:digit:]]+$ ]] + case $? in + 0) + # string matched the pattern + [ "$choice" -ge 1 -a "$choice" -le "$count" ] && break + ;; + 1) + # string did not match the pattern + continue + ;; + 2) + echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2 + ;; + *) + echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2 + ;; + esac + done + if [ "$choice" = "c" ]; then + echo $"Clearing device blacklist..." + cio_ignore -R || echo $"Device blacklist could not be cleared" + fi + [ "$choice" = "m" ] && break + # finally extract config info from selected item + # array nettable starts at index zero, user input starts at index one + choice=$((choice - 1)) + local item cutype chp chpidtype devdrv devname chlist cardtype + read item cutype chp chpidtype devdrv devname chlist cardtype <<< ${nettable[$choice]} + # $NETTYPE happens to be exactly the network driver name + if [ "$devdrv" = "ctcm" ]; then + NETTYPE="ctc" + else + NETTYPE=$devdrv + fi + SUBCHANNELS=$chlist + break + done + echo +} + +declare -r PREFIXFORMAT=[[:xdigit:]]* +declare -r SSIDFORMAT=[0-3] +declare -r BUSIDFORMAT=[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] +declare -r IDFORMAT=$PREFIXFORMAT.$SSIDFORMAT.$BUSIDFORMAT +declare -r SUBCHANNEL_TYPE_IO=0 + +. /lib/s390-tools/znetcontrolunits + +function cardtype2cleartext() { + local cardtype=$1 + case $cardtype in + OSD_10GIG) echo "OSA card in OSD mode, 10 Gigabit Ethernet" ;; + OSD_1000) echo "OSA card in OSD mode, Gigabit Ethernet" ;; + OSD_100) echo "OSA card in OSD mode, Fast Ethernet" ;; + OSD_GbE_LANE) echo "OSA card in OSD mode, Gigabit Ethernet, LAN Emulation" ;; + OSD_FE_LANE) echo "OSA card in OSD mode, Fast Ethernet, LAN Emulation" ;; + OSD_TR_LANE) echo "OSA card in OSD mode, Token Ring, LAN Emulation" ;; + OSD_ATM_LANE) echo "OSA card in OSD mode, ATM, LAN Emulation" ;; + OSD_Express) echo "OSA card in OSD mode, unknown link type" ;; + HSTR) echo "OSA card in OSD mode, High Speed Token Ring" ;; + OSN) echo "OSA for NCP, ESCON/CDLC bridge" ;; + HiperSockets) echo "HiperSockets with CHPID type IQD" ;; + "GuestLAN QDIO") echo "GuestLAN based on OSA (QDIO)" ;; + "GuestLAN Hiper") echo "GuestLAN based on HiperSockets" ;; + unknown) echo "other" ;; + *) echo "unknown" + echo "l.$LINENO: found unknown card_type, code needs to be fixed" 1>&2 + ;; + esac +} + +# returns true iff running under z/VM +function isVM() { + local cpu_version=$(cat /proc/cpuinfo |grep "^processor " | head -n1 | sed 's/.*version = ([[:xdigit:]][[:xdigit:]]).*/1/' | tr '[:lower:]' '[:upper:]') + if [ "$cpu_version" = "FF" ]; then + return 0 + else + return 1 + fi +} + +# watch out: potential error message as side effect +function isLayer2Default() { + # Read default from sysfs because according to device + # drivers book there are differences in the default between + # OSA (l2), hipersockets (l3). + # This only works here in installer where nobody has overwritten + # the default setting with another custom value already! + if [ ! -f /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/layer2 ]; then + echo $"Could not read layer mode from sysfs" + return 1 + fi + local layer2 + read layer2 < /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/layer2 + if [ "$layer2" = "1" ]; then + return 0 + else + return 1 + fi +} + +# returns true iff either LAYER2 has been set to 1 or is the default +# watch out: potential error message as side effect +function isLayer2() { + case "x$LAYER2" in + x0) return 1 ;; # layer 3 + x1) return 0 ;; # layer 2 + x) # LAYER2 is unset or empty => qeth driver default applies. + isLayer2Default + return $? + ;; + *) echo "l.$LINENO: unknown value "$LAYER2" for LAYER2, code needs to be fixed" 1>&2 + return 2 ;; + esac +} + +# returns true iff qeth device $SCH_R_DEVBUSID +# is capable of supporting IPv6 +# watch out: potential error message as side effect +function ipv6_capable() { + [ "$NETTYPE" = "qeth" ] || return 1 + case $cardtype in + OSD_10GIG|OSD_1000|OSD_100|OSD_Express|HiperSocket s|"GuestLAN QDIO") + return 0 ;; + OSD_GbE_LANE|OSD_FE_LANE|OSD_TR_LANE|OSD_ATM_LANE) return 1 ;; + HSTR|OSN|unknown) return 1 ;; + "GuestLAN Hiper") return 1 ;; + *) echo $"Unknown card_type to determine IPv6 support" + return 1 ;; + esac +} + +# sets device online _and_ retrieves DEVICE at the same time +function set_device_online() { + echo $"Activating network device..." + local sysnettype + case "${NETTYPE}" in + qeth|lcs) sysnettype=${NETTYPE} ;; + ctc) sysnettype=ctcm ;; + esac + if ! [ -f /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online ]; then + echo $"Sysfs path to set device online does not exist." + return 1 + fi + if ! sysecho /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online "1"; then + echo $"Could not set device ($SUBCHANNELS) online" + return 1 + fi + udevadm settle + local i=1 + while : ; do + local online + read online < /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online + [ "$online" == "1" ] && break + sleep 1 + i=$((i+1)) + if [ "$i" -gt 10 ]; then + echo $"Could not set device ($SUBCHANNELS) online within timeout" + return 1 + fi + done + if [ "$NETTYPE" = "lcs" -o "$NETTYPE" = "ctc" ]; then + if [ ! -d /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/net ]; then + echo $"Device $SUBCHANNELS does not have required sysfs directory 'net'" + return 1 + fi + DEVICE=$(ls /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/net/) + if [ "$DEVICE" = "" ]; then + echo $"Could not get device name for $SUBCHANNELS" + return 1 + fi + else # qeth + if [ ! -f /sys/devices/qeth/$SCH_R_DEVBUSID/if_name ]; then + echo $"Device $SUBCHANNELS does not have required sysfs attribute 'if_name'" + return 1 + fi + # (device needs to be online to read if_name from sysfs attribute!) + read DEVICE < /sys/devices/qeth/$SCH_R_DEVBUSID/if_name + if [ "$DEVICE" = "" ]; then + echo $"Could not get device name for $SUBCHANNELS" + return 1 + fi + if [ -f /sys/devices/qeth/$SCH_R_DEVBUSID/card_type ]; then + read cardtype < /sys/devices/qeth/$SCH_R_DEVBUSID/card_type + #debug echo "$cardtype" + # device is now online and link type will be known + echo -n $"Detected: " + cardtype2cleartext "$cardtype" + else + echo $"Could not read qeth network card type from sysfs." + fi + fi +} + +# sets device up and blocks until device appears to be up +function set_device_up() { + if [ -z "$DEVICE" ]; then + echo $"Could not determine interface name to bring up device $SUBCHANNELS" + return 1 + fi + # Device does not come up fast enough to use "ip" to configure, so block. + # While OSA come up themselves after setting online, + # e.g. HiperSockets won't => set them up explicitly for the following check + debug ip link set up $DEVICE + local i=1 + while : ; do + local tst=$(ip -o link show up dev $DEVICE) + [ -n "$tst" ] && break + sleep 1 + i=$((i+1)) + if [ "$i" -gt 10 ]; then + echo $"Could not bring up device $DEVICE within timeout" + return 1 + fi + done + return 0 +} + +function syntax_check_domainname() { + # - match against regex adopted from RFC1035,sec.2.3.1 or RFC1034,sec.3.5 + # (Internationalized Domain Names in Applications (IDNA) [RFC4690] + # have to be entered after encoding by punycode [RFC3492]) + [[ "$1" =~ ^[[:alpha:]]([[:alnum:]-]{0,61}[[:alnum:]])?(.[[:alpha:]]([[:alnum:]-]{0,61}[[:alnum:]])?)*$ ]] + case $? in + 0) + # string matched the pattern + return 0 + ;; + 1) + # string did not match the pattern + echo "$2" + ;; + 2) + echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2 + ;; + *) + echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2 + ;; + esac + return 1 +} + +function disable_ipv6_autoconf() { + sysctl -w net.ipv6.conf.all.accept_ra=0 > /dev/null + sysctl -w net.ipv6.conf.all.accept_redirects=0 > /dev/null + sysctl -w net.ipv6.conf.all.autoconf=0 > /dev/null + sysctl -w net.ipv6.conf.default.accept_ra=0 > /dev/null + sysctl -w net.ipv6.conf.default.accept_redirects=0 > /dev/null + sysctl -w net.ipv6.conf.default.autoconf=0 > /dev/null +} + +function configure_ipv6_address() { + # device needs to be online + # arp flag needs to be on for ipv6 over osa because of ndisc. + # happens automatically by the driver. do NOT mess with default setting. + #NO#debug ip link set dev $DEVICE arp on + if ! debug ip -6 address add $IPADDR/$NETMASK dev $DEVICE; then + echo $"Could net set IPv6 address $IPADDR/$NETMASK for device $DEVICE" + return 1 + fi + # network route has been set by above "ip address add" already + # take care of MTU, which is bundled with ifconfig in the other IPv4 cases + if [ -n "$MMTU" ]; then + if ! debug ip link set $DEVICE $MMTU; then + echo $"Could net set maximum transfer unit ($MMTU) for device $DEVICE" + return 1 + fi + fi + return 0 +} + +function configure_ipv4_address() { + # it's IPv4 and we can make use of ipcalc for better usability + if ipcalc -bmnp $ipcalc_arg > /tmp/ipcalc.$$.out 2> /dev/null; then + . /tmp/ipcalc.$$.out + else + echo $"Could not calculate network address and broadcast address from" + echo $" IPv4 address $IPADDR and netmask $NETMASK" + return 1 + fi + rm /tmp/ipcalc.$$.out + # device needs to be online + if ! debug ifconfig $DEVICE $IPADDR $MMTU netmask $NETMASK broadcast $BROADCAST; then + echo $"Could not set IPv4 address $IPADDR for device $DEVICE" + echo $" with network mask $NETMASK and broadcast address $BROADCAST" + [ -n "$MMTU" ] && echo $" and maximum transfer unit: $MMTU" + return 1 + fi + # This network route is already there after ifconfig! + #if ! debug route add -net $NETWORK netmask $NETMASK dev $DEVICE; then + # echo $"Could not add network route to $NETWORK/$NETMASK on device $DEVICE" + # return 1 + #fi + return 0 +} + +function handle_mtu() { + # don't ask for MTU, but use it if it has been set in the .parm file + # don't overwrite MMTU if it has been set for CTC + [ -n "$MTU" -a -z "$MMTU" ] && MMTU="mtu $MTU" +} + +function rollback_config() { + # each transaction to roll back may fail, if previous setup has not + # made progress that far to reach a certain transation + # => error output is misleading and should be avoided + [ -n "$DEVICE" ] && tv ip -4 route flush default dev $DEVICE + [ -n "$DEVICE" ] && tv ip -6 route flush default dev $DEVICE + # address flush seems to be effective for all address families + [ -n "$DEVICE" ] && ip address flush dev $DEVICE + if [ -n "$NETTYPE" ]; then + if [ -n "$SCH_R_DEVBUSID" ]; then + local sysnettype + case "${NETTYPE}" in + qeth|lcs) sysnettype=${NETTYPE} ;; + ctcm) sysnettype=ctcm ;; + esac + [ -f /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online ] && + sysecho /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online "0" + udevadm settle + [ -f /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/ungroup ] && + sysecho /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/ungroup "1" + udevadm settle + fi + fi + [ -z "$mtu_was_set" ] && unset MTU + [ -z "$mmtu_was_set" ] && unset MMTU + [ -z "$vswitch_was_set" ] && unset VSWITCH + # prevent possible reuse of an old DEVICE on restarting dialog + unset DEVICE + # set activated DASDs offline again + local dasd + while read dasd < /proc/dasd/devices; do + dasd=${dasd%%(*} + sysecho /sys/bus/ccw/devices/$dasd/online 0 + done + udevadm settle +} + +### workflow helper functions + +# workflow ideas: +# - setting/applying single configuration steps right away save us explicit +# syntactical & semantic checks PLUS we get direct feedback on error +# - check error level of forked external programs and react on errors + +unset reenter +unset redoitem +unset interaction_happened + +function reenter() { + [ -z "$reenter" ] && return 1 + # reenter menu should only be shown if NOT redoing item + if [ -n "$redoitem" ]; then + # unset redoitem # wrong => do NOT do this here + return 1 + fi + return 0 +} + +function reenter_menu() { + local oldvalue=$1 + interaction_happened="yes" + # unsetting input here is not sufficient, since reenter_menu + # is not called for predefined parameters + # which then might get assigned a previous old input of another parameter! + #unset input + reenter || return 0 + # don't present reenter menu for empty parameters + # (currently ignoring parameters that are allowed to be empty!) + # this could be improved by checking if variable has been set/defined + #[ -z "$1" ] && return 0 + while : ; do + if [ -n "$helptext" ]; then + echo $"0) default is previous "$oldvalue", 1) new value, ?) help" + else + echo $"0) default is previous "$oldvalue", 1) new value" + fi + # uncoded alternative: 2) skip parameter + local answer + read answer + [ -z "$answer" ] && return 1 + case $answer in + 0) return 1 ;; + 1) # Deciding to enter new value gets user out of reenter-mode + # temporarily for this parameter. + # To put it differently: redoing does NOT present old values. + redoitem="yes" + echo -n $"new value: " + return 0 + ;; + "?") input="?" + return 1 + ;; + esac + done +} + +function workflow_item_menu() { + local noredo=$1 + # default is to continue if running kickstart to prevent interaction + [ -n "$RUNKS" ] && return 0 + interaction_happened="yes" + while : ; do + unset redoitem + if [ "$noredo" = "noredo" ]; then + echo $"1) continue, 2) restart dialog, 3) halt, 4) shell" + else + echo $"0) redo this parameter, 1) continue, 2) restart dialog, 3) halt, 4) shell" + fi + local answer + read answer + case $answer in + 0) [ "$noredo" = "noredo" ] && continue + redoitem="yes" + continue 2 + ;; + 1) return 0 ;; # can be used to break at caller on ignore + 2) reenter="yes" + rollback_config + continue 3 + ;; + 3) tv doshutdown + exit 0 + ;; + 4) echo $"Enter 'exit' at the shell prompt to get back to the installation dialog." + /bin/bash + if [ "$noredo" != "noredo" ] && [ -n "$question_prefix" ]; then + $question_prefix + echo + fi + ;; # stay in workflow item menu + esac + done +} + +# input variables: PARMNAME, question_prefix, question_choices, +# "options" ... +# output variables: $question_prefix, $helptext +# modifies: the variable named $PARMNAME, $OPTIND +function ask() { + [ $# -lt 3 ] && echo "l.$LINENO: too few arguments (<3), please fix calling code." 1>&2 + local PARMNAME=$1 + shift + question_prefix=$1 + shift + local question_choices=$1 + shift + local exception + local syntax_check + unset helptext + local handle + local finish + local optname + OPTIND=1 + while getopts ":e:s:h:c:f:" optname; do + case $optname in + e) exception=$OPTARG ;; + s) syntax_check=$OPTARG ;; + h) helptext=$OPTARG ;; + c) handle=$OPTARG ;; + f) finish=$OPTARG ;; + "?") ;; # ignore invalid option + :) echo "l.$LINENO: Missing parameter to option -$OPTARG" 1>&2 ;; + esac + done + while : ; do + unset input + local input + # actually ask question if one of the following is true: + # - $PARMNAME parameter has not been set yet, e.g. not in parm file + # - on 2nd and further attempts, i.e. redoing the parameter + # - on having restarted the whole dialog + # describing the same from another viewpoint: + # - if $PARMNAME has been set, try to check syntax and apply + # - on redo, $PARMNAME has been set and reenter is false, + # but still ask question again + # - on reenter, $PARMNAME might have been set, but still ask question + if [ -z "${!PARMNAME}" -o -n "$redoitem" -o -n "$reenter" ]; then + # one empty line to separate parameter questions from each other + echo + $question_prefix + if reenter; then + echo + else + $question_choices + fi + # on reenter, give choice between old value and entering new one + reenter_menu ${!PARMNAME} && read input + && [ "$input" != "?" ] && eval ${PARMNAME}=$input + # escaping the $ in the RHS of the eval statement makes it safe + fi + if [ -n "$helptext" ] && [ "$input" = "?" ]; then + $helptext + continue + fi + # optional: default or exceptional handling + [ -n "$exception" ] && $exception + if [ -n "$syntax_check" -a -z "$handle" ]; then + # some parameters have only syntax check (and deferred config): + if $syntax_check; then + break + else + workflow_item_menu && break + fi + elif [ -n "$syntax_check" -a -n "$handle" ]; then + # most common parameters have syntax and configuration: + # user might still continue on syntax error + $syntax_check || workflow_item_menu + # optional: actual configuration + if $handle; then + # parmname has been configured successfully + break + else + # user might still continue on configuration failure + workflow_item_menu && break + fi + elif [ -n "$finish" ]; then + # few parameters need special handling done by their own function: + $finish + else + echo $"Unsupported calling of ask function, please fix calling code" + fi + done # PARMNAME + # disable potential temporary redoing-mode during reenter-mode + unset redoitem +} + +### NETTYPE + +function syntax_check_nettype() { + # - NETTYPE in {qeth,lcs,ctc} + [[ "$NETTYPE" =~ (^qeth$)|(^lcs$)|(^ctc$) ]] + case $? in + 0) + # string matched the pattern + return 0 + ;; + 1) + # string did not match the pattern + ;; + 2) + echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2 + ;; + *) + echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2 + ;; + esac + echo $"Incorrect format or value for network type (NETTYPE): $NETTYPE" + return 1 +} + +function question_prefix_nettype() { + echo -n $"Network type" +} + +function question_choices_nettype() { + echo $" (qeth, lcs, ctc, ? for help). Default is qeth:" +} + +function helptext_nettype() { + echo $" Help text for network type:" + echo $" qeth: OSA-Express Fast Ethernet, Gigabit Ethernet (including 1000Base-T)," + echo $" High Speed Token Ring, Hipersockets, and ATM (running Ethernet LAN emulation)" + echo $" features in QDIO mode." + echo $" [default]" + echo $" lcs: OSA-2 Ethernet/Token Ring, OSA-Express Fast Ethernet in non-QDIO mode," + echo $" OSA-Express High Speed Token Ring in non-QDIO mode and Gigabit Ethernet" + echo $" in non-QDIO mode." + echo $" ctc: Deprecated, useful for migration." +} + +function exception_nettype() { + # - default is qeth since it should be common + if [ -z "$NETTYPE" ]; then + NETTYPE=qeth + break + fi +} + +function finish_nettype() { + if syntax_check_nettype; then + break + else + # necessary parts which would otherwise be done by workflow_item_menu + interaction_happened="yes" + redoitem="yes" + fi +} + +function do_nettype() { + ask NETTYPE + question_prefix_nettype question_choices_nettype + -h helptext_nettype -e exception_nettype -f finish_nettype +} + +### CHANDEV + +function do_chandev() { + echo + echo $"The CHANDEV variable isn't used anymore, please update your " + echo $".parm or the .conf file to use NETTYPE, SUBCHANNELS, etc. instead." + echo +} + +### SUBCHANNELS + +function syntax_check_subchannels() { + SUBCHANNELS=$(echo $SUBCHANNELS | tr ABCDEF abcdef) + # - make subchannel question dependent on NETTYPE (2 vs. 3 subchannels) + if [ "$NETTYPE" = "qeth" ]; then + # - match against regex, depending on qeth + [[ "$SUBCHANNELS" =~ ^[[:xdigit:]]+.[0-3].[[:xdigit:]]{4},[[:xdigit:]]+.[0-3].[[:xdigit:]]{4},[[:xdigit:]]+.[0-3].[[:xdigit:]]{4}$ ]] + else + # - match against regex, depending on lcs/ctc + [[ "$SUBCHANNELS" =~ ^[[:xdigit:]]+.[0-3].[[:xdigit:]]{4},[[:xdigit:]]+.[0-3].[[:xdigit:]]{4}$ ]] + fi + case $? in + 0) + # string matched the pattern + return 0 + ;; + 1) + # string did not match the pattern + echo $"Incorrect format for channels (SUBCHANNELS): $SUBCHANNELS" + ;; + 2) + echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2 + ;; + *) + echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2 + ;; + esac + return 1 +} + +function semantic_check_subchannels() { + local subch_count + if [ "$NETTYPE" = "qeth" ]; then + subch_count=3 + else + subch_count=2 + fi + # done: make subchannel handling more robust by not relying on REMATCH + local -a subch_array + IFS=, + read -a subch_array <<< "indexzero,$SUBCHANNELS" + unset IFS + local i + local all_subch_good=0 + for ((i=1; i <= $subch_count; i++)); do + local devbusid=${subch_array[$i]} + # remember first subchannel for potential undo of ccwgroup + # (via /sys/devices/qeth/$SCH_R_DEVBUSID/ungroup) + [ "$i" -eq 1 ] && SCH_R_DEVBUSID=$devbusid + local prefix ssid devno foo + IFS=. + read prefix ssid devno foo <<< "$devbusid" + unset IFS + local dev_p=$(echo /sys/devices/css$prefix/$IDFORMAT/$devbusid) + # - check for existence of devnos in sysfs + if [ ! -d "$dev_p" -a "$cio_wc_bytes" != "0" ]; then + # - try to free from /proc/cio_ignore if they don't exist + echo $"Device $devbusid not present, trying to clear from blacklist and resense..." + if ! znet_cio_free -d $devbusid; then + echo $"Device $devbusid could not be cleared from device blacklist" + fi + fi + # reevaluate since globbing might not have worked before device existed + dev_p=$(echo /sys/devices/css$prefix/$IDFORMAT/$devbusid) + if [ ! -d "$dev_p" ]; then + echo $"Device $devbusid does not exist" + all_subch_good=1 + continue + fi + # devno does exist now + local subch_p=${dev_p%/*} + local subch=${subch_p##*/} + # filter definitely unusable subchannels ... + # - check for subchannel type I/O + if [ -f $subch_p/type ]; then + local type + read type < $subch_p/type + if [ "$type" != "$SUBCHANNEL_TYPE_IO" ]; then + echo $"Channel $subch (device $devbusid) is not of type I/O" + all_subch_good=1 + continue + fi + fi + # - check for correct CU type/model, depending on qeth/lcs/ctc + if [ ! -f $dev_p/cutype ]; then + echo $"Device $devbusid does not have required sysfs attribute 'cutype'" + all_subch_good=1 + continue + fi + local cutype + read cutype < $dev_p/cutype + if search_cu $cutype; then + local driver + if [ "$NETTYPE" = "ctc" ]; then + driver="ctcm" + else + driver=$NETTYPE + fi + if [ "${CU_DEVDRV[$cu_idx]}" != "$driver" ]; then + echo $"Device $devbusid has control unit type $cutype," + echo $" which does not match your selected network type $NETTYPE" + all_subch_good=1 + continue + fi + else + echo $"Device $devbusid has control unit type $cutype which is unknown" + all_subch_good=1 + continue + fi + # read CHPIDs information about subchannels + if [ ! -f $subch_p/chpids ]; then + echo $"Channel $subch (device $devbusid) does not have required sysfs attribute 'chpids'" + all_subch_good=1 + continue + fi + local chpid_list + read chpid_list < $subch_p/chpids + local -a chpids + read -a chpids <<< "$chpid_list" + if [ ${#chpids[@]} -ne 8 ]; then + echo $"sysfs reported ${#chpids[@]} CHPIDs instead of expected 8, code needs fix" + fi + if [ ! -f $subch_p/pimpampom ]; then + echo $"Channel $subch (device $devbusid) does not have required sysfs attribute 'pimpampom'" + all_subch_good=1 + continue + fi + local pim pam pom foo + read pim pam pom foo < $subch_p/pimpampom + local pimchpidZ="" + for ((chp=0; chp < 8; chp++)); do + local mask=$((0x80 >> chp)) + if (( 0x$pim & $mask )); then + pimchpidZ=${pimchpidZ}${chpids[chp]} + else + pimchpidZ=${pimchpidZ}"ZZ" + fi + done + local pimchpids=${pimchpidZ//ZZ/} + if [ "x$pimchpids" == "x" ]; then + echo $"Channel $subch (device $devbusid) does not have any installed channel path" + all_subch_good=1 + continue + fi + # compare parts of different subchannels for required matches + if [ "$i" -eq 1 ]; then + # remember parts of first subchannel for comparison + local sch_r_prefix=$prefix + local sch_r_ssid=$ssid + local sch_r_devno=$devno + local sch_r_pimchipidZ=$pimchpidZ + local sch_r_cutype=$cutype + else + local comparison=0 + # $sch_r_... might be empty if first channel was wrong + # => be sure to quote all variable accesses in test statements. + # - all subchannels must be of same CU type/model + if [ "$cutype" != "$sch_r_cutype" ]; then + echo $"Device $devbusid does not have the same control unit type as device $SCH_R_DEVBUSID" + comparison=1 + fi + # - all subchannels must have same CHPIDs + if [ "$pimchpidZ" != "$sch_r_pimchipidZ" ]; then + echo $"Device $devbusid does not have the same CHPIDs as device $SCH_R_DEVBUSID" + comparison=1 + fi + # - all subchannels should have same prefix & ssid ? + if [ "$prefix" != "$sch_r_prefix" + -o "$ssid" != "$sch_r_ssid" ]; then + echo $"Device $devbusid does not have the same prefix and subchannel set ID as device $SCH_R_DEVBUSID" + comparison=1 + fi + if [ "$i" -eq 2 ]; then + local sch_w_devbusid=$devbusid + local sch_w_devno=$devno + # TODO: not true for CTCM => relax + # - write_devbusid == read_devbusid+1 + if [ $((0x$devno)) -ne $((0x$sch_r_devno + 1)) ]; then + echo $"Device bus ID of write channel (dev $devbusid) must be one larger than" + echo $" that of read channel (dev $SCH_R_DEVBUSID)" + comparison=1 + fi + elif [ "$i" -eq 3 ]; then + # check data subchannel unequal to read/write subchannel + # (also seems to be handled by ccwgroup kernel subsystem) + if [ "$devbusid" = "$sch_w_devbusid" + -o "$devbusid" = "$SCH_R_DEVBUSID" ]; then + echo $"Device bus ID of data channel (dev $devbusid) must be different to that of" + echo $" read channel ($SCH_R_DEVBUSID) and write channel ($sch_w_devbusid)" + comparison=1 + fi + fi + if [ "$comparison" != 0 ]; then + all_subch_good=1 + continue + fi + fi + # filter potentially good subchannels ... + if [ -h $dev_p/group_device ]; then + echo $"Device $devbusid is already in a ccwgroup and thus unavailable" + all_subch_good=1 + continue + fi + if [ ! -f $dev_p/online ]; then + echo $"Device $devbusid does not have required sysfs attribute 'online'" + all_subch_good=1 + continue + fi + local online + read online < $dev_p/online + if [ "$online" = "1" ]; then + echo $"Device $devbusid is already in use and thus unavailable" + all_subch_good=1 + continue + fi + # - check availability + if [ ! -f $dev_p/availability ]; then + echo $"Device $devbusid does not have required sysfs attribute 'availability'" + all_subch_good=1 + continue + fi + local availability + read availability < $dev_p/availability + if [ "$availability" != "good" ]; then + echo $"Device $devbusid is not available but '$availiability'" + all_subch_good=1 + continue + fi + + done # for ((i=1; i <= $subch_count; i++)) + if [ "$all_subch_good" = "0" ]; then + return 0 + fi + return 1 +} + +function handle_subchannels() { + # - try to establish ccwgroup right here and fail out on error + local driver + if [ "$NETTYPE" = "ctc" ]; then + driver="ctcm" + else + driver=$NETTYPE + fi + # if necessary, + # rebind hybrid devices (3088/08 and 3088/1f) to user specified driver + local curdrv + curdrv=$(readlink /sys/bus/ccw/devices/$SCH_R_DEVBUSID/driver) + curdrv=${curdrv##*/} + if [ "$curdrv" = "lcs" -a "$NETTYPE" = "ctc" ]; then + sysecho /sys/bus/ccw/drivers/lcs/unbind "$SCH_R_DEVBUSID" + sysecho /sys/bus/ccw/drivers/ctcm/bind "$SCH_R_DEVBUSID" + fi + if [ "$curdrv" = "ctcm" -a "$NETTYPE" = "lcs" ]; then + sysecho /sys/bus/ccw/drivers/ctcm/unbind "$SCH_R_DEVBUSID" + sysecho /sys/bus/ccw/drivers/lcs/bind "$SCH_R_DEVBUSID" + fi + local channel2 + channel2=${SUBCHANNELS##*,} + curdrv=$(readlink /sys/bus/ccw/devices/$channel2/driver) + curdrv=${curdrv##*/} + if [ "$curdrv" = "lcs" -a "$NETTYPE" = "ctc" ]; then + sysecho /sys/bus/ccw/drivers/lcs/unbind "$channel2" + sysecho /sys/bus/ccw/drivers/ctcm/bind "$channel2" + fi + if [ "$curdrv" = "ctcm" -a "$NETTYPE" = "lcs" ]; then + sysecho /sys/bus/ccw/drivers/ctcm/unbind "$channel2" + sysecho /sys/bus/ccw/drivers/lcs/bind "$channel2" + fi + # create ccwgroup + if sysecho /sys/bus/ccwgroup/drivers/${driver}/group "$SUBCHANNELS"; then + udevadm settle + case "$NETTYPE" in + qeth) + # Just preliminary card_type info until device goes online! + # In fact it seems enough to separate OSA from HiperSockets. + if [ -f /sys/devices/qeth/$SCH_R_DEVBUSID/card_type ]; then + read cardtype < /sys/devices/qeth/$SCH_R_DEVBUSID/card_type + else + echo $"Could not read qeth network card type from sysfs." + fi + ;; + ctc|lcs) + if [ -f /sys/devices/$driver/$SCH_R_DEVBUSID/type ]; then + local type + read type < /sys/devices/$driver/$SCH_R_DEVBUSID/type + [ "$type" = "CTC/A" ] && + type="channel-to-channel adapter (CTC/A)" + echo $"Detected: $type" + else + echo $"Could not read ctc network card type from sysfs." + fi + ;; + esac + return 0 + else + echo $"Channels $SUBCHANNELS could not be grouped" + fi + return 1 +} + +function question_prefix_subchannels() { + if [ "$NETTYPE" = "qeth" ]; then + echo -n $"Read,write,data channel" + else + echo -n $"Read,write channel" + fi +} + +function question_choices_subchannels() { + if [ "$NETTYPE" = "qeth" ]; then + echo $" (e.g. 0.0.0300,0.0.0301,0.0.0302 or ? for help)." + else + echo $" (e.g. 0.0.0600,0.0.0601 or ? for help)" + fi +} + +function helptext_subchannels() { + if [ "$NETTYPE" = "qeth" ]; then + echo $" Help text for qeth channels:" + echo $" Enter the device bus ID of your CCW devices." + echo $" QETH needs three channels for read, write, and data," + echo $" e.g. 0.0.0300,0.0.0301,0.0.0302" + else + echo $" Help text for lcs/ctc channels:" + echo $" Enter the device bus ID of your CCW devices." + echo $" CTC/ESCON and LCS need two channels for read and write," + echo $" e.g. 0.0.0600,0.0.0601 will configure the CTC or ESCON interface" + echo $" with the channels 0x600 and 0x601" + fi +} + +function finish_subchannels() { + syntax_check_subchannels || workflow_item_menu + # continuing on syntax error is doomed to fail, + # since handle_subchannels relies on the regex-based strict parsing + # in syntax_check_subchannels which does not match anything then + # news: relaxed by splitting semantic check and actual handling + semantic_check_subchannels || workflow_item_menu + if handle_subchannels; then + break + else + workflow_item_menu && break + fi +} + +function do_subchannels() { + ask SUBCHANNELS + question_prefix_subchannels question_choices_subchannels + -h helptext_subchannels -f finish_subchannels +} + +### PORTNAME (qeth) + +function syntax_check_portname() { + # - 1-8 characters, we convert it to upper case + PORTNAME=$(echo $PORTNAME | tr '[:lower:]' '[:upper:]') + local portname_len=${#PORTNAME} + if [ "$portname_len" -ge 1 -a "$portname_len" -le 8 ]; then + return 0 + fi + echo $"Incorrect string length [1..8] for portname (PORTNAME): $PORTNAME" + return 1 +} + +function handle_portname() { + [ -n "$PORTNAME" ] || return 0 + # - try to set portname right here w/ error handling + if sysecho /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/portname "$PORTNAME"; then + return 0 + else + echo $"Portname '$PORTNAME' could not be configured for $SUBCHANNELS" + fi + return 1 +} + +function hint_portname() { + if [ -f /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/portname ]; then + local pname_hint + read pname_hint < /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/portname + if [ "$pname_hint" = "no portname required" ]; then + echo $" * Your configuration does not require a portname. *" + fi + fi +} + +function question_prefix_portname(){ + echo -n $"Portname" +} + +function question_choices_portname(){ + echo $" (1..8 characters, or ? for help). Default is no portname:" +} + +function helptext_portname(){ + echo $" Help text for portname:" + # updated text describing when portname is obsolete; + # taken from: + # SA22-7935-09, Open Systems Adapter-Express Customer's + # Guide and Reference, 10th ed. May 2008, IBM, p.17f. + # SC33-8411-00, Device Drivers, Features, and Commands, + # 1st ed. May 2008, IBM, p.116. + echo $" Portname of the OSA-Express feature in QDIO mode and z/VM Guest LAN." + echo $" This parameter is optional with:" + echo $" - z/VM 4.4.0 or z/VM 4.3.0 with APARs VM63308 and PQ73878" + echo $" - z800, z900 with >= Driver 3G - EC stream J11204, MCL032 (OSA level 3.33)" + echo $" - z890, z990, z9, z10 mainframes" + hint_portname + echo $" If portname is used, all operating systems sharing port must use same name." + echo $" Input empty string if you don't want to enter a portname. [default]" +} + +function exception_portname(){ + [ -z "$PORTNAME" ] && break +} + +function do_portname() { + ask PORTNAME + question_prefix_portname question_choices_portname + -h helptext_portname + -e exception_portname -s syntax_check_portname -c handle_portname +} + +### PORTNO (qeth) + +function syntax_check_qeth_portno() { + case $PORTNO in + 0|1) + return 0 + ;; + esac + echo $"Incorrect format or value for relative port number (PORTNO): $PORTNO" + return 1 +} + +function handle_qeth_portno() { + if sysecho /sys/devices/qeth/$SCH_R_DEVBUSID/portno "$PORTNO"; then + return 0 + fi + echo $"Could not configure relative port number $PORTNO for $SUBCHANNELS" + return 1 +} + +function question_prefix_portno() { + echo -n $"Relative port number for OSA" +} + +function question_choices_portno() { + echo $" (0, 1, or ? for help). Default is 0:" +} + +function helptext_portno() { + echo $" Help text for relative port number for OSA with 2 ports per CHPID:" + echo $" This applies to:" + echo $" - OSA-Express3 Gigabit Ethernet on z10 systems" + echo $" - OSA-Express ATM on zSeries 800 and 900 systems" + echo $" 0 for relative port number 0 [default]" + echo $" 1 for relative port number 1" + echo $" Input empty string to not modify the default configuration." +} + +function exception_portno() { + # Writing portno of e.g. hipersockets device fails. + # Therefore, do not configure on empty default value. + [ -z "$PORTNO" ] && break +} + +function do_portno() { + ask PORTNO + question_prefix_portno question_choices_portno + -h helptext_portno -e exception_portno + -s syntax_check_qeth_portno -c handle_qeth_portno +} + +### LAYER2 + +function syntax_check_layer2() { + # - $LAYER2 in {0,1} + case $LAYER2 in + 0|1) + return 0 + ;; + esac + echo $"Incorrect format or value for layer2 mode (LAYER2): $LAYER2" + return 1 +} + +function handle_layer2() { + [ "$NETTYPE" == "qeth" ] || return 0 + [ -n "$LAYER2" ] || return 0 + # - try to set layer2 mode right here w/ error handling + if sysecho /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/layer2 "$LAYER2"; then + return 0 + else + echo $"Layer2 mode '$LAYER2' could not be configured for $SUBCHANNELS" + fi + return 1 +} + +function question_prefix_layer2() { + echo -n $"Layer mode" +} + +function question_choices_layer2() { + echo -n $" (0 for layer3, 1 for layer2, or ? for help)." + if [ "$isLayer2Default" = "yes" ]; then + echo $" Default is 1:" + else + echo $" Default is 0:" + fi +} + +function helptext_layer2() { + echo $" Help text for OSA mode of operation: layer 2 vs. layer 3" + if [ "$isLayer2Default" = "yes" ]; then + echo $" 0 for layer 3 mode (may not work with dhcp, tcpdump, etc.)" + echo $" 1 for layer 2 mode [default]" + else + echo $" 0 for layer 3 mode [default] (may not work with dhcp, tcpdump, etc.)" + echo $" 1 for layer 2 mode" + fi +} + +function exception_layer2() { + if [ -z "$LAYER2" ]; then + isLayer2Default && LAYER2=1 || LAYER2=0 + # do not break, always apply, default may differ from online layer mode + #break + fi +} + +function do_layer2() { + isLayer2Default && isLayer2Default=yes || isLayer2Default=no + ask LAYER2 + question_prefix_layer2 question_choices_layer2 + -h helptext_layer2 -e exception_layer2 + -s syntax_check_layer2 -c handle_layer2 +} + +### MACADDR + +function syntax_check_macaddr() { + # - match against regex + [[ "$MACADDR" =~ ^[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]$ ]] + case $? in + 0) + # string matched the pattern + return 0 + ;; + 1) + # string did not match the pattern + echo $"Incorrect format for mac address (MACADDR): $MACADDR" + ;; + 2) + echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2 + ;; + *) + echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2 + ;; + esac + return 1 +} + +function handle_macaddr() { + # - try to set macaddr right here w/ error handlg. + # device needs to be online + if debug ifconfig $DEVICE hw ether $MACADDR; then + return 0 + fi + echo $"MAC address $MACADDR could not be configured for" + echo $" $SUBCHANNELS (network device $DEVICE)" + return 1 +} + +function question_prefix_macaddr() { + echo -n $"Unique MAC address" +} + +function question_choices_macaddr() { + macaddr_default=$(ifconfig $DEVICE | grep 'HWaddr' | sed 's/.*HWaddr ([[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]).*/1/') + echo $" (e.g. 02:00:00:00:00:00, ? for help). Default is $macaddr_default:" +} + +function helptext_macaddr() { + echo $" Help text for MAC address:" + if [ -z "${cardtype//OSD_*/}" ]; then + echo $" For real OSA in layer 2 mode, a random MAC address is automatically assigned." + else + echo $" If connecting to a layer 2 VSWITCH, a MAC address is automatically assigned." + fi + echo $" You may accept the automatic MAC address with an empty input. [default]" + echo $" If the automatic address is not unique, please provide a MAC address." + [ -z "${cardtype//OSD_*/}" ] && + echo $" For real OSA, the provided address must be different from that of the OSA." + echo $" You may override the automatic MAC address with non-empty input." + echo $" An example MAC address would be: 02:00:00:00:00:00" +} + +function exception_macaddr() { + if [ -z "$MACADDR" ]; then + if [ -z "${cardtype//OSD_*/}" ]; then + # keep random default MAC address of real OSA, + # so the OSA comes up with the same MAC each time in the future + MACADDR=$macaddr_default + else + # virtual OSA in layer2 is GuestLAN or VSWITCH + VSWITCH=1 + fi + break + fi +} + +function do_macaddr() { + ask MACADDR + question_prefix_macaddr question_choices_macaddr + -h helptext_macaddr -e exception_macaddr + -s syntax_check_macaddr -c handle_macaddr +} + +### CTCPROT + +function syntax_check_ctcprot() { + case "x$CTCPROT" in + x|x0) + unset CTCPROT + return 0 + ;; + x1|x3) + return 0 + ;; + x2) + echo $"CTC tty's are not usable for this installation (CTCPROT)" + ;; + *) + echo $"Incorrect format or value for CTC protocol (CTCPROT): $CTCPROT" + ;; + esac + return 1 +} + +function handle_ctcprot() { + [ -n "$CTCPROT" ] || return 0 + if sysecho /sys/devices/ctcm/${SCH_R_DEVBUSID}/protocol "$CTCPROT"; then + return 0 + fi + echo $"Could not configure CTC protocol $CTCPROT for $SUBCHANNELS" + return 1 +} + +function question_prefix_ctcprot() { + echo -n $"CTC protocol" +} + +function question_choices_ctcprot() { + echo $" (0, 1, 3, or ? for help). Default is 0:" +} + +function helptext_ctcprot() { + echo $" Help text for CTC protocol:" + echo $" Protocol which should be used for the CTC interface" + echo $" 0 for compatibility with p.e. VM TCP service machine [default]" + echo $" 1 for enhanced package checking for Linux peers" + echo $" 3 for compatibility with OS/390 or z/OS peers" +} + +function do_ctcprot() { + ask CTCPROT + question_prefix_ctcprot question_choices_ctcprot + -h helptext_ctcprot -s syntax_check_ctcprot -c handle_ctcprot +} + +### PORTNAME (LCS portno) + +function syntax_check_lcs_portno() { + [[ "$PORTNAME" =~ ^[[:digit:]]+$ ]] + case $? in + 0) + # string matched the pattern + return 0 + ;; + 1) + # string did not match the pattern + ;; + 2) + echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2 + ;; + *) + echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2 + ;; + esac + echo $"Incorrect format for LCS port number (PORTNAME): $PORTNAME" + return 1 +} + +function handle_lcs_portno() { + [ -n "$PORTNAME" ] || return 0 + if sysecho /sys/devices/lcs/$SCH_R_DEVBUSID/portno "$PORTNAME"; then + return 0 + fi + echo $"Could not configure relative port number $PORTNAME for $SUBCHANNELS" + return 1 +} + +function question_prefix_lcs_portno() { + echo -n $"Relative port number of your LCS device" +} + +function question_choices_lcs_portno() { + echo $" (number or ? for help). Default is 0:" +} + +function helptext_lcs_portno() { + echo $" Help text for relative port number of LCS device:" + echo $" Required for OSA-Express ATM cards only." +} + +function exception_lcs_portno() { + [ -z "$PORTNAME" ] && break +} + +function do_lcs_portno() { + # LCS portno and QETH portname share the parameter variable PORTNAME. + # For compatibility with existing parm files we keep this scheme. + ask PORTNAME + question_prefix_lcs_portno question_choices_lcs_portno + -e exception_lcs_portno + -h helptext_lcs_portno -s syntax_check_lcs_portno -c handle_lcs_portno +} + +### HOSTNAME + +function syntax_check_hostname() { + syntax_check_domainname "$HOSTNAME" "Incorrect format for hostname (HOSTNAME): $HOSTNAME" +} + +function handle_hostname() { + if ! hostname $HOSTNAME; then + echo $"Could not configure hostname $HOSTNAME" + return 1 + fi + return 0 +} + +function question_prefix_hostname() { + echo -n $"Hostname of your new Linux guest" +} + +function question_choices_hostname() { + echo $" (FQDN e.g. s390.redhat.com or ? for help):" +} + +function helptext_hostname() { + echo $" Help text for hostname:" + echo $" Enter the full qualified domain name of your host." +} + +function do_hostname() { + ask HOSTNAME + question_prefix_hostname question_choices_hostname + -h helptext_hostname -s syntax_check_hostname -c handle_hostname +} + +### IPADDR + +function syntax_check_ipaddr() { + unset ipv4 + unset ipv6 + if checkipv4 $IPADDR; then + ipv4="yes" + return 0 + elif [ "$ipv6_capable" = "yes" ] && checkipv6 $IPADDR; then + ipv6="yes" + return 0 + fi + echo $"Incorrect format for IP address (IPADDR): $IPADDR" + return 1 +} + +function question_prefix_ipaddr() { + echo -n $"IPv4 address" + [ "$ipv6_capable" = "yes" ] && echo -n $" / IPv6 addr." +} + +function question_choices_ipaddr() { + echo -n $" (e.g. 10.0.0.2" + [ "$ipv6_capable" = "yes" ] && echo -n $" / 2001:0DB8::" + echo $" or ? for he |
| All times are GMT. The time now is 11:26 AM. |
VBulletin, Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.