3 * Copyright (c) 1994 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
28 * This program is intended to run on afs DB servers.
29 * Its function is to forward KA requests to a fakeka server
30 * running on an MIT kerberos server.
33 #include <afsconfig.h>
34 #include <afs/param.h>
44 int getopt (int, char * const *, const char *);
49 #define BUFFER_SIZE 2048
54 int num_servers, cur_server;
55 struct sockaddr_in *servers;
67 setup_servers(int argc, char **argv)
75 servers = malloc(sizeof(*servers) * num_servers);
77 perrorexit("malloc failed");
79 for (i = 0; i < num_servers; i++) {
82 fwdport = htons(7004);
85 port = strchr(host, '/');
89 if (isdigit(port[0])) {
90 fwdport = htons(atoi(port));
93 struct servent *srv = getservbyname(port, "udp");
95 fprintf(stderr, "%s: unknown service %s\n", prog, port);
98 fwdport = srv->s_port;
102 if (isdigit(host[0])) {
103 fwdaddr = inet_addr(host);
106 struct hostent *h = gethostbyname(host);
108 fprintf(stderr, "%s: unknown host %s\n", prog, host);
111 bcopy(h->h_addr, &fwdaddr, 4);
114 servers[i].sin_family = AF_INET;
115 servers[i].sin_addr.s_addr = fwdaddr;
116 servers[i].sin_port = fwdport;
122 setup_socket(u_short port)
125 struct sockaddr_in sin;
127 s = socket(AF_INET, SOCK_DGRAM, 0);
129 perrorexit("Couldn't create socket");
131 sin.sin_family = AF_INET;
132 sin.sin_addr.s_addr = 0;
133 sin.sin_port = htons(port);
135 rv = bind(s, (struct sockaddr *)&sin, sizeof(sin));
137 perrorexit("Couldn't bind socket");
144 packet_is_reply(struct sockaddr_in *from)
148 for (i = 0; i < num_servers; i++) {
149 struct sockaddr_in *sin = &servers[i];
151 if (from->sin_addr.s_addr == sin->sin_addr.s_addr &&
152 from->sin_port == sin->sin_port)
163 main(int argc, char **argv)
170 "usage: %s [-p port] <host>[/port] [host/port ...]\n",
178 while ((c = getopt(argc, argv, "p:")) != -1) {
184 fprintf(stderr, "%s: invalid option '%c'\n", prog, c);
190 * hmm, different implementations of getopt seem to do different things
191 * when there aren't any options. linux sets optind = 1, which I would
192 * call correct, but sunos sets optind = 0. try to do the right thing.
197 setup_servers(argc - optind, argv + optind);
198 s = setup_socket(port);
200 openlog("ka-forwarder", LOG_PID, LOG_DAEMON);
203 char buf[BUFFER_SIZE], *bufp, *sendptr;
204 struct sockaddr_in from, reply, *to;
209 fromlen = sizeof(from);
211 rv = recvfrom(s, bufp, sizeof(buf) - 8,
212 0, (struct sockaddr *)&from, &fromlen);
214 syslog(LOG_ERR, "recvfrom: %m");
219 if (packet_is_reply(&from)) {
220 /* this is a reply, forward back to user */
223 reply.sin_family = AF_INET;
224 bcopy(bufp, &reply.sin_addr.s_addr, 4);
225 bcopy(bufp + 4, &reply.sin_port, 2);
230 /* this is a request, forward to server */
232 cur_server = (cur_server + 1) % num_servers;
233 to = &servers[cur_server];
235 bcopy(&from.sin_addr.s_addr, bufp - 8, 4);
236 bcopy(&from.sin_port, bufp - 4, 2);
244 strcpy(a1, inet_ntoa(from.sin_addr));
245 strcpy(a2, inet_ntoa(to->sin_addr));
247 syslog(LOG_INFO, "forwarding %"AFS_SIZET_FMT" bytes from %s/%d to %s/%d\n",
248 sendlen, a1, htons(from.sin_port), a2, htons(to->sin_port));
251 rv = sendto(s, sendptr, sendlen,
252 0, (struct sockaddr *)to, sizeof(*to));
254 syslog(LOG_ERR, "sendto: %m");