/*++ Copyright (c) 1992 Microsoft Corporation Module Name: supp.c Abstract: Support routines for the RIP test program Author: Sam Patton (sampa) 04-Oct-1993 Environment: User mode sockets app Revision History: dd-mmm-yyy --*/ #include #include #include #include #include "types.h" #include "proto.h" int trace = 0; void Usage( char * ExeName) { int SpaceAllocated; char * SpaceBuffer; char Space[2] = " "; unsigned int i; char * NameBuffer; if (trace) { printf("Usage entered\n"); } for (NameBuffer = ExeName+strlen(ExeName); ; NameBuffer --) { if (NameBuffer == ExeName) { break; } if (*NameBuffer == '\\') { NameBuffer ++; break; } } SpaceBuffer = (char *) malloc((strlen(NameBuffer) + 1) * sizeof(char)); if (SpaceBuffer) { SpaceAllocated = 1; for (i=0; i \n", SpaceBuffer); printf("%s \n", SpaceBuffer); printf("%s
\n", SpaceBuffer); printf("%s \n", SpaceBuffer); printf("%s ....\n", SpaceBuffer); printf("%s send -f \n", SpaceBuffer); printf("%s -f [commandfile] ...\n", NameBuffer); printf("%s receive [timeout]\n", NameBuffer); for (i=0; i of the form 11.1.15.76\n"); printf(" 1 for request\n"); printf(" 2 for response\n"); printf(" 3 for traceon\n"); printf(" 4 for traceoff\n"); printf(" 5 for reserved Sun command\n"); printf(" 1 for rfc 1058\n"); printf("
2 for ip\n"); printf(" integer 0-16\n"); printf(" 0\n"); printf(" [timeout] timeout in seconds to wait for RIP packet\n"); printf(" file containing arguments for the send command\n"); printf(" file containing commands of the above form\n"); if (SpaceAllocated) { free(SpaceBuffer); } } PRIP_ANNOUNCEMENT ReceiveRipAnnouncement( int argc, char * argv[]) /*++ Routine Description: This listens for a RIP announcement from a given router. Arguments: argc - number of command line arguments argv - array of command line arguments Return Value: Pointer to a RIP_ANNOUNCEMENT structure. NULL on failure. --*/ { BOOL ReceiveAny; struct sockaddr_in RemoteAddress; int ReuseFlag; struct sockaddr_in RipAddress; unsigned int RipAddressLength; PRIP_ANNOUNCEMENT RipAnnouncement; SOCKET RipSocket; unsigned char RipBuffer[RIP_BUFFER_SIZE]; int Status; if (trace) { printf("ReceiveRipAnnouncement entered\n"); } // // argv[2] should be the ip address of the machine that I want to receive // from. If there is no argv[2], receive any announcement. // if (argc < 2) { Usage(argv[0]); fprintf(stderr, "Incorrect number of arguments\n"); return NULL; } if (argc == 3) { ReceiveAny = FALSE; } else { ReceiveAny = TRUE; } if (!ReceiveAny) { RemoteAddress.sin_addr.S_un.S_addr = inet_addr(argv[2]); } // // Open the RIP socket. // Socket 520, UDP // if (trace) { printf("ReceiveRipAnnouncement - socket\n"); } RipSocket = socket( AF_INET, SOCK_DGRAM, 0); if (RipSocket == INVALID_SOCKET) { fprintf(stderr, "Error opening listening RIP socket\n"); return NULL; } // // Set the socket to be reusable // ReuseFlag = 1; Status = setsockopt( RipSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &ReuseFlag, sizeof(ReuseFlag)); if (Status) { fprintf(stderr, "Error setting RIP socket to be reusable\n"); closesocket(RipSocket); return NULL; } // // Bind to socket 520 // RipAddress.sin_family = AF_INET; RipAddress.sin_port = htons(520); RipAddress.sin_addr.s_addr = htonl(INADDR_ANY); if (trace) { printf("ReceiveRipAnnouncement - bind\n"); } Status = bind( RipSocket, (struct sockaddr *) &RipAddress, sizeof(RipAddress)); if (Status) { fprintf(stderr, "Error binding listening RIP socket\n"); closesocket(RipSocket); return NULL; } // // Get a RIP announcement // if (trace) { printf("ReceiveRipAnnouncement - recvfrom\n"); } do { RipAddressLength = sizeof(RipAddress); Status = recvfrom( RipSocket, RipBuffer, sizeof(RipBuffer), 0, (struct sockaddr *) &RipAddress, &RipAddressLength); } while ((!ReceiveAny) && RipAddress.sin_addr.S_un.S_addr != RemoteAddress.sin_addr.S_un.S_addr); if (trace) { printf("ReceiveRipAnnouncement - ParseRipAnnouncement\n"); } RipAnnouncement = ParseRipAnnouncement( RipBuffer, Status, &RipAddress, RipAddressLength); closesocket(RipSocket); return RipAnnouncement; } PRIP_ANNOUNCEMENT ParseRipAnnouncement( char * RipBuffer, int RipBufferLength, struct sockaddr_in * RemoteAddress, int RemoteAddressLength) /*++ Routine Description: This parses a given rip announcement into a RIP_ANNOUNCEMENT structure for further parsing. Arguments: RipBuffer - buffer containing the rip announcement RipBufferLength - length of the buffer. RemoteAddress - originating machine RemoteAddressLength - length of address. Return Value: A RIP_ANNOUNCEMENT pointer if successful. NULL if not. --*/ { PRIP_ANNOUNCEMENT RipAnnouncement; PRIP_ADDRESS_FIELD RipAddressField, AddressFieldPtr; char * CurrentPointer; if (trace) { printf("ParseRipAnnouncement entered\n"); } RipAnnouncement = (PRIP_ANNOUNCEMENT) malloc (sizeof(RIP_ANNOUNCEMENT)); if (RipAnnouncement == NULL) { return NULL; } // // Copy the first part of the RIP announcement into the structure. // memmove(RipAnnouncement, RipBuffer, 4); memmove(&RipAnnouncement->RemoteAddress,RemoteAddress, RemoteAddressLength); RipAnnouncement->Address = NULL; // // Copy the address fields into the structure // for (CurrentPointer = RipBuffer + 4; CurrentPointer < RipBuffer + RipBufferLength; CurrentPointer += 20) { RipAddressField = (PRIP_ADDRESS_FIELD) malloc (sizeof(RIP_ADDRESS_FIELD)); if (RipAddressField == NULL) { FreeRipAnnouncement(RipAnnouncement); return NULL; } memmove(RipAddressField, CurrentPointer, 20); RipAddressField->Next = NULL; if (RipAnnouncement->Address == NULL) { RipAnnouncement->Address = RipAddressField; } else { for (AddressFieldPtr = RipAnnouncement->Address; AddressFieldPtr->Next; AddressFieldPtr = AddressFieldPtr->Next); AddressFieldPtr->Next = RipAddressField; } } return RipAnnouncement; } void FreeRipAnnouncement( PRIP_ANNOUNCEMENT RipAnnouncement) /*++ Routine Description: This frees all of the structures associated with a RIP_ANNOUNCEMENT. Arguments: RipAnnouncement - announcement to be freed Return Value: None --*/ { PRIP_ADDRESS_FIELD AddressField1, AddressField2; if (trace) { printf("FreeRipAnnouncement entered\n"); } if (RipAnnouncement->Address) { if (RipAnnouncement->Address->Next) { AddressField1 = RipAnnouncement->Address; AddressField2 = RipAnnouncement->Address->Next; while (AddressField2->Next) { AddressField1 = AddressField2; AddressField2 = AddressField2->Next; } free(AddressField2); AddressField1->Next = NULL; FreeRipAnnouncement(RipAnnouncement); } else { free(RipAnnouncement->Address); } } free(RipAnnouncement); } void PrintRipAnnouncement( PRIP_ANNOUNCEMENT RipAnnouncement) /*++ Routine Description: This prints out a RIP announcement in human readable format. Arguments: RipAnnouncement - announcement to print. Return Value: None --*/ { PRIP_ADDRESS_FIELD AddressFieldPtr; struct in_addr InAddress; if (trace) { printf("PrintRipAnnouncement entered\n"); } // // Print out the first part // printf("Source - %s\n", inet_ntoa(RipAnnouncement->RemoteAddress.sin_addr)); printf("Port - %lu\n", (long) htons(RipAnnouncement->RemoteAddress.sin_port)); printf("Command - %x\n", (long) RipAnnouncement->Command); printf("Version - %x\n", (long) RipAnnouncement->Version); printf("Reserved - %x\n", (long) htons(RipAnnouncement->Reserved1)); printf("\n"); // // Print out the address part // for (AddressFieldPtr = RipAnnouncement->Address; AddressFieldPtr; AddressFieldPtr = AddressFieldPtr->Next) { printf("AddressFamily - %x\n", (long) htons(AddressFieldPtr->AddressFamily)); printf("Reserved - %x\n", (long) htons(AddressFieldPtr->Reserved1)); InAddress.S_un.S_addr = AddressFieldPtr->Address; printf("Address - %s\n", inet_ntoa(InAddress)); printf("Reserved - %x\n", (long) htonl(AddressFieldPtr->Reserved2)); printf("Reserved - %x\n", (long) htonl(AddressFieldPtr->Reserved3)); printf("Metric - %x\n", (long) htonl(AddressFieldPtr->Metric)); printf("\n"); } } void ProcessCommandFile( int argc, char * argv[]) /*++ Routine Description: This function processes a command file and does all of the requests in the command file. Arguments: argc - number of arguments argv - array of arguments Return Value: None --*/ { FILE * InputFile; char InputBuffer[256]; char * ArgPointer; int NumArgs; BOOL InArg; char ** ArgArray; if (argc == 2) { Usage(argv[0]); return; } argc -= 2; argv += 2; while (argc != 0) { // // Open input file // InputFile = fopen(*argv, "r"); if (InputFile == NULL) { printf("Error opening file %s\n", *argv); return; } // // Read the file and process the commands. Each line is a seperate // command. // while (fgets(InputBuffer, 256, InputFile) != NULL) { // // Count the arguments // NumArgs = 1; InArg = FALSE; for (ArgPointer = InputBuffer; *ArgPointer; ArgPointer ++) { if ((*ArgPointer == ' ') || (*ArgPointer == '\t') || (*ArgPointer == '\n')) { if (InArg) { NumArgs ++; InArg = FALSE; } } else { InArg = TRUE; } } if (NumArgs > 1) { // // Allocate the argument array // ArgArray = (char **) malloc (sizeof(char *) * NumArgs); if (ArgArray == NULL) { printf("Error processing file %s\n", *argv); return; } NumArgs = 1; InArg = FALSE; for (ArgPointer = InputBuffer; *ArgPointer; ArgPointer ++) { if ((*ArgPointer == ' ') || (*ArgPointer == '\t') || (*ArgPointer == '\n')) { if (InArg) { NumArgs ++; InArg = FALSE; *ArgPointer = '\0'; } } else { if (!InArg) { InArg = TRUE; ArgArray[NumArgs] = ArgPointer; } } } ArgArray[0] = "Script RIP_TEST"; main(NumArgs, ArgArray); } } fclose(InputFile); argc --; argv ++; } } PRIP_ANNOUNCEMENT CreateRipAnnouncementFromCommandLine( int argc, char * argv[]) /*++ Routine Description: This function creates a RIP announcement from the given arguments. The arguments are of two possible forms - see usage above for the formats. Arguments: argc - number of arguments argv - array of arguments Return Value: A rip announcement on success. NULL on failure --*/ { PRIP_ADDRESS_FIELD AddressFieldPtr; char ArgBuffer[80]; char * ExeName = argv[0]; FILE * InputFile; PRIP_ADDRESS_FIELD RipAddressField; PRIP_ANNOUNCEMENT RipAnnouncement; int Status; if (trace) { printf("CreateRipAnnouncementFromCommandLine entered\n"); } if (argc < 4) { Usage(argv[0]); return NULL; } argc -= 1; argv += 1; RipAnnouncement = (PRIP_ANNOUNCEMENT) malloc (sizeof(RIP_ANNOUNCEMENT)); if (RipAnnouncement == NULL) { return NULL; } RipAnnouncement->RemoteAddress.sin_family = AF_INET; RipAnnouncement->RemoteAddress.sin_port = htons(520); RipAnnouncement->Address = NULL; if (strncmp(argv[1], "-f", 2) != 0) { // // Case 1 - all of the arguments are on the command line // // // First argument - ip address // argc --; argv ++; if (trace) { printf("%d ip address %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); return NULL; } RipAnnouncement->RemoteAddress.sin_addr.S_un.S_addr = inet_addr(*argv); // // Second argument - source port // argc --; argv ++; if (trace) { printf("%d source port %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); return NULL; } RipAnnouncement->LocalAddress.sin_family = AF_INET; RipAnnouncement->LocalAddress.sin_port = htons((WORD) atoi(*argv)); RipAnnouncement->LocalAddress.sin_addr.s_addr = htonl(INADDR_ANY); // // Third argument - command // argc --; argv ++; if (trace) { printf("%d command %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); return NULL; } RipAnnouncement->Command = atoi(*argv); // // Fourth argument - version // argc --; argv ++; if (trace) { printf("%d version %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); return NULL; } RipAnnouncement->Version = atoi(*argv); // // Fifth argument - reserved1 // argc --; argv ++; if (trace) { printf("%d reserved1 %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); return NULL; } RipAnnouncement->Reserved1 = htons((WORD) atoi(*argv)); // // The rest of the arguments are addresses to be filled in // while (argc > 1) { RipAddressField = (PRIP_ADDRESS_FIELD) malloc (sizeof(RIP_ADDRESS_FIELD)); if (RipAddressField == NULL) { FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->Next = NULL; if (RipAnnouncement->Address == NULL) { RipAnnouncement->Address = RipAddressField; } else { for (AddressFieldPtr = RipAnnouncement->Address; AddressFieldPtr->Next; AddressFieldPtr = AddressFieldPtr->Next); AddressFieldPtr->Next = RipAddressField; } // // Address Family // argc --; argv ++; if (trace) { printf("%d Address Family %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->AddressFamily = htons((WORD) atoi(*argv)); // // Reserved1 // argc --; argv ++; if (trace) { printf("%d Reserved1 %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->Reserved1 = htons((WORD) atoi(*argv)); // // Address // argc --; argv ++; if (trace) { printf("%d Address %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->Address = inet_addr(*argv); // // Reserved2 // argc --; argv ++; if (trace) { printf("%d Reserved2 %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->Reserved2 = htonl(atoi(*argv)); // // Reserved3 // argc --; argv ++; if (trace) { printf("%d Reserved3 %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->Reserved3 = htonl(atoi(*argv)); // // Metric // argc --; argv ++; if (trace) { printf("%d Metric %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->Metric = htonl(atoi(*argv)); } } else { // // Case 2 - the arguments are in a file // // // File name // argc --; argc --; argv ++; argv ++; if (trace) { printf("%d File name %s\n", argc, *argv); } if (argc == 0) { Usage(ExeName); return NULL; } InputFile = fopen(*argv, "r"); if (InputFile == NULL) { printf("Error opening file %s\n", *argv); FreeRipAnnouncement(RipAnnouncement); return NULL; } // // First argument - ip address // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("ip address %s\n", ArgBuffer); } RipAnnouncement->RemoteAddress.sin_addr.S_un.S_addr = inet_addr(ArgBuffer); // // Second argument - source port // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("source port %s\n", ArgBuffer); } RipAnnouncement->LocalAddress.sin_family = AF_INET; RipAnnouncement->LocalAddress.sin_port = htons((WORD) atoi(ArgBuffer)); RipAnnouncement->LocalAddress.sin_addr.s_addr = htonl(INADDR_ANY); // // Third argument - command // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("command %s\n", ArgBuffer); } RipAnnouncement->Command = atoi(ArgBuffer); // // Fourth argument - version // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("version %s\n", ArgBuffer); } RipAnnouncement->Version = atoi(ArgBuffer); // // Fifth argument - reserved1 // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("reserved1 %s\n", ArgBuffer); } RipAnnouncement->Reserved1 = htons((WORD) atoi(ArgBuffer)); // // The rest of the arguments are addresses to be filled in // while (1) { RipAddressField = (PRIP_ADDRESS_FIELD) malloc (sizeof(RIP_ADDRESS_FIELD)); if (RipAddressField == NULL) { FreeRipAnnouncement(RipAnnouncement); return NULL; } RipAddressField->Next = NULL; if (RipAnnouncement->Address == NULL) { RipAnnouncement->Address = RipAddressField; } else { for (AddressFieldPtr = RipAnnouncement->Address; AddressFieldPtr->Next; AddressFieldPtr = AddressFieldPtr->Next); AddressFieldPtr->Next = RipAddressField; } // // Address Family // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { // // End of file // break; } if (trace) { printf("Address Family %s\n", ArgBuffer); } RipAddressField->AddressFamily = htons((WORD) atoi(ArgBuffer)); // // Reserved1 // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("Reserved1 %s\n", ArgBuffer); } RipAddressField->Reserved1 = htons((WORD) atoi(ArgBuffer)); // // Address // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("Address %s\n", ArgBuffer); } RipAddressField->Address = inet_addr(ArgBuffer); // // Reserved2 // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("Reserved2 %s\n", ArgBuffer); } RipAddressField->Reserved2 = htonl(atoi(ArgBuffer)); // // Reserved3 // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("Reserved3 %s\n", ArgBuffer); } RipAddressField->Reserved3 = htonl(atoi(ArgBuffer)); // // Metric // Status = fscanf(InputFile, "%s", ArgBuffer); if (Status != 1) { Usage(ExeName); FreeRipAnnouncement(RipAnnouncement); return NULL; } if (trace) { printf("Metric %s\n", ArgBuffer); } RipAddressField->Metric = htonl(atoi(ArgBuffer)); } } return RipAnnouncement; } BOOL SendRipAnnouncement( PRIP_ANNOUNCEMENT RipAnnouncement) /*++ Routine Description: This function sends a RIP announcement with the given arguments. Arguments: RipAnnouncement - announcment to send. Return Value: TRUE on success FALSE on failure --*/ { char * CurrentPointer; int ReuseFlag; PRIP_ADDRESS_FIELD RipAddressField; unsigned char RipBuffer[RIP_BUFFER_SIZE]; SOCKET RipSocket; int Status; if (trace) { printf("SendRipAnnouncement entered\n"); } CurrentPointer = (char *) RipBuffer; memmove(CurrentPointer, RipAnnouncement, 4); CurrentPointer += 4; RipAddressField = RipAnnouncement->Address; while (RipAddressField) { memmove(CurrentPointer, RipAddressField, 20); CurrentPointer += 20; RipAddressField = RipAddressField->Next; } // // Open the local socket. // RipSocket = socket( AF_INET, SOCK_DGRAM, 0); if (RipSocket == INVALID_SOCKET) { fprintf(stderr, "Error opening source RIP socket\n"); return FALSE; } // // Set the socket to be reusable // ReuseFlag = 1; Status = setsockopt( RipSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &ReuseFlag, sizeof(ReuseFlag)); if (Status) { fprintf(stderr, "Error setting RIP socket to be reusable\n"); closesocket(RipSocket); return FALSE; } // // Bind to socket // Status = bind( RipSocket, (struct sockaddr *) &RipAnnouncement->LocalAddress, sizeof(RipAnnouncement->LocalAddress)); if (Status) { fprintf(stderr, "Error binding source RIP socket\n"); closesocket(RipSocket); return FALSE; } Status = sendto( RipSocket, RipBuffer, CurrentPointer-RipBuffer, 0, (struct sockaddr *) &RipAnnouncement->RemoteAddress, sizeof(RipAnnouncement->RemoteAddress)); closesocket(RipSocket); if (trace) { printf("sendto returned %d\n", Status); printf("GetLastError %lx\n", GetLastError()); } if (Status == (CurrentPointer-RipBuffer)) { return TRUE; } else { return FALSE; } }