Использование драйвера IPX/SPX в сети Novell Netware

Модератор: push0ret

Ответить
Аватара пользователя
push0ret
Набирающий обороты
Сообщения: 32
Зарегистрирован: Вс дек 29, 2024 2:48 pm
Благодарил (а): 22 раза
Поблагодарили: 26 раз

Использование драйвера IPX/SPX в сети Novell Netware

Сообщение push0ret »

Hello World!

Ранее я уже рассказал про структуру протокола IPX. Пора начать использовать драйвер IPX/SPX из набора программного обеспечения "NetWare C-Interface for DOS". В этой теме опишу функции драйвера IPX/SPX, а также расскажу как его использовать при помощи языка ассемблера. Их названия набора программного обеспечения можно понять, что данный драйвер подразумевает то, что будет использоваться с помощью языка С, я же буду использовать язык ассемблера.

Инициализация драйвера в программе

Для начала работы с функциями драйвера IPX/SPX необходимо получить адрес резидентной программы, которую загружает в память драйвер. Для этого используем мультиплексное прерывание 2Fh с параметром в регистре AX = 7A00h. Если после выполнения прерывания регистр AL будет равен 0FFh, то драйвер IPX загружен и с ним можно работать, адрес точки входа (дальний адрес резидентной программы) будет записан в регистрах ES:DI, его необходимо сохранить для последующего использования. Процедура инициализации драйвера IPX:

Код: Выделить всё

.286
.model	tiny
code	segment
org	100h

init_ipx:

mov ax, 7A00h
int 2Fh

cmp al, 0FFh
jnz exit

mov ipx_entry, di
mov ipx_entry+2, es

exit:

mov ax, 4C00h
int 21h

ipx_entry	dw	2d dup(0)

code	ends
end	init_ipx
Теперь мы знаем в какой области памяти находится процедура драйвера IPX/SPX и можем использовать функции драйвера.

Структура для работы с драйвером IPX/SPX

Взаимодействие программы с драйвером происходит с помощью структуры ECB (Event control block). Структура имеет следующий вид:
ecb.PNG
ecb.PNG (18.67 КБ) 173 просмотра
При использовании языка С, структуру можно объявить таким образом:

Код: Выделить всё

struct ECB {
                void far        *Link;
                void far        (*ESRAddress)(void);
                unsigned char   InUse;
                unsigned char   CCode;
                unsigned int    Socket;
                unsigned int    ConnectionId;
                unsigned int    RrestOfWorkspace;
                unsigned char   DriverWorkspace[12];
                unsigned char   ImmAddress[6];
                unsigned int    FragmentCnt;
                struct {
                        void far        *Address;
                        unsigned int Size;
                } Packet[2];
};
При использовании языка ассемблера, структуру можно объявить так:

Код: Выделить всё

ECB	struc

Link		dw	2d dup(0)
ESRAddress	dw	2d dup(0)
InUse		db	?
CCode		db	?
Socket		dw	?
IPXWorkspace	db	4d dup(0)
DrvWorkspace	db	12d dup(0)
ImmAdress	db	6d dup(0)
FragmentCnt	dw	?
Address		dw	2d dup(0)
Size_		dw	?

ECB		ends
Перед тем как вызвать функцию IPX, программа записывает в поле InUse нулевое значение. Пока операция приёма или передачи данных, связанная с данным ECB, не завершилась, поле InUse содержит ненулевые значения:

FFh ECB используется для передачи пакета данных;
FEh ECB используется для приема пакета данных, предназначенного программе с определенным сокетом;
FDh ECB используется функциями асинхронного управления событиями AES (Asynchronous Event Sheduler), ECB
находится в состоянии ожидания истечения заданного временного интервала;
FBh пакет данных принят или передан, но ECB находится во внутренней очереди IPX в ожидании завершения обработки.

Если блок ECB использовался для приема пакета, то в поле CCode могут находиться следующие значения:

00 пакет был принят без ошибок;
FFh указанный в ECB сокет не был предварительно открыт программой;
FDh переполнение пакета: либо поле количества фрагментов в пакете FragmentCnt равно нулю, либо буферы, описанные дескрипторами фрагментов, имеют недостаточный размер для записи принятого пакета;
FCh запрос на прием данного пакета был отменен специальной функцией драйвера IPX.

Если ECB использовался для передачи пакета, в поле CCode после завершения передачи могут находиться следующие значения:

00 пакет был передан без ошибок (что, кстати, не означает, что пакет был доставлен по назначению и успешно принят станцией-адресатом, так как протокол IPX не обеспечивает гарантированной доставки пакетов);
FFh пакет невозможно передать физически из-за неисправности в сетевом адаптере или в сети;
FEh пакет невозможно доставить по назначению, так как станция с указанным адресом не существует или неисправна;
FDh сбойный: либо имеет длину меньше 30 байт, либо первый фрагмент пакета по размеру меньше размера стандартного заголовка пакета IPX, либо поле количества фрагментов в пакете FragmentCnt равно нулю;
FCh запрос на передачу данного пакета был отменен специальной функцией драйвера IPX.

