Initial revision
[freeradius.git] / src / main / util.c
1 /*
2  * util.c       Various utility functions.
3  *
4  * Version:     @(#)util.c  2.20  17-Jul-1999  miquels@cistron.nl
5  */
6
7 char util_sccsid[] =
8 "@(#)util.c     2.20 Copyright 1997-1999 Cistron Internet Services B.V.";
9
10 #include        "autoconf.h"
11
12 #include        <sys/types.h>
13 #include        <sys/socket.h>
14 #include        <sys/time.h>
15 #include        <netinet/in.h>
16 #include        <arpa/inet.h>
17
18 #include        <stdio.h>
19 #include        <stdlib.h>
20 #include        <string.h>
21 #include        <netdb.h>
22 #include        <pwd.h>
23 #include        <time.h>
24 #include        <ctype.h>
25 #include        <signal.h>
26
27 #include        "radiusd.h"
28
29 /*
30  *      Call getpwnam but cache the result.
31  */
32 struct passwd *rad_getpwnam(char *name)
33 {
34         static struct passwd *lastpwd;
35         static char lastname[64];
36         static time_t lasttime = 0;
37         time_t now;
38
39         now = time(NULL);
40
41         if ((now <= lasttime + 5 ) && strncmp(name, lastname, 64) == 0)
42                 return lastpwd;
43
44         strncpy(lastname, name, 63);
45         lastname[63] = 0;
46         lastpwd = getpwnam(name);
47         lasttime = now;
48
49         return lastpwd;
50 }
51
52 #if defined (sun) && defined(__svr4__)
53 /*
54  *      The signal() function in Solaris 2.5.1 sets SA_NODEFER in
55  *      sa_flags, which causes grief if signal() is called in the
56  *      handler before the cause of the signal has been cleared.
57  *      (Infinite recursion).
58  */
59 void (*sun_signal(int signo, void (*func)(int)))(int)
60 {
61         struct sigaction act, oact;
62
63         act.sa_handler = func;
64         sigemptyset(&act.sa_mask);
65         act.sa_flags = 0;
66 #ifdef  SA_INTERRUPT            /* SunOS */
67         act.sa_flags |= SA_INTERRUPT;
68 #endif
69         if (sigaction(signo, &act, &oact) < 0)
70                 return SIG_ERR;
71         return oact.sa_handler;
72 }
73 #endif
74
75
76 /*
77  *      Free an AUTHREQ struct.
78  */
79 void request_free(REQUEST *request)
80 {
81         if (request->packet)
82                 rad_free(request->packet);
83         if (request->proxy)
84                 rad_free(request->proxy);
85         free(request);
86 }
87
88
89 /*
90  *      Build a reply radius packet, based on the request data.
91  */
92 RADIUS_PACKET *build_reply(int code, REQUEST *request,
93         VALUE_PAIR *vps, char *user_msg)
94 {
95         RADIUS_PACKET   *rp;
96         VALUE_PAIR      *vp;
97
98         if ((rp = rad_alloc(0)) == NULL) {
99                 fprintf(stderr, "out of memory\n");
100                 exit(1);
101         }
102         rp->dst_ipaddr = request->packet->src_ipaddr;
103         rp->dst_port   = request->packet->src_port;
104         rp->id         = request->packet->id;
105         rp->code       = code;
106         memcpy(rp->vector, request->packet->vector, sizeof(rp->vector));
107         rp->vps        = paircopy(vps);
108
109         /*
110          *      Need to copy PROXY_PAIRS from request->packet->vps
111          */
112         if ((vp = paircopy2(request->packet->vps, PW_PROXY_STATE)) != NULL)
113                 pairadd(&(rp->vps), vp);
114
115         if (user_msg && !(vp = paircreate(PW_REPLY_MESSAGE, PW_TYPE_STRING))) {
116                 strcpy(vp->strvalue, user_msg);
117                 vp->length = strlen(user_msg);
118                 pairadd(&(rp->vps), vp);
119         }
120
121         return rp;
122 }
123