K2.6 patches and update.
[tomato.git] / release / src-rt / wl / nas / nas_wksp_radius.c
blobf8a88324a03e9f1baace6f569254c3af0ca85a31
1 /*
2 * Radius support for NAS workspace
3 * Copyright (C) 2010, Broadcom Corporation
4 * All Rights Reserved.
5 *
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 $
13 #include <typedefs.h>
14 #include <assert.h>
15 #include <unistd.h>
16 #include <proto/eap.h>
17 #include <errno.h>
19 #include "nas.h"
20 #include "nas_wksp.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 */
35 int
36 nas_radius_open(nas_wksp_t *nwksp, nas_wpa_cb_t *nwcb)
38 nas_t *nas = &nwcb->nas;
39 int n, i;
42 * Prevent a descriptor leak in case the connection was broken by
43 * the server and some one tries to re-establish the connection
44 * with the server.
46 if (nas->wan != NAS_WKSP_UNK_FILE_DESC) {
47 NASDBG("%s: close radius socket %d\n", nas->interface, nas->wan);
48 close(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);
55 goto exit0;
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,
65 nas->wan);
66 nas_sleep_ms(NAS_WKSP_RADIUS_SLEEP*1000);
67 continue;
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);
72 return 0;
75 /* It should never come to here - error! */
76 close(nas->wan);
77 exit0:
78 NASDBG("%s: failed to open radius socket\n", nas->interface);
79 nas->wan = NAS_WKSP_UNK_FILE_DESC;
80 return errno;
83 /* close the connection to radius server */
84 void
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);
90 close(nas->wan);
91 nas->wan = NAS_WKSP_UNK_FILE_DESC;
95 /* establish connection to radius server for each interface */
96 int
97 nas_wksp_open_radius(nas_wksp_t *nwksp)
99 nas_wpa_cb_t *nwcb;
100 int i;
102 for (i = 0; i < nwksp->nwcbs; i ++) {
103 nwcb = nwksp->nwcb[i];
104 assert(nwcb);
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);
111 return 0;
114 /* close connection to radius server for each interface */
115 void
116 nas_wksp_close_radius(nas_wksp_t *nwksp)
118 nas_wpa_cb_t *nwcb;
119 int i;
121 for (i = 0; i < nwksp->nwcbs; i ++) {
122 nwcb = nwksp->nwcb[i];
123 assert(nwcb);
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)
134 int ret;
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,
144 nas->wan);
145 ret = send(nas->wan, (char *)radius, length, 0);
146 if (ret < 0)
147 NASDBG("%s: resend error %d to radius socket %d\n",
148 nas->interface, errno, nas->wan);
152 return ret;
155 #endif /* #ifdef NAS_WKSP_BUILD_NAS_AUTH */