Также необходимо объявлять в программе структуру пакета, т.к. её адрес и размер указываются в полях Adress и Size структуры ECB, структура пакета IPX была показана здесь: viewtopic.php?t=366

Описание функций драйвера IPX/SPX

IPXOpenSocket

Параметры:

BX = 0
AL = тип сокета (0 - короткоживущий, 0FFh - долгоживущий)
DX = запрашиваемый номер сокета или 0, если хотим получить динамический номер сокета

Возвращаемые значения:

AL = результат работы функции (0 - сокет открыт, 0FFh - сокет уже был открыт раньше, 0FEh - таблица сокетов переполнена)
DX = присвоенный номер сокета

Данная процедура открывает сокет, желательно номер открытого сокета записать куда-либо.

IPXCloseSocket

Параметры:

BX = 1d
DX = номер закрываемого сокета

Не сложно догадаться для чего нужна эта функция, для того, чтобы закрыть ранее открытый сокет.

IPXListenForPacket

Параметры:

BX = 4d
ES:SI = адрес заполненного блока ECB

В блоке ECB необходимо заполнить поля:

ESRAddress;
Socket;
FragmentCnt;
Address;
Size.

После прихода пакета в поле CCode использованного блока ECB драйвер IPX записывает код результата приема пакета, а в поле ImmAddress - адрес станции, которая прислала пакет. Если пакет пришел из другой сети, в этом поле будет записан адрес моста.

IPXSendPacket

Параметры:

BX = 3d
ES:SI = адрес заполненного блока ECB

В блоке ECB необходимо заполнить поля:

ESRAddress;
Socket;
ImmAddress;
FragmentCnt;
Address;
Size.

Также необходимо заполнить структуру пакета IPX, а конкретно поля:

PacketType;
DestNetwork;
DestNode;
DestSocket.

Сразу после вызова функции IPXSendPacket в поле InUse записывается значение FFh. После завершения процесса передачи пакета в поле InUse записывается значение 00h. Результат выполнения передачи пакета можно узнать, если из поля CCode.

Пример использования функции драйвера IPX/SPX:

Код: Выделить всё

.model	tiny
code	segment
org	100h

start

;Init IPX

pusha

mov ax, 7A00h
int 2Fh

cmp al, 0FFh
jnz exit

;Write adress of resident program

mov ipx_entry, di
mov ipx_entry+2, es

popa

;Open socket

pusha

xor bx, bx
mov dx, 4001h
xor ax, ax
call dword ptr [ipx_entry]

popa

exit:

mov ax, 4C00h
int 21h

ipx_entry	dw	2d dup(0)

code	ends
end	start
Привёл в пример использование функции открытия сокета, я описал все функции, которыми пользовался сам, на самом деле функций больше, можно посмотреть в документации "NetWare C-Interface for DOS".

Была использована версия компилятора MASM 6.11 в контексте операционной системы MS-DOS 6.22, а также набор программ от Novell Netware Client.

Спасибо за внимание!
С уважением, push0ret!

Код: Выделить всё

push 0
ret
Аватара пользователя
push0ret
Набирающий обороты
Сообщения: 32
Зарегистрирован: Вс дек 29, 2024 2:48 pm
Благодарил (а): 22 раза
Поблагодарили: 26 раз

Re: Использование драйвера IPX/SPX в сети Novell Netware

Сообщение push0ret »

Простая система клиент-сервер, использующая протокол IPX и драйверы Novell Netware C-interface.

Клиент:

Код: Выделить всё

.model  tiny
.286
code    segment
org	100h

start:

;Check IPX

pusha

mov ax, 7A00h
int 2Fh

cmp al, 0FFh
jnz exit_err_ipx

mov word ptr [ipx_entry], di
mov word ptr [ipx_entry+2], es

;Check SPX

mov bx, 10h
xor ax, ax
call dword ptr [ipx_entry]

cmp ax, 0FFh
jnz exit_err_spx

popa

;Open socket

pusha

xor bx, bx
mov al, 0FFh
mov dx, 4444h
call dword ptr [ipx_entry]

mov ecbtx.socket, dx
mov ecbrx.socket, dx
mov ipxtx.destsocket, dx

popa

;IPXSendPacket

push cs
pop es

pusha

mov bx, 3d
;mov ax, mysocket
;mov ecbtx.socket, ax
mov ecbtx.fragmentcnt, 2d
mov ipxtx.packettype, 4d
mov ax, offset ipxtx
mov ecbtx.address1, ax
mov ecbtx.address1+2, es
mov ax, offset txbuf
mov ecbtx.address2, ax
mov ecbtx.address2+2, ax 
mov si, offset ecbtx.link
xor ax, ax
call dword ptr [ipx_entry]

