;+
;
; Overlay a packet driver and disable the get/set multicast list calls.
;
; By John Wilson.
;
; Usage:
;
; NOMCAST /I:60
; /I -- INT # of ethernet packet driver (default is to search from 20-FF)
;
; 06/26/97	JMBW	Created (based on NSLUT.ASM).
;
;-
	.radix	8
;
lf=	12
cr=	15
;
mcmax=	100d*6			;max size of multicast list (in bytes)
;
code	segment
	assume	cs:code
	org	100h
start:	jmp	short init	;go init
ent:	jmp	short ent1
	nop
pktdrv	db	'PKT DRVR',0	;signature
ent1:	cmp	ah,16h		;SET_MULTICAST_LIST?
	je	ent2
	cmp	ah,17h		;GET_MULTICAST_LIST?
	je	ent2
	db	0EAh		;JMP FAR
pdaddr	dw	?,?
ent2:	push	bp		;save
	mov	bp,sp		;point at stack
	or	byte ptr [bp+6],1 ;set CF
	pop	bp		;restore
	mov	dh,06h		;NO_MULTICAST
	iret
init:	cld			;DF=0
	mov	dx,offset banner ;point at banner
	mov	ah,09h		;func=print
	int	21h		;say hello
	; parse command line
	mov	si,80h		;pt at it
	lodsb			;get length
	cbw			;ah=0
	mov	cx,ax		;copy
jcl1:	call	skip		;skip blanks
	jnc	$+5
	 jmp	jcl8
	cmp	al,'/'		;switch?
	je	jcl2
	cmp	al,'-'
	jne	jcl3
jcl2:	inc	si		;skip it
	dec	cx
jcl3:	call	skip		;get switch char
	jc	jcl8
	inc	si		;skip the char
	dec	cx
	and	ax,337		;convert to upper, AH=0
	push	ax		;save
	jcxz	jcl5
	lodsb			;get char
	cmp	al,':'		;: or =
	je	jcl4
	cmp	al,'='
	jne	jcl5
jcl4:	dec	cx		;count it
	call	ghex		;get numeric arg
	pop	di		;restore cmd
	cmp	di,'I'		;<I>nterrupt # of packet driver?
	je	jcl7
jcl5:	mov	dx,offset usage	;pt at msg
	mov	cx,lusage	;length
	call	stderr		;print it
	mov	ax,4C01h	;func=punt
	int	21h
jcl6:	mov	ds:clrf,al	;set flag
	jmp	short jcl1
jcl7:	; /I:nn (set INT vector number of packet driver)
	mov	ds:intno,al	;save
	jmp	jcl1
jcl8:	; done, init packet driver
	mov	al,ds:intno	;get int # of packet driver
	test	al,al		;got one?
	jz	init1
	call	probe		;give it a try
	jc	init3
	jmp	short init4
init1:	; check all int #'s in [20h,0FFh]
	mov	al,20h		;starting posn
init2:	push	ax		;save
	call	probe		;give it a try
	pop	ax		;[restore]
	jnc	init4		;got one
	inc	al		;+1
	jnz	init2		;keep going unless it was FF
init3:	; driver not found
	mov	dx,offset nodrv	;pt at msg
	mov	cx,lnodrv
	call	stderr		;print on stderr
	mov	ax,4C01h	;func=punt
	int	21h
init4:	; found a driver, no need to open a handle for multicast stuff
	mov	al,ds:intno	;get int #
	mov	ah,35h		;func=get int vector
	int	21h
	mov	ds:pdaddr,bx	;save
	mov	ds:pdaddr+2,es
	mov	dx,offset ent	;set new entry point
	mov	al,ds:intno	;get int #
	mov	ah,25h		;func=set int vector
	int	21h
	mov	dx,offset init	;ending offset
	int	27h		;TSR
;+
;
; Print a msg on STDERR.
;
; dx	ptr
; cx	length
;
;-
stderr:	push	cs		;copy CS to DS
	pop	ds
	mov	bx,0002h	;handle=stderr
	mov	ah,40h		;func=write
	int	21h
	ret
;+
;
; Check for the existence of a packet driver and install our connection
; to it if it is found.
;
; al	int # (in the range [20h,0FFh])
;
; CF=0 on success.
;
;-
probe:	push	cs		;copy CS to DS
	pop	ds
	mov	ds:intno,al	;patch in INT #
	mov	ah,35h		;func=get int vector
	int	21h
	mov	ax,es		;0000:0000?
	or	ax,bx
	jz	prob1
	lea	di,[bx+3]	;pt at signature
	mov	si,offset pktdrv ;pt at string
	mov	cx,9d		;length
	repe	cmpsb		;check for signature
	je	prob2
