Ранее я уже рассказал про структуру протокола 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
Взаимодействие программы с драйвером происходит с помощью структуры ECB (Event control block). Структура имеет следующий вид:
При использовании языка С, структуру можно объявить таким образом:
Код: Выделить всё
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
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:DI = адрес заполненного блока ECB
В блоке ECB необходимо заполнить поля:
ESRAddress;
Socket;
FragmentCnt;
Address;
Size.
После прихода пакета в поле CCode использованного блока ECB драйвер IPX записывает код результата приема пакета, а в поле ImmAddress - адрес станции, которая прислала пакет. Если пакет пришел из другой сети, в этом поле будет записан адрес моста.
IPXSendPacket
Параметры:
BX = 3d
ES:DI = адрес заполненного блока 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
Была использована версия компилятора MASM 6.11 в контексте операционной системы MS-DOS 6.22, а также набор программ от Novell Netware Client.
Спасибо за внимание!
С уважением, push0ret!