popa

wait_tx:

cmp ecbtx.immaddress-7, 0FFh
jnz done_tx

pusha

mov bx, 0Ah
call dword ptr [ipx_entry]

popa

jmp wait_tx

done_tx:

cmp ecbtx.ccode, 0

mov ah, 9d
mov dx, offset donetx
int 21h

;IPXListenForPacket

pusha

push cs
pop es

mov bx, 4d
mov ecbrx.fragmentcnt, 2d
mov ax, offset ipxrx
mov ecbrx.address1, ax
mov ecbrx.address1+2, es
mov ax, offset rxbuf
mov ecbrx.address2, ax
mov ecbrx.address2+2, es
xor ax, ax
mov si, offset ecbrx.link
call dword ptr [ipx_entry]

popa

wait_rx:

cmp ecbrx.inuse, 0FEh
jnz done_rx

pusha

mov bx, 0Ah
call dword ptr [ipx_entry]

popa

jmp wait_rx

done_rx:

mov ah, 9d
mov dx, offset donerx
int 21h

jmp exit

exit_err_spx:

mov ah, 9d
mov dx, offset err_spx
int 21h
jmp exit

exit_err_ipx:

mov ah, 9d
mov dx, offset err_ipx
int 21h

exit:

push 100h
pop sp

mov ax, 4C00h
int 21h

err_ipx         db      'IPX NOT LOADED', 0Ah, 0Dh, 24h
err_spx         db      'SPX NOT LOADED', 0Ah, 0Dh, 24h
donetx          db      'Packet Send!', 0Ah, 0Dh, 24h
donerx          db      'Packet Received!', 0Ah, 0Dh, 24h

rxbuf           db      512d dup(0)
txbuf           db      'Client Demo', 500d dup(0)

mysocket        dw      ?

ipx_entry       dw      2d dup(0)

IPXtx_          struc

Checksum        dw      ?
Len             dw      ?
TransportCtrl   db      ?
PacketType      db      4d
DestNetwork     db      4d dup(0)
DestNode        db      6d dup(0FFh)
DestSocket      dw      ?
SourceNetwork   db      4d dup(0)
SourceNode      db      6d dup(0)
SourceSocket    dw      ?

IPXtx_         ends

ECBtx_          struc

Link            dw      2d dup(0)
ESRAddress      dw      2d dup(0)
InUse           db      ?
CCode           db      ?
Socket          dw      ?
IPXWorkspace    db      4d dup(0)
DRVWorkspace    db      12d dup(0)
ImmAddress      db      6d dup(0FFh)
FragmentCnt     dw      ?
Address1        dw      2d dup(0)
Size_1          dw      sizeof ipxtx
Address2        dw      2d dup(0)
Size_2          dw      sizeof txbuf

ECBtx_          ends

IPXrx_          struc

Checksum        dw      ?
Len             dw      ?
TransportCtrl   db      ?
PacketType      db      ?
DestNetwork     db      4d dup(0)
DestNode        db      6d dup(0)
DestSocket      dw      ?
SourceNetwork   db      4d dup(0)
SourceNode      db      6d dup(0)
SourceSocket    dw      ?

IPXrx_          ends

ECBrx_          struc

Link            dw      2d dup(0)
ESRAddress      dw      2d dup(0)
InUse           db      ?
CCode           db      ?
Socket          dw      ?
IPXWorkspace    db      4d dup(0)
DRVWorkspace    db      12d dup(0)
ImmAddress      db      6d dup(0)
FragmentCnt     dw      ?
Address1        dw      2d dup(0)
Size_1          dw      sizeof ipxrx
Address2        dw      2d dup(0)
Size_2          dw      sizeof rxbuf

ECBrx_          ends

ecbtx           ECBtx_  <>
ipxtx           IPXtx_  <>
ecbrx           ECBrx_  <>
ipxrx           IPXrx_  <>

code	ends
end     start
Сервер:

Код: Выделить всё

.model  tiny
.286
code    segment
org     100h

start:

;Check IPX

pusha

mov ax, 7A00h
int 2Fh

cmp al, 0FFh
jnz exit_err_ipx

mov word ptr [ipx_entry], di
mov word ptr [ipx_entry+2], es

;Check SPX

mov bx, 10h
xor ax, ax
call dword ptr [ipx_entry]

cmp ax, 0FFh
jnz exit_err_spx

popa

;Open socket

pusha

xor bx, bx
mov al, 0FFh
mov dx, 4444h
call dword ptr [ipx_entry]

mov ecbrx.socket, dx
mov ecbtx.socket, dx
mov ipxtx.destsocket, dx

