1 |
/* This file is part of GNU RADIUS. |
/* This file is part of GNU Radius. |
2 |
Copyright (C) 2000,2001 Sergey Poznyakoff |
Copyright (C) 2000,2001,2002,2003 Sergey Poznyakoff |
3 |
|
|
4 |
This program is free software; you can redistribute it and/or modify |
GNU Radius is free software; you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
7 |
(at your option) any later version. |
(at your option) any later version. |
8 |
|
|
9 |
This program is distributed in the hope that it will be useful, |
GNU Radius is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
GNU General Public License for more details. |
13 |
|
|
14 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
15 |
along with this program; if not, write to the Free Software |
along with GNU Radius; if not, write to the Free Software Foundation, |
16 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/ |
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
17 |
|
|
18 |
#define RADIUS_MODULE_POSTGRES_C |
#define RADIUS_MODULE_POSTGRES_C |
19 |
#ifdef HAVE_CONFIG_H |
#ifdef HAVE_CONFIG_H |
20 |
# include <config.h> |
# include <config.h> |
21 |
#endif |
#endif |
22 |
|
|
|
#ifndef lint |
|
|
static char rcsid[] = |
|
|
"@(#) $Id$" ; |
|
|
#endif |
|
|
|
|
23 |
#include <stdlib.h> |
#include <stdlib.h> |
24 |
#include <stdio.h> |
#include <stdio.h> |
25 |
#include <sys/time.h> |
#include <sys/time.h> |
41 |
static int rad_postgres_next_tuple(struct sql_connection *conn, void *data); |
static int rad_postgres_next_tuple(struct sql_connection *conn, void *data); |
42 |
static void rad_postgres_free(struct sql_connection *conn, void *data); |
static void rad_postgres_free(struct sql_connection *conn, void *data); |
43 |
|
|
|
#define CI_HOST "host=" |
|
|
#define CI_DBNAME "dbname=" |
|
|
#define CI_USER "user=" |
|
|
#define CI_PASSWORD "password=" |
|
|
|
|
|
#define CI_SIZE sizeof(CI_HOST) +\ |
|
|
sizeof(CI_DBNAME) +\ |
|
|
sizeof(CI_USER) +\ |
|
|
sizeof(CI_PASSWORD) |
|
|
|
|
|
static char * |
|
|
postgres_conninfo(type) |
|
|
int type; |
|
|
{ |
|
|
char *dbname; |
|
|
char *conninfo; |
|
|
int len; |
|
|
|
|
|
switch (type) { |
|
|
case SQL_AUTH: |
|
|
dbname = sql_cfg.auth_db; |
|
|
break; |
|
|
case SQL_ACCT: |
|
|
dbname = sql_cfg.acct_db; |
|
|
break; |
|
|
} |
|
|
|
|
|
len = CI_SIZE + |
|
|
strlen(sql_cfg.server) + |
|
|
strlen(dbname) + |
|
|
strlen(sql_cfg.login) + |
|
|
strlen(sql_cfg.password) + 1; |
|
|
conninfo = emalloc(len); |
|
|
|
|
|
snprintf(conninfo, len - 1, |
|
|
"%s%s %s%s %s%s %s%s", |
|
|
CI_HOST, sql_cfg.server, |
|
|
CI_DBNAME, dbname, |
|
|
CI_USER, sql_cfg.login, |
|
|
CI_PASSWORD, sql_cfg.password); |
|
|
return conninfo; |
|
|
} |
|
|
|
|
44 |
/* ************************************************************************* */ |
/* ************************************************************************* */ |
45 |
/* Interface routines */ |
/* Interface routines */ |
46 |
int |
static int |
47 |
rad_postgres_reconnect(type, conn) |
rad_postgres_reconnect(int type, struct sql_connection *conn) |
|
int type; |
|
|
struct sql_connection *conn; |
|
48 |
{ |
{ |
|
#if 1 |
|
49 |
PGconn *pgconn; |
PGconn *pgconn; |
50 |
char *dbname; |
char *dbname; |
51 |
char portbuf[16]; |
char portbuf[16]; |
81 |
conn->data = pgconn; |
conn->data = pgconn; |
82 |
conn->connected = 1; |
conn->connected = 1; |
83 |
return 0; |
return 0; |
|
|
|
|
#else |
|
|
PGconn *pgconn; |
|
|
int sockfd; |
|
|
int rc, active; |
|
|
struct timeval tv; |
|
|
fd_set fds; |
|
|
char *p; |
|
|
|
|
|
p = postgres_conninfo(type); |
|
|
debug(1, ("conninfo = \"%s\"", p)); |
|
|
pgconn = PQconnectStart(p); |
|
|
efree(p); |
|
|
if (!pgconn) { |
|
|
radlog(L_ERR, |
|
|
_("PQconnectStart failed")); |
|
|
return -1; |
|
|
} |
|
|
|
|
|
if (PQstatus(pgconn) == CONNECTION_BAD) { |
|
|
radlog(L_ERR, |
|
|
_("PQconnectStart failed: %s"), PQerrorMessage(pgconn)); |
|
|
PQfinish(pgconn); |
|
|
} |
|
|
|
|
|
sockfd = PQsocket(pgconn); |
|
|
active = 0; |
|
|
while ((rc = PQconnectPoll(pgconn)) != PGRES_POLLING_OK) { |
|
|
switch (rc) { |
|
|
case PGRES_POLLING_ACTIVE: |
|
|
active++; |
|
|
break; |
|
|
|
|
|
case PGRES_POLLING_READING: |
|
|
FD_ZERO(&fds); |
|
|
FD_SET(sockfd, &fds); |
|
|
tv.tv_sec = 5; |
|
|
tv.tv_usec = 0; |
|
|
rc = select(sockfd+1, &fds, NULL, NULL, &tv); |
|
|
if (rc == -1) |
|
|
goto err; |
|
|
active = FD_ISSET(sockfd, &fds); |
|
|
break; |
|
|
|
|
|
case PGRES_POLLING_WRITING: |
|
|
FD_ZERO(&fds); |
|
|
FD_SET(sockfd, &fds); |
|
|
tv.tv_sec = 5; |
|
|
tv.tv_usec = 0; |
|
|
rc = select(sockfd+1, NULL, &fds, NULL, &tv); |
|
|
if (rc == -1) |
|
|
goto err; |
|
|
active = FD_ISSET(sockfd, &fds); |
|
|
break; |
|
|
|
|
|
case PGRES_POLLING_FAILED: |
|
|
err: |
|
|
PQfinish(pgconn); |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
conn->data = pgconn; |
|
|
conn->connected = 1; |
|
|
return 0; |
|
|
#endif |
|
84 |
} |
} |
85 |
|
|
86 |
void |
static void |
87 |
rad_postgres_disconnect(conn, drop) |
rad_postgres_disconnect(struct sql_connection *conn, |
88 |
struct sql_connection *conn; |
int drop /* currently unused */) |
|
int drop; /* currently unused */ |
|
89 |
{ |
{ |
90 |
if (!conn->data) |
if (!conn->data) |
91 |
return; |
return; |
94 |
conn->connected = 0; |
conn->connected = 0; |
95 |
} |
} |
96 |
|
|
97 |
int |
static int |
98 |
rad_postgres_query(conn, query, return_count) |
rad_postgres_query(struct sql_connection *conn, char *query, int *return_count) |
|
struct sql_connection *conn; |
|
|
char *query; |
|
|
int *return_count; |
|
99 |
{ |
{ |
100 |
PGresult *res; |
PGresult *res; |
101 |
ExecStatusType stat; |
ExecStatusType stat; |
136 |
return rc; |
return rc; |
137 |
} |
} |
138 |
|
|
139 |
char * |
static char * |
140 |
rad_postgres_getpwd(conn, query) |
rad_postgres_getpwd(struct sql_connection *conn, char *query) |
|
struct sql_connection *conn; |
|
|
char *query; |
|
141 |
{ |
{ |
142 |
PGresult *res; |
PGresult *res; |
143 |
ExecStatusType stat; |
ExecStatusType stat; |
191 |
int curtuple; |
int curtuple; |
192 |
} EXEC_DATA; |
} EXEC_DATA; |
193 |
|
|
194 |
void * |
static void * |
195 |
rad_postgres_exec(conn, query) |
rad_postgres_exec(struct sql_connection *conn, char *query) |
|
struct sql_connection *conn; |
|
|
char *query; |
|
196 |
{ |
{ |
197 |
PGresult *res; |
PGresult *res; |
198 |
ExecStatusType stat; |
ExecStatusType stat; |
235 |
return (void*)data; |
return (void*)data; |
236 |
} |
} |
237 |
|
|
238 |
char * |
static char * |
239 |
rad_postgres_column(data, ncol) |
rad_postgres_column(void *data, int ncol) |
|
void *data; |
|
|
int ncol; |
|
240 |
{ |
{ |
241 |
EXEC_DATA *edata = (EXEC_DATA*)data; |
EXEC_DATA *edata = (EXEC_DATA*)data; |
242 |
if (!data) |
if (!data) |
250 |
} |
} |
251 |
|
|
252 |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
253 |
int |
static int |
254 |
rad_postgres_next_tuple(conn, data) |
rad_postgres_next_tuple(struct sql_connection *conn, void *data) |
|
struct sql_connection *conn; |
|
|
void *data; |
|
255 |
{ |
{ |
256 |
EXEC_DATA *edata = (EXEC_DATA*)data; |
EXEC_DATA *edata = (EXEC_DATA*)data; |
257 |
if (!data) |
if (!data) |
264 |
} |
} |
265 |
|
|
266 |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
267 |
void |
static void |
268 |
rad_postgres_free(conn, data) |
rad_postgres_free(struct sql_connection *conn, void *data) |
|
struct sql_connection *conn; |
|
|
void *data; |
|
269 |
{ |
{ |
270 |
EXEC_DATA *edata = (EXEC_DATA*)data; |
EXEC_DATA *edata = (EXEC_DATA*)data; |
271 |
|
|