prob1:	stc			;error return
	ret
prob2:	; found one, get information
	mov	ax,01FFh	;func=DRIVER_INFO
	call	pkdrv		;call pktd
	jc	prob5		;punt
	cmp	al,2		;basic+extended?
	je	prob3
	cmp	al,6		;basic+high-performance+extended?
	jne	prob4
prob3:	inc	ds:initf	;set flag
	clc
	ret
prob4:	mov	dx,offset nmult	;point at msg
	mov	cx,lnmult
	call	stderr		;print it
prob5:	stc
prob6:	ret
;
pkdrv:	; do INT instruction to call packet driver
	push	es		;save
	call	pkdrv1
	pop	es		;restore
	ret
;
pkdrv1:	; do INT instruction to call packet driver, return ES unscathed
	push	ds		;save
	db	0CDh		;INT nn
intno	db	0		;call the packet driver
	pop	ds		;restore
	ret
;+
;
; Skip blanks, control chars.
;
; Updates SI, CX, returns CF=1 if EOL.  Otherwise AL=first non-blank char.
;
;-
skip:	jcxz	skip3		;EOL already
skip1:	lodsb			;get a byte
	cmp	al,' '		;blank or ctrl char?
	jbe	skip2		;yes
	dec	si		;unget, CF=0 already
	ret
skip2:	loop	skip1		;loop
skip3:	stc			;hit EOL
	ret
;+
;
; Get a hex number (up to 48 bits)
;
; si	ptr to input line
; cx	# chars left
;
; dx:bx:ax returns number
;
;-
ghex:	xor	di,di		;init #
	xor	bx,bx
	xor	dx,dx
ghex1:	lodsb			;get a char
	cmp	al,'-'		;ignore embedded '-'
	je	ghex3
	cmp	al,':'		;and ':'
	je	ghex3		;(Weenix geeks)
	cmp	al,'0'		;digit?
	jb	ghex4
	cmp	al,'9'
	jbe	ghex2		;yes
	and	al,not 40	;cvt to upper
	cmp	al,'A'		;letter?
	jb	ghex4
	cmp	al,'F'
	ja	ghex4
	sub	al,7		;make A follow 9
ghex2:	sub	al,'0'		;convert to binary
	and	ax,0Fh		;isolate new digit
	push	cx		;save
	mov	cl,4		;bit count
	rol	di,cl		;make space
	rol	bx,cl
	sal	dx,cl
	mov	cx,di		;get lowest
	and	di,0FFF0h	;make space for new digit
	xor	cx,di		;isolate old one
	or	di,ax		;OR in new digit
	mov	al,bl		;get middle
	and	bl,0F0h		;make space for new digit
	xor	al,bl		;isolate old one
	or	bl,cl		;OR in new digit
	or	dl,al		;OR in new digi
	pop	cx		;restore
ghex3:	loop	ghex1		;around for more
ghex4:	dec	si		;unget (or not if off end, doesn't matter)
	mov	ax,di		;get low digits
	ret
;
	subttl	pure data
;
banner	db	'NOMCAST  V1.0  Disable get/set multicast list calls'
	db	cr,lf
	db	'By John Wilson <wilson@dbit.com>',cr,lf
	db	'MUST REBOOT TO REMOVE',cr,lf,'$'
;
usage	db	'Usage:  NOMCAST [/I:{int no}]'
	db	cr,lf
lusage=	$-usage
;
nodrv	db	'?Unable to find packet driver',cr,lf
lnodrv=	$-nodrv
;
nmult	db	'?Packet driver does not support multicasts',cr,lf
lnmult=	$-nmult
;
	subttl	impure data
;
initf	db	0		;NZ => pktd initted (well, located anyway)
addf	db	0		;NZ => add a new addr
remf	db	0		;NZ => remove an old address
clrf	db	0		;NZ => clear entire list
;
	subttl	pure storage
;
handle	dw	1 dup(?)	;handle for our packet type
addra	db	6 dup(?)	;addr to add
addrr	db	6 dup(?)	;addr to remove
;
mcbuf	db	mcmax dup(?)	;buf for fooling with multicast list
lbuf	db	80d+2 dup(?)	;output line buffer
;
code	ends
	end	start