popa

;IPXListenForPacket

pusha

push cs
pop es

mov bx, 4d
mov ecbrx.fragmentcnt, 2d
mov ax, offset ipxrx
mov ecbrx.address1, ax
mov ecbrx.address1+2, es
mov ax, offset rxbuf
mov ecbrx.address2, ax
mov ecbrx.address2+2, es
xor ax, ax
mov si, offset ecbrx.link
call dword ptr [ipx_entry]

popa

wait_rx:

cmp ecbrx.inuse, 0FEh
jnz done_rx

pusha

mov bx, 0Ah
call dword ptr [ipx_entry]

popa

jmp wait_rx

done_rx:

mov ah, 9d
mov dx, offset donerx
int 21h

;Write ImmAdress

push cx
push si
push di

mov si, offset ecbrx.immaddress
mov di, offset ecbtx.immaddress

cld
mov cx, 6d
rep movsb

pop di
pop si
pop cx

;IPXSendPacket

push cs
pop es

pusha

mov bx, 3d
;mov ax, mysocket
;mov ecbtx.socket, ax
mov ecbtx.fragmentcnt, 2d
mov ipxtx.packettype, 4d
mov ax, offset ipxtx
mov ecbtx.address1, ax
mov ecbtx.address1+2, es
mov ax, offset txbuf
mov ecbtx.address2, ax
mov ecbtx.address2+2, ax 
mov si, offset ecbtx.link
xor ax, ax
call dword ptr [ipx_entry]

popa

wait_tx:

cmp ecbtx.immaddress-7, 0FFh
jnz done_tx

pusha

mov bx, 0Ah
call dword ptr [ipx_entry]

popa

jmp wait_tx

done_tx:

cmp ecbtx.ccode, 0

mov ah, 9d
mov dx, offset donetx
int 21h


jmp exit

exit_err_spx:

mov ah, 9d
mov dx, offset err_spx
int 21h
jmp exit

exit_err_ipx:

mov ah, 9d
mov dx, offset err_ipx
int 21h

exit:

push 100h
pop sp

mov ax, 4C00h
int 21h

err_ipx         db      'IPX NOT LOADED', 0Ah, 0Dh, 24h
err_spx         db      'SPX NOT LOADED', 0Ah, 0Dh, 24h
donetx          db      'Packet Send!', 0Ah, 0Dh, 24h
donerx          db      'Packet Received!', 0Ah, 0Dh, 24h

rxbuf           db      512d dup(0)
txbuf           db      'Client Demo', 500d dup(0)

mysocket        dw      ?

ipx_entry       dw      2d dup(0)

IPXtx_          struc

Checksum        dw      ?
Len             dw      ?
TransportCtrl   db      ?
PacketType      db      4d
DestNetwork     db      4d dup(0)
DestNode        db      6d dup(0FFh)
DestSocket      dw      ?
SourceNetwork   db      4d dup(0)
SourceNode      db      6d dup(0)
SourceSocket    dw      ?

IPXtx_         ends

ECBtx_          struc

Link            dw      2d dup(0)
ESRAddress      dw      2d dup(0)
InUse           db      ?
CCode           db      ?
Socket          dw      ?
IPXWorkspace    db      4d dup(0)
DRVWorkspace    db      12d dup(0)
ImmAddress      db      6d dup(0FFh)
FragmentCnt     dw      ?
Address1        dw      2d dup(0)
Size_1          dw      sizeof ipxtx
Address2        dw      2d dup(0)
Size_2          dw      sizeof txbuf

ECBtx_          ends

IPXrx_          struc

Checksum        dw      ?
Len             dw      ?
TransportCtrl   db      ?
PacketType      db      ?
DestNetwork     db      4d dup(0)
DestNode        db      6d dup(0)
DestSocket      dw      ?
SourceNetwork   db      4d dup(0)
SourceNode      db      6d dup(0)
SourceSocket    dw      ?

IPXrx_          ends

ECBrx_          struc

Link            dw      2d dup(0)
ESRAddress      dw      2d dup(0)
InUse           db      ?
CCode           db      ?
Socket          dw      ?
IPXWorkspace    db      4d dup(0)
DRVWorkspace    db      12d dup(0)
ImmAddress      db      6d dup(0)
FragmentCnt     dw      ?
Address1        dw      2d dup(0)
Size_1          dw      sizeof ipxrx
Address2        dw      2d dup(0)
Size_2          dw      sizeof rxbuf

ECBrx_          ends

ecbtx           ECBtx_  <>
ipxtx           IPXtx_  <>
ecbrx           ECBrx_  <>
ipxrx           IPXrx_  <>

code    ends
end     start

Код: Выделить всё

push 0
ret
Ответить

Вернуться в «Системное программирование»