/* File : SAP.C Service Advertising Protocol related functions are defined in this file. Only nearest server queries are considered. */ /* Copyright (C) 1992 Indian Institute of Technology, Bombay Written by V. Srinivas and Vishwas Joglekar, Dept of Computer Science and Engineering. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "yapcbr.h" #include "ipxwatch.h" #include "sap.h" extern struct sap_tbl *sap_lookup[MAX_PRIME]; extern struct rxstruct *rxptr; extern void *ibuf_alloc(int type); int hash_lookup(int hashret,SAP_INFO *server_info); void slist(); int proc_sap_pkt(SAP_PKT *sap_pkt,unsigned char *disp,int bcast,WORD src_sock,WORD dest_sock); /* search for the node address in the hashed list */ int hash_lookup(int hashret,SAP_INFO *server_info) { struct sap_tbl *hash_ptr,*new_addr,*tmp; hash_ptr = sap_lookup[hashret]; tmp=hash_ptr; #ifdef DBG1 printf("Searching Hash table, bucket %d\n",hashret); #endif while(hash_ptr != 0){ if(memcmp(&(hash_ptr->server_address),&(server_info->sap_node),sizeof(INTERNET_ADDRESS)) == 0){ #ifdef DBG1 printf("Address found in Hash table, dev no %d\n",hash_ptr->dev); #endif /* reset the timer */ hash_ptr->elapsed_time = FLUSH_TIME; return(FOUND); } tmp = hash_ptr; hash_ptr = hash_ptr->next; } /* address not in table, add */ new_addr = (struct sap_tbl *)ibuf_alloc(NOVLSAP); if(new_addr == 0) { printf("Malloc failed \n"); return(0); } /* check the validity of the sap packet, if the no of hops is more than 16 then discard the packet */ if((server_info->hops_to_server & 0x0f00) > 0x0f00) return(NOTFOUND); memcpy(&(new_addr->server_address),&(server_info->sap_node),sizeof(INTERNET_ADDRESS)); memcpy(new_addr->server_name,server_info->server_name,48); new_addr->hops_to_server = server_info->hops_to_server; new_addr->dev = rxptr->dev; /* NIC on which the pkt was received */ new_addr->elapsed_time = FLUSH_TIME; new_addr->server_type = getword(server_info->server_type); new_addr->next = 0; if(tmp == 0) /* is this bucket empty ? */ sap_lookup[hashret] = new_addr; else /* the bucket is not empty */ tmp->next = new_addr; #ifdef DBG1 printf("Address not in table, added pkt recvd on dev %d\n",rxptr->dev); printf("Server name %s \n", sap_lookup[hashret]->server_name); prnt_hex(sap_lookup[hashret]->server_address.net_id,ETHER_ADDR_LEN); #endif return(NOTFOUND); } /* list all the servers by looking at the server information table */ void slist() { int i,serv_count=0,crow=6,key; struct sap_tbl *sap_ptr; unsigned char buf[25]; make_win(4,5,75,19,1,"SERVER INFORMATION"); disp_mesg("ESC Close Window "); gotoxy(2,4); _setcursortype(_NOCURSOR); make_win( 5,6,74,18,1,"Known NetWare Servers Type Network Node Address Timer"); crow=1; for(i=0;i< MAX_PRIME;i++){ sap_ptr = sap_lookup[i]; while(sap_ptr!= 0){ gotoxy(2,crow); cprintf("%-22.22s ",sap_ptr->server_name); cprintf("%.4d ",sap_ptr->server_type); buf[0] = '\0'; prnt_hex(sap_ptr->server_address.net_id,buf,4); cputs(buf); buf[0] = '\0'; prnt_hex(sap_ptr->server_address.node_id,buf,6); cputs(buf); /* cprintf(" %.3d",sap_ptr->dev); */ cprintf(" %.4d",sap_ptr->elapsed_time); sap_ptr = sap_ptr->next; crow++; if(crow == 10){ crow=1; while(getch() != CR); } if(kbhit()){ key = getch(); if(key == ESC) return; }; serv_count++; } /* while */ } gotoxy(5,15); while(getch() !=ESC); } /* Determine the type of SAP packet */ int proc_sap_pkt(SAP_PKT *sap_pkt,unsigned char *disp,int bcast,WORD src_sock,WORD dest_sock) { WORD server_type,resp_type,len; int i,no_of_servers,hashret; resp_type = getword(sap_pkt->resp_type); /* get sap pkt type */ /* The stupid sap protocol or rather novell's sap determines the the type of sap packet by looking at the packet length and the response type field, t o o b a d . . . */ len = getword(sap_pkt->header.length); /* get length of IPX packet */ switch(resp_type){ case GET_NEAREST_SERVER: if((bcast == TRUE) && (len == 34) && (dest_sock == SERVADP_SOCK)) sprintf(disp,"Get Nearest Server "); break; case SERV_IDENT_PKT: if(src_sock == SERVADP_SOCK){ /* check whether the packet is a Server Identification Packet */ if(bcast == TRUE && dest_sock == SERVADP_SOCK){ no_of_servers = (len- sizeof(IPX_HEADER) - sizeof(WORD))/sizeof(SAP_INFO); if(no_of_servers > 7) return(0); /* Invalid SAP packet */ for(i=0;isap_data.server_info[i].sap_node,10); hash_lookup(hashret,&sap_pkt->sap_data.server_info[i]); } sprintf(disp,"Server Ident Pkt %10.10s/%2d",sap_pkt->sap_data.server_info[0].server_name, getword((BYTE *) &sap_pkt->sap_data.server_info[0].hops_to_server)); return(1); } else{ sprintf(disp,"Give Nearest Server %10.10s/%2d/%2d",sap_pkt->sap_data.server_info[0].server_name, getword((BYTE *)&sap_pkt->sap_data.server_info[0].hops_to_server)); } }/*else prnt_hex(&sap_pkt->sap_data,disp,8); */ break; case GIVE_NEAREST_SERVER: if(src_sock == SERVADP_SOCK) sprintf(disp,"Give Nearest Server %10.10s/%2d/%2d",sap_pkt->sap_data.server_info[0].server_name, getword((BYTE *)&sap_pkt->sap_data.server_info[0].hops_to_server)); /* else prnt_hex(&sap_pkt->sap_data,disp,8); */ break; default : /* unknown sap packet ? */ /* prnt_hex(&sap_pkt->sap_data,disp,8); */ break; } return(1); }