/* RxRPC test server * * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * 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 * 2 of the License, or (at your option) any later version. */ #define _XOPEN_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include // drive with: // vos listvldb -encrypt // or: #define DO_BULK // openafs-1.4.2/src/rx/bulk.example/bulk_client -store /usr/share/doc/emacs-common-21.4/NEWS 172.16.18.111 /tmp/a #define OSERROR(X, Y) do { if ((long)(X) == -1) { perror(Y); exit(1); } } while(0) struct sockaddr_rxrpc { sa_family_t srx_family; /* address family */ unsigned short srx_service; /* service desired */ unsigned short transport_type; /* type of transport socket (SOCK_DGRAM) */ unsigned short transport_len; /* length of transport address */ union { sa_family_t family; /* transport address family */ struct sockaddr_in sin; /* IPv4 transport address */ struct sockaddr_in6 sin6; /* IPv6 transport address */ } transport; }; #define AF_RXRPC 33 #define PF_RXRPC AF_RXRPC #define SOL_RXRPC 272 #define RXRPC_USER_CALL_ID 1 /* User call ID specifier */ #define RXRPC_ABORT 2 /* Abort request / notification */ #define RXRPC_ACK 3 /* [Server] RPC op final ACK received */ #define RXRPC_RESPONSE 4 /* [Server] security response received */ #define RXRPC_NET_ERROR 5 /* network error received */ #define RXRPC_BUSY 6 /* server busy received */ #define RXRPC_LOCAL_ERROR 7 /* local error generated */ #define RXRPC_NEW_CALL 8 /* [Server] new incoming call notification */ #define RXRPC_ACCEPT 9 /* [Server] accept request */ #define RXRPC_SECURITY_KEY 1 /* [clnt] set client security key */ #define RXRPC_SECURITY_KEYRING 2 /* [srvr] set ring of server security keys */ #define RXRPC_EXCLUSIVE_CONNECTION 3 /* [clnt] use exclusive RxRPC connection */ #define RXRPC_MIN_SECURITY_LEVEL 4 /* minimum security level */ #define OSERROR(X, Y) do { if ((long)(X) == -1) { perror(Y); exit(1); } } while(0) static const unsigned char local_addr[4] = { 0, 0, 0, 0 }; #define RXRPC_ADD_CALLID(control, ctrllen, id) \ do { \ struct cmsghdr *__cmsg; \ __cmsg = (void *)(control) + (ctrllen); \ __cmsg->cmsg_len = CMSG_LEN(sizeof(unsigned long)); \ __cmsg->cmsg_level = SOL_RXRPC; \ __cmsg->cmsg_type = RXRPC_USER_CALL_ID; \ *(unsigned long *)CMSG_DATA(__cmsg) = (id); \ (ctrllen) += __cmsg->cmsg_len; \ } while (0) #define RXRPC_ADD_ABORT(control, ctrllen, abort_code) \ do { \ struct cmsghdr *__cmsg; \ __cmsg = (void *)(control) + (ctrllen); \ __cmsg->cmsg_len = CMSG_LEN(sizeof(unsigned long)); \ __cmsg->cmsg_level = SOL_RXRPC; \ __cmsg->cmsg_type = RXRPC_ABORT; \ *(unsigned long *)CMSG_DATA(__cmsg) = (abort_code); \ (ctrllen) += __cmsg->cmsg_len; \ } while (0) #define RXRPC_ADD_ACCEPT(control, ctrllen) \ do { \ struct cmsghdr *__cmsg; \ __cmsg = (void *)(control) + (ctrllen); \ __cmsg->cmsg_len = CMSG_LEN(0); \ __cmsg->cmsg_level = SOL_RXRPC; \ __cmsg->cmsg_type = RXRPC_ACCEPT; \ (ctrllen) += __cmsg->cmsg_len; \ } while (0) int server; /*****************************************************************************/ /* * send a reply to an operation */ static void send_reply(unsigned long user_id) { unsigned char control[4096]; struct msghdr msg; size_t ctrllen; int ret; ctrllen = 0; RXRPC_ADD_CALLID(control, ctrllen, user_id); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = NULL; msg.msg_iovlen = 0; msg.msg_control = control; msg.msg_controllen = ctrllen; msg.msg_flags = 0; ret = sendmsg(server, &msg, 0); OSERROR(ret, "sendmsg/reply"); } /*****************************************************************************/ /* * assign a call ID to a new incoming call */ static void assign_call_ID(void) { unsigned char control[4096]; struct msghdr msg; size_t ctrllen; int ret; static unsigned long call_ID = 0x10101; ctrllen = 0; RXRPC_ADD_ACCEPT(control, ctrllen); RXRPC_ADD_CALLID(control, ctrllen, call_ID++); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = NULL; msg.msg_iovlen = 0; msg.msg_control = control; msg.msg_controllen = ctrllen; msg.msg_flags = 0; ret = sendmsg(server, &msg, 0); OSERROR(ret, "sendmsg/accept"); } /*****************************************************************************/ /* * dump the control messages */ static void dump_cmsg(struct msghdr *msg) { struct cmsghdr *cmsg; unsigned long user_id; unsigned char *p; int abort_code; int n, assign = 0, nondata = 0; for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { n = cmsg->cmsg_len - CMSG_ALIGN(sizeof(*cmsg)); p = CMSG_DATA(cmsg); printf("CMSG: %zu: ", cmsg->cmsg_len); if (cmsg->cmsg_level == SOL_RXRPC) { switch (cmsg->cmsg_type) { case RXRPC_USER_CALL_ID: printf("RXRPC_USER_CALL_ID: "); if (n != sizeof(user_id)) goto dump_data; memcpy(&user_id, p, sizeof(user_id)); printf("%lx\n", user_id); continue; case RXRPC_ABORT: nondata = 1; printf("RXRPC_ABORT: "); if (n != sizeof(abort_code)) goto dump_data; memcpy(&abort_code, p, sizeof(abort_code)); printf("%d\n", abort_code); continue; case RXRPC_ACK: nondata = 1; printf("RXRPC_ACK"); if (n != 0) goto dump_data_colon; goto print_nl; case RXRPC_RESPONSE: nondata = 1; printf("RXRPC_RESPONSE"); if (n != 0) goto dump_data_colon; goto print_nl; case RXRPC_NET_ERROR: nondata = 1; printf("RXRPC_NET_ERROR: "); if (n != sizeof(abort_code)) goto dump_data; memcpy(&abort_code, p, sizeof(abort_code)); printf("%s\n", strerror(abort_code)); continue; case RXRPC_BUSY: nondata = 1; printf("RXRPC_BUSY"); if (n != 0) goto dump_data_colon; goto print_nl; case RXRPC_LOCAL_ERROR: nondata = 1; printf("RXRPC_LOCAL_ERROR: "); if (n != sizeof(abort_code)) goto dump_data; memcpy(&abort_code, p, sizeof(abort_code)); printf("%s\n", strerror(abort_code)); continue; case RXRPC_NEW_CALL: nondata = 1; printf("RXRPC_NEW_CALL\n"); assign = 1; continue; default: break; } } printf("l=%d t=%d", cmsg->cmsg_level, cmsg->cmsg_type); dump_data_colon: printf(": "); dump_data: printf("{"); for (; n > 0; n--, p++) printf("%02x", *p); printf("}"); print_nl: printf("\n"); } if (assign) assign_call_ID(); if (!nondata && !(msg->msg_flags & MSG_MORE)) send_reply(user_id); } void dump_data(void *p, size_t len) { #define INT_PER_LINE (8 * 4) size_t loop; unsigned char buf[41], *b, ch, yoffs; yoffs = 0; b = buf; for (loop = 0; loop < len; loop++) { if (!yoffs) { printf("%08zx: ", loop); yoffs = 1; } ch = *(const char *) p; printf("%02x", ch); *b++ = isprint(ch) ? ch : '.'; p++; if (loop % INT_PER_LINE == INT_PER_LINE - 1) { *b = 0; printf(" %s\n", buf); b = buf; yoffs = 0; } else if (loop % 4 == 3) { putchar(' '); } } if (loop % INT_PER_LINE > 0) { for (loop %= INT_PER_LINE; loop < INT_PER_LINE; loop++) { printf(" "); if (loop % 4 == 3) putchar(' '); } *b = 0; printf("%s\n", buf); } } /*****************************************************************************/ /* * */ int main(int argc, char *argv[]) { struct sockaddr_rxrpc srx; unsigned char buffer[4096], control[4096]; struct msghdr msg; struct iovec iov[3]; int ret, loop, keyring, key; /* make the server fall over randomly occasionally */ signal(SIGALRM, SIG_DFL); //alarm(5); server = socket(AF_RXRPC, SOCK_DGRAM, PF_INET); OSERROR(server, "socket"); keyring = add_key("keyring", "AFSkeys", NULL, 0, KEY_SPEC_PROCESS_KEYRING); OSERROR(keyring, "add_key/ring"); const char secret[8] = { 0xa7, 0x83, 0x8a, 0xcb, 0xc7, 0x83, 0xec, 0x94 }; key = add_key("rxrpc_s", "52:2", secret, 8, keyring); OSERROR(key, "add_key"); ret = setsockopt(server, SOL_RXRPC, RXRPC_SECURITY_KEYRING, "AFSkeys", 7); OSERROR(ret, "set keyring"); /* bind an address to the local endpoint */ srx.srx_family = AF_RXRPC; #ifndef DO_BULK srx.srx_service = 52; /* AFS VL service */ #else srx.srx_service = 4; /* BULK service */ #endif srx.transport_type = SOCK_DGRAM; srx.transport_len = sizeof(srx.transport.sin); srx.transport.sin.sin_family = AF_INET; #ifndef DO_BULK srx.transport.sin.sin_port = htons(7003); /* VL server */ #else srx.transport.sin.sin_port = htons(34835); /* BULK server */ #endif memcpy(&srx.transport.sin.sin_addr, &local_addr, 4); ret = bind(server, (struct sockaddr *) &srx, sizeof(srx)); OSERROR(ret, "bind"); //system("netstat -ua"); /* wait for calls to come in */ ret = listen(server, 4); OSERROR(ret, "listen"); /* wait for calls to come in */ for (;;) { iov[0].iov_base = buffer; iov[0].iov_len = sizeof(buffer); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = control; msg.msg_controllen = sizeof(control); msg.msg_flags = 0; ret = recvmsg(server, &msg, 0); OSERROR(ret, "recvmsg"); printf("RECV: %d [fl:%d]\n", ret, msg.msg_flags); printf("CMSG: %zu\n", msg.msg_controllen); printf("IOV: %zu [0]=%zu\n", msg.msg_iovlen, iov[0].iov_len); dump_cmsg(&msg); #if 1 for (loop = 0; loop < ret; loop++) { printf("%02x", buffer[loop]); if (loop % 40 == 39) putchar('\n'); else if (loop % 4 == 3) putchar(' '); } putchar('\n'); #endif } }