2 * Radius support for NAS workspace
3 * Copyright (C) 2010, Broadcom Corporation
6 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
7 * the contents of this file may not be disclosed to third parties, copied
8 * or duplicated in any form, in whole or in part, without the prior
9 * written permission of Broadcom Corporation.
10 * $Id: nas_wksp_radius.c 241388 2011-02-18 03:33:22Z stakita $
16 #include <proto/eap.h>
21 #include "nas_radius.h"
22 #include "nas_wksp_radius.h"
24 #ifdef NAS_WKSP_BUILD_NAS_AUTH
26 * Common NAS communication routines that can be used under different
27 * OSs. These functions need to be re-implemented only when the socket
28 * layer interface provided for the specific operating system is not
29 * the similiar kind to that in this implementation.
31 #define NAS_WKSP_RADIUS_TRIES 5
32 #define NAS_WKSP_RADIUS_SLEEP 5 /* in seconds */
34 /* establish connection to radius server */
36 nas_radius_open(nas_wksp_t
*nwksp
, nas_wpa_cb_t
*nwcb
)
38 nas_t
*nas
= &nwcb
->nas
;
42 * Prevent a descriptor leak in case the connection was broken by
43 * the server and some one tries to re-establish the connection
46 if (nas
->wan
!= NAS_WKSP_UNK_FILE_DESC
) {
47 NASDBG("%s: close radius socket %d\n", nas
->interface
, nas
->wan
);
49 nas
->wan
= NAS_WKSP_UNK_FILE_DESC
;
52 /* Connect to server */
53 if ((nas
->wan
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
54 NASDBG("%s: Unable to create radius socket\n", nas
->interface
);
58 /* Give the RADIUS server a little time in case it's on
59 * the WAN. It could be opened on demand later, but it's
60 * good to get an open descriptor now if possible.
62 for (i
= 0; i
< NAS_WKSP_RADIUS_TRIES
; i
++) {
63 if (connect(nas
->wan
, (struct sockaddr
*)&nas
->server
, sizeof(nas
->server
)) < 0) {
64 NASDBG("%s: Unable to connect radius socket %d\n", nas
->interface
,
66 nas_sleep_ms(NAS_WKSP_RADIUS_SLEEP
*1000);
69 n
= sizeof(nas
->client
);
70 getsockname(nas
->wan
, (struct sockaddr
*)&nas
->client
, (socklen_t
*)&n
);
71 NASDBG("%s: opened radius socket %d\n", nas
->interface
, nas
->wan
);
75 /* It should never come to here - error! */
78 NASDBG("%s: failed to open radius socket\n", nas
->interface
);
79 nas
->wan
= NAS_WKSP_UNK_FILE_DESC
;
83 /* close the connection to radius server */
85 nas_radius_close(nas_wksp_t
*nwksp
, nas_wpa_cb_t
*nwcb
)
87 nas_t
*nas
= &nwcb
->nas
;
88 if (nas
->wan
!= NAS_WKSP_UNK_FILE_DESC
) {
89 NASDBG("%s: close radius socket %d\n", nas
->interface
, nas
->wan
);
91 nas
->wan
= NAS_WKSP_UNK_FILE_DESC
;
95 /* establish connection to radius server for each interface */
97 nas_wksp_open_radius(nas_wksp_t
*nwksp
)
102 for (i
= 0; i
< nwksp
->nwcbs
; i
++) {
103 nwcb
= nwksp
->nwcb
[i
];
105 /* open connection to radius server */
106 if (CHECK_RADIUS(nwcb
->nas
.mode
)) {
107 /* open connection to radius server */
108 nas_radius_open(nwksp
, nwcb
);
114 /* close connection to radius server for each interface */
116 nas_wksp_close_radius(nas_wksp_t
*nwksp
)
121 for (i
= 0; i
< nwksp
->nwcbs
; i
++) {
122 nwcb
= nwksp
->nwcb
[i
];
124 if (CHECK_RADIUS(nwcb
->nas
.mode
)) {
125 nas_radius_close(nwksp
, nwcb
);
130 /* send radius packet to radius server */
132 nas_radius_send_packet(nas_t
*nas
, radius_header_t
*radius
, int length
)
135 nas_wpa_cb_t
*nwcb
= (nas_wpa_cb_t
*)nas
->appl
;
136 NASDBG("%s: sending packet to radius socket %d\n", nas
->interface
, nas
->wan
);
137 if ((ret
= send(nas
->wan
, (char *)radius
, length
, 0)) < 0) {
138 NASDBG("%s: send error %d to radius socket %d\n", nas
->interface
, errno
, nas
->wan
);
139 /* Try re-opening it once before giving up. */
140 /* This could happen if the peer has been reset */
141 if (errno
== EBADF
) {
142 if (!nas_radius_open(nwcb
->nwksp
, nwcb
)) {
143 NASDBG("%s: resending packet to radius socket %d\n", nas
->interface
,
145 ret
= send(nas
->wan
, (char *)radius
, length
, 0);
147 NASDBG("%s: resend error %d to radius socket %d\n",
148 nas
->interface
, errno
, nas
->wan
);
155 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */