*=*=*=*= ether_listen.html =*=*=*=*
program ether_listen
c
c This program runs against the ethernet adapter in
c promiscuous mode, examining all the packets and
c distinguishing between them. The name of the controller
c is ESA0 as the code was intended for use on a VS3100.
c Change this to whatever the device name of the controller
c you in fact have is (see the I/O users manual for details)
c
c The subroutine "display" uses SMG routines to display
c real time graphs of the ethernet traffic.
c
c This program does not look at the contents of each packet,
c although it could easily do so: the data in buffer(istart:)
c is the place.
c
c (c) J.J.Bunn 1991 CERN
c
parameter (lbuffer=1500,lpacket=20)
implicit integer(a-z)
C
INCLUDE '($SSDEF)'
INCLUDE '($IODEF)'
INCLUDE '($DVIDEF)'
C
character*17 cdest,csorc
character*5 cprot
character*8 cform
character*(lbuffer) cbuf
character*(lpacket) cblank,cpacket
character*50 ctime
real mbs,t1,t2
integer*4 iosb(2),p2desc(2)
integer*2 channel,transfer,completion,errsum
integer*2 ldata
byte destination(6),source(6)
byte protocol(2)
byte packet(lpacket)
byte buffer(lbuffer)
byte b1(4),b2(4)
equivalence (buffer,cbuf)
equivalence (b1,iosb(1))
equivalence (b2,iosb(2))
equivalence (b1(1),completion)
equivalence (b1(3),transfer)
equivalence (b2(3),errsum)
equivalence (cpacket,packet)
equivalence (packet(1),destination(1))
equivalence (packet(7),source(1))
equivalence (packet(13),protocol)
equivalence (buffer(1),ldata)
C
STRUCTURE /ITEMLIST/
INTEGER*2 BUFLEN
INTEGER*2 ITEMCODE
INTEGER*4 BUFFADD
INTEGER*4 RETLADD
END STRUCTURE
C
RECORD /ITEMLIST/ ITEM_LIST(10)
c
cdec$ options/align=(records=packed)
structure /plist/
integer*2 param_id
integer*4 param_value
end structure
c
record /plist/ p2_list(10)
cdec$ end options
c
C Assign the controller port (for VS 3100)
C
STATUS = SYS$ASSIGN('ESA0:',channel,,)
status = lib$signal(%val(status))
c
iofunc = io$_setmode .or. io$m_ctrl .or. io$m_startup
c
nma$c_pcli_prm = 2840 ! promiscuous
nma$c_pcli_pad = 2842 ! padding
nma$c_pcli_mlt = 2841 ! multicast/broadcast
nma$c_pcli_pty = 2830 ! protocol type
nma$c_pcli_fmt = 2770 ! packet format
nma$c_pcli_bfn = 1105 ! receive buffers
nma$c_pcli_bus = 2801 ! max port receive size in bytes
nma$c_state_on = 0
nma$c_state_off = 1
nma$c_linfm_eth = 1
nma$c_linfm_802 = 2
p2_list(1).param_id = nma$c_pcli_prm
p2_list(1).param_value = nma$c_state_on
p2_list(2).param_id = nma$c_pcli_pad
p2_list(2).param_value = nma$c_state_off
p2desc(1) = 12 ! bytes in p2_list
p2desc(2) = %loc(p2_list)
c
c NB you'll need privilege to do this. Probably PHY_IO at least.
c
status = sys$qiow(,%val(channel),%val(iofunc),iosb
& ,,,,p2desc,,,,)
status = lib$signal(%val(status))
write(6,*) ' promiscuous '
write(6,*) ' completion ',completion
write(6,*) ' transfer ',transfer
write(6,*) ' errsum ',errsum
if(completion.eq.ss$_badparam) write(6,*) iosb
c
do i=1,lpacket
cblank(i:i) = char(0)
end do
c
c read a packet
c
iofunc = io$_readpblk ! .or. io$m_now
c
npackets = 0
status = lib$date_time(ctime)
read(ctime(19:23),'(f5.2)') t1
sum = 0
1 continue
cpacket = cblank
status = sys$qiow(,%val(channel),%val(iofunc),iosb
& ,,,buffer,%val(lbuffer),,,packet,)
npackets = npackets + 1
write(cdest,500) destination
write(csorc,500) source
c
c determine packet type
c
if(packet(17).ne.0.or.packet(18).ne.0) then
cform = '802 ext.'
istart = 7
else if(packet(15).ne.0.or.packet(16).ne.0) then
cform = '802'
istart = 6
else
cform = 'Standard'
write(cprot,501) protocol
status = lib$date_time(ctime)
c call display(transfer,cprot,ctime)
istart = 1
if(ldata.eq.transfer-2) istart = 3
endif
500 format(z2.2,'-',z2.2,'-',z2.2,'-',z2.2,'-',z2.2,'-',z2.2)
501 format(z2.2,'-',z2.2)
c
c write source and destination addresses in standard format, if needed
c
write(6,*) ' Source ',csorc
write(6,*) ' Destination ',cdest
write(6,*) ' IEEE ',cform,' PROTOCOL ',cprot
write(6,*) ' IOSB ',iosb
write(6,*) ' Transfer ',transfer,' bytes'
write(6,*) ' --------------------------------------'
c
c we stop after 10000 packets
c
if(npackets.lt.100000) goto 1
c
c shut down the port
c
100 continue
iofunc = io$_setmode .or. io$m_ctrl .or. io$m_shutdown
status = sys$qiow(,%val(channel),%val(iofunc),iosb
& ,,,,,,,,)
write(6,*) ' shut'
write(6,*) ' completion ',completion
write(6,*) ' transfer ',transfer
write(6,*) ' errsum ',errsum
c
c deassign the channel
c
status = sys$dassgn(%val(channel))
status = sys$exit(%val(1))
c
end
*=*=*=*= DISPLAY.html =*=*=*=*
SUBROUTINE DISPLAY(size,protocol,time)
c
c plots graphs of protocol types in real time.
c Unknown protocol types are dumped in the file 'unknown.protocols'
c
implicit integer (a-z)
include '($smgdef)'
c
parameter (maxprot=20,maxcon=60)
character*10 cprot_type(maxprot)
character*(*) time
character*(*) protocol
character*(maxcon) cbar
character*6 cnum
integer count(maxprot),data(maxprot)
data icall /0/
c
IF(icall.LE.0) THEN
icall = 1
do 6 ip=1,maxcon
cbar(ip:ip) = char(113)
6 continue
do 1 i=1,maxprot
count(i) = 0
data(i) = 0
1 continue
c
c Here we define the names of the standard protocols of interest
c
cprot_type(1) = 'Vitalink'
cprot_type(2) = 'X.75'
cprot_type(3) = 'Dump/Load'
cprot_type(4) = 'DEC Cons.'
cprot_type(5) = 'DECnet IV'
cprot_type(6) = 'LAT'
cprot_type(7) = 'TCP Sys'
cprot_type(8) = 'Novell'
cprot_type(9) = 'LAVC'
cprot_type(10)= 'DEC Bridge'
cprot_type(11)= 'IP'
cprot_type(12)= 'EtherTalk'
cprot_type(13)= 'Apollo Dom'
cprot_type(14)= 'Appletalk'
cprot_type(15)= 'ARP'
cprot_type(16)= 'Apple ARP'
cprot_type(17)= 'Unknown'
nprot = 17
c
c open the file that will contain the dump of unknown
c protocols
c
open(1,file='unknown.protocols',status='new')
c
c Create the pasteboard for the Terminal Screen
c
STATUS = SMG$CREATE_PASTEBOARD(IDP,,ROWS,COLS)
IF(.NOT.STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
c
STATUS=SMG$CREATE_VIRTUAL_DISPLAY
& (ROWS-2,COLS-2,ID,SMG$M_BORDER)
IF(.NOT.STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
c
STATUS = SMG$LABEL_BORDER(ID,' Ethernet Listen ',,,SMG$M_BOLD)
STATUS = SMG$PASTE_VIRTUAL_DISPLAY(ID,IDP,2,2)
IF(.NOT.STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
status = smg$set_broadcast_trapping(id)
c
do 5 ip=1,nprot
status=smg$put_chars(id,cprot_type(ip),ip+3,1,,
& %ref(smg$m_bold),,%ref(smg$c_ascii))
5 continue
c
endif
STATUS=SMG$PUT_CHARS(ID,'Time is '//time(:24),1,1,,
& %REF(SMG$M_normal),,%REF(SMG$C_ASCII))
if(protocol.eq.'80-80') then
iprot = 1
else if(protocol.eq.'08-01') then
iprot = 2
else if(protocol.eq.'60-01') then
iprot = 3
else if(protocol.eq.'60-02') then
iprot = 4
else if(protocol.eq.'60-03') then
iprot = 5
else if(protocol.eq.'60-04') then
iprot = 6
else if(protocol.eq.'90-02') then
iprot = 7
else if(protocol.eq.'81-37') then
iprot = 8
else if(protocol.eq.'60-07') then
iprot = 9
else if(protocol.eq.'80-38') then
iprot = 10
else if(protocol.eq.'80-39') then
iprot = 2
else if(protocol.eq.'80-40') then
iprot = 2
else if(protocol.eq.'80-41') then
iprot = 2
else if(protocol.eq.'80-42') then
iprot = 2
else if(protocol.eq.'08-00') then
iprot = 11
else if(protocol.eq.'80-9B') then
iprot = 12
else if(protocol.eq.'80-19') then
iprot = 13
else if(protocol.eq.'AA-AA') then
iprot = 14
else if(protocol.eq.'08-06') then
iprot = 15
else if(protocol.eq.'80-F3') then
iprot = 16
else
write(1,*) protocol
iprot = 17
endif
count(iprot) = count(iprot) + 1
data(iprot) = data(iprot) + 1
if (count(iprot).gt.maxcon) then
c
c counts need re-setting (depending on what we want, we could
c re-scale here instead)
c
count(iprot) = 1
endif
irow = iprot + 3
ic = count(iprot)
if(ic.eq.1) status = smg$erase_chars(id,maxcon,irow,11)
status = smg$put_chars(id,cbar(1:1),irow,10+ic,,
&%ref(smg$m_bold),,%ref(smg$c_spec_graphics))
write(cnum,'(i6)') data(iprot)
status = smg$put_chars(id,cnum,irow,maxcon+13,,
&%ref(smg$m_normal),,%ref(smg$c_ascii))
end