1 /* netio.c network I/O functions
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 shishi_sendrecv_udp (Shishi
* handle
,
26 struct sockaddr
*addr
,
27 const char *indata
, int inlen
,
28 char *outdata
, int *outlen
, int timeout
)
31 struct sockaddr_in
*lsa_inp
= (struct sockaddr_in
*) &lsa
;
34 struct sockaddr_storage from_sa
;
35 int length
= sizeof (struct sockaddr_storage
);
40 memset (&lsa
, 0, sizeof (lsa
));
41 lsa_inp
->sin_family
= AF_INET
;
42 lsa_inp
->sin_addr
.s_addr
= htonl (INADDR_ANY
);
44 sockfd
= socket (AF_INET
, SOCK_DGRAM
, 0);
47 shishi_error_set (handle
, strerror (errno
));
48 return SHISHI_SOCKET_ERROR
;
51 if (bind (sockfd
, (struct sockaddr
*) &lsa
, sizeof (lsa
)) != 0)
53 shishi_error_set (handle
, strerror (errno
));
55 return SHISHI_BIND_ERROR
;
58 bytes_sent
= sendto (sockfd
, (const void *) indata
, inlen
,
59 0, addr
, sizeof (*addr
));
60 if (bytes_sent
!= inlen
)
62 shishi_error_set (handle
, strerror (errno
));
63 return SHISHI_SENDTO_ERROR
;
67 FD_SET (sockfd
, &readfds
);
68 tout
.tv_sec
= timeout
;
70 if ((rc
= select (sockfd
+ 1, &readfds
, NULL
, NULL
, &tout
)) != 1)
73 shishi_error_set (handle
, strerror (errno
));
75 shishi_error_clear (handle
);
76 return SHISHI_KDC_TIMEOUT
;
79 *outlen
= recvfrom (sockfd
, outdata
, *outlen
, 0,
80 (struct sockaddr
*) &from_sa
, &length
);
84 shishi_error_set (handle
, strerror (errno
));
85 return SHISHI_RECVFROM_ERROR
;
88 if (close (sockfd
) != 0)
90 shishi_error_set (handle
, strerror (errno
));
91 return SHISHI_CLOSE_ERROR
;
98 shishi_kdc_sendrecv_static (Shishi
* handle
, char *realm
,
99 const char *indata
, size_t inlen
,
100 char *outdata
, size_t * outlen
)
105 for (i
= 0; i
< handle
->nrealminfos
; i
++)
106 if (realm
&& strcmp (handle
->realminfos
[i
].name
, realm
) == 0)
108 for (j
= 0; j
< handle
->kdcretries
; j
++)
109 for (k
= 0; k
< handle
->realminfos
[i
].nkdcaddresses
; k
++)
111 struct Shishi_kdcinfo
*ki
=
112 &handle
->realminfos
[i
].kdcaddresses
[k
];
114 if (VERBOSE (handle
))
116 printf ("Sending to %s (%s)...\n", ki
->name
,
117 inet_ntoa (((struct sockaddr_in
*)
118 &ki
->sockaddress
)->sin_addr
));
121 rc
= shishi_sendrecv_udp (handle
, &ki
->sockaddress
,
122 indata
, inlen
, outdata
, outlen
,
124 if (rc
!= SHISHI_KDC_TIMEOUT
)
128 shishi_error_clear (handle
);
129 return SHISHI_KDC_TIMEOUT
;
132 shishi_error_printf (handle
, "No KDC defined for realm %s", realm
);
133 return SHISHI_KDC_NOT_KNOWN_FOR_REALM
;
137 shishi_kdc_sendrecv_srv_1 (Shishi
* handle
, char *realm
,
138 const char *indata
, size_t inlen
,
139 char *outdata
, size_t * outlen
,
144 for (; rrs
; rrs
= rrs
->next
)
146 dns_srv_t srv
= (dns_srv_t
) rrs
->rr
;
147 struct addrinfo hints
;
151 if (rrs
->class != C_IN
)
153 if (rrs
->type
!= T_SRV
)
156 if (VERBOSE (handle
))
157 printf ("Located SRV RRs server %s:%d...\n", srv
->name
, srv
->port
);
159 memset (&hints
, 0, sizeof(hints
));
160 hints
.ai_socktype
= SOCK_DGRAM
;
161 asprintf (&port
, "%d", srv
->port
);
162 rc
= getaddrinfo (srv
->name
, port
, &hints
, &ai
);
167 shishi_warn (handle
, "Unknown KDC host `%s' (gai rc %d)",
173 if (VERBOSE (handle
))
174 printf ("Sending to %s:%d (%s)...\n", srv
->name
, srv
->port
,
175 inet_ntoa (((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
));
177 rc
= shishi_sendrecv_udp (handle
, ai
->ai_addr
,
178 indata
, inlen
, outdata
, outlen
,
183 if (rc
!= SHISHI_KDC_TIMEOUT
)
187 return SHISHI_KDC_TIMEOUT
;
191 shishi_kdc_sendrecv_srv (Shishi
* handle
, char *realm
,
192 const char *indata
, size_t inlen
,
193 char *outdata
, size_t * outlen
)
199 if (VERBOSE (handle
))
200 printf ("Finding SRV RRs for %s...\n", realm
);
202 asprintf (&tmp
, "_kerberos._udp.%s", realm
);
203 rrs
= _shishi_resolv(tmp
, T_SRV
);
207 rc
= shishi_kdc_sendrecv_srv_1 (handle
, realm
, indata
, inlen
,
208 outdata
, outlen
, rrs
);
211 shishi_error_printf (handle
, "No KDC SRV RRs for realm %s", realm
);
212 rc
= SHISHI_KDC_NOT_KNOWN_FOR_REALM
;
215 _shishi_resolv_free (rrs
);
221 shishi_kdc_sendrecv_direct (Shishi
* handle
, char *realm
,
222 const char *indata
, size_t inlen
,
223 char *outdata
, size_t * outlen
)
226 struct addrinfo hints
;
231 if (VERBOSE (handle
))
232 printf ("Trying direct realm host mapping for %s...\n", realm
);
234 se
= getservbyname ("kerberos", NULL
);
236 asprintf (&port
, "%d", ntohs(se
->s_port
));
238 asprintf (&port
, "%d", 88);
240 memset (&hints
, 0, sizeof(hints
));
241 hints
.ai_socktype
= SOCK_DGRAM
;
242 rc
= getaddrinfo (realm
, port
, &hints
, &ai
);
248 shishi_error_printf (handle
, "No direct realm host for realm %s", realm
);
249 return SHISHI_KDC_NOT_KNOWN_FOR_REALM
;
252 if (VERBOSE (handle
))
253 printf ("Sending to %s:%s (%s)...\n", realm
, port
,
254 inet_ntoa (((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
));
256 rc
= shishi_sendrecv_udp (handle
, ai
->ai_addr
,
257 indata
, inlen
, outdata
, outlen
,
266 shishi_kdc_sendrecv (Shishi
* handle
, char *realm
,
267 const char *indata
, size_t inlen
,
268 char *outdata
, size_t * outlen
)
272 rc
= shishi_kdc_sendrecv_static (handle
, realm
,
273 indata
, inlen
, outdata
, outlen
);
275 if (rc
== SHISHI_KDC_TIMEOUT
|| rc
== SHISHI_KDC_NOT_KNOWN_FOR_REALM
)
276 rc
= shishi_kdc_sendrecv_srv (handle
, realm
,
277 indata
, inlen
, outdata
, outlen
);
278 if (rc
== SHISHI_KDC_TIMEOUT
|| rc
== SHISHI_KDC_NOT_KNOWN_FOR_REALM
)
279 rc
= shishi_kdc_sendrecv_direct (handle
, realm
,
280 indata
, inlen
, outdata
, outlen
);