1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
/*
* $Source$
* $Author$
*
* Copyright 1990 by the Massachusetts Institute of Technology.
*
* For copying and distribution information, please see the file
* <krb5/copyright.h>.
*
* Network code for Kerberos v5 KDC.
*/
#if !defined(lint) && !defined(SABER)
static char rcsid_network_c[] =
"$Id$";
#endif /* !lint & !SABER */
#include <krb5/copyright.h>
#include <krb5/osconf.h>
#include <krb5/krb5.h>
#include <krb5/ext-proto.h>
#include <stdio.h>
#include <krb5/libos-proto.h>
#include <errno.h>
#include <com_err.h>
#include <krb5/kdb.h>
#include "kdc_util.h"
#include "extern.h"
#include "kdc5_err.h"
#ifdef KRB5_USE_INET
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
extern char *krb5_kdc_udp_portname;
extern int errno;
static int udp_port_fd = -1;
krb5_error_code
setup_network(prog)
const char *prog;
{
struct servent *sp;
struct sockaddr_in sin;
krb5_error_code retval;
sp = getservbyname(krb5_kdc_udp_portname, "udp");
if (!sp) {
com_err(prog, 0, "%s/udp service unknown\n",
krb5_kdc_udp_portname);
return KDC5_NOPORT;
}
if ((udp_port_fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
retval = errno;
com_err(prog, 0, "Cannot create server socket");
return retval;
}
bzero((char *)&sin, sizeof(sin));
sin.sin_port = sp->s_port;
if (bind(udp_port_fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
retval = errno;
com_err(prog, 0, "Cannot bind server socket");
return retval;
}
return 0;
}
krb5_error_code
listen_and_process(prog)
const char *prog;
{
int cc, saddr_len;
krb5_error_code retval;
struct sockaddr_in saddr;
krb5_fulladdr faddr;
krb5_address addr;
krb5_data request;
krb5_data *response;
char pktbuf[MAX_DGRAM_SIZE];
if (udp_port_fd == -1)
return KDC5_NONET;
while (!signal_requests_exit) {
saddr_len = sizeof(saddr);
if ((cc = recvfrom(udp_port_fd, pktbuf, sizeof(pktbuf), 0,
(struct sockaddr *)&saddr, &saddr_len)) != -1) {
if (!cc)
continue; /* zero-length packet? */
request.length = cc;
request.data = pktbuf;
faddr.port = ntohs(saddr.sin_port);
faddr.address = &addr;
addr.addrtype = ADDRTYPE_INET;
addr.length = 4;
addr.contents = (krb5_octet *) &saddr.sin_addr; /* XXX net order or host order? */
if (retval = dispatch(&request, &faddr, &response)) {
com_err(prog, retval, "while dispatching");
continue;
}
if ((cc = sendto(udp_port_fd, response->data, response->length, 0,
(struct sockaddr *)&saddr, saddr_len)) != response->length) {
switch (cc) {
case -1:
com_err(prog, errno, "while sending reply to %s/%d",
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
break;
default:
com_err(prog, 0, "short reply write %d vs %d\n",
response->length, cc);
break;
}
}
krb5_free_data(response);
} else {
switch (errno) {
case EINTR:
continue;
default:
com_err(prog, errno, "while receiving from network");
break;
}
}
}
return 0;
}
krb5_error_code
closedown_network(prog)
const char *prog;
{
if (udp_port_fd == -1)
return KDC5_NONET;
(void) close(udp_port_fd);
udp_port_fd = -1;
return 0;
}
#endif /* INET */
|