Commit b382bfa3aa3f8ef3b35d06c286b09bf9b19a5793

Authored by Georg Hopp
1 parent dee510b3

add system information gathering, in cfengine speek this will create our hard classes

Showing 1 changed file with 315 additions and 0 deletions
  1 +#!/bin/dash
  2 +
  3 +##
  4 +# This is a first test what static informations I can gather from a
  5 +# system. The minimal requirement are the IP addresses because
  6 +# on these I build up my classes.
  7 +# The system type is also important...we might need to be running
  8 +# on variuous UNIX flavours. (But for now we focus on various linux
  9 +# flavours and maybe FreeBSD.
  10 +#
  11 +
  12 +
  13 +# Function calculates number of bit in a netmask
  14 +#
  15 +mask2cidr() {
  16 + local NBITS=0
  17 + local OLDIFS="${IFS}"
  18 + IFS=.
  19 +
  20 + for DEC in $1
  21 + do
  22 + case ${DEC} in
  23 + 255) NBITS=$((NBITS+8));;
  24 + 254) NBITS=$((NBITS+7));;
  25 + 252) NBITS=$((NBITS+6));;
  26 + 248) NBITS=$((NBITS+5));;
  27 + 240) NBITS=$((NBITS+4));;
  28 + 224) NBITS=$((NBITS+3));;
  29 + 192) NBITS=$((NBITS+2));;
  30 + 128) NBITS=$((NBITS+1));;
  31 + 0);;
  32 + *) NBITS=0; IFS="${OLDIFS}"; return 1
  33 + esac
  34 + done
  35 + IFS="${OLDIFS}"
  36 + ${ECHO} "${NBITS}"
  37 +}
  38 +
  39 +cidr2mask() {
  40 + local MASK=""
  41 + local FULL_OCTETS=$((${1}/8))
  42 + local PARTIAL_OCTET=$((${1}%8))
  43 +
  44 + for I in 0 1 2 3
  45 + do
  46 + if [ ${I} -lt ${FULL_OCTETS} ]
  47 + then
  48 + MASK="${MASK}255"
  49 + elif [ ${I} -eq ${FULL_OCTETS} ]
  50 + then
  51 + MASK="${MASK}$((256-(1<<(8-${PARTIAL_OCTET}))))"
  52 + else
  53 + MASK="${MASK}0"
  54 + fi
  55 + ${TEST} ${I} -lt 3 && MASK="${MASK}."
  56 + done
  57 +
  58 + ${ECHO} ${MASK}
  59 +}
  60 +
  61 +##
  62 +# retrieve interfaces. I prefer using ip if it is
  63 +# available, else I fallback to ifconfig... don't know
  64 +# how to retrieve this information on other systems.
  65 +#
  66 +get_if_data() {
  67 + if [ ${IP} ]
  68 + then
  69 + eval $(${IP} -o link | ${AWK} '{
  70 + sub(/:/,"",$1);
  71 + no=$1;
  72 + sub(/:/,"",$2);
  73 + name=$2;
  74 + for (i=3; i<NF; i++) {
  75 + if ($i == "state") {
  76 + i++; state=$i
  77 + }
  78 + if ($i ~ /link/) {
  79 + i++; mac=$i;
  80 + classes=classes mac " "
  81 + }
  82 + }
  83 + print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";";
  84 + if ("UP" == state) classes=classes mac " "
  85 + }
  86 + BEGIN {
  87 + classes=""
  88 + }
  89 + END {
  90 + print "CLASSES=\"${CLASSES}" classes " \";";
  91 + print "NINTERFACES=" FNR ";"
  92 + }')
  93 +
  94 + eval $(${IP} -o addr | ${AWK} '{
  95 + sub(/:/,"",$1);
  96 + no=$1;
  97 + if ($3 == "inet") {
  98 + sub(/[\/%].*/,"",$4);
  99 + print "IF" no "_IPV4=\"${IF" no "_IPV4}" $4 " \";";
  100 + classes=classes $4 " "
  101 + }
  102 + if ($3 == "inet6") {
  103 + sub(/[\/%].*/,"",$4);
  104 + print "IF" no "_IPV6=\"${IF" no "_IPV6}" $4 " \";";
  105 + classes=classes $4 " "
  106 + }
  107 + }
  108 + BEGIN {
  109 + classes=""
  110 + }
  111 + END {
  112 + print "CLASSES=\"${CLASSES}" classes " \";"
  113 + }')
  114 + else
  115 + if [ ${IFCONFIG} ]
  116 + then
  117 + #eval $(${IFCONFIG} -a | ${AWK} '{
  118 + eval $(ifconfig -a | awk '
  119 + /ether/ { mac=$2 }
  120 + /inet / { ipv4=ipv4 $2 " " }
  121 + /inet6/ { ipv6=ipv6 $2 " " }
  122 + /^[^ \t]/ {
  123 + if ("" != ipv4 || "" != ipv6) state="UP"; else state="DOWN";
  124 + if ("" != name) {
  125 + print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";" \
  126 + "IF" no "_IPV4=\"${IF" no "_IPV4}" ipv4 " \";" \
  127 + "IF" no "_IPV6=\"${IF" no "_IPV6}" ipv6 " \";";
  128 + no++;
  129 + }
  130 + ipv4=ipv6="";
  131 + sub(/:/,"",$1);
  132 + name=$1
  133 + }
  134 + BEGIN {
  135 + no=1;
  136 + }
  137 + END {
  138 + if ("" != ipv4 || "" != ipv6) state="UP"; else state="DOWN";
  139 + print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";" \
  140 + "IF" no "_IPV4=\"${IF" no "_IPV4}" ipv4 " \";" \
  141 + "IF" no "_IPV6=\"${IF" no "_IPV6}" ipv6 " \";";
  142 + print "NINTERFACES=" no
  143 + }')
  144 + else
  145 + ${LOGGER} -p local0.warn 'Found no way to retrieve interface information.'
  146 + fi
  147 + fi
  148 +}
  149 +
  150 +##
  151 +# start guessing the system type
  152 +# 1. get informations via uname
  153 +#
  154 +get_host_info() {
  155 + OS="$(${UNAME} -o)"
  156 + KERNEL="$(${UNAME} -s)"
  157 + VERSION="$(${UNAME} -r)"
  158 + PLATFORM="$(${UNAME} -m)"
  159 + HOSTNAME="$(${UNAME} -n)"
  160 + CLASSES="$(${ECHO} -e "${OS}\n${KERNEL}\n${VERSION}\n${PLATFORM}\n${HOSTNAME}" |\
  161 + ${SORT} -u | ${TR} "\n" " ")"
  162 +}
  163 +
  164 +##
  165 +# if we are on a linux try to figure out wich distribution we are
  166 +# running.
  167 +# First look what kind of realease file we have:
  168 +#
  169 +# 00 01 - Novell SuSE ---> /etc/SuSE-release
  170 +# 00 02 - Red Hat ---> /etc/redhat-release, /etc/redhat_version
  171 +# 00 04 - Fedora ---> /etc/fedora-release
  172 +# 00 08 - Slackware ---> /etc/slackware-release, /etc/slackware-version
  173 +# 00 10 - Debian ---> /etc/debian_release, /etc/debian_version
  174 +# 00 20 - Mandrake ---> /etc/mandrake-release
  175 +# 00 40 - Yellow dog ---> /etc/yellowdog-release
  176 +# 00 80 - Sun JDS ---> /etc/sun-release
  177 +# 01 00 - Solaris/Sparc ---> /etc/release
  178 +# 02 00 - Gentoo ---> /etc/gentoo-release
  179 +#
  180 +# Here I follow a pessimistic way because I prefere to have no
  181 +# identification at all over a wrong one...so I check for all these files.
  182 +# If I can't find any or find multiple of them I assume this system
  183 +# as unidentified. Anyway when I found one I still check the content...
  184 +# Here I need some help as I don't know the valid content of these files.
  185 +# For now I assume that at least the name of the distribution is in
  186 +# the file.
  187 +#
  188 +get_dist_info() {
  189 + if [ -z "${KERNEL}" ]
  190 + then
  191 + get_host_info
  192 + fi
  193 +
  194 + if [ "Linux" = "${KERNEL}" ]
  195 + then
  196 + local SUSE=1
  197 + local REDHAT=2
  198 + local FEDORA=4
  199 + local SLACKWARE=8
  200 + local DEBIAN=16
  201 + local MANDRAKE=32
  202 + local YELLOWDOG=64
  203 + local SUNJDS=128
  204 + local GENTOO=256
  205 + local SOLARIS=512
  206 +
  207 + local LAST=${SOLARIS}
  208 +
  209 + local CHK=$((SUSE|REDHAT|FEDORA|SLACKWARE|DEBIAN|MANDRAKE|\
  210 + YELLOWDOG|SUNJDS|GENTOO|SOLARIS))
  211 +
  212 + eval local FILES_${SUSE}=\'/etc/SuSE-release\'
  213 + eval local FILES_${REDHAT}=\'/etc/redhat-release /etc/redhat_version\'
  214 + eval local FILES_${FEDORA}=\'/etc/fedora-release\'
  215 + eval local FILES_${SLACKWARE}=\'/etc/slackware-release /etc/slackware-version\'
  216 + eval local FILES_${DEBIAN}=\'/etc/debian_release /etc/debian_version\'
  217 + eval local FILES_${MANDRAKE}=\'/etc/mandrake-release\'
  218 + eval local FILES_${YELLOWDOG}=\'/etc/yellowdog-release\'
  219 + eval local FILES_${SUNJDS}=\'/etc/sun-release\'
  220 + eval local FILES_${GENTOO}=\'/etc/gentoo-release\'
  221 + eval local FILES_${SOLARIS}=\'/etc/release\'
  222 +
  223 + local CUR=1
  224 + while [ ${CUR} -le ${LAST} ]
  225 + do
  226 + local DIR
  227 +
  228 + eval local FILES=\"\${FILES_${CUR}}\"
  229 +
  230 + for DIR in ${FILES}
  231 + do
  232 + ${TEST} -f ${DIR} || CHK=$((CHK&~CUR))
  233 + done
  234 +
  235 + CUR=$((CUR*2))
  236 + done
  237 +
  238 + DIST="Unknown"
  239 +
  240 + ${TEST} ${CHK} -eq ${SUSE} && DIST="Suse"
  241 + ${TEST} ${CHK} -eq ${REDHAT} && DIST="Redhat"
  242 + ${TEST} ${CHK} -eq ${FEDORA} && DIST="Fedora"
  243 + ${TEST} ${CHK} -eq ${SLACKWARE} && DIST="Slakware"
  244 + ${TEST} ${CHK} -eq ${DEBIAN} && DIST="Debian"
  245 + ${TEST} ${CHK} -eq ${MANDRAKE} && DIST="Mandrake"
  246 + ${TEST} ${CHK} -eq ${YELLOWDOG} && DIST="Yellowdog"
  247 + ${TEST} ${CHK} -eq ${SUNJDS} && DIST="Sun"
  248 + ${TEST} ${CHK} -eq ${GENTOO} && DIST="Gentoo"
  249 + ${TEST} ${CHK} -eq ${SOLARIS} && DIST="Solaris"
  250 +
  251 + if [ 'Unknown' != "${DIST}" ]
  252 + then
  253 + eval ${GREP} -iq ${DIST} \${FILES_${CHK}} || DIST="Unknown"
  254 + fi
  255 +
  256 + CLASSES="${CLASSES}${DIST} "
  257 + else
  258 + DIST="${OS}"
  259 + fi
  260 +}
  261 +
  262 +##
  263 +# Here now starts the usage of the functions defined above.
  264 +#
  265 +
  266 +##
  267 +# first specify some programs
  268 +#
  269 +WHICH="/usr/bin/which"
  270 +UNAME="$(${WHICH} uname)"
  271 +TEST="$(${WHICH} test)"
  272 +GREP="$(${WHICH} grep)"
  273 +AWK="$(${WHICH} awk)"
  274 +ECHO="$(${WHICH} echo)"
  275 +SORT="$(${WHICH} sort)"
  276 +TR="$(${WHICH} tr)"
  277 +PRINTF="$(${WHICH} printf)"
  278 +LOGGER="$(${WHICH} logger)"
  279 +IP="$(${WHICH} ip)"
  280 +IFCONFIG="$(${WHICH} ifconfig)"
  281 +
  282 +get_dist_info
  283 +get_if_data
  284 +
  285 +##
  286 +# report everysthing
  287 +#
  288 +
  289 +${PRINTF} "%15s : %s\n" "OS" "${OS}"
  290 +${PRINTF} "%15s : %s\n" "KERNEL" "${KERNEL}"
  291 +${PRINTF} "%15s : %s\n" "VERSION" "${VERSION}"
  292 +${PRINTF} "%15s : %s\n" "PLATFORM" "${PLATFORM}"
  293 +${PRINTF} "%15s : %s\n" "DIST" "${DIST}"
  294 +${PRINTF} "%15s : %s\n" "HOSTNAME" "${HOSTNAME}"
  295 +${PRINTF} "%15s : %s\n" "# INTERFACES" "${NINTERFACES}"
  296 +
  297 +NO=1
  298 +while [ ${NO} -le ${NINTERFACES:=0} ]
  299 +do
  300 + eval printf \"%15s : %s\\\n\" \"IF${NO}_NAME\" \"\${IF${NO}_NAME}\"
  301 + eval printf \"%15s : %s\\\n\" \"IF${NO}_MAC\" \"\${IF${NO}_MAC}\"
  302 + eval printf \"%15s : %s\\\n\" \"IF${NO}_STATE\" \"\${IF${NO}_STATE}\"
  303 + eval printf \"%15s : %s\\\n\" \"IF${NO}_IPV4\" \"\${IF${NO}_IPV4}\"
  304 + eval printf \"%15s : %s\\\n\" \"IF${NO}_IPV6\" \"\${IF${NO}_IPV6}\"
  305 + NO=$((NO+1))
  306 +done
  307 +
  308 +${PRINTF} "%15s : %s\n" "CLASSES" "${CLASSES}"
  309 +
  310 +echo
  311 +echo $(mask2cidr 255.255.128.0)
  312 +echo $(cidr2mask 17)
  313 +eval echo \$\(cidr2mask $(mask2cidr 255.255.128.0)\)
  314 +
  315 +# vim: set ts=4 sw=4:
Please register or login to post a comment