1#!/bin/bash 2 3# netdisco_2_glpi.sh - make fusioninventory-compatible xml from netdisco data 4# format is netdisco_2_glpi.sh target 5 6# POC Netdisco-to-Fusioninventory XML generator 7 8# This is ugly, slow and commits the Cardinal Sin of directly querying the database, 9# ...but it works.... 10 11 12# our local internal domain is mars. Yours might be venus or internal or something else. 13 14export TARGET=$1".mars" 15export IP=`host $TARGET | rev | cut -f1 -d" " | rev` 16 17# pickup switch details known to ND. Get counters from RRD (if you want them, else leave that section out) 18# this keeps switch loading to minimum 19 20## NB: SNMP implementations on switches and other devices are increasingly broken in terms of "standards compliance" 21## and also in terms of cpu consumption. The less they're polled the better. 22 23## "Too many" polls from different NMS programs can affect networking performance! 24## As such, it is frequently beneficial to "proxy" as much as possible. 25 26## Postel's Principle says to be conservative in what you send and liberal in what you accept, 27## But there's nothing wrong with cleaning up what you accept and sending it along better formatted, 28## Especially when some badly broken stuff can break the Net. 29 30 31# NB for bash use: 32# Whatever you do, keep the echoed $STRING part inside the speechmarks or random badness 33# may happen (read the bash manual on string quoting and the differences between single, double 34# or no quotemarks.) 35 36#"firmwares" and "infos" 37echo -e "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" 38echo -e "<REQUEST>" 39echo -e " <CONTENT>" 40echo -e " <DEVICE>" 41echo -e " <FIRMWARES>" 42echo -e " <DESCRIPTION>device firmware</DESCRIPTION>" 43 export MANUFACTURER=`echo -e "select vendor from device where ip = '$IP' " | psql -Aqt ` 44echo -e " <MANUFACTURER>$MANUFACTURER</MANUFACTURER>" 45 export MODEL=`echo -e "select model from device where ip = '$IP' " | psql -Aqt ` 46echo -e " <NAME>$MODEL</NAME>" 47echo -e " <TYPE>device</TYPE>" 48 export VERSION=`echo -e "select os_ver from device where ip = '$IP' " | psql -Aqt ` 49echo -e " <VERSION>$VERSION</VERSION>" 50echo -e " </FIRMWARES>" 51echo -e " <INFO>" 52 export COMMENTS=`echo -e "select description from device where ip = '$IP' " | psql -Aqt ` 53echo -e " <COMMENTS>$COMMENTS</COMMENTS>" 54 export CONTACT=`echo -e "select contact from device where ip = '$IP' " | psql -Aqt ` 55echo -e " <CONTACT>$CONTACT</CONTACT>" 56echo -e " <FIRMWARE>$VERSION</FIRMWARE>" 57## this is the GLPI device ID - leave at zero and let GLPI find it. 58echo -e " <ID>0</ID>" 59echo -e " <IPS>" 60 for DEVIP in `echo -e "select alias from device_ip where ip = '$IP' order by alias asc " | psql -Aqt ` 61 do 62echo -e " <IP>$DEVIP</IP>" 63 done 64echo -e " </IPS>" 65 export LOCATION=`echo -e "select location from device where ip = '$IP' " | psql -Aqt ` 66echo -e " <LOCATION>${LOCATION//\&/_}</LOCATION>" 67 export DEVMAC=`echo -e "select mac from device where ip = '$IP' " | psql -Aqt ` 68 if [ -z $DEVMAC ]; then 69 export DEVMAC=`echo -e "select mac from node_ip where ip = '$IP' " | psql -Aqt ` 70 fi 71echo -e " <MAC>$DEVMAC</MAC>" 72echo -e " <MANUFACTURER>$MANUFACTURER</MANUFACTURER>" 73echo -e " <MODEL>$MODEL</MODEL>" 74 export NAME=`echo -e "select name from device where ip = '$IP' " | psql -Aqt ` 75echo -e " <NAME>$NAME</NAME>" 76 export SERIAL=`echo -e "select serial from device where ip = '$IP' " | psql -Aqt ` 77 78## Did Netdisco fail to pickup the serial number? (FIA would have too. ND looks in more places!) 79## kludge in the MAC as the serial in this case (FI4G won't inmport without a serial) 80 if [ -z "$SERIAL" ]; then 81 export SERIAL=$MAC 82 fi 83## Huawei Cloudengines. 84### .1.3.6.1.2.1.47.1.1.1.1.11. 85#Local kludge: This is a stack. If the Stack Master changes then so does the reported SN 86# (and the system MAC) which means that Fusion/GLPI treats it as a different (new) switch. 87# 88# There's a PR in train to handle this better 89# 90# Force the SN to remain constant. 91 if [ $1 = "abcdaa" ]; then 92 export SERIAL="210235924710EA00XXXX" 93 fi 94### .1.3.6.1.2.1.47.1.1.1.1.11. 95 if [ $1 = "abcdab" ]; then 96 export SERIAL="210235924710EA00XXXX" 97 fi 98### .1.3.6.1.2.1.47.1.1.1.1.11. 99 if [ $1 = "abcdac" ]; then 100 export SERIAL="210235924610EA00XXXX" 101 fi 102# this is a Huawei AC6605 access controller. Not a stack but the SN isn't detected) 103### .1.3.6.1.2.1.47.1.1.1.1.11.9 104 if [ $1 = "abcda4" ]; then 105 export SERIAL="21023579169WH600XXXX" 106 fi 107### .1.3.6.1.2.1.47.1.1.1.1.11.9 108 if [ $1 = "abcda9" ]; then 109 export SERIAL="210235791610F200XXXX" 110 fi 111echo -e " <SERIAL>$SERIAL</SERIAL>" 112 113### NB: if Serial and/or MAC are blank, things WILL break horribly and randomly. 114### It also means your switch is not supported - YET - and you need to generate a snmpwalk 115### then ask for assistance in the Netdisco groups. 116### Assistance is available on IRC freenode - #netdisco or on http://netdisco.org/ 117### (you need to register your handle thanks to spammer attacks) 118 119 120echo -e " <TYPE>NETWORKING</TYPE>" 121 122## this bit demonstrates the kind of thing I like about pgsql - it has a lot of builtin functions you can take ## for granted that require jumping through hoops in mysql. 123## Note that IP addresses, time, MACs and many other net-related things are stored internally as 124## numerics and converted to whatever you need when displayed. See postgres.org 125 126 export UPTIME="("`echo -e "select uptime from device where ip= '$IP' " | psql -Aqt `") "`echo -e "select justify_hours ((select uptime from device where ip= '$IP') / 100 * interval '1s' ) " | psql -Aqt ` 127echo -e " <UPTIME>$UPTIME</UPTIME>" 128echo -e " </INFO>" 129 130# some fields returned from some switches have spaces in them. 131# which will mess up loops - so we need to stop that happening. 132# - first, save the interfield spacer 133SAVEIFS=$IFS 134# This changes the "interfield spacing" from whitespace to "newline" 135IFS=$(echo -en "\n\b") 136# We''ll change it back at the end of the script. 137 138# and now, on with the show (oh glorious spaghetti code, how we love thee) 139echo -e " <PORTS>" 140for PORT in `echo -e "select port from device_port where ip = '$IP' " | psql -Aqt ` 141 do 142 echo -e " <PORT>" 143 export IFDESCR=`echo -e "select descr from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 144 echo -e " <IFDESCR>$IFDESCR</IFDESCR>" 145 export IFALIAS=`echo -e "select name from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 146 echo -e " <IFALIAS>$IFALIAS</IFALIAS>" 147 export IFNAME=`echo -e "select port from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 148 echo -e " <IFNAME>$IFNAME</IFNAME>" 149 150# make sure you are using Netdisco 2.40.6 or later (release 2019/3/06) or this won't work! 151# There are other ways of extracting IFNUMBER but they aren't as reliable because some switches 152# (EG: Cisco sg300) give the same name to vlan AND vlanif so simple pattern matching isn't the answer. 153 export IFNUMBER=`echo -e "select ifindex from device_port_properties where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 154echo -e " <IFNUMBER>$IFNUMBER</IFNUMBER>" 155 156 export IFMTU=`echo -e "select mtu from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 157 echo -e " <IFMTU>$IFMTU</IFMTU>" 158 export IFMAC=`echo -e "select mac from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 159## Some switches are broken and report bogus MACs here (eg: Zyxel XGS- series) 160 case "$IFMAC" in 161 00:00:00:00:00*) 162 export IFMAC=$DEVMAC 163 ;; 164 *) 165 ### placeholder add else anything needed here 166 esac 167 echo -e " <MAC>$IFMAC</MAC>" 168 export IFLASTCHANGE=`echo -e "select justify_hours ((select lastchange from device_port where ip= '$IP' and port='$PORT') / 100 * interval '1s' ) " | psql -Aqt ` 169 echo -e " <IFLASTCHANGE>$IFLASTCHANGE</IFLASTCHANGE>" 170 171# have we got any IP addresses? 172 if [[ `echo -e "select count(alias) from device_ip where ip = '$IP' and port= '$PORT' " | psql -Aqt ` -ge 1 ]] ; then 173 export PORTIP=`echo -e "select alias from device_ip where ip = '$IP' and port= '$PORT' limit 1 " | psql -Aqt ` 174 echo -e " <IP>$PORTIP</IP>" 175 echo -e " <IPS>" 176 for PORTIP in `echo -e "select alias from device_ip where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 177 do 178 echo -e " <IP>$PORTIP</IP>" 179 done 180 echo -e " </IPS>" 181 fi 182 183 export IFSPEED=`echo -e "select raw_speed from device_port_properties where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 184 echo -e " <IFSPEED>$IFSPEED</IFSPEED>" 185 186### this seems to be ifadminstatus 1=up, 2=down, 3=testing ### 187 export IFINTERNALSTATUS=`echo -e "select up_admin from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 188 case "$IFINTERNALSTATUS" in 189 up) 190 echo -e " <IFINTERNALSTATUS>1</IFINTERNALSTATUS>" 191 ;; 192 down) 193 echo -e " <IFINTERNALSTATUS>2</IFINTERNALSTATUS>" 194 ;; 195 *) 196 esac 197 198### this seems to be ifstatus 1=up, 2=down, 3=testing ### 199 export IFSTATUS=`echo -e "select up from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 200 case "$IFSTATUS" in 201 up) 202 echo -e " <IFSTATUS>1</IFSTATUS>" 203 ;; 204 down) 205 echo -e " <IFSTATUS>2</IFSTATUS>" 206 ;; 207 *) 208 esac 209 210#### portduplex 1=unknown 2=half 3=full - only valid for ethernet ports ### 211 export IFPORTDUPLEX=`echo -e "select duplex from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 212 case "$IFPORTDUPLEX" in 213 half) 214 echo -e " <IFPORTDUPLEX>2</IFPORTDUPLEX>" 215 ;; 216 full) 217 echo -e " <IFPORTDUPLEX>3</IFPORTDUPLEX>" 218 ;; 219 *) 220 esac 221 222# Huawei ports aren't always picked up properly. Force the issue 223# Not that it matters 224# - FI4G has decided that Type 53 is a physical, not aggregate port. 225# Because some makers return 53 for real ports. Edit your plugin to fix. 226 case "$IFDESCR" in 227 NULL*) 228 echo -e " <IFTYPE>1</IFTYPE>" 229 ;; 230 InLoopBack*) 231 echo -e " <IFTYPE>24</IFTYPE>" 232 ;; 233 Vlanif*) 234 echo -e " <IFTYPE>53</IFTYPE>" 235 ;; 236 Eth-Trunk*) 237 echo -e " <IFTYPE>161</IFTYPE>" 238 ;; 239 Stack-Port*) 240 echo -e " <IFTYPE>161</IFTYPE>" 241 ;; 242 *) 243 # iftype other=1, ethernetCsmacd=6, propPointToPointSerial=22, softwareLoopback=24 244 # propVirtual=53, tunnel=131, l2vlan=135, ieee8023adLag=161, ifPwType=246, 245 export IFTYPE=`echo -e "select type from device_port where ip = '$IP' and port = '$PORT' " | psql -Aqt ` 246 case "$IFTYPE" in 247 other) 248 echo -e " <IFTYPE>1</IFTYPE>" 249 ;; 250 ethernetCsmacd) 251 echo -e " <IFTYPE>6</IFTYPE>" 252 ;; 253 propPointToPointSerial) 254 echo -e " <IFTYPE>22</IFTYPE>" 255 ;; 256 softwareLoopback) 257 echo -e " <IFTYPE>24</IFTYPE>" 258 ;; 259 propVirtual) 260 echo -e " <IFTYPE>53</IFTYPE>" 261 ;; 262 tunnel) 263 echo -e " <IFTYPE>131</IFTYPE>" 264 ;; 265 l2vlan) 266 echo -e " <IFTYPE>135</IFTYPE>" 267 ;; 268 ieee8023adLag) 269 echo -e " <IFTYPE>161</IFTYPE>" 270 ;; 271 ifPwType) 272 echo -e " <IFTYPE>246</IFTYPE>" 273 ;; 274 *) 275 esac 276 esac 277 278#### ############################################################# 279#### netdisco can't provide these, get them elsewhere # 280#### in my case, that's my rrd files. Your milage (and paths) may vary #### 281### this section may be entirely optional - g-bougard can advise 282 export RRDPORT=${PORT,,} 283 export RRDFILE=/var/lib/mrtg/"$1"/"$1"_"${RRDPORT//\//_}".rrd 284 if [ -f "$RRDFILE" ]; then 285 export RRDSTATS=`rrdtool lastupdate "$RRDFILE" | tail -n1` 286 if [ -n "$RRDSTATS" ]; then 287 export IFINOCTETS=`echo $RRDSTATS | rev | cut -f2 -d" " | rev` 288 echo -e " <IFINOCTETS>$IFINOCTETS</IFINOCTETS>" 289 echo -e " <IFINERRORS>0</IFINERRORS>" 290 export IFOUTOCTETS=`echo $RRDSTATS | rev | cut -f1 -d" " | rev` 291 echo -e " <IFOUTOCTETS>$IFOUTOCTETS</IFOUTOCTETS>" 292 echo -e " <IFOUTERRORS>0</IFOUTERRORS>" 293 fi 294 fi 295#### ############################################################# 296 297 298### ND can tell if the neighbour is a "upstream" (switch), but glpi doesn't know how to handle that 299 300## TRUNK == "More than one VLAN" 301 export TRUNK=`echo -e "select count(vlan) from device_port_vlan where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 302 if [[ $TRUNK -le 1 ]]; then 303 echo -e " <TRUNK>0</TRUNK>" 304 elif [[ $TRUNK -ge 2 ]]; then 305 echo -e " <TRUNK>1</TRUNK>" 306 fi 307 if [[ $TRUNK -ge 1 ]]; then 308 echo -e " <VLANS>" 309 for VLAN in `echo -e "select vlan from device_port_vlan where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 310 do 311 echo -e " <VLAN>" 312 export VLANNAME=`echo -e "select description from device_vlan where ip = '$IP' and vlan= '$VLAN' " | psql -Aqt ` 313 314## If you have gvrp, vlans keep appearing on various switches without descriptions 315## and this adds bogons to GLPI. This just forcibly cleans that up 316 317 case "$VLANNAME" in 318 default) 319 export VLANNAME="0001-DEFAULT" 320 ;; 321 DEFAULT) 322 export VLANNAME="0001-DEFAULT" 323 ;; 324 default) 325 export VLANNAME="0001-DEFAULT" 326 ;; 327 VLAN\ 0001) 328 export VLANNAME="0001-DEFAULT" 329 ;; 330 VLAN\ 0069) 331 export VLANNAME="0069-userspace" 332 ;; 333 VLAN\ 0070) 334 export VLANNAME="0070-userspace" 335 ;; 336 VLAN\ 0071) 337 export VLANNAME="0071-userspace" 338 ;; 339 VLAN\ 0073) 340 export VLANNAME="0073-userspace" 341 ;; 342 VLAN\ 0256) 343 export VLANNAME="0256-CGROUP" 344 ;; 345 VLAN\ 0500) 346 export VLANNAME="0500-MULTICAST" 347 ;; 348 VLAN\ 0511) 349 export VLANNAME="0511-Mailservers" 350 ;; 351 VLAN\ 511) 352 export VLANNAME="0511-Mailservers" 353 ;; 354 MAIL-Heartbeat) 355 export VLANNAME="0511-Mailservers" 356 ;; 357 VLAN\ 0640) 358 export VLANNAME="0640-PRINTERS" 359 ;; 360 VLAN\ 0641) 361 export VLANNAME="0641-IPMIS" 362 ;; 363 SWITCHES) 364 export VLANNAME="0642-SWITCHES" 365 ;; 366 SWITCHES_142) 367 export VLANNAME="0642-SWITCHES" 368 ;; 369 VLAN\ 0642) 370 export VLANNAME="0642-SWITCHES" 371 ;; 372 VLAN\ 0643) 373 export VLANNAME="0643-user-IPMIS" 374 ;; 375 VLAN\ 0645) 376 export VLANNAME="0645-user-misc" 377 ;; 378 VLAN\ 0646) 379 export VLANNAME="0646-UPS" 380 ;; 381 VLAN\ 0670) 382 export VLANNAME="0670-Frobuzz(isol)" 383 ;; 384 VLAN\ 0671) 385 export VLANNAME="0671-Foobar(isolated)" 386 ;; 387 VLAN\ 0672) 388 export VLANNAME="0672-IMAGING" 389 ;; 390 VLAN\ 0700) 391 export VLANNAME="0700-EDUROAM-WANSIDE" 392 ;; 393 VLAN\ 2000) 394 export VLANNAME="2000-FIREWALL-ZONE" 395 ;; 396 VLAN\ 2001) 397 export VLANNAME="2001-MAILFIREWALL" 398 ;; 399 VLAN\ 3500) 400 export VLANNAME="3500-WAPS" 401 ;; 402 VLAN\ 3550) 403 export VLANNAME="3550-EDUROAM-WAPSIDE" 404 ;; 405 VLAN\ 4003) 406 export VLANNAME="4003-Packetfence-quarantine" 407 ;; 408 VLAN\ 4004) 409 export VLANNAME="4004-Packetfence-reg" 410 ;; 411 VLAN\ 4059) 412 export VLANNAME="4059-trill" 413 ;; 414 VLAN\ 4094) 415 export VLANNAME="4094-parking" 416 ;; 417 *) 418 esac 419 420### NB: ND has fields to mark if this is tagged, untagged and if it's PVID. 421### BUT, the XML spec for FI-Agent has no indication showing these 422### so all vlans end up being imported UNTAGGED! 423 echo -e " <NAME>$VLANNAME</NAME>" 424 echo -e " <NUMBER>$VLAN</NUMBER>" 425 echo -e " </VLAN>" 426 done 427 echo -e " </VLANS>" 428 fi 429 430## Aggregate = LACP trunking, portchannel, ethernet bonding, various other names for combining ports for higher Bandwidth. 431 export AGGREGATE=`echo -e "select is_master from device_port where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 432 if [ "$AGGREGATE" == "t" ]; then 433 echo -e " <AGGREGATE>" 434 for SLAVEPORT in `echo -e "select port from device_port where ip = '$IP' and slave_of= '$PORT' " | psql -Aqt ` 435 do 436 export SLAVEIFNUMBER=`echo -e "select ifindex from device_port_properties where ip = '$IP' and port = '$SLAVEPORT' " | psql -Aqt ` 437 echo -e " <PORT>$SLAVEIFNUMBER</PORT>" 438 done 439 echo -e " </AGGREGATE>" 440 fi 441 echo -e " <CONNECTIONS>" 442 443## What MACs are on the far side of the link? 444 export CONNECTIONS=`echo -e "select count(mac) from node where switch = '$IP' and port= '$PORT' and active= 't' " | psql -Aqt ` 445 if [[ $CONNECTIONS -ge 1 ]]; then 446 echo -e " <CONNECTION>" 447 for REMOTEMAC in `echo -e "select mac from node where switch = '$IP' and port= '$PORT' and active= 't' " | psql -Aqt ` 448 do 449 echo -e " <MAC>$REMOTEMAC</MAC>" 450 done 451 echo -e " </CONNECTION>" 452 fi 453 454 455## Is this a LLDP/CDP neighbour? (fold this down to CDP for either) 456 export CDP=`echo -e "select count(remote_port) from device_port where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 457 if [[ $CDP -ge 1 ]]; then 458 echo -e " <CDP>1</CDP>" 459 echo -e " <CONNECTION>" 460 export SYSNAME=`echo -e "select device.name from device join device_port on device.ip=device_port.remote_ip where device_port.ip='$IP' and port ='$PORT' " | psql -Aqt ` 461 if [ -n "$SYSNAME" ]; then 462 echo -e " <SYSNAME>$SYSNAME</SYSNAME>" 463 fi 464 export SYSMAC=`echo -e "select remote_id from device_port where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 465 echo -e " <SYSMAC>$SYSMAC</SYSMAC>" 466 export SYSIP=`echo -e "select remote_ip from device_port where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 467 echo -e " <IP>$SYSIP</IP>" 468 export SYSIFDESCR=`echo -e "select remote_port from device_port where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 469 if [ -n "$SYSIFDESCR" ]; then 470 ## Take care of Zyxel borkage 471 if [ "$SYSIFDESCR" == "Sid 1, Port 46" ]; then 472 export SYSIFDESCR="Switch 1 - Port 46" 473 fi 474 if [ "$SYSIFDESCR" == "Sid 1, Port 48" ]; then 475 export SYSIFDESCR="Switch 1 - Port 48" 476 fi 477 echo -e " <IFDESCR>$SYSIFDESCR</IFDESCR>" 478 fi 479 export SYSIFNUMBER=`echo -e "select ifindex from device_port_properties where ip = '$SYSIP' and port = '$SYSIFDESCR' " | psql -Aqt ` 480##################################################### 481#### PURE KLUDGE AND ONLY FOR WAP WORK AT MY SITE until I wirk out how to interrogate them! 482 export WAPCHECK=`echo -e "select remote_is_wap from device_port_properties where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 483 if [ "$WAPCHECK" == "t" ]; then 484 export SYSIFNUMBER="1" 485 fi 486## same for IPphones - most have a switch and slave ports in them. 487## This is important if you don't want either device showing up as an unmanaged hubs 488## with a cloud of other devices hanging off them. 489 export PHONECHECK=`echo -e "select remote_is_phone from device_port_properties where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 490 if [ "$PHONECHECK" == "t" ]; then 491 export SYSIFNUMBER="1" 492 fi 493##################################################### 494 # this just covers remaining bases (switches we don't handle) 495 if [ -z $SYSIFNUMBER ]; then 496 export SYSIFNUMBER="1" 497 fi 498 echo -e " <IFNUMBER>$SYSIFNUMBER</IFNUMBER>" 499 500 export SYSDESCR=`echo -e "select remote_type from device_port where ip = '$IP' and port= '$PORT' " | psql -Aqt ` 501 if [ -n "$SYSDESCR" ]; then 502 echo -e " <SYSDESCR>$SYSDESCR</SYSDESCR>" 503 fi 504 export NODEMAC=`echo -e "select mac from node_ip where ip='$SYSIP' " | psql -Aqt ` 505 echo -e " <MAC>$NODEMAC</MAC>" 506 echo -e " </CONNECTION>" 507 fi 508 echo -e " </CONNECTIONS>" 509 echo -e " </PORT>" 510done 511IFS=$SAVEIFS 512echo -e " </PORTS>" 513echo -e " </DEVICE>" 514echo -e " <MODULEVERSION>3.1</MODULEVERSION>" 515echo -e " <PROCESSNUMBER>1</PROCESSNUMBER>" 516echo -e " </CONTENT>" 517echo -e " <DEVICEID>foo</DEVICEID>" 518echo -e " <QUERY>SNMPQUERY</QUERY>" 519echo -e "</REQUEST>" 520 521exit 0 522