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>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/ioctl.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
54 int getopt (int, char * const *, const char *);
59 #define BUFFER_SIZE 2048
64 int num_servers
, cur_server
;
65 struct sockaddr_in
*servers
;
77 setup_servers(int argc
, char **argv
)
85 servers
= malloc(sizeof(*servers
) * num_servers
);
87 perrorexit("malloc failed");
89 for (i
= 0; i
< num_servers
; i
++) {
92 fwdport
= htons(7004);
95 port
= strchr(host
, '/');
99 if (isdigit(port
[0])) {
100 fwdport
= htons(atoi(port
));
103 struct servent
*srv
= getservbyname(port
, "udp");
105 fprintf(stderr
, "%s: unknown service %s\n", prog
, port
);
108 fwdport
= srv
->s_port
;
112 if (isdigit(host
[0])) {
113 fwdaddr
= inet_addr(host
);
116 struct hostent
*h
= gethostbyname(host
);
118 fprintf(stderr
, "%s: unknown host %s\n", prog
, host
);
121 bcopy(h
->h_addr
, &fwdaddr
, 4);
124 servers
[i
].sin_family
= AF_INET
;
125 servers
[i
].sin_addr
.s_addr
= fwdaddr
;
126 servers
[i
].sin_port
= fwdport
;
132 setup_socket(u_short port
)
135 struct sockaddr_in sin
;
137 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
139 perrorexit("Couldn't create socket");
141 sin
.sin_family
= AF_INET
;
142 sin
.sin_addr
.s_addr
= 0;
143 sin
.sin_port
= htons(port
);
145 rv
= bind(s
, (struct sockaddr
*)&sin
, sizeof(sin
));
147 perrorexit("Couldn't bind socket");
154 packet_is_reply(struct sockaddr_in
*from
)
158 for (i
= 0; i
< num_servers
; i
++) {
159 struct sockaddr_in
*sin
= &servers
[i
];
161 if (from
->sin_addr
.s_addr
== sin
->sin_addr
.s_addr
&&
162 from
->sin_port
== sin
->sin_port
)
173 main(int argc
, char **argv
)
180 "usage: %s [-p port] <host>[/port] [host/port ...]\n",
188 while ((c
= getopt(argc
, argv
, "p:")) != -1) {
194 fprintf(stderr
, "%s: invalid option '%c'\n", prog
, c
);
200 * hmm, different implementations of getopt seem to do different things
201 * when there aren't any options. linux sets optind = 1, which I would
202 * call correct, but sunos sets optind = 0. try to do the right thing.
207 setup_servers(argc
- optind
, argv
+ optind
);
208 s
= setup_socket(port
);
210 openlog("ka-forwarder", LOG_PID
, LOG_DAEMON
);
213 char buf
[BUFFER_SIZE
], *bufp
, *sendptr
;
214 struct sockaddr_in from
, reply
, *to
;
219 fromlen
= sizeof(from
);
221 rv
= recvfrom(s
, bufp
, sizeof(buf
) - 8,
222 0, (struct sockaddr
*)&from
, &fromlen
);
224 syslog(LOG_ERR
, "recvfrom: %m");
229 if (packet_is_reply(&from
)) {
230 /* this is a reply, forward back to user */
233 reply
.sin_family
= AF_INET
;
234 bcopy(bufp
, &reply
.sin_addr
.s_addr
, 4);
235 bcopy(bufp
+ 4, &reply
.sin_port
, 2);
240 /* this is a request, forward to server */
242 cur_server
= (cur_server
+ 1) % num_servers
;
243 to
= &servers
[cur_server
];
245 bcopy(&from
.sin_addr
.s_addr
, bufp
- 8, 4);
246 bcopy(&from
.sin_port
, bufp
- 4, 2);
254 strcpy(a1
, inet_ntoa(from
.sin_addr
));
255 strcpy(a2
, inet_ntoa(to
->sin_addr
));
257 syslog(LOG_INFO
, "forwarding %"AFS_SIZET_FMT
" bytes from %s/%d to %s/%d\n",
258 sendlen
, a1
, htons(from
.sin_port
), a2
, htons(to
->sin_port
));
261 rv
= sendto(s
, sendptr
, sendlen
,
262 0, (struct sockaddr
*)to
, sizeof(*to
));
264 syslog(LOG_ERR
, "sendto: %m");