/* * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Oliver Tappe, zooey@hirschkaefer.de * Axel Dörfler, axeld@pinc-software.de */ #include #include #include #include #include #include #include #include extern const char* __progname; static const size_t kBufferSize = 1500; static const uint32 kFrameType = 0x8998; static const char* kProgramName = __progname; static void parse_mac_address(const char* string, uint8* mac) { if (sscanf(string, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) < 6) { fprintf(stderr, "%s: Invalid MAC address.\n", kProgramName); exit(EXIT_FAILURE); } } static void link_client(int fd, const BNetworkAddress& server) { char buffer[kBufferSize]; while (fgets(buffer, kBufferSize, stdin) != NULL) { size_t length = strlen(buffer); if (length > 0) length--; if (sendto(fd, buffer, length, 0, server, server.Length()) < 0) { fprintf(stderr, "%s: sendto(): %s\n", kProgramName, strerror(errno)); exit(EXIT_FAILURE); } printf("sent %" B_PRIuSIZE " bytes...\n", length); ssize_t bytesRead = recvfrom(fd, buffer, kBufferSize - 1, 0, NULL, NULL); if (bytesRead < 0) { fprintf(stderr, "%s: recvfrom(): %s\n", kProgramName, strerror(errno)); exit(EXIT_FAILURE); } buffer[bytesRead] = 0; printf("-> %s\n", buffer); } } static void link_server(int fd) { while (true) { BNetworkAddress client; socklen_t length = sizeof(client); char buffer[kBufferSize]; ssize_t bytesRead = recvfrom(fd, buffer, kBufferSize - 1, 0, client, &length); if (bytesRead < 0) { fprintf(stderr, "%s: recvfrom(): %s\n", kProgramName, strerror(errno)); exit(EXIT_FAILURE); } buffer[bytesRead] = '\0'; printf("got <%s> from client %s\n", buffer, client.ToString().String()); for (int i = 0; i < bytesRead; i++) { if (islower(buffer[i])) buffer[i] = toupper(buffer[i]); else if (isupper(buffer[i])) buffer[i] = tolower(buffer[i]); } printf("replying <%s>\n", buffer); if (sendto(fd, buffer, bytesRead, 0, client, client.Length()) < 0) { fprintf(stderr, "%s: sendto(): %s\n", kProgramName, strerror(errno)); exit(EXIT_FAILURE); } } } int main(int argc, char** argv) { enum { CLIENT_MODE, SERVER_MODE, BROADCAST_MODE, } mode = CLIENT_MODE; if (argc < 3) { fprintf(stderr, "usage: %s client \n" "or %s broadcast\n" "or %s server\n", kProgramName, kProgramName, kProgramName); exit(EXIT_FAILURE); } BNetworkInterface interface(argv[1]); BNetworkAddress link; if (interface.GetHardwareAddress(link) != B_OK) perror("get hardware address"); BNetworkAddress server; if (!strcmp(argv[2], "client")) { mode = CLIENT_MODE; if (argc < 4) { fprintf(stderr, "usage: %s client \n", kProgramName); exit(EXIT_FAILURE); } uint8 macAddress[6]; parse_mac_address(argv[3], macAddress); server.SetToLinkLevel(macAddress, sizeof(macAddress)); } else if (!strcmp(argv[2], "broadcast")) { mode = BROADCAST_MODE; uint8 broadcastAddress[6]; for (size_t i = 0; i < sizeof(broadcastAddress); i++) broadcastAddress[i] = 0xff; server.SetToLinkLevel(broadcastAddress, sizeof(broadcastAddress)); } else if (!strcmp(argv[2], "server")) mode = SERVER_MODE; int fd = socket(AF_LINK, SOCK_DGRAM, 0); if (fd < 0) perror("socket"); // bind to protocol link.SetLinkLevelFrameType(kFrameType); server.SetLinkLevelFrameType(kFrameType); if (bind(fd, link, link.Length()) != 0) perror("bind"); socklen_t length = sizeof(link); if (getsockname(fd, link, &length) != 0) perror("getsockname"); printf("bound to %s\n", link.ToString().String()); if (mode == BROADCAST_MODE) { int option = 1; setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)); } switch (mode) { case CLIENT_MODE: case BROADCAST_MODE: link_client(fd, server); break; case SERVER_MODE: link_server(fd); break; } return 0; }