View | Details | Raw Unified | Return to bug 15619
Collapse All | Expand All

(-)pppd/Makefile (+4 lines)
Lines 36-39 Link Here
36
DPADD+=	${LIBDES}
36
DPADD+=	${LIBDES}
37
.endif
37
.endif
38
38
39
# RADIUS support
40
CFLAGS+=-DRADIUS
41
SRCS+=rad_dict.c rad_funcs.c rad_md5.c rad_regexp.c rad_sendserver.c rad_users.c rad_util.c pppradius.c
42
39
.include <bsd.prog.mk>
43
.include <bsd.prog.mk>
(-)pppd/auth.c (-4 / +35 lines)
Lines 80-85 Link Here
80
#endif
80
#endif
81
#include "pathnames.h"
81
#include "pathnames.h"
82
82
83
#ifdef RADIUS
84
#include "radius.h"
85
#endif
86
83
/* Used for storing a sequence of words.  Usually malloced. */
87
/* Used for storing a sequence of words.  Usually malloced. */
84
struct wordlist {
88
struct wordlist {
85
    struct wordlist	*next;
89
    struct wordlist	*next;
Lines 179-184 Link Here
179
    minutes = (etime-stime)/60;
183
    minutes = (etime-stime)/60;
180
    syslog(LOG_NOTICE, "Connection terminated, connected for %d minutes\n",
184
    syslog(LOG_NOTICE, "Connection terminated, connected for %d minutes\n",
181
	minutes > 1 ? minutes : 1);
185
	minutes > 1 ? minutes : 1);
186
    if (reqradius)
187
	rad_acct_stop(RADIUS_name);
182
}
188
}
183
189
184
/*
190
/*
Lines 247-257 Link Here
247
253
248
    phase = PHASE_AUTHENTICATE;
254
    phase = PHASE_AUTHENTICATE;
249
    auth = 0;
255
    auth = 0;
256
    syslog(LOG_DAEMON, "Authentication phase began");
250
    if (go->neg_chap) {
257
    if (go->neg_chap) {
251
	ChapAuthPeer(unit, our_name, go->chap_mdtype);
258
	ChapAuthPeer(unit, our_name, go->chap_mdtype);
252
	auth |= CHAP_PEER;
259
	auth |= CHAP_PEER;
253
    } else if (go->neg_upap) {
260
    } else if (go->neg_upap) {
261
	syslog(LOG_DAEMON, "Authentication with PAP");
254
	upap_authpeer(unit);
262
	upap_authpeer(unit);
263
	syslog(LOG_DAEMON, "Authntication finished");
255
	auth |= PAP_PEER;
264
	auth |= PAP_PEER;
256
    }
265
    }
257
    if (ho->neg_chap) {
266
    if (ho->neg_chap) {
Lines 263-275 Link Here
263
	    if (!get_pap_passwd(passwd))
272
	    if (!get_pap_passwd(passwd))
264
		syslog(LOG_ERR, "No secret found for PAP login");
273
		syslog(LOG_ERR, "No secret found for PAP login");
265
	}
274
	}
266
	upap_authwithpeer(unit, user, passwd);
267
	auth |= PAP_WITHPEER;
275
	auth |= PAP_WITHPEER;
268
    }
276
    }
269
    auth_pending[unit] = auth;
277
    auth_pending[unit] = auth;
270
278
271
    if (!auth)
279
	syslog(LOG_DAEMON, "Link established");
280
281
    if (!auth) {
282
	syslog(LOG_DAEMON, "óÏÂÉÒÁÅÍÓÑ × network phase");
272
	network_phase(unit);
283
	network_phase(unit);
284
    } else {
285
	syslog(LOG_DAEMON, "Stop network growth!");
286
    }
273
}
287
}
274
288
275
/*
289
/*
Lines 291-296 Link Here
291
	did_authup = 1;
305
	did_authup = 1;
292
    }
306
    }
293
307
308
	syslog(LOG_DAEMON, "after path_authup");
294
#ifdef CBCP_SUPPORT
309
#ifdef CBCP_SUPPORT
295
    /*
310
    /*
296
     * If we negotiated callback, do it now.
311
     * If we negotiated callback, do it now.
Lines 670-676 Link Here
670
    if (f == NULL) {
685
    if (f == NULL) {
671
	syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
686
	syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
672
	ret = UPAP_AUTHNAK;
687
	ret = UPAP_AUTHNAK;
673
674
    } else {
688
    } else {
675
	check_access(f, filename);
689
	check_access(f, filename);
676
	remote = ipwo->accept_remote? 0: ipwo->hisaddr;
690
	remote = ipwo->accept_remote? 0: ipwo->hisaddr;
Lines 691-696 Link Here
691
	}
705
	}
692
    }
706
    }
693
707
708
    /* here will be radius login */
709
#ifdef RADIUS
710
    if (ret == UPAP_AUTHNAK && reqradius)
711
	if (rad_auth(user, passwd) == OK_RC)
712
		if (rad_acct_start(user) == OK_RC)
713
			ret = UPAP_AUTHACK;
714
#endif
715
694
    if (ret == UPAP_AUTHNAK) {
716
    if (ret == UPAP_AUTHNAK) {
695
        if (*msg == (char *) 0)
717
        if (*msg == (char *) 0)
696
	    *msg = "Login incorrect";
718
	    *msg = "Login incorrect";
Lines 1028-1034 Link Here
1028
    }
1050
    }
1029
1051
1030
#else
1052
#else
1031
    char *tty;
1053
	char *tty;
1054
	syslog(LOG_DAEMON, "plogout");
1055
1056
#ifdef RADIUS
1057
	if (reqradius) {
1058
		if (rad_acct_stop(user) != OK_RC) {
1059
			syslog(LOG_DAEMON, "Can't stop accounting user");
1060
		}	
1061
	}
1062
#endif
1032
1063
1033
    tty = devnam;
1064
    tty = devnam;
1034
    if (strncmp(tty, "/dev/", 5) == 0)
1065
    if (strncmp(tty, "/dev/", 5) == 0)
(-)pppd/conf.h (+97 lines)
Line 0 Link Here
1
#ifndef CONF_H
2
#define CONF_H
3
4
/*
5
 *
6
 *	RADIUS
7
 *	Remote Authentication Dial In User Service
8
 *
9
 *
10
 *	Livingston Enterprises, Inc.
11
 *	6920 Koll Center Parkway
12
 *	Pleasanton, CA   94566
13
 *
14
 *	Copyright 1992 Livingston Enterprises, Inc.
15
 *
16
 *	Permission to use, copy, modify, and distribute this software for any
17
 *	purpose and without fee is hereby granted, provided that this
18
 *	copyright and permission notice appear on all copies and supporting
19
 *	documentation, the name of Livingston Enterprises, Inc. not be used
20
 *	in advertising or publicity pertaining to distribution of the
21
 *	program without specific prior permission, and notice be given
22
 *	in supporting documentation that copying and distribution is by
23
 *	permission of Livingston Enterprises, Inc.
24
 *
25
 *	Livingston Enterprises, Inc. makes no representations about
26
 *	the suitability of this software for any purpose.  It is
27
 *	provided "as is" without express or implied warranty.
28
 *
29
 */
30
31
/*
32
 *	@(#)conf.h	0.1 10/11/94
33
 */
34
35
#define	RADIUS_VERSION		" 2.4.23C " /* MUST be surrounded by spaces */
36
37
#if defined(__alpha)
38
typedef unsigned int UINT4;
39
typedef int INT4;
40
#else	/* defined(alpha) */
41
typedef unsigned long UINT4;
42
typedef long INT4;
43
#endif	/* defined(alpha) */
44
45
#if defined(unixware) || defined(sys5) || defined(M_UNIX) || defined(sun)
46
#include	<string.h>
47
#else	/* unixware */
48
#include	<strings.h>
49
#endif	/* unixware */
50
51
#if defined(bsdi)
52
#include	<machine/inline.h>
53
#include	<machine/endian.h>
54
#else	/* bsdi */
55
#ifndef	__FreeBSD__
56
#include	<malloc.h>
57
#endif	/* __FreeBSD__ */
58
#endif	/* bsdi */
59
60
/* #ifdef SYSV this is needed even on SunOS 4.1.3 */
61
#include	<pwd.h>
62
/* #endif XXX SYSV */
63
64
#if defined(aix)
65
#include	<sys/select.h>
66
#endif	/* aix */
67
68
#if defined(__hpux)
69
#include	<unistd.h>
70
#endif	/* __hpux */
71
72
#ifdef	USE_NDBM
73
#include	<ndbm.h>
74
#include	<fcntl.h>
75
#endif	/* USE_NDBM */
76
77
#if defined(USE_DBM)
78
#include	<dbm.h>
79
#if defined(sun)
80
#define NULL 0
81
#endif	/* sun */
82
#if defined(__sgi)
83
#ifdef dbm_error64
84
#define store store64
85
#define dbminit dbminit64
86
#define dbmclose dbmclose64
87
#endif	/* dbm_error64 */
88
#endif	/* __sgi */
89
#endif	/* USE_DBM */
90
91
#if defined(linux)
92
#include	<unistd.h>
93
#define MIN(a, b)      ((a) < (b) ? (a) : (b))
94
#define MAX(a, b)      ((a) > (b) ? (a) : (b))
95
#endif	/* linux */
96
97
#endif /* CONF_H */
(-)pppd/md4.c (+298 lines)
Line 0 Link Here
1
/*
2
** ********************************************************************
3
** md4.c -- Implementation of MD4 Message Digest Algorithm           **
4
** Updated: 2/16/90 by Ronald L. Rivest                              **
5
** (C) 1990 RSA Data Security, Inc.                                  **
6
** ********************************************************************
7
*/
8
9
/*
10
** To use MD4:
11
**   -- Include md4.h in your program
12
**   -- Declare an MDstruct MD to hold the state of the digest
13
**          computation.
14
**   -- Initialize MD using MDbegin(&MD)
15
**   -- For each full block (64 bytes) X you wish to process, call
16
**          MD4Update(&MD,X,512)
17
**      (512 is the number of bits in a full block.)
18
**   -- For the last block (less than 64 bytes) you wish to process,
19
**          MD4Update(&MD,X,n)
20
**      where n is the number of bits in the partial block. A partial
21
**      block terminates the computation, so every MD computation
22
**      should terminate by processing a partial block, even if it
23
**      has n = 0.
24
**   -- The message digest is available in MD.buffer[0] ...
25
**      MD.buffer[3].  (Least-significant byte of each word
26
**      should be output first.)
27
**   -- You can print out the digest using MDprint(&MD)
28
*/
29
30
/* Implementation notes:
31
** This implementation assumes that ints are 32-bit quantities.
32
*/
33
34
#define TRUE  1
35
#define FALSE 0
36
37
/* Compile-time includes
38
*/
39
#include <stdio.h>
40
#include "md4.h"
41
#include "pppd.h"
42
43
/* Compile-time declarations of MD4 "magic constants".
44
*/
45
#define I0  0x67452301       /* Initial values for MD buffer */
46
#define I1  0xefcdab89
47
#define I2  0x98badcfe
48
#define I3  0x10325476
49
#define C2  013240474631     /* round 2 constant = sqrt(2) in octal */
50
#define C3  015666365641     /* round 3 constant = sqrt(3) in octal */
51
/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
52
** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
53
** Table 2, page 660.
54
*/
55
56
#define fs1  3               /* round 1 shift amounts */
57
#define fs2  7
58
#define fs3 11
59
#define fs4 19
60
#define gs1  3               /* round 2 shift amounts */
61
#define gs2  5
62
#define gs3  9
63
#define gs4 13
64
#define hs1  3               /* round 3 shift amounts */
65
#define hs2  9
66
#define hs3 11
67
#define hs4 15
68
69
/* Compile-time macro declarations for MD4.
70
** Note: The "rot" operator uses the variable "tmp".
71
** It assumes tmp is declared as unsigned int, so that the >>
72
** operator will shift in zeros rather than extending the sign bit.
73
*/
74
#define f(X,Y,Z)             ((X&Y) | ((~X)&Z))
75
#define g(X,Y,Z)             ((X&Y) | (X&Z) | (Y&Z))
76
#define h(X,Y,Z)             (X^Y^Z)
77
#define rot(X,S)             (tmp=X,(tmp<<S) | (tmp>>(32-S)))
78
#define ff(A,B,C,D,i,s)      A = rot((A + f(B,C,D) + X[i]),s)
79
#define gg(A,B,C,D,i,s)      A = rot((A + g(B,C,D) + X[i] + C2),s)
80
#define hh(A,B,C,D,i,s)      A = rot((A + h(B,C,D) + X[i] + C3),s)
81
82
/* MD4print(MDp)
83
** Print message digest buffer MDp as 32 hexadecimal digits.
84
** Order is from low-order byte of buffer[0] to high-order byte of
85
** buffer[3].
86
** Each byte is printed with high-order hexadecimal digit first.
87
** This is a user-callable routine.
88
*/
89
void
90
MD4Print(MDp)
91
MD4_CTX *MDp;
92
{
93
  int i,j;
94
  for (i=0;i<4;i++)
95
    for (j=0;j<32;j=j+8)
96
      printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
97
}
98
99
/* MD4Init(MDp)
100
** Initialize message digest buffer MDp.
101
** This is a user-callable routine.
102
*/
103
void
104
MD4Init(MDp)
105
MD4_CTX *MDp;
106
{
107
  int i;
108
  MDp->buffer[0] = I0;
109
  MDp->buffer[1] = I1;
110
  MDp->buffer[2] = I2;
111
  MDp->buffer[3] = I3;
112
  for (i=0;i<8;i++) MDp->count[i] = 0;
113
  MDp->done = 0;
114
}
115
116
/* MDblock(MDp,X)
117
** Update message digest buffer MDp->buffer using 16-word data block X.
118
** Assumes all 16 words of X are full of data.
119
** Does not update MDp->count.
120
** This routine is not user-callable.
121
*/
122
static void
123
MDblock(MDp,Xb)
124
MD4_CTX *MDp;
125
unsigned char *Xb;
126
{
127
  register unsigned int tmp, A, B, C, D;
128
  unsigned int X[16];
129
  int i;
130
131
  for (i = 0; i < 16; ++i) {
132
    X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24);
133
    Xb += 4;
134
  }
135
136
  A = MDp->buffer[0];
137
  B = MDp->buffer[1];
138
  C = MDp->buffer[2];
139
  D = MDp->buffer[3];
140
  /* Update the message digest buffer */
141
  ff(A , B , C , D ,  0 , fs1); /* Round 1 */
142
  ff(D , A , B , C ,  1 , fs2);
143
  ff(C , D , A , B ,  2 , fs3);
144
  ff(B , C , D , A ,  3 , fs4);
145
  ff(A , B , C , D ,  4 , fs1);
146
  ff(D , A , B , C ,  5 , fs2);
147
  ff(C , D , A , B ,  6 , fs3);
148
  ff(B , C , D , A ,  7 , fs4);
149
  ff(A , B , C , D ,  8 , fs1);
150
  ff(D , A , B , C ,  9 , fs2);
151
  ff(C , D , A , B , 10 , fs3);
152
  ff(B , C , D , A , 11 , fs4);
153
  ff(A , B , C , D , 12 , fs1);
154
  ff(D , A , B , C , 13 , fs2);
155
  ff(C , D , A , B , 14 , fs3);
156
  ff(B , C , D , A , 15 , fs4);
157
  gg(A , B , C , D ,  0 , gs1); /* Round 2 */
158
  gg(D , A , B , C ,  4 , gs2);
159
  gg(C , D , A , B ,  8 , gs3);
160
  gg(B , C , D , A , 12 , gs4);
161
  gg(A , B , C , D ,  1 , gs1);
162
  gg(D , A , B , C ,  5 , gs2);
163
  gg(C , D , A , B ,  9 , gs3);
164
  gg(B , C , D , A , 13 , gs4);
165
  gg(A , B , C , D ,  2 , gs1);
166
  gg(D , A , B , C ,  6 , gs2);
167
  gg(C , D , A , B , 10 , gs3);
168
  gg(B , C , D , A , 14 , gs4);
169
  gg(A , B , C , D ,  3 , gs1);
170
  gg(D , A , B , C ,  7 , gs2);
171
  gg(C , D , A , B , 11 , gs3);
172
  gg(B , C , D , A , 15 , gs4);
173
  hh(A , B , C , D ,  0 , hs1); /* Round 3 */
174
  hh(D , A , B , C ,  8 , hs2);
175
  hh(C , D , A , B ,  4 , hs3);
176
  hh(B , C , D , A , 12 , hs4);
177
  hh(A , B , C , D ,  2 , hs1);
178
  hh(D , A , B , C , 10 , hs2);
179
  hh(C , D , A , B ,  6 , hs3);
180
  hh(B , C , D , A , 14 , hs4);
181
  hh(A , B , C , D ,  1 , hs1);
182
  hh(D , A , B , C ,  9 , hs2);
183
  hh(C , D , A , B ,  5 , hs3);
184
  hh(B , C , D , A , 13 , hs4);
185
  hh(A , B , C , D ,  3 , hs1);
186
  hh(D , A , B , C , 11 , hs2);
187
  hh(C , D , A , B ,  7 , hs3);
188
  hh(B , C , D , A , 15 , hs4);
189
  MDp->buffer[0] += A;
190
  MDp->buffer[1] += B;
191
  MDp->buffer[2] += C;
192
  MDp->buffer[3] += D;
193
}
194
195
/* MD4Update(MDp,X,count)
196
** Input: X -- a pointer to an array of unsigned characters.
197
**        count -- the number of bits of X to use.
198
**          (if not a multiple of 8, uses high bits of last byte.)
199
** Update MDp using the number of bits of X given by count.
200
** This is the basic input routine for an MD4 user.
201
** The routine completes the MD computation when count < 512, so
202
** every MD computation should end with one call to MD4Update with a
203
** count less than 512.  A call with count 0 will be ignored if the
204
** MD has already been terminated (done != 0), so an extra call with
205
** count 0 can be given as a "courtesy close" to force termination
206
** if desired.
207
*/
208
void
209
MD4Update(MDp,X,count)
210
MD4_CTX *MDp;
211
unsigned char *X;
212
unsigned int count;
213
{
214
  unsigned int i, tmp, bit, byte, mask;
215
  unsigned char XX[64];
216
  unsigned char *p;
217
218
  /* return with no error if this is a courtesy close with count
219
  ** zero and MDp->done is true.
220
  */
221
  if (count == 0 && MDp->done) return;
222
  /* check to see if MD is already done and report error */
223
  if (MDp->done)
224
  { printf("\nError: MD4Update MD already done."); return; }
225
226
  /* Add count to MDp->count */
227
  tmp = count;
228
  p = MDp->count;
229
  while (tmp)
230
  { tmp += *p;
231
  *p++ = tmp;
232
  tmp = tmp >> 8;
233
  }
234
235
  /* Process data */
236
  if (count == 512)
237
  { /* Full block of data to handle */
238
    MDblock(MDp,X);
239
  }
240
  else if (count > 512) /* Check for count too large */
241
  {
242
    printf("\nError: MD4Update called with illegal count value %d.",
243
	   count);
244
    return;
245
  }
246
  else /* partial block -- must be last block so finish up */
247
  {
248
    /* Find out how many bytes and residual bits there are */
249
    byte = count >> 3;
250
    bit =  count & 7;
251
    /* Copy X into XX since we need to modify it */
252
    for (i=0;i<=byte;i++)   XX[i] = X[i];
253
    for (i=byte+1;i<64;i++) XX[i] = 0;
254
    /* Add padding '1' bit and low-order zeros in last byte */
255
    mask = 1 << (7 - bit);
256
    XX[byte] = (XX[byte] | mask) & ~( mask - 1);
257
    /* If room for bit count, finish up with this block */
258
    if (byte <= 55)
259
    {
260
      for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
261
      MDblock(MDp,XX);
262
    }
263
    else /* need to do two blocks to finish up */
264
    {
265
      MDblock(MDp,XX);
266
      for (i=0;i<56;i++) XX[i] = 0;
267
      for (i=0;i<8;i++)  XX[56+i] = MDp->count[i];
268
      MDblock(MDp,XX);
269
    }
270
    /* Set flag saying we're done with MD computation */
271
    MDp->done = 1;
272
  }
273
}
274
275
/*
276
** Finish up MD4 computation and return message digest.
277
*/
278
void
279
MD4Final(buf, MD)
280
unsigned char *buf;
281
MD4_CTX *MD;
282
{
283
  int i, j;
284
  unsigned int w;
285
286
  MD4Update(MD, NULL, 0);
287
  for (i = 0; i < 4; ++i) {
288
    w = MD->buffer[i];
289
    for (j = 0; j < 4; ++j) {
290
      *buf++ = w;
291
      w >>= 8;
292
    }
293
  }
294
}
295
296
/*
297
** End of md4.c
298
****************************(cut)***********************************/
(-)pppd/md4.h (+64 lines)
Line 0 Link Here
1
2
/*
3
** ********************************************************************
4
** md4.h -- Header file for implementation of                        **
5
** MD4 Message Digest Algorithm                                      **
6
** Updated: 2/13/90 by Ronald L. Rivest                              **
7
** (C) 1990 RSA Data Security, Inc.                                  **
8
** ********************************************************************
9
*/
10
11
#ifndef __P
12
# if defined(__STDC__) || defined(__GNUC__)
13
#  define __P(x) x
14
# else
15
#  define __P(x) ()
16
# endif
17
#endif
18
19
20
/* MDstruct is the data structure for a message digest computation.
21
*/
22
typedef struct {
23
	unsigned int buffer[4]; /* Holds 4-word result of MD computation */
24
	unsigned char count[8]; /* Number of bits processed so far */
25
	unsigned int done;      /* Nonzero means MD computation finished */
26
} MD4_CTX;
27
28
/* MD4Init(MD4_CTX *)
29
** Initialize the MD4_CTX prepatory to doing a message digest
30
** computation.
31
*/
32
extern void MD4Init __P((MD4_CTX *MD));
33
34
/* MD4Update(MD,X,count)
35
** Input: X -- a pointer to an array of unsigned characters.
36
**        count -- the number of bits of X to use (an unsigned int).
37
** Updates MD using the first "count" bits of X.
38
** The array pointed to by X is not modified.
39
** If count is not a multiple of 8, MD4Update uses high bits of
40
** last byte.
41
** This is the basic input routine for a user.
42
** The routine terminates the MD computation when count < 512, so
43
** every MD computation should end with one call to MD4Update with a
44
** count less than 512.  Zero is OK for a count.
45
*/
46
extern void MD4Update __P((MD4_CTX *MD, unsigned char *X, unsigned int count));
47
48
/* MD4Print(MD)
49
** Prints message digest buffer MD as 32 hexadecimal digits.
50
** Order is from low-order byte of buffer[0] to high-order byte
51
** of buffer[3].
52
** Each byte is printed with high-order hexadecimal digit first.
53
*/
54
extern void MD4Print __P((MD4_CTX *));
55
56
/* MD4Final(buf, MD)
57
** Returns message digest from MD and terminates the message
58
** digest computation.
59
*/
60
extern void MD4Final __P((unsigned char *, MD4_CTX *));
61
62
/*
63
** End of md4.h
64
****************************(cut)***********************************/
(-)pppd/md5.h (+73 lines)
Line 0 Link Here
1
/* GLOBAL.H - RSAREF types and constants
2
 */
3
4
/* PROTOTYPES should be set to one if and only if the compiler supports
5
  function argument prototyping.
6
  The following makes PROTOTYPES default to 0 if it has not already
7
  been defined with C compiler flags.
8
 */
9
10
#ifndef PROTOTYPES
11
#define PROTOTYPES 0
12
#endif
13
14
/* POINTER defines a generic pointer type */
15
typedef unsigned char *POINTER;
16
17
/* UINT2 defines a two byte word */
18
typedef unsigned short int UINT2;
19
20
/* UINT4 defines a four byte word */
21
#if defined(__alpha)
22
typedef unsigned int UINT4;
23
#else
24
typedef unsigned long int UINT4;
25
#endif
26
27
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
28
   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
29
  returns an empty list.
30
 */
31
32
#if PROTOTYPES
33
#define PROTO_LIST(list) list
34
#else
35
#define PROTO_LIST(list) ()
36
#endif
37
38
/* MD5.H - header file for MD5C.C
39
 */
40
41
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
42
rights reserved.
43
44
License to copy and use this software is granted provided that it
45
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
46
Algorithm" in all material mentioning or referencing this software
47
or this function.
48
49
License is also granted to make and use derivative works provided
50
that such works are identified as "derived from the RSA Data
51
Security, Inc. MD5 Message-Digest Algorithm" in all material
52
mentioning or referencing the derived work.
53
54
RSA Data Security, Inc. makes no representations concerning either
55
the merchantability of this software or the suitability of this
56
software for any particular purpose. It is provided "as is"
57
without express or implied warranty of any kind.
58
59
These notices must be retained in any copies of any part of this
60
documentation and/or software.
61
 */
62
63
/* MD5 context. */
64
typedef struct
65
{
66
	UINT4           state[4];  /* state (ABCD) */
67
	UINT4           count[2];  /* number of bits, modulo 2^64 (lsb first) */
68
	unsigned char   buffer[64]; /* input buffer */
69
} MD5_CTX;
70
71
void MD5Init    PROTO_LIST ((MD5_CTX *));
72
void MD5Update  PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int));
73
void MD5Final   PROTO_LIST ((unsigned char[16], MD5_CTX *));
(-)pppd/options.c (+19 lines)
Lines 58-63 Link Here
58
#include "ipxcp.h"
58
#include "ipxcp.h"
59
#endif /* IPX_CHANGE */
59
#endif /* IPX_CHANGE */
60
60
61
#ifdef RADIUS
62
#include "radius.h"
63
#endif
64
65
int reqradius;
66
61
#include <net/ppp_comp.h>
67
#include <net/ppp_comp.h>
62
68
63
#define FALSE	0
69
#define FALSE	0
Lines 148-153 Link Here
148
#ifdef OLD_OPTIONS
154
#ifdef OLD_OPTIONS
149
static int setupapfile __P((char **));
155
static int setupapfile __P((char **));
150
#endif
156
#endif
157
static int radiusauth __P((char **));
151
static int nochap __P((char **));
158
static int nochap __P((char **));
152
static int reqchap __P((char **));
159
static int reqchap __P((char **));
153
static int noaccomp __P((char **));
160
static int noaccomp __P((char **));
Lines 294-299 Link Here
294
    {"+pap", 0, reqpap},	/* Require PAP auth from peer */
301
    {"+pap", 0, reqpap},	/* Require PAP auth from peer */
295
    {"refuse-pap", 0, nopap},	/* Don't agree to auth to peer with PAP */
302
    {"refuse-pap", 0, nopap},	/* Don't agree to auth to peer with PAP */
296
    {"-pap", 0, nopap},		/* Don't allow UPAP authentication with peer */
303
    {"-pap", 0, nopap},		/* Don't allow UPAP authentication with peer */
304
    {"radius", 0, radiusauth},  /* Require authentication on RADIUS server */
297
    {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */
305
    {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */
298
    {"+chap", 0, reqchap},	/* Require CHAP authentication from peer */
306
    {"+chap", 0, reqchap},	/* Require CHAP authentication from peer */
299
    {"refuse-chap", 0, nochap},	/* Don't agree to auth to peer with CHAP */
307
    {"refuse-chap", 0, nochap},	/* Don't agree to auth to peer with CHAP */
Lines 1372-1377 Link Here
1372
    lcp_wantoptions[0].neg_upap = 1;
1380
    lcp_wantoptions[0].neg_upap = 1;
1373
    setauth(NULL);
1381
    setauth(NULL);
1374
    return 1;
1382
    return 1;
1383
}
1384
1385
/*
1386
 * radiusauth - Sets reqradius variable to authenticate thru radius server
1387
 */
1388
static int
1389
radiusauth(argv)
1390
	char **argv;
1391
{
1392
	reqradius = 1;
1393
	return 1;
1375
}
1394
}
1376
1395
1377
#if OLD_OPTIONS
1396
#if OLD_OPTIONS
(-)pppd/ppp.pam (+6 lines)
Line 0 Link Here
1
#%PAM-1.0
2
# Information for the PPPD process with the 'login' option.
3
auth	required	/lib/security/pam_pwdb.so shadow nullok
4
auth	required	/lib/security/pam_nologin.so
5
account	required	/lib/security/pam_permit.so
6
session	required	/lib/security/pam_permit.so
(-)pppd/pppradius.c (+394 lines)
Line 0 Link Here
1
#include	<sys/types.h>
2
#include	<sys/socket.h>
3
#include	<sys/param.h>
4
#include	<netinet/in.h>
5
#include	<sys/time.h>
6
#include	<sys/signal.h>
7
#include	<sys/termios.h>
8
#ifdef	SVR4
9
#include	<sys/systeminfo.h>
10
#endif	/* SVR4 */
11
12
#include	<netdb.h>
13
#include	<pwd.h>
14
#include	<stdio.h>
15
#include	<stdlib.h>
16
#include	<time.h>
17
#include	<unistd.h>
18
19
#include	"radius.h"
20
21
#ifndef RESPONSE_TIMEOUT
22
#define RESPONSE_TIMEOUT 3
23
#endif
24
25
#ifndef MAX_RETRIES
26
#define MAX_RETRIES	10
27
#endif
28
29
char            recv_buffer[4096];
30
char            send_buffer[4096];
31
char            ourhostname[MAXHOSTNAMELEN];
32
char           *progname;
33
char           *radius_dir;
34
int             debug_flag = 0;
35
int             dumpcore = 0;
36
int             file_logging = 2;   /* 0 => syslog, 1 => logfile, 2 => stderr */
37
int             zap_logfile = 0;
38
int             authfile_cnt = 0;
39
int             clients_cnt = 0;
40
int             users_cnt = 0;
41
time_t          birthdate;
42
AATVPTR		rad_authen_aatv = (AATV *) NULL;
43
AATVPTR         rad_ipc_aatv = (AATV *) NULL;
44
AATV           *authtype_tv[PW_AUTH_MAX + 1];
45
FILE           *ddt = NULL;
46
FILE           *msgfd = stderr;
47
extern void     dir_init();
48
49
static void     radpwtst_usage ();
50
51
typedef struct string_list_struct
52
{
53
	struct string_list_struct *next;
54
	char                      *str;
55
}string_list;
56
57
int	RADIUS_port;
58
int	RADIUS_asi;
59
int	RADIUS_data;
60
time_t	RADIUS_bt;
61
time_t	RADIUS_et;
62
char	*RADIUS_name;
63
64
int rad_auth(char *name, char *password)
65
{
66
	int		result;
67
	int		retries;
68
	int		new_old;
69
	char		*client_name = (char *)NULL;
70
	char		*clear_pw = (char *)NULL;
71
	string_list	*vplist = NULL;
72
	string_list	**vpnext = &vplist;
73
	char		msg[4096];
74
	char		passwd[AUTH_PASS_LEN + 1];
75
	SEND_DATA	data;
76
	int		send_server();
77
78
	syslog(LOG_DAEMON, "Trying to authenticate: %s with password: %s\n", name, password);
79
80
	data.code = PW_ACCESS_REQUEST;
81
	data.svc_port = 1645;
82
	data.server = "ns.link-ul.ru";
83
	radius_dir = "/var/adm/raddb";
84
	data.timeout = RESPONSE_TIMEOUT;
85
	data.user_file = (char *)NULL;
86
	data.group = (char *)NULL;
87
	data.send_pairs = (VALUE_PAIR *)NULL;
88
89
	retries = MAX_RETRIES;
90
	new_old = 0;
91
	data.ustype=PW_FRAMED;
92
	data.fptype=PW_PPP;
93
	data.port_num = RADIUS_port;
94
95
	*vpnext = (string_list *)malloc(sizeof(string_list));
96
	(*vpnext)->str = "NAS-Port-Type=0";
97
	(*vpnext)->next = (string_list *)NULL;
98
	vpnext = &((*vpnext)->next);
99
	data.user_name = name;
100
	data.password = password;
101
102
	dir_init();
103
104
	if (dict_init() != 0) {
105
		fprintf(stderr, "Missing directory in /var/adm/raddb\n");
106
		exit(-1);
107
	}
108
	for ( ; vplist ; vplist = vplist->next) {
109
		if (pair_parse (vplist->str, &data.send_pairs) != 0) {
110
			fprintf (stderr,
111
				"%s: Invalid attribute-value pair, '%s'\n",
112
				 progname, vplist->str);
113
			exit(-1);
114
		}
115
	}
116
	data.seq_nbr = RADIUS_data = (u_char) rand();
117
	if (gethostname(ourhostname, sizeof(ourhostname)) < 0) {
118
		perror("gethostname");
119
		exit(-1);
120
	}
121
	if (client_name == (char *)NULL) {
122
		if ((data.client_id = get_ipaddr(ourhostname)) == 0) {
123
			printf("Couldn't get own IP address!\n");
124
			data.client_id = 0;
125
		}
126
	} else
127
		data.client_id = get_ipaddr(client_name);
128
	if ((data.user_file != (char *)NULL)&&(data.group == (char *)NULL))
129
		data.group = "DEFAULT";
130
	msg[0] = '\0';
131
	result = send_server(&data, &retries, msg);
132
	if (result == OK_RC) { 
133
		printf("\"%s\" authentication OK", data.user_name);
134
		RADIUS_name = (char *)malloc(strlen(data.user_name)+1);
135
		strcpy(RADIUS_name, data.user_name);
136
	} else {
137
		printf("\"%s\" authentication failed", data.user_name);
138
		if (result != BADRESP_RC)
139
			printf("(RC=%i)", result);
140
	}
141
	if (msg[0])
142
		printf(": %s", msg);
143
	putchar('\n');
144
145
	return (result);
146
}
147
148
int rad_acct_start(char *name)
149
{
150
151
	int		result;
152
	int		retries;
153
	int		new_old;
154
	char		*client_name = (char *)NULL;
155
	char		*clear_pw = (char *)NULL;
156
	string_list	*vplist = NULL;
157
	string_list	**vpnext = &vplist;
158
	char		msg[4096];
159
	char		passwd[AUTH_PASS_LEN + 1];
160
	SEND_DATA	data;
161
	int		send_server();
162
	char		*str;
163
164
	data.code = PW_ACCOUNTING_REQUEST;
165
	data.svc_port = 1646;
166
	data.server = "ns.link-ul.ru";
167
	radius_dir = "/var/adm/raddb";
168
	data.timeout = RESPONSE_TIMEOUT;
169
	data.user_file = (char *)NULL;
170
	data.group = (char *)NULL;
171
	data.send_pairs = (VALUE_PAIR *)NULL;
172
	retries = MAX_RETRIES;
173
	new_old = 0;
174
	data.ustype = PW_FRAMED;
175
	data.fptype = PW_PPP;
176
	data.port_num = RADIUS_port;
177
	data.user_name = name;
178
	data.password = "";
179
180
	if (pair_parse("NAS-Port-Type=0", &data.send_pairs) != 0) {
181
		fprintf(stderr, "Invalid attribute-value pair\n");
182
		exit(-1);
183
	}
184
	
185
	if (pair_parse("Acct-Status-Type=1", &data.send_pairs) != 0) {
186
		fprintf(stderr, "Invalid attribute acct-status-type\n");
187
		exit(-1);
188
	}
189
190
	if (pair_parse("Acct-Authentic=3", &data.send_pairs) != 0) {
191
		fprintf(stderr, "Invalid attribute acct-authentic\n");
192
		exit(-1);
193
	}
194
195
	if (pair_parse("Acct-Delay-Time=0", &data.send_pairs) != 0) {
196
		fprintf(stderr, "Invalid attribute acct-delay-time\n");
197
		exit(-1);
198
	}
199
200
	str = (char *)malloc(128);
201
	RADIUS_asi = rand();
202
	sprintf(str, "Acct-Session-Id=%x", RADIUS_asi);
203
	if (pair_parse(str, &data.send_pairs) != 0) {
204
		fprintf(stderr, "Invalid attribute acct-session-id\n");
205
		exit(-1);
206
	}
207
208
	dir_init();
209
	if (dict_init() != 0) {
210
		fprintf(stderr, "Missing directory in /var/adm/raddb\n");
211
		exit(-1);
212
	}
213
214
	data.seq_nbr = (++RADIUS_data);
215
	if (gethostname(ourhostname, sizeof(ourhostname)) < 0) {
216
		perror("gethostname");
217
		exit(-1);
218
	}
219
	if (client_name == (char *)NULL) {
220
		if ((data.client_id = get_ipaddr(ourhostname)) == 0) {
221
			printf("Couldn't get own IP address!\n");
222
			data.client_id = 0;
223
		}
224
	} else
225
		data.client_id = get_ipaddr(client_name);
226
	if ((data.user_file != (char *)NULL)&&(data.group == (char *)NULL))
227
		data.group = "DEFAULT";
228
	msg[0] = '\0';
229
	result = send_server(&data, &retries, msg);
230
231
	if (result == OK_RC) 
232
		printf("\"%s\" accounting start OK", data.user_name);
233
	else {
234
		printf("\"%s\" accounting start failed", data.user_name);
235
		if (result != BADRESP_RC)
236
			printf("(RC=%i)", result);
237
	}
238
	if (msg[0])
239
		printf(": %s", msg);
240
	putchar('\n');
241
242
	RADIUS_bt = time(NULL);
243
244
	return (result);
245
}
246
247
int rad_acct_stop(char *name)
248
{
249
	int		result;
250
	int		retries;
251
	int		new_old;
252
	char		*client_name = (char *)NULL;
253
	char		*clear_pw = (char *)NULL;
254
	string_list	*vplist = NULL;
255
	string_list	**vpnext = &vplist;
256
	char		msg[4096];
257
	char		passwd[AUTH_PASS_LEN + 1];
258
	SEND_DATA	data;
259
	int		send_server();
260
	char		*str;
261
262
	data.code = PW_ACCOUNTING_REQUEST;
263
	data.svc_port = 1646;
264
	data.server = "ns.link-ul.ru";
265
	radius_dir = "/var/adm/raddb";
266
	data.timeout = RESPONSE_TIMEOUT;
267
	data.user_file = (char *)NULL;
268
	data.group = (char *)NULL;
269
	data.send_pairs = (VALUE_PAIR *)NULL;
270
	retries = MAX_RETRIES;
271
	new_old = 0;
272
	data.ustype = PW_FRAMED;
273
	data.fptype = PW_PPP;
274
	data.port_num = RADIUS_port;
275
	data.user_name = name;
276
	data.password = "";
277
278
	if (pair_parse("NAS-Port-Type=0", &data.send_pairs) != 0) {
279
		fprintf(stderr, "Invalid attribute-value pair\n");
280
		exit(-1);
281
	}
282
283
	if (pair_parse("Acct-Status-Type=2", &data.send_pairs) != 0) {
284
		fprintf(stderr, "Invalid attribute acct-status-type\n");
285
		exit(-1);
286
	}
287
288
	if (pair_parse("Acct-Authentic=3", &data.send_pairs) != 0) {
289
		fprintf(stderr, "Invalid attribute acct-authentic\n");
290
		exit(-1);
291
	}
292
293
	if (pair_parse("Acct-Delay-Time=0", &data.send_pairs) != 0) {
294
		fprintf(stderr, "Invalid attribute acct-delay-time\n");
295
		exit(-1);
296
	}
297
298
	if (pair_parse("Acct-Output-Octets=0", &data.send_pairs) != 0) {
299
		fprintf(stderr, "Invalid attribute acct-output-octets\n");
300
		exit(-1);
301
	}
302
303
	if (pair_parse("Acct-Input-Octets=0", &data.send_pairs) != 0) {
304
		fprintf(stderr, "Invalid attribute acct-inpute-octets\n");
305
		exit(-1);
306
	}
307
308
	if (pair_parse("Acct-Input-Packets=0", &data.send_pairs) != 0) {
309
		fprintf(stderr, "Invalid attribute aÓÓt-inpute-packets\n");
310
		exit(-1);
311
	}
312
313
	if (pair_parse("Acct-Output-Packets=0", &data.send_pairs) != 0) {
314
		fprintf(stderr, "Invalid attribute acct-output-packets\n");
315
		exit(-1);
316
	}
317
318
	str = (char *)malloc(128);
319
	sprintf(str,"Acct-Session-Id=%x", RADIUS_asi);
320
	if (pair_parse(str, &data.send_pairs) != 0) {
321
		fprintf(stderr, "Invalid attribute acct-session-id\n");
322
		exit(-1);
323
	}
324
325
	RADIUS_et = time(NULL);
326
	sprintf(str,"Acct-Session-Time=%ld",RADIUS_et-RADIUS_bt);
327
	if (pair_parse(str, &data.send_pairs) != 0) {
328
		fprintf(stderr, "Invalid attribute acct-session-time\n");
329
		exit(-1);
330
	}
331
332
	dir_init();
333
	if (dict_init() != 0) {
334
		fprintf(stderr, "Missing directory in /var/adm/raddb\n");
335
		exit(-1);
336
	}
337
338
	data.seq_nbr = (++RADIUS_data);
339
	if (gethostname(ourhostname, sizeof(ourhostname)) < 0) {
340
		perror("gethostname");
341
		exit(-1);
342
	}
343
	if (client_name == (char *)NULL) {
344
		if ((data.client_id = get_ipaddr(ourhostname)) == 0) {
345
			printf("Couldn't get own IP address!\n");
346
			data.client_id = 0;
347
		}
348
	} else
349
		data.client_id = get_ipaddr(client_name);
350
	if ((data.user_file != (char *)NULL)&&(data.group == (char *)NULL))
351
		data.group = "DEFAULT";
352
	msg[0] = '\0';
353
	result = send_server(&data, &retries, msg);
354
	if (result == OK_RC) 
355
		printf("\"%s\" accounting stop OK", data.user_name);
356
	else {
357
		printf("\"%s\" accounting stop failed", data.user_name);
358
		if (result != BADRESP_RC)
359
			printf("(RC=%i)", result);
360
	}
361
	if (msg[0])
362
		printf(": %s", msg);
363
	putchar('\n');
364
365
	return (result);
366
}
367
368
#if 0
369
int main (int argc, char *argv[])
370
{
371
	progname = *argv;
372
	srand(time(0));
373
	RADIUS_port = rand();
374
375
	if (argc != 3)
376
		radpwtst_usage();
377
	if (authenticate(argv[1], argv[2]) != OK_RC)
378
		exit(-1);
379
	if (accounting_start(argv[1]) != OK_RC)
380
		exit(-1);
381
	printf("Press any key to finish\n");
382
	getchar();
383
	if (accounting_stop(argv[1]) != OK_RC)
384
		exit(-1);
385
} /* end of main () */
386
387
static void
388
radpwtst_usage ()
389
390
{
391
	printf ("Usage: %s username password\n", progname);
392
	exit (-1);
393
} /* end of radpwtst_usage () */
394
#endif
(-)pppd/rad_dict.c (+365 lines)
Line 0 Link Here
1
/*
2
 *
3
 *	RADIUS
4
 *	Remote Authentication Dial In User Service
5
 *
6
 *
7
 *	Livingston Enterprises, Inc.
8
 *	6920 Koll Center Parkway
9
 *	Pleasanton, CA   94566
10
 *
11
 *	Copyright 1992 Livingston Enterprises, Inc.
12
 *
13
 *	Permission to use, copy, modify, and distribute this software for any
14
 *	purpose and without fee is hereby granted, provided that this
15
 *	copyright and permission notice appear on all copies and supporting
16
 *	documentation, the name of Livingston Enterprises, Inc. not be used
17
 *	in advertising or publicity pertaining to distribution of the
18
 *	program without specific prior permission, and notice be given
19
 *	in supporting documentation that copying and distribution is by
20
 *	permission of Livingston Enterprises, Inc.
21
 *
22
 *	Livingston Enterprises, Inc. makes no representations about
23
 *	the suitability of this software for any purpose.  It is
24
 *	provided "as is" without express or implied warranty.
25
 *
26
 * Public entry points in this file:
27
 *
28
 * dict_attrfind
29
 * dict_attrget
30
 * dict_init
31
 * dict_valfind
32
 * dict_valget
33
 *
34
 */
35
36
static char     sccsid[] =
37
		"@(#)dict.c 1.2 Copyright 1992 Livingston Enterprises Inc";
38
39
static char     rcsid[] = "$Id: dict.c,v 1.9 1996/05/17 14:19:03 web Exp $";
40
41
#include	<stdio.h>
42
#include	<stdlib.h>
43
#include	<time.h>
44
#include	<sys/types.h>
45
#include	<ctype.h>
46
#include	<netinet/in.h>
47
#include	<syslog.h>
48
49
#include	"radius.h"
50
51
extern int      debug_flag;
52
extern char    *radius_dir;
53
54
static DICT_ATTR *dictionary_attributes;
55
static DICT_VALUE *dictionary_values;
56
57
/*************************************************************************
58
 *
59
 *	Function: dict_init
60
 *
61
 *	Purpose: Initialize the dictionary.  Read all ATTRIBUTES into
62
 *		 the dictionary_attributes list.  Read all VALUES into
63
 *		 the dictionary_values list.
64
 *
65
 *************************************************************************/
66
67
int
68
dict_init ()
69
70
{
71
	FILE           *dictfd;
72
	char            dummystr[AUTH_ID_LEN];
73
	char            namestr[AUTH_ID_LEN];
74
	char            valstr[AUTH_ID_LEN];
75
	char            attrstr[AUTH_ID_LEN];
76
	char            typestr[AUTH_ID_LEN];
77
	int             line_no;
78
	DICT_ATTR      *attr;
79
	DICT_VALUE     *dval;
80
	char            buffer[256];
81
	int             value;
82
	int             type;
83
	static char    *func = "dict_init";
84
85
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
86
87
	sprintf (buffer, "%s/%s", radius_dir, RADIUS_DICTIONARY);
88
	if ((dictfd = fopen (buffer, "r")) == (FILE *) NULL)
89
	{
90
		fprintf (stderr, "%s: Couldn't open dictionary: %s\n",
91
			 func, buffer);
92
		return (-1);
93
	}
94
95
	line_no = 0;
96
	while (fgets (buffer, sizeof (buffer), dictfd) != (char *) NULL)
97
	{
98
		line_no++;
99
100
		/* Skip empty space */
101
		if (*buffer == '#' || *buffer == '\0' || *buffer == '\n')
102
		{
103
			continue;
104
		}
105
106
		if (strncmp (buffer, "ATTRIBUTE", 9) == 0)
107
		{
108
109
			/* Read the ATTRIBUTE line */
110
			if (sscanf (buffer, "%s%s%s%s", dummystr, namestr,
111
				    valstr, typestr) != 4)
112
			{
113
				fprintf (stderr,
114
			    "%s: Invalid attribute on line %d of dictionary\n",
115
					 func, line_no);
116
				return (-1);
117
			}
118
119
			/*
120
			 * Validate all entries
121
			 */
122
			if (strlen (namestr) > NAME_LENGTH)
123
			{
124
				fprintf (stderr,
125
			   "%s: Invalid name length on line %d of dictionary\n",
126
					 func, line_no);
127
				return (-1);
128
			}
129
130
			if (!isdigit (*valstr))
131
			{
132
				fprintf (stderr,
133
				 "%s: Invalid value on line %d of dictionary\n",
134
					 func, line_no);
135
				return (-1);
136
			}
137
			value = atoi (valstr);
138
139
			if (strcmp (typestr, "string") == 0)
140
			{
141
				type = PW_TYPE_STRING;
142
			}
143
			else if (strcmp (typestr, "integer") == 0)
144
			{
145
				type = PW_TYPE_INTEGER;
146
			}
147
			else if (strcmp (typestr, "ipaddr") == 0)
148
			{
149
				type = PW_TYPE_IPADDR;
150
			}
151
			else if (strcmp (typestr, "date") == 0)
152
			{
153
				type = PW_TYPE_DATE;
154
			}
155
			else if (strcmp (typestr, "octets") == 0)
156
			{
157
				type = PW_TYPE_OCTETS;
158
			}
159
			else if (strcmp (typestr, "vendor") == 0)
160
			{
161
				type = PW_TYPE_VENDOR;
162
			}
163
			else
164
			{
165
				fprintf (stderr,
166
				  "%s: Invalid type on line %d of dictionary\n",
167
					 func, line_no);
168
				return (-1);
169
			}
170
171
			/* Create a new attribute for the list */
172
			if ((attr =
173
				(DICT_ATTR *) malloc (sizeof (DICT_ATTR)))
174
							== (DICT_ATTR *) NULL)
175
			{
176
				fprintf (stderr, "%s: FATAL out of memory\n",
177
					func);
178
				abort ();
179
			}
180
			strcpy (attr->name, namestr);
181
			attr->value = value;
182
			attr->type = type;
183
184
			/* Insert it into the list */
185
			attr->next = dictionary_attributes;
186
			dictionary_attributes = attr;
187
		}
188
		else if (strncmp (buffer, "VALUE", 5) == 0)
189
		{
190
			/* Read the VALUE line */
191
			if (sscanf (buffer, "%s%s%s%s", dummystr, attrstr,
192
				    namestr, valstr) != 4)
193
			{
194
				fprintf (stderr,
195
			   "%s: Invalid value entry on line %d of dictionary\n",
196
					 func, line_no);
197
				return (-1);
198
			}
199
200
			/*
201
			 * Validate all entries
202
			 */
203
			if (strlen (attrstr) > NAME_LENGTH)
204
			{
205
				fprintf (stderr,
206
		      "%s: Invalid attribute length on line %d of dictionary\n",
207
					 func, line_no);
208
				return (-1);
209
			}
210
211
			if (strlen (namestr) > NAME_LENGTH)
212
			{
213
				fprintf (stderr,
214
			   "%s: Invalid name length on line %d of dictionary\n",
215
					 func, line_no);
216
				return (-1);
217
			}
218
219
			if (!isdigit (*valstr))
220
			{
221
				fprintf (stderr,
222
				 "%s: Invalid value on line %d of dictionary\n",
223
					 func, line_no);
224
				return (-1);
225
			}
226
			value = atoi (valstr);
227
228
			/* Create a new VALUE entry for the list */
229
			if ((dval =
230
				(DICT_VALUE *) malloc (sizeof (DICT_VALUE)))
231
							== (DICT_VALUE *) NULL)
232
			{
233
				fprintf (stderr, "%s: FATAL out of memory\n",
234
					func);
235
				abort ();
236
			}
237
			strcpy (dval->attrname, attrstr);
238
			strcpy (dval->name, namestr);
239
			dval->value = value;
240
241
			/* Insert it into the list */
242
			dval->next = dictionary_values;
243
			dictionary_values = dval;
244
		}
245
	}
246
	fclose (dictfd);
247
	return (0);
248
} /* end of dict_init () */
249
250
/*************************************************************************
251
 *
252
 *	Function: dict_attrget
253
 *
254
 *	Purpose: Return the full attribute structure based on the
255
 *		 attribute id number.
256
 *
257
 *************************************************************************/
258
259
DICT_ATTR *
260
dict_attrget (attribute)
261
262
int             attribute;
263
264
{
265
	DICT_ATTR      *attr;
266
267
	attr = dictionary_attributes;
268
	while (attr != (DICT_ATTR *) NULL)
269
	{
270
		if (attr->value == attribute)
271
		{
272
			return (attr);
273
		}
274
		attr = attr->next;
275
	}
276
	return ((DICT_ATTR *) NULL);
277
} /* end of dict_attrget () */
278
279
/*************************************************************************
280
 *
281
 *	Function: dict_attrfind
282
 *
283
 *	Purpose: Return the full attribute structure based on the
284
 *		 attribute name.
285
 *
286
 *************************************************************************/
287
288
DICT_ATTR *
289
dict_attrfind (attrname)
290
291
char           *attrname;
292
{
293
	DICT_ATTR      *attr;
294
295
	attr = dictionary_attributes;
296
	while (attr != (DICT_ATTR *) NULL)
297
	{
298
		if (strcasecmp (attr->name, attrname) == 0)
299
		{
300
			return (attr);
301
		}
302
		attr = attr->next;
303
	}
304
	return ((DICT_ATTR *) NULL);
305
} /* end of dict_attrfind () */
306
307
/*************************************************************************
308
 *
309
 *	Function: dict_valfind
310
 *
311
 *	Purpose: Return the full value structure based on the
312
 *		 value name.
313
 *
314
 *************************************************************************/
315
316
DICT_VALUE *
317
dict_valfind (valname)
318
319
char           *valname;
320
321
{
322
	DICT_VALUE     *val;
323
324
	val = dictionary_values;
325
	while (val != (DICT_VALUE *) NULL)
326
	{
327
		if (strcasecmp (val->name, valname) == 0)
328
		{
329
			return (val);
330
		}
331
		val = val->next;
332
	}
333
	return ((DICT_VALUE *) NULL);
334
} /* end of dict_valfind () */
335
336
/*************************************************************************
337
 *
338
 *	Function: dict_valget
339
 *
340
 *	Purpose: Return the full value structure based on the
341
 *		 actual value and the associated attribute name.
342
 *
343
 *************************************************************************/
344
345
DICT_VALUE *
346
dict_valget (value, attrname)
347
348
UINT4           value;
349
char           *attrname;
350
351
{
352
	DICT_VALUE     *val;
353
354
	val = dictionary_values;
355
	while (val != (DICT_VALUE *) NULL)
356
	{
357
		if (strcmp (val->attrname, attrname) == 0 &&
358
				val->value == value)
359
		{
360
			return (val);
361
		}
362
		val = val->next;
363
	}
364
	return ((DICT_VALUE *) NULL);
365
} /* end of dict_valget () */
(-)pppd/rad_funcs.c (+2269 lines)
Line 0 Link Here
1
/*
2
 * RADIUS -- Remote Authentication Dial In User Service
3
 * 
4
 * COPYRIGHT  (c)  1992, 1993, 1994, 1995, 1996
5
 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INCORPORATED
6
 * ALL RIGHTS RESERVED
7
 * 
8
 * PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS AND REDISTRIBUTE
9
 * THIS SOFTWARE AND SUCH DERIVATIVE WORKS IN BINARY FORM ONLY FOR ANY PURPOSE,
10
 * SO LONG AS NO FEE IS CHARGED, AND SO LONG AS THE COPYRIGHT NOTICE ABOVE, THIS
11
 * GRANT OF PERMISSION, AND THE DISCLAIMER BELOW APPEAR IN ALL COPIES MADE; AND
12
 * SO LONG AS THE NAME OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY
13
 * ADVERTISING OR PUBLICITY PERTAINING TO THE USE OR DISTRIBUTION OF THIS
14
 * SOFTWARE WITHOUT SPECIFIC, WRITTEN PRIOR AUTHORIZATION.
15
 * 
16
 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE UNIVERSITY
17
 * OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE
18
 * UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
19
 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
 * A PARTICULAR PURPOSE.  THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
21
 * LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
22
 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN
23
 * CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
24
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
25
 * 
26
 * For a License to distribute source code or to charge a fee for the program
27
 * or a product containing the program, contact MERIT at the University of
28
 * Michigan:
29
 * 
30
 * aaa-license@merit.edu
31
 * 
32
 * [This version puts NO LIMITS on the use.  It grants the right to create
33
 * DERIVATIVE WORKS.  The user may copy and distribute the code in the form
34
 * received AND DERIVATIVE WORKS, so long as no fee is charged.  If copies are
35
 * made, our copyright notice and the disclaimer must be included on them.  USE
36
 * THIS VERSION WITH CARE.  THIS VERSION VERY LIKELY WILL KILL ANY POTENTIAL
37
 * FOR LATER COMMERCIALIZATION OF THE SOFTWARE.]
38
 *
39
 *
40
 * Public entry points in this file:
41
 * 
42
 * add_string
43
 * authtype_toa
44
 * avpair_add
45
 * avpair_assign
46
 * avpair_copy
47
 * avpair_get
48
 * avpair_new
49
 * avpair_vtoa
50
 * compress_file
51
 * debug_list
52
 * debug_pair
53
 * dumpit
54
 * fprint_attr_val
55
 * gen_valpairs
56
 * get_errmsg
57
 * get_passwd
58
 * get_vp
59
 * get_last_vp
60
 * insert_vp
61
 * loghead
62
 * logit
63
 * missing_attribute
64
 * parse_realm
65
 * prune_pairs
66
 * _reply_message
67
 * reply_sprintf
68
 * setupsock
69
 * trunc_logfile
70
 * type_string
71
 * 
72
 */
73
74
static char     rcsid[] = "$Id: funcs.c,v 1.99 1996/06/14 16:14:47 web Exp $";
75
76
#include	<sys/types.h>
77
#include	<sys/param.h>
78
79
#if defined(sys5)
80
#include	<sys/sysmacros.h>
81
#endif	/* sys5 */
82
83
#include	<sys/socket.h>
84
#include	<sys/time.h>
85
86
#if defined(aix) || defined(ultrix)
87
#include	<fcntl.h>
88
#else	/* aix */
89
#include	<sys/fcntl.h>
90
#endif	/* aix */
91
92
#include	<sys/wait.h>
93
#include	<net/if.h>
94
#include	<netinet/in.h>
95
#include	<arpa/inet.h>
96
97
#include	<stdio.h>
98
#include	<netdb.h>
99
#include	<time.h>
100
#include	<ctype.h>
101
#include	<errno.h>
102
#include	<dirent.h>
103
#include	<syslog.h>
104
#include	<unistd.h>
105
#include	<varargs.h>
106
107
#include	"radius.h"
108
109
extern int       debug_flag;
110
extern int       dumpcore;
111
extern int       file_logging;
112
extern int       spawn_flag;
113
extern int       zap_logfile;
114
115
#if !defined(__FreeBSD__) && !defined(_BSDI_VERSION) && !defined(__NetBSD__)
116
extern int       sys_nerr;
117
extern char     *sys_errlist[];
118
#endif	/* __FreeBSD__ */
119
120
extern FILE     *ddt;
121
extern FILE     *msgfd;
122
extern char     *radius_dir;
123
extern AATVPTR   rad_authen_aatv;
124
extern time_t    birthdate;
125
extern char      recv_buffer[4096];
126
extern char      send_buffer[4096];
127
extern char      ourhostname[MAXHOSTNAMELEN];
128
129
/*************************************************************************
130
 *
131
 *	Function: add_string (string, convert)
132
 *
133
 *	Purpose: Store string in storage block, returning pointer.  
134
 *		 Optimizes string storage allocation and allows only
135
 *		 one copy of string to be stored.  A NULL string pointer
136
 *		 returns a pointer to a null string.
137
 *
138
 *		 If convert is non-zero, the string is stored in lower-case.
139
 *		 Thus a case insensitive match is performed to attempt to
140
 *		 find an already existing copy of the string in the table.
141
 *
142
 *		 Use this only to store non-dynamic (i.e., configuration)
143
 *		 strings as there is no way to delete strings and lookups
144
 *		 to see if a string is already is present are quite 
145
 *		 inefficient.
146
 *
147
 *************************************************************************/
148
149
char *
150
add_string (string, convert)
151
152
char          *string;
153
int            convert;
154
155
{
156
	typedef struct char_blk
157
	{
158
		struct char_blk        *next;
159
		char		       *next_ptr;
160
		int			rem_len;
161
		char			strings[2048];
162
	} CHAR_BLK;
163
164
	static CHAR_BLK *first_blk = (CHAR_BLK *) NULL;
165
	CHAR_BLK        *last_blk;
166
	CHAR_BLK        *blk;
167
	CHAR_BLK        *space_blk; /* 1st block with sufficient space */
168
	register char   *ptr;
169
	register char	*fptr;
170
	register char	*str;
171
	register UINT4	 len;
172
	register UINT4	 slen;
173
	char		 lcstr[AUTH_ID_LEN]; /* Case converted string */
174
	static char     *func = "add_string";
175
	
176
	if (!string)
177
	{
178
		string = "";	/* Convert NULL pointer to null string */
179
	}
180
181
	/* Copy input to all lowercase */
182
	if (convert & ASLC)
183
	{
184
		for (ptr = lcstr, fptr = string ; *fptr ; )
185
		{
186
			*ptr++ = tolower (*fptr++);
187
		}
188
		*ptr++ = '\0';
189
		len = ptr - lcstr;
190
		string = lcstr;
191
	}
192
	else
193
	{
194
		len = strlen (string) + 1;
195
	}
196
197
	space_blk = (CHAR_BLK *) NULL;
198
199
	/* See if we're already storing this string */
200
	for (blk = last_blk = first_blk ; blk ; last_blk = blk, blk = blk->next)
201
	{
202
		for (str = blk->strings ; str < blk->next_ptr ; str += slen)
203
		{
204
			if (len > (slen = (UINT4) *str++))
205
			{
206
				continue;
207
			}
208
		
209
			fptr = slen - len + str; 
210
			ptr = string;
211
			while (*ptr++ == *fptr)
212
			{
213
				if (*fptr++ == '\0') /* Found it! */
214
				{	
215
					return fptr - len;
216
				}
217
			}
218
		}
219
		if (space_blk == (CHAR_BLK *) NULL && blk->rem_len > len)
220
		{
221
			space_blk = blk;
222
		}
223
	}
224
225
	if (convert & FINDONLY)
226
	{
227
		return NULL;
228
	}
229
230
	/* Need to store new string.  See if we found space in previous block */
231
	if (space_blk == (CHAR_BLK *) NULL)
232
	{
233
		if ((blk = (CHAR_BLK *) malloc (sizeof(CHAR_BLK))) 
234
							== (CHAR_BLK *) NULL)
235
		{
236
			logit (LOG_DAEMON, LOG_ALERT,
237
				"%s: FATAL couldn't allocate CHAR_BLK storage",
238
				func);
239
			abort ();
240
		}
241
		blk->next_ptr = blk->strings;
242
		blk->rem_len = sizeof (blk->strings);
243
		blk->next = (CHAR_BLK *) NULL;
244
		if (last_blk == (CHAR_BLK *) NULL)
245
		{
246
			first_blk = blk;
247
		}
248
		else
249
		{
250
			last_blk->next = blk;
251
		}
252
		space_blk = blk;
253
	}
254
	fptr = space_blk->next_ptr;
255
	*fptr++ = len;
256
	strcpy (fptr, string);
257
	space_blk->next_ptr = fptr + len;
258
	space_blk->rem_len -= len + 1;
259
	return fptr;
260
} /* end of add_string () */
261
262
/******************************************************************************
263
 *
264
 *	Function: authtype_toa
265
 *
266
 *	Purpose: Return a string representation of the authreq code.
267
 *
268
 *	Returns: pointer to static string.
269
 *
270
 *****************************************************************************/
271
272
char *
273
authtype_toa (code)
274
275
int             code;		/* code indicating authen, acct, etc. */
276
277
{
278
	static char *typelist[] =
279
	{
280
		"invalid(0)",		/* invalid */
281
		"access",		/* PW_ACCESS_REQUEST */
282
		"accept",		/* PW_ACCESS_ACCEPT */
283
		"reject",		/* PW_ACCESS_REJECT */
284
		"acct-req",		/* PW_ACCOUNTING_REQUEST */
285
		"acct-resp",		/* PW_ACCOUNTING_RESPONSE */
286
		"acct-status",		/* PW_ACCOUNTING_STATUS */
287
		"pw-request",		/* PW_PASSWORD_REQUEST */
288
		"pw-ack",		/* PW_PASSWORD_ACK */
289
		"pw-reject",		/* PW_PASSWORD_REJECT */
290
		"acct-msg",		/* PW_ACCOUNTING_MESSAGE */
291
		"access-challenge",	/* PW_ACCESS_CHALLENGE */
292
		"status-server",	/* PW_STATUS_SERVER */
293
		"status-client"		/* PW_STATUS_CLIENT */
294
	};
295
	static char unknown[20];
296
297
	if ((code <= 0) || ((sizeof (typelist) / sizeof (typelist[0])) <= code))
298
	{
299
		if (code == PW_FORWARDING)
300
		{
301
			return "forwarding";
302
		}
303
304
		sprintf (unknown, "invalid(%d)", code);
305
		return unknown;
306
	}
307
 
308
	return typelist[code];
309
} /* end of authtype_toa () */
310
311
/******************************************************************************
312
 *
313
 *	Function: avpair_add
314
 *
315
 *	Purpose: Add an attribute-value pair to the given list.
316
 *
317
 *	Returns: pointer to added a/v pair upon success,
318
 *		 NULL pointer upon failure.
319
 *
320
 *	Remarks: Always appends the new pair to the end of the list.
321
 *
322
 *****************************************************************************/
323
324
VALUE_PAIR *
325
avpair_add (list, attrid, pval, len)
326
327
VALUE_PAIR    **list;		/* a list of attribute-value pairs. */
328
int             attrid;		/* Attribute id number. */
329
void           *pval;		/* Pointer to value. */
330
int             len;		/* length of value, or 0 */
331
332
{
333
	VALUE_PAIR     *vp;
334
335
	vp = avpair_new (attrid, pval, len);
336
337
	if (vp != (VALUE_PAIR *) NULL)
338
	{
339
		insert_vp (list, (VALUE_PAIR *) NULL, vp);
340
	}
341
342
	return vp;
343
344
} /* end of avpair_add */
345
346
/******************************************************************************
347
 *
348
 *	Function: avpair_assign
349
 *
350
 *	Purpose: Assign the given raw value to an attribute-value pair.
351
 *
352
 *	Returns:  0 on success,
353
 *		 -1 on failure.
354
 *
355
 *****************************************************************************/
356
357
int
358
avpair_assign (vp, pval, len)
359
360
VALUE_PAIR     *vp;	/* pointer to the attribute-value pair */
361
void           *pval;	/* pointer to value to be assigned */
362
int             len;	/* for strings: */
363
			/*  len == 0 ==> null-terminated ASCII string */
364
			/*  len > 0  ==> len is length of raw binary data */
365
			/* for non-strings: */
366
			/*  len == 0 ==> just plain data, just gets copied */
367
			/*  len > 0  ==> convert data from network ... */
368
			/*		... representation before copying */
369
370
{
371
	int             result = -1;
372
	static char    *func = "avpair_assign";
373
374
	if (len < 0 || len > AUTH_STRING_LEN)
375
	{
376
		logit (LOG_DAEMON, LOG_ERR, "%s: bad attribute length %d",
377
			func, len);
378
	}
379
	else
380
	{
381
		switch (vp->type)
382
		{
383
		    case PW_TYPE_STRING: /* Use lvalue field to store length. */
384
		    case PW_TYPE_OCTETS:
385
		    case PW_TYPE_VENDOR:
386
			if (len > 0) /* use length to control the raw copy */
387
			{
388
				memcpy (vp->strvalue, (char *) pval, len);
389
				vp->strvalue[len] = 0; /* In case of string! */
390
				vp->lvalue = len;
391
			}
392
			else /* len == 0 means the string is NULL terminated */
393
			{
394
				strncpy (vp->strvalue, (char *) pval,
395
					AUTH_STRING_LEN);
396
				vp->lvalue = strlen ((char *) pval);
397
			}
398
			result = 0;
399
			break;
400
401
		    case PW_TYPE_DATE:
402
		    case PW_TYPE_INTEGER:
403
		    case PW_TYPE_IPADDR:
404
			if (len > 0) /* need to convert the raw network value */
405
			{
406
				vp->lvalue = ntohl(* (UINT4 *) pval);
407
			}
408
			else /* len == 0 indicates just plain data */
409
			{
410
				memcpy (&vp->lvalue, pval, sizeof (vp->lvalue));
411
			}
412
			*vp->strvalue = '\0'; /* Insure null for type IPADDR */
413
			result = 0;
414
			break;
415
416
		    default:
417
			dprintf(1, (LOG_DAEMON, LOG_DEBUG,
418
				"%s: Unknown attribute %d", func, vp->type));
419
		}
420
	}
421
	return result;
422
} /* end of avpair_assign () */
423
424
/******************************************************************************
425
 *
426
 *	Function: avpair_copy
427
 *
428
 *	Purpose: Copy a specified attribute-value pair from one given
429
 *		 list to another.
430
 *
431
 *	Returns: 0 if the attribute-value pair doesn't exist in the source list,
432
 *		 1 (non-zero) if the attribute-value pair is copied.
433
 *
434
 ******************************************************************************
435
 */
436
437
int
438
avpair_copy (pdst, psrc, attr)
439
440
VALUE_PAIR    **pdst;
441
VALUE_PAIR     *psrc;
442
int             attr;
443
444
{
445
	VALUE_PAIR     *pvp;
446
	VALUE_PAIR     *pnew;
447
	static char    *func = "avpair_copy";
448
449
	if ((pvp = get_vp (psrc, attr)) == (VALUE_PAIR *) NULL)
450
	{
451
		return 0;
452
	}
453
454
	if ((pnew = (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
455
							== (VALUE_PAIR *) NULL)
456
	{
457
		logit (LOG_DAEMON, LOG_ALERT, "%s: FATAL out of memory", func);
458
		abort ();
459
	}
460
461
	memcpy ((char *) pnew, (char *) pvp, sizeof (VALUE_PAIR));
462
	pnew->next = (VALUE_PAIR *) NULL;
463
	insert_vp (pdst, (VALUE_PAIR *) NULL, pnew);
464
465
	return 1;
466
} /* end of avpair_copy () */
467
468
/*******************************************************************************
469
 *
470
 *	Function: avpair_get
471
 *
472
 *	Purpose: Find specified a/v pair from a list and return its value.
473
 *
474
 *	Returns: Type of the attribute on success (look at PW_TYPE_*),
475
 *		 or -1 on failure.
476
 *
477
 ******************************************************************************/
478
479
int
480
avpair_get (pval, vplist, attrid)
481
482
void           *pval;		/* OUT: buffer for returning value */
483
VALUE_PAIR     *vplist;		/* pointer to list of attribute-value pairs */
484
int             attrid;		/* attribute to find */
485
486
{
487
	VALUE_PAIR        *vp;
488
	static char       *func = "avpair_get";
489
490
	vp = get_vp (vplist, attrid);
491
	if (vp == (VALUE_PAIR *) NULL)
492
	{
493
		return (-1);
494
	}
495
496
	switch (vp->type)
497
	{
498
	    case PW_TYPE_STRING:
499
		strcpy ((char *) pval, vp->strvalue);
500
		break;
501
502
	    case PW_TYPE_OCTETS:
503
	    case PW_TYPE_VENDOR:
504
		memcpy ((char *) pval, vp->strvalue, vp->lvalue);
505
		break;
506
507
	    case PW_TYPE_DATE:
508
	    case PW_TYPE_INTEGER:
509
	    case PW_TYPE_IPADDR:
510
		*((UINT4 *) pval) = vp->lvalue;
511
		break;
512
513
	    default:
514
		dprintf(1, (LOG_DAEMON, LOG_DEBUG,
515
			"%s: Unknown attribute %d", func, vp->type));
516
	}
517
	return vp->type;
518
} /* end of avpair_get () */
519
520
/******************************************************************************
521
 *
522
 *	Function: avpair_new
523
 *
524
 *	Purpose: Make an new attribute-value pair with given parameters.
525
 *
526
 *	Returns: Pointer to generated a/v pair when successful,
527
 *		 NULL when failure.
528
 *
529
 *****************************************************************************/
530
531
VALUE_PAIR *
532
avpair_new (attrid, pval, len)
533
534
int             attrid;		/* integer id number of the attribute */
535
void           *pval;		/* pointer to value */
536
int             len;		/* length of value, or 0 */
537
538
{
539
	VALUE_PAIR     *vp = (VALUE_PAIR *) NULL;
540
	DICT_ATTR      *pda;
541
	static char    *func = "avpair_new";
542
543
	if ((pda = dict_attrget (attrid)) == (DICT_ATTR *) NULL)
544
	{
545
		dprintf(1, (LOG_DAEMON, LOG_DEBUG,
546
				"%s: Unknown attribute %d", func, attrid));
547
	}
548
	else
549
	{
550
		if ((vp = (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
551
							!= (VALUE_PAIR *) NULL)
552
		{
553
			strncpy (vp->name, pda->name, sizeof (vp->name));
554
			vp->attribute = attrid;
555
			vp->next = (VALUE_PAIR *) NULL;
556
			vp->type = pda->type;
557
			if (avpair_assign (vp, pval, len) == 0)
558
			{
559
				return vp;
560
			}
561
			free (vp);
562
			vp = (VALUE_PAIR *) NULL;
563
		}
564
		else
565
		{
566
			logit (LOG_DAEMON, LOG_ALERT, "%s: FATAL out of memory",
567
				func);
568
			abort ();
569
		}
570
	}
571
	return vp;
572
} /* end of avpair_new () */
573
574
#define	MAX_AVPAIR_VTOA 20
575
576
/*************************************************************************
577
 *
578
 *	Function: avpair_vtoa
579
 *
580
 *	Purpose: Produce a string representation of the value of a pair.
581
 *
582
 *************************************************************************/
583
584
char *
585
avpair_vtoa (vp, sws)
586
587
VALUE_PAIR	*vp;
588
int		 sws;
589
590
{
591
  int             max;
592
  int             pos;
593
  UINT4           num;
594
  char           *c;
595
  char           *p;
596
  DICT_VALUE     *dval;
597
  struct in_addr  inad;
598
  static char     buffers[MAX_AVPAIR_VTOA][1024];
599
  static int      ndx = 0;
600
  char           *buff = buffers[ndx];
601
  static char    *func = "avpair_vtoa";
602
603
  if (vp == (VALUE_PAIR *) NULL)
604
  {
605
	if ((sws & AVPAIR_VTOA_NULL) != 0)
606
	{
607
		return "";
608
	}
609
	return NULL;
610
  }
611
612
  ndx++;
613
  if (ndx > MAX_AVPAIR_VTOA)
614
  {
615
	ndx = 0;
616
  }
617
618
  switch (vp->type)
619
  {
620
    case PW_TYPE_STRING:
621
	p = (char *) buff;
622
	c = vp->strvalue;
623
624
	if ((sws & AVPAIR_VTOA_QUOTE) != 0)
625
	{
626
		*p++ = '\'';
627
	}
628
629
	max = vp->lvalue;
630
	if (max == 0)
631
	{
632
	  dprintf(2, (LOG_DAEMON, LOG_DEBUG,
633
		       "%s: Using strlen() for vp 0x%p {type=%d, attr=%d}",
634
		       func, vp, vp->type, vp->attribute));
635
	  max = strlen (vp->strvalue);
636
	}
637
638
	pos = 0;
639
	for (pos = 0; pos < max; pos++)
640
	{
641
		if (c[pos] == '\0')
642
		{
643
			break;
644
		}
645
646
		switch (c[pos])
647
		{
648
		    case '\b':		/* BACKSPACE */
649
			*p++ = '\\';
650
			*p++ = 'b';
651
			break;
652
653
		    case '\r':		/* Carriage Return */
654
			*p++ = '\\';
655
			*p++ = 'r';
656
			break;
657
658
		    case '\n':		/* Newline / Line feed */
659
			*p++ = '\\';
660
			*p++ = 'n';
661
			break;
662
663
		    case '\t':		/* Horizontal tab */
664
			*p++ = '\\';
665
			*p++ = 't';
666
			break;
667
668
		    case '\\':		/* Self-escape */
669
			*p++ = '\\';
670
			*p++ = '\\';
671
			break;
672
673
		    case '\'':		/* Quote-escape */
674
			*p++ = '\\';
675
			*p++ = '\'';
676
			break;
677
678
		    default:
679
			if ((' ' <= c[pos]) && (c[pos] < 0x7f))
680
			{
681
				*p++ = c[pos];
682
			}
683
			else
684
			{
685
				char tmp[10];
686
687
				if (c[pos] == 0)
688
				{
689
					strcpy (p, "\\0");
690
				}
691
				else
692
				{
693
					sprintf (tmp, "\\x%2.2x",
694
						(unsigned char) c[pos]);
695
					strcpy (p, tmp);
696
				}
697
				p += strlen (p);
698
			}
699
		}
700
	}  /* for each character... */
701
702
	if ((sws & AVPAIR_VTOA_QUOTE) != 0)
703
	{
704
		*p++ = '\'';
705
	}
706
707
	*p = '\0';
708
 
709
	break;
710
711
    case PW_TYPE_INTEGER:
712
	dval = dict_valget (vp->lvalue, vp->name);
713
	if (dval != (DICT_VALUE *) NULL)
714
	{
715
		strcpy (buff, dval->name);
716
	}
717
	else
718
	{
719
#if defined(__alpha)
720
	sprintf (buff, "%d", vp->lvalue);
721
#else	/* defined(alpha) */
722
	sprintf (buff, "%ld", vp->lvalue);
723
#endif	/* defined(alpha) */
724
	}
725
	break;
726
 
727
    case PW_TYPE_IPADDR:
728
	inad.s_addr = htonl(vp->lvalue);
729
	strcpy (buff, inet_ntoa (inad));
730
	break;
731
 
732
    case PW_TYPE_DATE:
733
	strftime (buff, sizeof (buff), "%b %e %Y",
734
	gmtime ((time_t *) & vp->lvalue));
735
	break;
736
 
737
738
    case PW_TYPE_OCTETS:
739
	strcpy (buff, "0x");
740
	p = (char *) buff;
741
	p += strlen (buff);
742
	c = vp->strvalue;
743
744
	for (pos = 0; pos < vp->lvalue; pos++)
745
	{
746
		char tmp[3];
747
 
748
		sprintf (tmp, "%2.2x", c[pos]);
749
		strcpy (p, tmp);
750
		if (pos % 4 == 3)
751
		{
752
			strcat (p, " ");
753
		}
754
		p += strlen (p);
755
	}
756
	*p = '\0';
757
	break;
758
759
    case PW_TYPE_VENDOR:
760
	c = vp->strvalue;
761
	if (*c != 0)
762
	{
763
		logit (LOG_DAEMON, LOG_ERR,
764
			"%s: Invalid vendor-specific code, 0x%x", func, *c);
765
		return NULL;
766
	}
767
	memcpy ((char *) &num, c, 4);
768
	pos = ntohl(num);
769
770
	sprintf (buff, "v%d-", pos);
771
	for (pos = 4; pos < vp->lvalue; pos++)
772
	{
773
		char tmp[3];
774
 
775
		sprintf (tmp, "%2.2x", c[pos]);
776
		strcpy (p, tmp);
777
		p += strlen (p);
778
	}
779
	*p = '\0';
780
	break;
781
782
    default:
783
	if (sws & AVPAIR_VTOA_NULL)
784
	{
785
		return "";
786
	}
787
	return NULL;
788
  } /* switch (vp) */
789
790
return buff;
791
792
} /* end of avpair_vtoa () */
793
794
/*************************************************************************
795
 *
796
 *	Function: compress_file
797
 *
798
 *	Purpose: Compress and reopen a file.
799
 *
800
 *************************************************************************/
801
802
void
803
compress_file (fd, fname)
804
805
FILE          **fd;
806
char           *fname;
807
808
{
809
	int             pid;
810
	struct tm      *clock;
811
	time_t          now;
812
	char            today[80];
813
	char            name[128];
814
	char            newname[128];
815
	static char    *func = "compress_file";
816
817
	now = time (0);
818
	now -= 86400; /* the archived log is for yesterday! */
819
	sprintf (name, "%s/%s", radius_dir, fname);
820
	clock = localtime (&now);
821
	strftime (today, 15, "%y%m%d", clock);
822
	sprintf (newname, "%s/%s.%s", radius_dir, fname, today);
823
	if (link (name, newname) < 0) /* get another handle */
824
	{
825
		return;
826
	}
827
828
	if (unlink (name) < 0)
829
	{
830
		return;
831
	}
832
833
	sync ();		/* update disk metadata */
834
835
	fclose (*fd);
836
837
	if ((*fd = fopen (name, "w")) == (FILE *) NULL)
838
	{
839
		return;
840
	}
841
842
	now += 86400; /* correct the time now */
843
	strcpy (today, ctime (&now));
844
	fprintf (*fd,
845
		"%-24.24s: created by PID %u Version %s up since %-24.24s\n",
846
		today, getpid (), RADIUS_VERSION, ctime (&birthdate));
847
#ifndef SCO
848
	fchmod (fileno (*fd), 0644);
849
#endif	/* SCO */
850
	
851
	if (spawn_flag > 0) /* only compress if we won't block */
852
	{
853
		pid = (int) fork ();
854
		if (pid < 0) /* error */
855
		{
856
	      		logit (LOG_DAEMON, LOG_ALERT,
857
				"%s: fork: %s", func, get_errmsg ());
858
			exit (-5);
859
		}
860
		if (pid > 0) /* parent */
861
		{
862
			return;
863
		}
864
		else /* in child */
865
		{
866
			execl (RADIUS_COMPRESS, RADIUS_COMPRESS,
867
				newname, (char *) NULL);
868
			exit (0);
869
		}
870
	}
871
872
	return;
873
} /* end of compress_file () */
874
875
/*************************************************************************
876
 *
877
 *	Function: debug_list
878
 *
879
 *	Purpose: Print the value pair list to the desired File.
880
 *
881
 *************************************************************************/
882
883
void
884
debug_list (fd, pair)
885
886
FILE           *fd;
887
VALUE_PAIR     *pair;
888
889
{
890
	VALUE_PAIR     *vp;
891
892
	if (debug_flag)
893
	{
894
		if (ddt)
895
		{
896
			fd = ddt;
897
		}
898
899
		vp = pair;
900
901
		while (vp != (VALUE_PAIR *) NULL)
902
		{
903
			debug_pair (fd, vp);
904
			vp = vp->next;
905
		}
906
	}
907
	return;
908
} /* end of debug_list () */
909
910
/*************************************************************************
911
 *
912
 *	Function: debug_pair
913
 *
914
 *	Purpose: Print the Attribute-value pair to the desired File.
915
 *
916
 *************************************************************************/
917
918
void
919
debug_pair (fd, pair)
920
921
FILE           *fd;
922
VALUE_PAIR     *pair;
923
924
{
925
	if (debug_flag)
926
	{
927
		if (ddt)
928
		{
929
			fd = ddt;
930
		}
931
932
		fputs ("    ", fd);
933
		fprint_attr_val (fd, pair);
934
		fputs ("\n", fd);
935
	}
936
	return;
937
} /* end of debug_pair () */
938
939
/*************************************************************************
940
 *
941
 *	Function: dumpit
942
 *
943
 *	Purpose: Dump the memory area using logit()
944
 *
945
 *	Usage: dumpit (facility, level, ptr, ptrlen, offset, format, args, ...);
946
 *
947
 *		Where facility and level are found in syslog.h and the
948
 *		format is just a printf-style format string using the args.
949
 *
950
 *************************************************************************/
951
952
int
953
dumpit (facility, level, ptr, ptrlen, offset, format, va_alist)
954
955
int           facility;		/* Logging facility, see dprintf() */
956
int           level;		/* Logging level, see dprintf() */
957
char         *ptr;		/* Pointer to start of dumping region. */
958
unsigned int  ptrlen;		/* Length of the region to dump. */
959
unsigned int  offset;		/* Offset from "ptr" to where to start dump. */
960
char         *format;		/* A sprintf() like format string. */
961
va_dcl				/* Arguments for sprintf() string. */
962
963
{
964
	va_list         pvar;
965
	int             done;
966
967
	static char     buffer[MAXPATHLEN]; /* Work area. */
968
969
	va_start (pvar);
970
	vsprintf (buffer, format, pvar);
971
	va_end (pvar);
972
973
	if (strlen (buffer) > 0)
974
	{
975
		logit (facility, level, "%s", buffer);
976
	}
977
978
	logit (facility, level, "Hex dump at 0x%p/%x for %d bytes", ptr, offset,
979
	       ptrlen);
980
981
	while (ptrlen > 0)
982
	{
983
	    done = hex_dump (buffer, ptr, ptrlen, offset);
984
	    ptrlen -= done;
985
	    offset += done;
986
	    ptr += done;
987
	    logit (facility, level, "%s", buffer);
988
	}
989
990
	return 0;
991
992
} /* end of dumpit () */
993
994
void
995
fprint_attr_val (fd, pair)
996
997
FILE           *fd;
998
VALUE_PAIR     *pair;
999
1000
{
1001
	char           *val;
1002
1003
	if (pair->name[0] == '\0')
1004
	{
1005
		return;
1006
	}
1007
1008
	if ((val = avpair_vtoa (pair, 0)) != (char *) NULL)
1009
	{
1010
	    fprintf (fd, "%s = %s", pair->name, val);
1011
	}
1012
	else
1013
	{
1014
	    fprintf (fd, "%s is unknown", pair->name);
1015
	}
1016
1017
	return;
1018
1019
} /* end of fprint_attr_val () */
1020
1021
/*************************************************************************
1022
 *
1023
 *	Function: gen_valpairs
1024
 *
1025
 *	Purpose: Takes attribute/value pairs from buffer and builds a
1026
 *		 value_pair list using allocated memory.
1027
 *
1028
 *************************************************************************/
1029
1030
VALUE_PAIR *
1031
gen_valpairs (auth)
1032
1033
AUTH_HDR       *auth;
1034
1035
{
1036
	int             attribute;
1037
	int             attrlen;
1038
	int             bad_packet = 0; /* Set to one if bad packet rec'v'd. */
1039
	int             len;
1040
	UINT4           lvalue;
1041
	u_char         *ptr;
1042
	DICT_ATTR      *attr;
1043
	VALUE_PAIR     *vp;
1044
	VALUE_PAIR     *pair;
1045
	static char    *func = "gen_valpairs";
1046
1047
	dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func));
1048
1049
	/*
1050
	 *	Extract attribute-value pairs
1051
	 */
1052
	ptr = auth->data;
1053
	len = ntohs(auth->length) - AUTH_HDR_LEN; /* length of attributes */
1054
	vp = (VALUE_PAIR *) NULL;
1055
1056
	while (len > 0)
1057
	{
1058
		attribute = *ptr++;
1059
		attrlen = *ptr++;
1060
		attrlen -= 2;
1061
		if (attrlen < 0 || attrlen > AUTH_STRING_LEN || attrlen > len)
1062
		{
1063
			dumpit (LOG_DAEMON, LOG_ERR, ptr, attrlen, 0,
1064
				"Received attribute %d with invalid length %d",
1065
				attribute, attrlen);
1066
			bad_packet = 1;
1067
			break;
1068
		}
1069
1070
		if ((attr = dict_attrget (attribute)) == (DICT_ATTR *) NULL)
1071
		{
1072
			ddumpx(1, (LOG_DAEMON, LOG_DEBUG, ptr, attrlen, 0,
1073
				"Received unknown attribute %d of length %d",
1074
				attribute, attrlen));
1075
			bad_packet = 1;
1076
		}
1077
		else
1078
		{
1079
			if ((pair =
1080
				(VALUE_PAIR *) malloc (sizeof (VALUE_PAIR))) ==
1081
					(VALUE_PAIR *) NULL)
1082
			{
1083
				logit (LOG_DAEMON, LOG_ALERT,
1084
					"%s: FATAL out of memory", func);
1085
				abort ();
1086
			}
1087
			strcpy (pair->name, attr->name);
1088
			pair->attribute = attr->value;
1089
			pair->type = attr->type;
1090
			pair->next = (VALUE_PAIR *) NULL;
1091
1092
			switch (attr->type)
1093
			{
1094
1095
			    case PW_TYPE_STRING:
1096
			    case PW_TYPE_OCTETS:
1097
			    case PW_TYPE_VENDOR:
1098
				memcpy (pair->strvalue, (char *) ptr, attrlen);
1099
				pair->strvalue[attrlen] = '\0';
1100
				pair->lvalue = attrlen;
1101
				debug_pair (stdout, pair);
1102
				insert_vp (&vp, (VALUE_PAIR *) NULL, pair);
1103
				break;
1104
1105
			    case PW_TYPE_INTEGER:
1106
			    case PW_TYPE_IPADDR:
1107
				memcpy ((char *) &lvalue, (char *) ptr,
1108
					sizeof (UINT4));
1109
				pair->lvalue = ntohl(lvalue);
1110
				*pair->strvalue = '\0'; /* zap DNS for IPADDR */
1111
				debug_pair (stdout, pair);
1112
				insert_vp (&vp, (VALUE_PAIR *) NULL, pair);
1113
				break;
1114
1115
			    default:
1116
				dprintf(1, (LOG_DAEMON, LOG_DEBUG,
1117
					"    %s (Unknown Type)", attr->name));
1118
				free (pair);
1119
				break;
1120
			}
1121
1122
		}
1123
		ptr += attrlen;
1124
		len -= attrlen + 2;
1125
	}
1126
1127
	if (bad_packet)
1128
	{
1129
		ddumpx(1, (LOG_DAEMON, LOG_DEBUG, auth->data,
1130
			ntohs(auth->length) - AUTH_HDR_LEN, 0,
1131
			"Dump of entire bad packet"));
1132
	}
1133
1134
	return (vp);
1135
} /* end of gen_valpairs () */
1136
1137
/*************************************************************************
1138
 *
1139
 *	Function: get_errmsg
1140
 *
1141
 *	Purpose: Return pointer to static string which gives complete
1142
 *		 filesystem error message.
1143
 *
1144
 *************************************************************************/
1145
1146
char *
1147
get_errmsg ()
1148
1149
{
1150
	static char     errmsg[80];
1151
1152
	if (errno < sys_nerr)
1153
	{
1154
		return (char *) sys_errlist[errno];
1155
	}
1156
	else
1157
	{
1158
		sprintf (errmsg, "Error %d", errno);
1159
		return errmsg;
1160
	}
1161
} /* end of get_errmsg () */
1162
1163
/******************************************************************************
1164
 *
1165
 *	Function: get_passwd
1166
 *
1167
 *	Purpose: Decrypts password contained in the PW_USER_PASSWORD or
1168
 *		 PW_ENCRYPTED_PASSWORD value-pair in the AUTH_REQ queue
1169
 *		 entry.  Tries to match one of these passwords against
1170
 *		 the "user_secret", if the "user_secret" is not a NULL
1171
 *		 pointer.  Will also perform a CHAP authentication check,
1172
 *		 if the PW_CHAP_PASSWORD value-pair is found in the request
1173
 *		 and "user_secret" is provided.
1174
 *
1175
 *	Returns: 2 to indicate CHAP failure,
1176
 *		 1 to indicate PASSWORD match failure,
1177
 *		 0 to indicate success,
1178
 *		-1 if no PASSWORD or CHAP value-pair is present.
1179
 *
1180
 ******************************************************************************/
1181
1182
int
1183
get_passwd (authreq, pw, user_secret, salt)
1184
1185
AUTH_REQ       *authreq;	/* Pointer to authentication request.  */
1186
char           *pw;		/* Receives decrypted password.        */
1187
				/* (If NULL, only CHAP is attempted.)  */
1188
char           *user_secret;	/* Secret we share with this user or   */
1189
				/* NULL.  If NULL, CHAP is not allowed */
1190
				/* and the password match check is not */
1191
				/* performed */
1192
char           *salt;		/* Encryption salt.  If this and the   */
1193
				/* user_secret are both non-NULL, then */
1194
				/* crypt() is called to encrypt the    */
1195
				/* password before attempting to match */
1196
				/* the user_secret or the check CHAP   */
1197
				/* reply.*/
1198
1199
{
1200
	VALUE_PAIR     *item;
1201
	u_char          buffer[AUTH_PASS_LEN + AUTH_VECTOR_LEN + 1];
1202
	int             i;
1203
	int             secretlen;
1204
	int             result;
1205
	u_char          digest[CHAP_VALUE_LENGTH];
1206
	u_char         *ptr;
1207
	char           *crypt ();
1208
	static char    *func = "get_passwd";
1209
1210
	dprintf(3, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func));
1211
1212
	if (pw != NULL &&
1213
		(item = get_vp (authreq->request, PW_USER_PASSWORD))
1214
							!= (VALUE_PAIR *) NULL)
1215
	{
1216
		/* Use the secret to setup the decryption digest */
1217
		secretlen = strlen ((char *) authreq->secret);
1218
		strcpy ((char *) buffer, (char *) authreq->secret);
1219
		memcpy ((char *) buffer + secretlen, (char *) authreq->vector,
1220
			AUTH_VECTOR_LEN);
1221
		md5_calc (digest, buffer, secretlen + AUTH_VECTOR_LEN);
1222
		memcpy (pw, item->strvalue, AUTH_PASS_LEN);
1223
		for (i = 0; i < AUTH_PASS_LEN; i++)
1224
		{
1225
			pw[i] ^= digest[i];
1226
		}
1227
		pw[AUTH_PASS_LEN] = '\0'; /* thanks to billw@cisco.com */
1228
		result = 0;
1229
		if (user_secret != (char *) NULL)
1230
		{
1231
			if (salt != (char *) NULL)
1232
			{
1233
				pw = crypt (pw, salt);
1234
			}
1235
1236
			if ((result = strcmp (pw, user_secret)) != 0)
1237
			{
1238
				result = 1;	/* Indicate pw match failure */
1239
			}
1240
		}
1241
	}
1242
	else if (user_secret != (char *) NULL &&
1243
			(item = get_vp (authreq->request, PW_CHAP_PASSWORD))
1244
							!= (VALUE_PAIR *) NULL)
1245
	{
1246
		/* Use MD5 to verify CHAP */
1247
		ptr = buffer;
1248
		*ptr++ = *item->strvalue;
1249
		strcpy ((char *) ptr, user_secret);
1250
1251
		/*
1252
		 * Allow for CHAP using an encrypted password. (The client
1253
		 * encrypts the password before generating the CHAP challenge
1254
		 * reply.)  This lets CHAP be used even when passwords are
1255
		 * stored in an encrypted form.  No clients provide this
1256
		 * capability yet, but they could start doing so now!
1257
		 */
1258
1259
		if (salt != (char *) NULL)
1260
		{
1261
			ptr = (u_char *) crypt ((char *) ptr, salt);
1262
		}
1263
1264
		secretlen = strlen ((char *) ptr);
1265
		ptr += secretlen;
1266
		memcpy ((char *) ptr, (char *) authreq->vector,
1267
			AUTH_VECTOR_LEN);
1268
		md5_calc (digest, buffer,
1269
			  1 + CHAP_VALUE_LENGTH + secretlen);
1270
		/* Compare them */
1271
		if ((result = memcmp ((char *) digest, item->strvalue + 1,
1272
				      CHAP_VALUE_LENGTH)) != 0)
1273
		{
1274
			result = 2;	/* Indicate CHAP failure */
1275
		}
1276
1277
	}
1278
	else
1279
	{
1280
		if (pw)
1281
			*pw = '\0';	/* Return null as pw */
1282
		result = -1;	/* -1 indicates no PW or CHAP vp in request */
1283
	}
1284
	return (result);
1285
} /* end of get_passwd () */
1286
1287
/*************************************************************************
1288
*
1289
*	Function: get_last_vp
1290
*
1291
*	Purpose: Find the last attribute value-pair (which matches the specified
1292
*		 attribute) from the specified value-pair list.
1293
*
1294
*************************************************************************/
1295
1296
VALUE_PAIR *
1297
get_last_vp (vp, attr)
1298
1299
VALUE_PAIR     *vp;
1300
UINT4           attr;
1301
1302
{
1303
	VALUE_PAIR     *last_vp;
1304
1305
	/*
1306
	 *	Find the first matching value-pair.
1307
	 */	
1308
1309
	for (; vp != (VALUE_PAIR *) NULL && vp->attribute != attr; vp = vp->next)
1310
	{
1311
		continue;
1312
	}
1313
1314
	/*
1315
	 *	If we run off the end of the list, return a NULL.
1316
	 */
1317
	if (vp == (VALUE_PAIR *) NULL)
1318
	{
1319
		return (VALUE_PAIR *) NULL;
1320
	}
1321
1322
	/* 
1323
	 *	Scan the remainder of the list for a match.
1324
	 *	If we found a match, return it.
1325
	 */
1326
	last_vp = get_last_vp (vp->next, attr);
1327
1328
	if (last_vp != (VALUE_PAIR *) NULL)
1329
	{
1330
		return (last_vp);
1331
	}
1332
1333
	/* If didn't find a match, return the one we found above. */
1334
	return (vp);	
1335
1336
} /* end of get_last_vp () */
1337
1338
/*************************************************************************
1339
*
1340
*	Function: get_vp
1341
*
1342
*	Purpose: Find the first attribute value-pair (which matches the given
1343
*		 attribute) from the specified value-pair list.
1344
*
1345
*************************************************************************/
1346
1347
VALUE_PAIR *
1348
get_vp (vp, attr)
1349
1350
VALUE_PAIR     *vp;
1351
UINT4           attr;
1352
1353
{
1354
	for (; vp != (VALUE_PAIR *) NULL && vp->attribute != attr; vp = vp->next)
1355
	{
1356
		continue;
1357
	}
1358
1359
	return (vp);
1360
} /* end of get_vp () */
1361
1362
/*************************************************************************
1363
 *
1364
 *	Function: hex_dump
1365
 *
1366
 *	Purpose: Format a region of octets into a formatted string
1367
 *		 suitable for displaying that region of memory.
1368
 *
1369
 *************************************************************************/
1370
1371
int
1372
hex_dump (buffer, data, len, offset)
1373
1374
char         *buffer;
1375
char         *data;
1376
int           len;
1377
int           offset;
1378
1379
{
1380
    int             i = 0;
1381
    int             j = 0;
1382
    int             size = 0;
1383
    int             wlen = 0;
1384
    char            hex[3];  /* a hex string placeholder. */
1385
    unsigned char  *start = (unsigned char *) data;
1386
1387
    if ((!buffer) || (!data) || (len <= 0))
1388
    {
1389
	return -1;
1390
    }
1391
1392
    sprintf (buffer, "0x%p:", data);
1393
    
1394
    buffer += strlen (buffer);
1395
    if (offset >= 0)
1396
    {
1397
	sprintf (buffer, " 0x%4.4x|", offset);
1398
	buffer += strlen (buffer);
1399
    }
1400
    
1401
    if (len > 16)
1402
    {
1403
	len = 16;
1404
    }
1405
    
1406
    /* Dump the data in hexadecimal. */
1407
1408
    for (i = 0; i < len; i += 4)
1409
    {
1410
	wlen = i + 4;
1411
	if (wlen > len)
1412
	{
1413
		wlen = len;
1414
	}
1415
1416
	strcat (buffer, " ");
1417
	buffer++;
1418
	for ( j = i; j < wlen; j++)
1419
	{
1420
	    sprintf (hex, "%2.2X", *start++);
1421
	    strcat (buffer, hex);
1422
	    buffer += 2;
1423
	    size++;
1424
	}
1425
	
1426
	for ( ; j < (i + 4) ; j++)
1427
	{
1428
	    strcat (buffer, "..");
1429
	    buffer += 2;
1430
	}
1431
    }
1432
    
1433
    for ( ; i < 16 ; i += 4)
1434
    {
1435
	strcat (buffer, " ........");
1436
	buffer += 9;
1437
    }
1438
1439
    /* Dump the data in ASCII. */
1440
1441
    strcat (buffer, "| |");
1442
    buffer += strlen (buffer);
1443
    for (i = 0; i < len; i++)
1444
    {
1445
	if ((' ' <= *data) && (*data < 0x7f))
1446
	{
1447
	    *buffer++ = *data;
1448
	}
1449
	else
1450
	{
1451
	    *buffer++ = '.';
1452
	}
1453
	data++;
1454
    }
1455
1456
    for ( ; i < 16 ; i++)
1457
    {
1458
	*buffer++ = '|';
1459
    }
1460
1461
    *buffer++ = '|';
1462
    *buffer = '\0';  /* Terminate the string. */
1463
1464
    return size;
1465
 
1466
} /* end of hex_dump () */
1467
1468
/*************************************************************************
1469
 *
1470
 *	Function: insert_vp
1471
 *
1472
 *	Purpose: Given the address of an existing list "a" and a pointer
1473
 *		 to an entry "p" in that list, add the value pair "b" to
1474
 *		 the "a" list after the "p" entry.  If "p" is NULL, add
1475
 *		 the value pair "b" to the end of "a".
1476
 *
1477
 *************************************************************************/
1478
1479
void
1480
insert_vp (a, p, b)
1481
1482
VALUE_PAIR     **a;
1483
VALUE_PAIR     *p;
1484
VALUE_PAIR     *b;
1485
1486
{
1487
	VALUE_PAIR     *this_node;
1488
	VALUE_PAIR     *vp;
1489
	static char    *func = "insert_vp";
1490
1491
	if (b->next != (VALUE_PAIR *) NULL)
1492
	{
1493
		logit (LOG_DAEMON, LOG_ALERT,
1494
			"%s: FATAL value pair (0x%p) next ptr. (0x%p) not NULL",
1495
			func, b, b->next);
1496
		dumpcore = 1;
1497
		abort ();
1498
	}
1499
1500
	if (*a == (VALUE_PAIR *) NULL)
1501
	{
1502
		*a = b;
1503
		return;
1504
	}
1505
1506
	vp = *a;
1507
1508
	if ( p == (VALUE_PAIR *) NULL) /* run to end of "a" list */
1509
	{
1510
		while (vp != (VALUE_PAIR *) NULL)
1511
		{
1512
			this_node = vp;
1513
			vp = vp->next;
1514
		}
1515
	}
1516
	else /* look for the "p" entry in the "a" list */
1517
	{
1518
		this_node = *a;
1519
		while (this_node != (VALUE_PAIR *) NULL)
1520
		{
1521
			if (this_node == p)
1522
			{
1523
				break;
1524
			}
1525
			this_node = this_node->next;
1526
		}
1527
	}
1528
1529
	b->next = this_node->next;
1530
	this_node->next = b;
1531
1532
	return;
1533
} /* end of insert_vp () */
1534
1535
/*************************************************************************
1536
 *
1537
 *	Function: logit
1538
 *
1539
 *	Purpose: Log the provided error message to the error logging facility.
1540
 *
1541
 *	Usage: logit (facility, level, format, args, ...);
1542
 *
1543
 *		Where facility and level are found in syslog.h and the
1544
 *		format is just a printf-style format string using the args.
1545
 *
1546
 *************************************************************************/
1547
1548
int
1549
logit (va_alist)
1550
1551
va_dcl
1552
1553
{
1554
	va_list         pvar;
1555
	int             priority;
1556
	int             facility;
1557
	int             level;
1558
	char           *format;
1559
	time_t          timeval;
1560
	char            filename[MAXPATHLEN];
1561
	static char     buffer[MAXPATHLEN];
1562
	static char    *func = "logit";
1563
1564
	va_start (pvar);
1565
	facility = va_arg (pvar, int);
1566
	level = va_arg (pvar, int);
1567
	format = va_arg (pvar, char *);
1568
	vsprintf (buffer, format, pvar);
1569
	va_end (pvar);
1570
1571
	if (file_logging == 1) /* log it to the logfile */
1572
	{
1573
		if (msgfd == stderr)
1574
		{
1575
			msgfd = (FILE *) NULL;
1576
		}
1577
1578
		if (msgfd == (FILE *) NULL)
1579
		{
1580
			sprintf (filename, "%s", RADIUS_LOG);
1581
			msgfd = fopen (filename, "a");
1582
1583
			if (msgfd == (FILE *) NULL)
1584
			{
1585
				fprintf (stderr,
1586
					"%s: Couldn't open %s for logging\n",
1587
					func, filename);
1588
				msgfd = stderr;
1589
			}
1590
		}
1591
1592
		if (level != LOG_DEBUG) /* don't log debugging messages */
1593
		{
1594
			timeval = time (0);
1595
			fprintf (msgfd, "%-24.24s: %s\n",
1596
				ctime (&timeval), buffer);
1597
1598
			if (level == LOG_ALERT)
1599
			{
1600
				fflush (msgfd);
1601
			}
1602
		}
1603
	}
1604
	else /* was not logging to a file */
1605
	{
1606
		if (file_logging == 2) /* log it to stderr */
1607
		{
1608
			fprintf (msgfd, "%s\n", buffer);
1609
		}
1610
		else /* log it to syslog(3) */
1611
		{
1612
			zap_logfile = 0;
1613
			priority = facility | level;
1614
			syslog (priority, "%s", buffer);
1615
		}
1616
	}
1617
1618
	if (level == LOG_DEBUG && ddt != (FILE *) NULL)
1619
	{
1620
		fprintf (ddt, "%s\n", buffer); /* log it to pre-opened device */
1621
	}
1622
1623
	return 0;
1624
} /* end of logit () */
1625
1626
/******************************************************************************
1627
 *
1628
 *	Function: loghead
1629
 *
1630
 *	Purpose: Write a header in a logfile if it is empty.  This function
1631
 *		 guarantees the header is only written once at the very
1632
 *		 beginning of the file.
1633
 *
1634
 *	Usage: loghead (file, format, args, ...);
1635
 *
1636
 *		Where file is a FILE pointer to an open file and the
1637
 *		format is just a printf style format string using the args.
1638
 *
1639
 *****************************************************************************/
1640
1641
int
1642
loghead (va_alist)
1643
1644
va_dcl
1645
1646
{
1647
	va_list          pvar;
1648
	int              fd;
1649
	char            *format;
1650
	FILE            *fp;
1651
	struct flock     lck;
1652
1653
	va_start (pvar);
1654
	fp = va_arg (pvar, FILE *);
1655
	fd = fileno (fp);
1656
	lck.l_type = F_WRLCK;
1657
	lck.l_whence = 0;
1658
	lck.l_start = SEEK_SET;
1659
	lck.l_len = 0L;
1660
	lck.l_pid = (pid_t) 0;
1661
	fcntl (fd, F_SETLKW, lck);
1662
	if (lseek (fd, 0L, SEEK_CUR) == (off_t) 0L)
1663
	{
1664
		format = va_arg (pvar, char *);
1665
		vfprintf (fp, format, pvar);
1666
		va_end (pvar);
1667
	}
1668
	lck.l_type = F_UNLCK;
1669
	fcntl (fd, F_SETLK, lck);
1670
	return 0;
1671
} /* end of loghead () */
1672
1673
/*************************************************************************
1674
 *
1675
 *	Function: missing_attribute
1676
 *
1677
 *	Purpose: Generate standard log message for missing attributes.
1678
 *
1679
 *************************************************************************/
1680
1681
void
1682
missing_attribute (authreq, func, attribute, etc)
1683
1684
AUTH_REQ       *authreq;
1685
char	       *func;		/* Function which called us. */
1686
int		attribute;	/* Missing attribute. */
1687
char	       *etc;		/* Optional additional information. */
1688
1689
{
1690
	VALUE_PAIR    *vp;
1691
	DICT_ATTR     *attr = dict_attrget (attribute);
1692
	char          *attr_name;
1693
	char           unknown_attr[20];
1694
1695
	if (attr != (DICT_ATTR *) NULL)
1696
	{
1697
		attr_name = attr->name;  /* Mark name. */
1698
	}
1699
	else
1700
	{
1701
		sprintf (unknown_attr, "unknown(%d)", attribute);
1702
		attr_name = unknown_attr;
1703
	}
1704
1705
	/* Get NAS-Identifier or IP address. */
1706
	if ((vp = get_vp (authreq->cur_request, PW_NAS_IDENTIFIER))
1707
							== (VALUE_PAIR *) NULL)
1708
	{
1709
		vp = get_vp (authreq->cur_request, PW_NAS_IP_ADDRESS);
1710
	}
1711
1712
	logit (LOG_DAEMON, LOG_ERR,
1713
       "%s:* MISSING %s (%d) in %s (type %d) request %d from %s via. %s[%d] %s",
1714
		func, attr_name, attribute, authtype_toa (authreq->code),
1715
		authreq->code, authreq->id,
1716
		(vp == (VALUE_PAIR *) NULL) ? "?" : avpair_vtoa (vp, 0),
1717
		ip_hostname (authreq->ipaddr), authreq->udp_port,
1718
		(etc == (char *) NULL)  ? "" : etc);
1719
	return;
1720
} /* end of missing_attribute () */
1721
1722
/*************************************************************************
1723
 *
1724
 *	Function: parse_realm
1725
 *
1726
 *	Purpose: Split user entered string found in PW_USER_NAME into
1727
 *		 the PW_USER_ID and PW_USER_REALM a/v pairs and hang
1728
 *		 them both on both the authreq->request and the
1729
 *		 authreq->cur_request lists for later use.
1730
 *
1731
 *	Returns: pointer to the realm a/v pair,
1732
 *		 NULL otherwise.
1733
 *
1734
 *************************************************************************/
1735
1736
VALUE_PAIR *
1737
parse_realm (authreq)
1738
1739
AUTH_REQ       *authreq;
1740
1741
{
1742
	int             count;
1743
	int             type;
1744
	VALUE_PAIR     *vp;
1745
	VALUE_PAIR    **vp_prev;
1746
	DICT_ATTR      *attr;
1747
	char           *agent;
1748
	char           *filter;
1749
	char           *pos;
1750
	char           *realm;
1751
	char           *u_realm;
1752
	char           *userid;
1753
	char            name[AUTH_ID_LEN + 1];
1754
	static char    *func = "parse_realm";
1755
1756
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1757
1758
	if ((vp = get_vp (authreq->cur_request, PW_USER_REALM))
1759
							!= (VALUE_PAIR *) NULL)
1760
	{
1761
		return vp;	/* It's already there, so just return it! */
1762
	}
1763
1764
	if ((vp = get_vp (authreq->cur_request, PW_USER_ID))
1765
							== (VALUE_PAIR *) NULL)
1766
	{
1767
		return vp;	/* The PW_USER_ID must be there to parse! */
1768
	}
1769
1770
	/* Make a local copy of the name. */
1771
	strncpy (name, vp->strvalue, AUTH_ID_LEN);
1772
	name[AUTH_ID_LEN] = '\0'; /* Guarantee a null terminated string. */
1773
1774
	if ((pos = strchr (name, '@')) != (char *) NULL) /* Is the '@' style. */
1775
	{
1776
		if ((userid = strtok (name, "@")) == (char *) NULL)
1777
		{
1778
			return (VALUE_PAIR *) NULL; /* Can't use a null name. */
1779
		}
1780
		if ((u_realm = strtok (NULL, "")) == (char *) NULL)
1781
		{
1782
			u_realm = "";
1783
		}
1784
	}
1785
	else /* There was no '@' in the User-Id. */
1786
	{
1787
		if ((pos = strchr (name, '/')) != (char *) NULL) /* '/' style */
1788
		{
1789
			if ((u_realm = strtok (name, "/")) == (char *) NULL)
1790
			{
1791
				u_realm = "";
1792
			}
1793
			if ((userid = strtok (NULL, "")) == (char *) NULL)
1794
			{
1795
				return (VALUE_PAIR *) NULL; /* Name was null. */
1796
			}
1797
		}
1798
		else /* There was neither '@' nor '/' in the User-Id. */
1799
		{
1800
			userid = name;
1801
			u_realm = "";
1802
		}
1803
	}
1804
1805
	/* Check for null user id. */
1806
	if ((userid == (char *) NULL) || (*userid == '\0'))
1807
	{
1808
		return (VALUE_PAIR *) NULL; /* Name was null. */
1809
	}
1810
1811
	strcpy (vp->strvalue, userid);	/* Modify the existing value... */
1812
	vp->lvalue = strlen (vp->strvalue);	/* and set length correctly. */
1813
1814
	/* Next, build the realm a/v pair. */
1815
	if ((vp = (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
1816
							== (VALUE_PAIR *) NULL)
1817
	{
1818
		logit (LOG_DAEMON, LOG_ALERT,
1819
			"%s: FATAL out of memory", func);
1820
		abort ();
1821
	}
1822
1823
	attr = dict_attrget (PW_USER_REALM);
1824
	strcpy (vp->name, attr->name);
1825
	vp->attribute = attr->value;
1826
	vp->type = attr->type;
1827
	vp->next = (VALUE_PAIR *) NULL;
1828
1829
	if ((u_realm == (char *) NULL) || (u_realm[0] == '\0'))
1830
	{
1831
		vp->strvalue[0] = '\0';
1832
		vp->lvalue = 0;
1833
	}
1834
	else /* There is a realm string. */
1835
	{
1836
		if (find_auth_type (u_realm, PW_PROTTYPE_DFLT,
1837
					(char *) authreq->file_pfx, &type,
1838
					&agent, &realm, &filter) != 0)
1839
		{
1840
			strcpy (vp->strvalue, u_realm);
1841
		}
1842
		else /* Use primary (canonical) realm name. */
1843
		{
1844
			strcpy (vp->strvalue, realm);
1845
		}
1846
		vp->lvalue = strlen (vp->strvalue);	/* Set length */
1847
	}
1848
	
1849
	/*
1850
	 *	Now stick it at end of original request items on the
1851
	 *	cur_request list so it can be included in cur_count.
1852
	 */
1853
	count = authreq->cur_count;
1854
	vp_prev = &authreq->cur_request;
1855
	while (count-- > 0)
1856
	{
1857
		if ((vp_prev = &(*vp_prev)->next) == (VALUE_PAIR **) NULL)
1858
		{
1859
			logit (LOG_DAEMON, LOG_ERR,
1860
				"%s: cur_count is bad!", func);
1861
			abort ();
1862
		}
1863
	}
1864
	vp->next = *vp_prev;
1865
	*vp_prev = vp;
1866
1867
	authreq->cur_count++; /* indicate and record the additional a/v pair */
1868
1869
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: name = '%s', realm = '%s'",
1870
		func, userid, vp->strvalue));
1871
1872
	return vp;
1873
} /* end of parse_realm () */
1874
1875
/*************************************************************************
1876
 *
1877
 *	Function: prune_pairs    XXX: turn this into an AATV later
1878
 *
1879
 *	Purpose: Remove all extraneous a/v pairs before replying to NAS.
1880
 *
1881
 *	Returns: 0 == normal return,
1882
 *		-1 == some error occurred.
1883
 *
1884
 *	Remark: This code may change the order of the a/v pairs returned.
1885
 *
1886
 *************************************************************************/
1887
1888
int
1889
prune_pairs (authreq, vendor, result)
1890
1891
AUTH_REQ       *authreq;	/* modify this request's cur_request list */
1892
PRUN_LIST      *vendor;		/* for this vendor's NAS */
1893
int             result;		/* the packet type Access-Accept or -Reject */
1894
1895
{
1896
	int             i;
1897
	int             j;
1898
	int             msg_flag;
1899
	int             success;
1900
	VALUE_PAIR    **prev_ptr;
1901
	VALUE_PAIR     *vp;
1902
	short           cnt[256];	/* holds the count of each attribute */
1903
	static char    *func = "prune_pairs";
1904
1905
	switch (result)
1906
	{
1907
	    case EV_ACK:
1908
		msg_flag = PRUN_FLG1;
1909
		break;
1910
1911
	    case EV_NAK:
1912
		msg_flag = PRUN_FLG2;
1913
		break;
1914
1915
	    case EV_ACC_CHAL: /* Not handled according to RADIUS DRAFT RFC */
1916
		return 0;
1917
		break;
1918
1919
	    default:
1920
		return (-1);
1921
		break;
1922
	}
1923
1924
	if (result == EV_ACK && authreq->code == PW_ACCOUNTING_REQUEST) /* no */
1925
	{
1926
		list_free (authreq->cur_request);
1927
		authreq->cur_request = (VALUE_PAIR *) NULL;
1928
		return 0;
1929
	}
1930
1931
	/* Initialize the array cnt[]. */
1932
1933
	memset (cnt, '\0', sizeof (cnt));
1934
1935
	/* Record the frequency of each reply a/v pair. */
1936
1937
	prev_ptr = &authreq->cur_request;
1938
	for ( vp = *prev_ptr;
1939
		vp != (VALUE_PAIR *) NULL ;
1940
		vp = *prev_ptr)
1941
	{
1942
		if (vp->attribute > 255) /* then it must be a check-item */
1943
		{
1944
			*prev_ptr = vp->next;
1945
			free (vp);	/* this one is not allowed */
1946
		}
1947
		else /* it is a reply-item, so count it */
1948
		{
1949
			++cnt[vp->attribute];
1950
			prev_ptr = &vp->next;
1951
		}
1952
	}
1953
1954
	/* Prune the cur_request list. */
1955
1956
	prev_ptr = &authreq->cur_request;
1957
	for (vp = *prev_ptr;
1958
		vp != (VALUE_PAIR *) NULL;
1959
		vp = *prev_ptr)
1960
	{
1961
		j = 0;
1962
		success = 0;
1963
		while (vendor->rules[j].value > 0) /* last element is == zero */
1964
		{
1965
			if (vendor->rules[j].value == vp->attribute)
1966
			{
1967
				success = 1;
1968
				break;
1969
			}
1970
			j++;
1971
		}
1972
1973
		if (success) /* then j is the index into the rules array */
1974
		{
1975
			/* See if this attribute type is allowed in this msg? */
1976
			if (vendor->rules[j].flags & msg_flag)
1977
			{
1978
				i = vendor->rules[j].count;
1979
				if (i < 0)
1980
				{
1981
					i = 9999; /* pick a suitable infinity */
1982
				}
1983
1984
				if (cnt[vp->attribute] > i) /* reduce counter */
1985
				{
1986
					if (cnt[vp->attribute] > 0) /* if pos */
1987
					{
1988
						--cnt[vp->attribute];
1989
					}
1990
					*prev_ptr = vp->next;
1991
					free (vp); /* this one is not allowed */
1992
					vp = (VALUE_PAIR *) NULL;
1993
				}
1994
				else /* it's a keeper! */
1995
				{
1996
					prev_ptr = &vp->next;
1997
				}
1998
			}
1999
			else /* no, unconditionally remove this a/v pair */
2000
			{
2001
				*prev_ptr = vp->next;
2002
				free (vp);	/* this one is not allowed */
2003
				vp = (VALUE_PAIR *) NULL;
2004
			}
2005
		}
2006
		else /* this a/v pair is not in the rules, logit and leave it */
2007
		{
2008
			logit (LOG_AUTH, LOG_ERR,
2009
				"%s: odd attribute number %d in reply",
2010
				func, vp->attribute);
2011
			prev_ptr = &vp->next;
2012
		}
2013
	}
2014
2015
	return 0;
2016
} /* end of prune_pairs () */
2017
2018
/*************************************************************************
2019
 *
2020
 *	Function: _reply_message
2021
 *
2022
 *	Purpose: Generate a reply message and stick it into the list
2023
 *		 of reply items to send back to the client.
2024
 *
2025
 *	Returns: 0 == normal return
2026
 *		-1 == msgno is out of range
2027
 *
2028
 *	Remarks: The message is also logged.
2029
 *
2030
 *************************************************************************/
2031
2032
int
2033
_reply_message (authreq, msgno, func, filename, line)
2034
2035
AUTH_REQ       *authreq;	/* this authentication request */
2036
ERRORCODE       msgno;		/* message number */
2037
char           *func;		/* calling function name */
2038
char           *filename;	/* Filename were error occured. */
2039
int             line;		/* Line number where error occured. */
2040
2041
{
2042
	static char    *msg[] =
2043
	{
2044
		"Internal error",
2045
		"Configuration error",
2046
		"Out of memory",
2047
		"Error creating file",
2048
		"No token available",
2049
		"No ports available for guests",
2050
		"Too many simultaneous sessions",
2051
		"ABS failure",
2052
		"Error querying balance",
2053
		"Your account balance is too low"
2054
	};
2055
2056
	if ((u_int)(--msgno) < numbof(msg))
2057
	{
2058
		logit (LOG_AUTH, LOG_INFO, "%s: %s at %s line %d", func,
2059
			msg[msgno], filename, line);
2060
		reply_sprintf (0, authreq, "%s [%s()]", msg[msgno], func);
2061
		return 0;
2062
	}
2063
	reply_sprintf (0, authreq, "Software error [%s()]", func);
2064
	logit (LOG_AUTH, LOG_ERR, "%s: message %d out of range at %s line %d",
2065
		func, msgno, filename, line);
2066
	return (-1);
2067
} /* end of _reply_message () */
2068
2069
/*************************************************************************
2070
 *
2071
 *	Function: reply_sprintf
2072
 *
2073
 *	Purpose: Generate a reply message and stick it into the list
2074
 *		 of reply items to send back to the client.
2075
 *
2076
 *	Returns: 0 == normal return
2077
 *		-1 == authreq is bad somehow.
2078
 *
2079
 *	Remarks: The message is also logged if logsw is 1.
2080
 *               It ALWAYS adds a <CR><LF> ("\r\n") to the message.
2081
 *
2082
 *************************************************************************/
2083
2084
int
2085
reply_sprintf ( va_alist /* int logsw, AUTH_REQ *authreq, char *format, ... */)
2086
2087
va_dcl
2088
2089
{
2090
	va_list         pvar;
2091
2092
	int             logsw;  /* First argument. */
2093
	AUTH_REQ       *authreq;
2094
	VALUE_PAIR     *msg;
2095
	char           *format;
2096
2097
	char            buf[MAXPATHLEN];
2098
2099
	/* Gather parameters. */
2100
2101
	va_start (pvar);
2102
	logsw = va_arg (pvar, int);
2103
	authreq = va_arg (pvar, AUTH_REQ *);
2104
	format = va_arg (pvar, char *);
2105
2106
	/* Format message, add it to reply, log it if necessary. */
2107
2108
	vsprintf (buf, format, pvar);
2109
2110
	if ( logsw != 0 )
2111
	{
2112
	      logit (LOG_AUTH, LOG_INFO, "%s", buf);
2113
	}
2114
2115
	strcat (buf, "\r\n");     /* Force newline. */
2116
	if ((msg = get_last_vp (authreq->cur_request, PW_REPLY_MESSAGE))
2117
							!= (VALUE_PAIR *) NULL)
2118
	{
2119
		/* Check to see if there's any space remaining. */
2120
		if ((strlen (buf) + strlen (msg->strvalue)) > AUTH_STRING_LEN)
2121
		{
2122
			msg = (VALUE_PAIR *) NULL;
2123
		}
2124
	}
2125
2126
	/* Concatenate the new message onto the last message. */
2127
	if (msg != (VALUE_PAIR *) NULL)
2128
	{
2129
		strcat (msg->strvalue, buf);
2130
	}
2131
	else
2132
	{
2133
		avpair_add (&authreq->cur_request, PW_REPLY_MESSAGE, buf, 0);
2134
	}
2135
2136
	return 0;
2137
} /* end of reply_sprintf () */
2138
2139
/*************************************************************************
2140
 *
2141
 *	Function: setupsock
2142
 *
2143
 *	Purpose: Gets and binds a socket.
2144
 *
2145
 *************************************************************************/
2146
2147
int
2148
setupsock (sin, portnum)
2149
2150
struct sockaddr_in *sin;
2151
int             portnum;
2152
2153
{
2154
	int             sock;
2155
	int             sinlen;
2156
	static char    *func = "setupsock";
2157
2158
	/*
2159
	 * Get a socket.
2160
	 */
2161
	if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
2162
	{
2163
		fprintf (stderr, "%s: socket() UDP socket %d failed, %s\n",
2164
			func, portnum, sys_errlist[errno]);
2165
		exit (-11);
2166
	}
2167
	sinlen = sizeof (struct sockaddr_in);
2168
	memset ((char *) sin, '\0', sinlen);
2169
2170
	/*
2171
	 * Get server's listening port number
2172
	 */
2173
	sin->sin_port = htons(portnum);
2174
2175
	/*
2176
	 * Bind socket to port.  bind finds free port if portnum == 0
2177
	 */
2178
	sin->sin_family = AF_INET;
2179
	sin->sin_addr.s_addr = INADDR_ANY;
2180
	if (bind (sock, (struct sockaddr *) sin,
2181
		sizeof (struct sockaddr_in)) < 0)
2182
	{
2183
		fprintf (stderr, "%s: bind() UDP socket %d failed, %s\n",
2184
			func, portnum, sys_errlist[errno]);
2185
		exit (-11);
2186
	}
2187
	/* Retrieve complete socket info */
2188
	if (getsockname (sock, (struct sockaddr *) sin, &sinlen) < 0)
2189
	{
2190
		fprintf (stderr, "%s: getsockname() UDP socket %d failed, %s\n",
2191
			func, portnum, sys_errlist[errno]);
2192
		exit (-11);
2193
	}
2194
	return sock;
2195
} /* end of setupsock () */
2196
2197
/*************************************************************************
2198
 *
2199
 *	Function: trunc_logfile
2200
 *
2201
 *	Purpose: Truncate, compress and rename the logfile near midnight.
2202
 *
2203
 *************************************************************************/
2204
2205
void
2206
trunc_logfile (fd, fname)
2207
2208
FILE          **fd;
2209
char           *fname;
2210
2211
{
2212
	static int      archived = 0;
2213
	struct tm      *clock;
2214
	time_t          now;
2215
2216
	now = time (0);
2217
	clock = localtime (&now);
2218
	if (((clock->tm_wday == TRUNCATION_DAY) || (TRUNCATION_DAY == 7)) &&
2219
		(clock->tm_hour == 0 && archived == 0))
2220
	{
2221
		compress_file (fd, fname);
2222
2223
		archived = 1;
2224
	}
2225
	else
2226
	{
2227
		if (clock->tm_hour != 0)
2228
		{
2229
			archived = 0;
2230
		}
2231
	}
2232
2233
	return;
2234
} /* end of trunc_logfile () */
2235
2236
/*************************************************************************
2237
 *
2238
 *	Function: type_string
2239
 *
2240
 *	Purpose: Returns protocol type string for logging of authentication
2241
 *		 requests.
2242
 *
2243
 *************************************************************************/
2244
2245
char *
2246
type_string (authreq, protpair)
2247
2248
AUTH_REQ       *authreq;
2249
VALUE_PAIR     *protpair;
2250
2251
{
2252
	char           *ptr;
2253
	VALUE_PAIR     *user_type;
2254
	static char     string[10];
2255
2256
	user_type = get_vp (authreq->request, PW_SERVICE_TYPE);
2257
	if (user_type != (VALUE_PAIR *) NULL &&
2258
		user_type->lvalue == PW_AUTHENTICATE_ONLY)
2259
	{
2260
		ptr = "auth";
2261
	}
2262
	else
2263
	{
2264
		ptr = (protpair == (VALUE_PAIR *) NULL)
2265
			? "dumb" : avpair_vtoa (protpair, AVPAIR_VTOA_NULL);
2266
	}
2267
	strncpy (string, ptr, sizeof (string));
2268
	return (string);
2269
} /* end of type_string () */
(-)pppd/rad_md5.c (+370 lines)
Line 0 Link Here
1
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
2
 */
3
4
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
5
rights reserved.
6
7
License to copy and use this software is granted provided that it
8
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
9
Algorithm" in all material mentioning or referencing this software
10
or this function.
11
12
License is also granted to make and use derivative works provided
13
that such works are identified as "derived from the RSA Data
14
Security, Inc. MD5 Message-Digest Algorithm" in all material
15
mentioning or referencing the derived work.
16
17
RSA Data Security, Inc. makes no representations concerning either
18
the merchantability of this software or the suitability of this
19
software for any particular purpose. It is provided "as is"
20
without express or implied warranty of any kind.
21
22
These notices must be retained in any copies of any part of this
23
documentation and/or software.
24
 */
25
26
#include "md5.h"
27
28
/* Constants for MD5Transform routine.
29
 */
30
#define S11 7
31
#define S12 12
32
#define S13 17
33
#define S14 22
34
#define S21 5
35
#define S22 9
36
#define S23 14
37
#define S24 20
38
#define S31 4
39
#define S32 11
40
#define S33 16
41
#define S34 23
42
#define S41 6
43
#define S42 10
44
#define S43 15
45
#define S44 21
46
47
static void MD5Transform PROTO_LIST ((UINT4[4], unsigned char[64]));
48
static void Encode PROTO_LIST
49
                ((unsigned char *, UINT4 *, unsigned int));
50
static void Decode PROTO_LIST
51
                ((UINT4 *, unsigned char *, unsigned int));
52
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
53
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
54
55
static unsigned char PADDING[64] = {
56
	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
59
};
60
61
/* F, G, H and I are basic MD5 functions.
62
 */
63
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
64
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
65
#define H(x, y, z) ((x) ^ (y) ^ (z))
66
#define I(x, y, z) ((y) ^ ((x) | (~z)))
67
68
/* ROTATE_LEFT rotates x left n bits.
69
 */
70
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
71
72
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
73
Rotation is separate from addition to prevent recomputation.
74
 */
75
#define FF(a, b, c, d, x, s, ac) { \
76
 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
77
 (a) = ROTATE_LEFT ((a), (s)); \
78
 (a) += (b); \
79
  }
80
#define GG(a, b, c, d, x, s, ac) { \
81
 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
82
 (a) = ROTATE_LEFT ((a), (s)); \
83
 (a) += (b); \
84
  }
85
#define HH(a, b, c, d, x, s, ac) { \
86
 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
87
 (a) = ROTATE_LEFT ((a), (s)); \
88
 (a) += (b); \
89
  }
90
#define II(a, b, c, d, x, s, ac) { \
91
 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
92
 (a) = ROTATE_LEFT ((a), (s)); \
93
 (a) += (b); \
94
  }
95
96
md5_calc (output, input, inlen)
97
unsigned char  *output;
98
unsigned char  *input;		/* input block */
99
unsigned int    inlen;		/* length of input block */
100
{
101
	MD5_CTX         context;
102
103
	MD5Init (&context);
104
	MD5Update (&context, input, inlen);
105
	MD5Final (output, &context);
106
}
107
108
/* MD5 initialization. Begins an MD5 operation, writing a new context.
109
 */
110
void 
111
MD5Init (context)
112
MD5_CTX        *context;	/* context */
113
{
114
	context->count[0] = context->count[1] = 0;
115
116
	/*
117
	 * Load magic initialization constants.
118
	 */
119
	context->state[0] = 0x67452301;
120
	context->state[1] = 0xefcdab89;
121
	context->state[2] = 0x98badcfe;
122
	context->state[3] = 0x10325476;
123
}
124
125
/* MD5 block update operation. Continues an MD5 message-digest
126
  operation, processing another message block, and updating the
127
  context.
128
 */
129
void 
130
MD5Update (context, input, inputLen)
131
MD5_CTX        *context;	/* context */
132
unsigned char  *input;		/* input block */
133
unsigned int    inputLen;	/* length of input block */
134
{
135
	unsigned int    i,
136
	                index,
137
	                partLen;
138
139
	/* Compute number of bytes mod 64 */
140
	index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
141
142
	/* Update number of bits */
143
	if ((context->count[0] += ((UINT4) inputLen << 3))
144
			< ((UINT4) inputLen << 3))
145
		context->count[1]++;
146
	context->count[1] += ((UINT4) inputLen >> 29);
147
148
	partLen = 64 - index;
149
150
	/*
151
	 * Transform as many times as possible.
152
	 */
153
	if (inputLen >= partLen)
154
	{
155
		MD5_memcpy
156
			((POINTER) & context->buffer[index], (POINTER) input, partLen);
157
		MD5Transform (context->state, context->buffer);
158
159
		for (i = partLen; i + 63 < inputLen; i += 64)
160
			MD5Transform (context->state, &input[i]);
161
162
		index = 0;
163
	}
164
	else
165
		i = 0;
166
167
	/* Buffer remaining input */
168
	MD5_memcpy
169
		((POINTER) & context->buffer[index], (POINTER) & input[i],
170
		 inputLen - i);
171
}
172
173
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
174
  the message digest and zeroizing the context.
175
 */
176
void 
177
MD5Final (digest, context)
178
unsigned char   digest[16];	/* message digest */
179
MD5_CTX        *context;	/* context */
180
{
181
	unsigned char   bits[8];
182
	unsigned int    index,
183
	                padLen;
184
185
	/* Save number of bits */
186
	Encode (bits, context->count, 8);
187
188
	/*
189
	 * Pad out to 56 mod 64.
190
	 */
191
	index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
192
	padLen = (index < 56) ? (56 - index) : (120 - index);
193
	MD5Update (context, PADDING, padLen);
194
195
	/* Append length (before padding) */
196
	MD5Update (context, bits, 8);
197
198
	/* Store state in digest */
199
	Encode (digest, context->state, 16);
200
201
	/*
202
	 * Zeroize sensitive information.
203
	 */
204
	MD5_memset ((POINTER) context, 0, sizeof (*context));
205
}
206
207
/* MD5 basic transformation. Transforms state based on block.
208
 */
209
static void 
210
MD5Transform (state, block)
211
UINT4           state[4];
212
unsigned char   block[64];
213
{
214
	UINT4           a = state[0],
215
	                b = state[1],
216
	                c = state[2],
217
	                d = state[3],
218
	                x[16];
219
220
	Decode (x, block, 64);
221
222
	/* Round 1 */
223
	FF (a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
224
	FF (d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
225
	FF (c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
226
	FF (b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
227
	FF (a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
228
	FF (d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
229
	FF (c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
230
	FF (b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
231
	FF (a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
232
	FF (d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
233
	FF (c, d, a, b, x[10], S13, 0xffff5bb1);	/* 11 */
234
	FF (b, c, d, a, x[11], S14, 0x895cd7be);	/* 12 */
235
	FF (a, b, c, d, x[12], S11, 0x6b901122);	/* 13 */
236
	FF (d, a, b, c, x[13], S12, 0xfd987193);	/* 14 */
237
	FF (c, d, a, b, x[14], S13, 0xa679438e);	/* 15 */
238
	FF (b, c, d, a, x[15], S14, 0x49b40821);	/* 16 */
239
240
	/* Round 2 */
241
	GG (a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
242
	GG (d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
243
	GG (c, d, a, b, x[11], S23, 0x265e5a51);	/* 19 */
244
	GG (b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
245
	GG (a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
246
	GG (d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
247
	GG (c, d, a, b, x[15], S23, 0xd8a1e681);	/* 23 */
248
	GG (b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
249
	GG (a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
250
	GG (d, a, b, c, x[14], S22, 0xc33707d6);	/* 26 */
251
	GG (c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
252
	GG (b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
253
	GG (a, b, c, d, x[13], S21, 0xa9e3e905);	/* 29 */
254
	GG (d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
255
	GG (c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
256
	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);	/* 32 */
257
258
	/* Round 3 */
259
	HH (a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
260
	HH (d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
261
	HH (c, d, a, b, x[11], S33, 0x6d9d6122);	/* 35 */
262
	HH (b, c, d, a, x[14], S34, 0xfde5380c);	/* 36 */
263
	HH (a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
264
	HH (d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
265
	HH (c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
266
	HH (b, c, d, a, x[10], S34, 0xbebfbc70);	/* 40 */
267
	HH (a, b, c, d, x[13], S31, 0x289b7ec6);	/* 41 */
268
	HH (d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
269
	HH (c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
270
	HH (b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
271
	HH (a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
272
	HH (d, a, b, c, x[12], S32, 0xe6db99e5);	/* 46 */
273
	HH (c, d, a, b, x[15], S33, 0x1fa27cf8);	/* 47 */
274
	HH (b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
275
276
	/* Round 4 */
277
	II (a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
278
	II (d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
279
	II (c, d, a, b, x[14], S43, 0xab9423a7);	/* 51 */
280
	II (b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
281
	II (a, b, c, d, x[12], S41, 0x655b59c3);	/* 53 */
282
	II (d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
283
	II (c, d, a, b, x[10], S43, 0xffeff47d);	/* 55 */
284
	II (b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
285
	II (a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
286
	II (d, a, b, c, x[15], S42, 0xfe2ce6e0);	/* 58 */
287
	II (c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
288
	II (b, c, d, a, x[13], S44, 0x4e0811a1);	/* 60 */
289
	II (a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
290
	II (d, a, b, c, x[11], S42, 0xbd3af235);	/* 62 */
291
	II (c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
292
	II (b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
293
294
	state[0] += a;
295
	state[1] += b;
296
	state[2] += c;
297
	state[3] += d;
298
299
	/*
300
	 * Zeroize sensitive information.
301
	 */
302
	MD5_memset ((POINTER) x, 0, sizeof (x));
303
}
304
305
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
306
  a multiple of 4.
307
 */
308
static void 
309
Encode (output, input, len)
310
unsigned char  *output;
311
UINT4          *input;
312
unsigned int    len;
313
{
314
	unsigned int    i,
315
	                j;
316
317
	for (i = 0, j = 0; j < len; i++, j += 4)
318
	{
319
		output[j] = (unsigned char) (input[i] & 0xff);
320
		output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
321
		output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
322
		output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
323
	}
324
}
325
326
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
327
  a multiple of 4.
328
 */
329
static void 
330
Decode (output, input, len)
331
UINT4          *output;
332
unsigned char  *input;
333
unsigned int    len;
334
{
335
	unsigned int    i,
336
	                j;
337
338
	for (i = 0, j = 0; j < len; i++, j += 4)
339
		output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
340
			(((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
341
}
342
343
/* Note: Replace "for loop" with standard memcpy if possible.
344
 */
345
346
static void 
347
MD5_memcpy (output, input, len)
348
POINTER         output;
349
POINTER         input;
350
unsigned int    len;
351
{
352
	unsigned int    i;
353
354
	for (i = 0; i < len; i++)
355
		output[i] = input[i];
356
}
357
358
/* Note: Replace "for loop" with standard memset if possible.
359
 */
360
static void 
361
MD5_memset (output, value, len)
362
POINTER         output;
363
int             value;
364
unsigned int    len;
365
{
366
	unsigned int    i;
367
368
	for (i = 0; i < len; i++)
369
		((char *) output)[i] = (char) value;
370
}
(-)pppd/rad_regexp.c (+24 lines)
Line 0 Link Here
1
#include <string.h>
2
#include <sys/types.h>
3
#include <regexp.h>
4
5
int regimatch(const char *expr, const char *str) {
6
  regexp *exp;
7
  int res;
8
9
  exp = regcomp(expr);
10
  res = regexec(exp, str);
11
  free(exp);
12
  return res;
13
}
14
15
#if 0
16
int main(ac, av)
17
char *av[];
18
{
19
  char *s1, *s2;
20
  if (ac != 3) return 3;
21
  s1 = strdup(av[1]); s2 = strdup(av[2]);
22
  return regimatch(s1, s2);
23
}
24
#endif
(-)pppd/rad_sendserver.c (+866 lines)
Line 0 Link Here
1
/*
2
 *
3
 *	RADIUS   Remote Authentication Dial In User Service
4
 *
5
 *
6
 * COPYRIGHT  (c)  1992, 1993, 1994, 1995, 1996
7
 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INCORPORATED
8
 * ALL RIGHTS RESERVED
9
 * 
10
 * PERMISSION IS GRANTED TO USE, COPY, CREATE DERIVATIVE WORKS AND REDISTRIBUTE
11
 * THIS SOFTWARE AND SUCH DERIVATIVE WORKS IN BINARY FORM ONLY FOR ANY PURPOSE,
12
 * SO LONG AS NO FEE IS CHARGED, AND SO LONG AS THE COPYRIGHT NOTICE ABOVE, THIS
13
 * GRANT OF PERMISSION, AND THE DISCLAIMER BELOW APPEAR IN ALL COPIES MADE; AND
14
 * SO LONG AS THE NAME OF THE UNIVERSITY OF MICHIGAN IS NOT USED IN ANY
15
 * ADVERTISING OR PUBLICITY PERTAINING TO THE USE OR DISTRIBUTION OF THIS
16
 * SOFTWARE WITHOUT SPECIFIC, WRITTEN PRIOR AUTHORIZATION.
17
 * 
18
 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE UNIVERSITY
19
 * OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT WARRANTY BY THE
20
 * UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21
 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
 * A PARTICULAR PURPOSE.  THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
23
 * LIABLE FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
24
 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN
25
 * CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
26
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
27
 * 
28
 * For a License to distribute source code or to charge a fee for the program
29
 * or a product containing the program, contact MERIT at the University of
30
 * Michigan:
31
 * 
32
 * aaa-license@merit.edu
33
 * 
34
 * [This version puts NO LIMITS on the use.  It grants the right to create
35
 * DERIVATIVE WORKS.  The user may copy and distribute the code in the form
36
 * received AND DERIVATIVE WORKS, so long as no fee is charged.  If copies are
37
 * made, our copyright notice and the disclaimer must be included on them.  USE
38
 * THIS VERSION WITH CARE.  THIS VERSION VERY LIKELY WILL KILL ANY POTENTIAL
39
 * FOR LATER COMMERCIALIZATION OF THE SOFTWARE.]
40
 *
41
 *
42
 * Public entry points in this file:
43
 *
44
 * check_radius_reply (only public for the MINOS/MNET daemon)
45
 * dir_init
46
 * send_server
47
 * random_vector
48
 *
49
 */
50
51
static char     rcsid[] = "$Id: sendserver.c,v 1.54 1996/05/22 19:58:19 web Exp $";
52
53
#include	<sys/types.h>
54
#include	<sys/socket.h>
55
#include	<netinet/in.h>
56
#include	<arpa/inet.h>
57
#include	<sys/param.h>
58
#include	<sys/time.h>
59
60
#if !(defined(FD_SET) || defined(linux))
61
#include	<sys/select.h>
62
#endif	/* FD_SET */
63
64
#include	<errno.h>
65
#include	<netdb.h>
66
#include	<stdio.h>
67
#include	<stdlib.h>
68
#include	<syslog.h>
69
#include	<time.h>
70
#include	<unistd.h>
71
72
#include	"radius.h"
73
74
#if !defined(__FreeBSD__) && !defined(_BSDI_VERSION) && !defined(__NetBSD__)
75
extern char    *sys_errlist[];
76
#endif	/* __FreeBSD__ */
77
78
#ifndef DEFAULT_SERVER
79
#define DEFAULT_SERVER	"ns.link-ul.ru"
80
#endif
81
82
#ifndef DEFAULT_DIR
83
#define DEFAULT_DIR	"/var/adm/raddb"
84
#endif
85
86
#ifndef DEFAULT_DIR2
87
#define DEFAULT_DIR2	"/var/adm/raddb"
88
#endif
89
90
extern char     ourhostname[MAXHOSTNAMELEN];
91
extern char    *progname;
92
extern int      debug_flag;
93
extern char    *radius_dir;
94
95
int             radsock = 0;	/* fd for radius socket, if non-blocking mode */
96
static int      find_server PROTO ((char *, int, UINT4 *, char *, char *));
97
void            random_vector PROTO ((u_char *));
98
int             check_radius_reply PROTO ((u_char *, char *, u_char *, u_int, char *));
99
100
/*************************************************************************
101
*
102
*	dir_init - if not set, initializes global var for RADIUS clients
103
*
104
**************************************************************************/
105
106
void
107
dir_init ()
108
109
{
110
	if (radius_dir == NULL || radius_dir[0] == '\0')
111
	{
112
		radius_dir = DEFAULT_DIR;
113
		if (access (radius_dir, X_OK) != 0)
114
		{
115
			radius_dir = DEFAULT_DIR2;
116
		}
117
	}
118
	return;
119
} /* end of dir_init () */
120
121
/*************************************************************************
122
 *
123
 *	Function: pack_list
124
 *
125
 *	Purpose: Packs an attribute value pair list into a buffer.
126
 *
127
 *	Returns: Number of octets packed.
128
 *
129
 *************************************************************************/
130
131
static int
132
pack_list (vp, buf)
133
134
VALUE_PAIR     *vp;
135
char           *buf;
136
137
{
138
	int             length;
139
	int             total_length = 0;
140
	UINT4           lvalue;
141
142
	while (vp != (VALUE_PAIR *) NULL)
143
	{
144
		debug_pair (stderr, vp);
145
		*buf++ = vp->attribute;
146
147
		switch (vp->type)
148
		{
149
		    case PW_TYPE_STRING:
150
			/* length = length = (vp->lvalue > 0) ?
151
					vp->lvalue : strlen (vp->strvalue); */
152
			length = strlen (vp->strvalue);
153
			*buf++ = length + 2;
154
			memcpy (buf, vp->strvalue, length);
155
			buf += length;
156
			total_length += length + 2;
157
			break;
158
159
		    case PW_TYPE_INTEGER:
160
		    case PW_TYPE_IPADDR:
161
			*buf++ = sizeof (UINT4) + 2;
162
			lvalue = htonl (vp->lvalue);
163
			memcpy (buf, (char *) &lvalue, sizeof (UINT4));
164
			buf += sizeof (UINT4);
165
			total_length += sizeof (UINT4) + 2;
166
			break;
167
168
		    default:
169
			break;
170
		}
171
172
		vp = vp->next;
173
	}
174
	return total_length;
175
} /* end of pack_list () */
176
177
/*************************************************************************
178
*
179
*	send_server - Sends request to specified RADIUS server and waits
180
*		      for response.  Request is retransmitted every
181
*		      "response_timeout" seconds a maximum of "retry_max"
182
*		      times.  Result is 0 if response was received, -1 if
183
*		      a problem occurred, or +1 on no-response condition.
184
*		      Returns request retransmit count in "retries" if
185
*		      server does respond.
186
*
187
*	Returns:	-1 ERROR_RC   -- on local error,
188
*			 0 OK_RC      -- on valid response from server,
189
*			 1 TIMEOUT_RC -- after retries * resp_timeout seconds,
190
*			-2 BADRESP_RC -- if response from server had errors.
191
*
192
**************************************************************************/
193
194
int 
195
send_server (data, retries, msg)
196
197
SEND_DATA      *data;		/* Data structure built by clients */
198
int            *retries;	/* Maximum num of times to retransmit request */
199
				/* Receives number of retries required, also */
200
char           *msg;		/* Receives error or advisory message */
201
202
{
203
	u_char          seq_nbr;    /* Sequence number to use in request  */
204
	int             fptype;     /* Framed proto, ustype == PW_FRAMED */
205
	int             i;
206
	int             length;
207
	int             result;
208
	int             retry_max;
209
	int             salen;
210
	int             secretlen;
211
	int             sockfd;
212
	int             timeout;    /* Number of secs. to wait for response */
213
	int             total_length;
214
	int             ustype;     /* User service type for this user */
215
	UINT4           auth_ipaddr;
216
	UINT4           lvalue;
217
	UINT4           myipaddr;
218
	UINT4           port_num;   /* Port number to use in request  */
219
	AUTH_HDR       *auth;
220
	VALUE_PAIR     *check;
221
	char           *passwd;		/* User password (unencrypted) */
222
	u_char         *ptr;
223
	VALUE_PAIR     *reply;
224
	char           *server_name;	/* Name of server to query */
225
	struct sockaddr_in *sin;
226
	struct servent *svp;
227
	struct timeval  authtime;
228
	fd_set          readfds;
229
	struct sockaddr salocal;
230
	struct sockaddr saremote;
231
	u_char          md5buf[256];
232
	u_char          passbuf[AUTH_PASS_LEN];
233
	u_char          send_buffer[1024];
234
	u_char          recv_buffer[1024];
235
	u_char          vector[AUTH_VECTOR_LEN];
236
	char            file[MAXPATHLEN];
237
	char            secret[MAX_SECRET_LENGTH + 1];
238
239
#ifdef KCHAP
240
	char            kchap_auth;
241
	u_char          buffer[AUTH_PASS_LEN + AUTH_VECTOR_LEN + 1];
242
	u_char          digest[AUTH_VECTOR_LEN];
243
	u_char          user_secret[CHAP_VALUE_LENGTH + 1];
244
245
#endif	/* KCHAP */
246
247
	/* Set up some defaults */
248
	dir_init ();
249
250
	server_name = data->server;
251
	if (server_name == (char *) NULL || server_name[0] == '\0')
252
	{
253
		server_name = DEFAULT_SERVER;
254
	}
255
256
	ustype = data->ustype;
257
258
#ifdef	KCHAP
259
	if (ustype == 255) /* KCHAP indicator */
260
	{
261
		kchap_auth = 1;
262
		ustype = PW_AUTHENTICATE_ONLY;
263
	}
264
	else
265
	{
266
		kchap_auth = 0;
267
	}
268
#endif	/* KCHAP */
269
270
	if (find_server (server_name, ustype, &auth_ipaddr, secret, msg) != 0)
271
	{
272
		return (ERROR_RC);
273
	}
274
275
	timeout = data->timeout;
276
	if (timeout == 0)
277
	{
278
		timeout++;
279
	}
280
281
	if (data->svc_port == 0)
282
	{
283
		if ((svp = getservbyname ("radius", "udp")) == NULL)
284
		{
285
			data->svc_port = PW_AUTH_UDP_PORT;
286
		}
287
		else
288
		{
289
			data->svc_port = ntohs (svp->s_port);
290
		}
291
	}
292
293
	if (!radsock)
294
	{
295
		sockfd = socket (AF_INET, SOCK_DGRAM, 0);
296
		if (sockfd < 0)
297
		{
298
			memset (secret, '\0', sizeof (secret));
299
			sprintf (msg, "socket: %s\n", sys_errlist[errno]);
300
			return (ERROR_RC);
301
		}
302
303
		length = sizeof (salocal);
304
		sin = (struct sockaddr_in *) & salocal;
305
		memset ((char *) sin, '\0', length);
306
		sin->sin_family = AF_INET;
307
		sin->sin_addr.s_addr = INADDR_ANY;
308
		sin->sin_port = htons (0);
309
		if (bind (sockfd, (struct sockaddr *) sin, length) < 0 ||
310
			   getsockname (sockfd, (struct sockaddr *) sin,
311
					&length) < 0)
312
		{
313
			close (sockfd);
314
			memset (secret, '\0', sizeof (secret));
315
			sprintf (msg, "bind: %s\n", sys_errlist[errno]);
316
			return (ERROR_RC);
317
		}
318
		retry_max = *retries;	/* Max. numbers to try for reply */
319
		*retries = 0;	/* Init retry cnt for blocking call */
320
	}
321
	else
322
	{
323
		sockfd = radsock;
324
		retry_max = 0;	/* No retries if non-blocking */
325
	}
326
327
	/* Build an authentication request */
328
	auth = (AUTH_HDR *) send_buffer;
329
	auth->code = data->code;
330
	random_vector (vector);
331
	seq_nbr = data->seq_nbr;
332
	auth->id = seq_nbr;
333
	memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
334
	total_length = AUTH_HDR_LEN;
335
	ptr = auth->data;
336
337
	/* User Name */
338
	*ptr++ = PW_USER_NAME;
339
	length = strlen (data->user_name);
340
	if (length > AUTH_ID_LEN)
341
	{
342
		length = AUTH_ID_LEN;
343
	}
344
	*ptr++ = length + 2;
345
	memcpy ((char *) ptr, data->user_name, length);
346
	ptr += length;
347
	total_length += length + 2;
348
349
	passwd = data->password;
350
351
	if (auth->code != PW_ACCOUNTING_REQUEST)
352
	{
353
#ifdef  KCHAP
354
		if (kchap_auth)
355
		{
356
			/* User Password */
357
			*ptr++ = PW_CHAP_PASSWORD;
358
			*ptr++ = 1 + AUTH_VECTOR_LEN + 2;
359
			*ptr++ = seq_nbr;  /* Pass CHAP identifier to RADIUS */
360
			*buffer = seq_nbr;/* Put CHAP id in work area for md5 */
361
			afs_pwd_to_secret (passwd, user_secret);/* Get secret */
362
			user_secret[CHAP_VALUE_LENGTH] = '\0';
363
			memcpy ((char *) buffer + 1, (char *) user_secret,
364
				CHAP_VALUE_LENGTH);
365
			memcpy ((char *) buffer + 1 + CHAP_VALUE_LENGTH,
366
				(char *) vector, AUTH_VECTOR_LEN);
367
			md5_calc (digest, buffer,
368
			  	1 + CHAP_VALUE_LENGTH + AUTH_VECTOR_LEN);
369
			memcpy ((char *) ptr, (char *) digest, AUTH_VECTOR_LEN);
370
			ptr += AUTH_VECTOR_LEN;
371
			total_length += 1 + AUTH_VECTOR_LEN + 2;
372
		}
373
		else
374
		{
375
#endif	/* KCHAP */
376
377
			/* User Password */
378
			*ptr++ = PW_USER_PASSWORD;
379
			*ptr++ = AUTH_PASS_LEN + 2;
380
381
			/* Encrypt the Password */
382
			length = strlen (passwd);
383
			if (length > AUTH_PASS_LEN)
384
			{
385
				length = AUTH_PASS_LEN;
386
			}
387
			memset ((char *) passbuf, '\0', AUTH_PASS_LEN);
388
			memcpy ((char *) passbuf, passwd, length);
389
390
			/* Calculate the MD5 Digest */
391
			secretlen = strlen (secret);
392
			strcpy ((char *) md5buf, secret);
393
			memcpy ((char *) md5buf + secretlen,
394
				(char *) auth->vector, AUTH_VECTOR_LEN);
395
			md5_calc (ptr, md5buf, secretlen + AUTH_VECTOR_LEN);
396
397
			/* Xor the password into the MD5 digest */
398
			for (i = 0; i < AUTH_PASS_LEN; i++)
399
			{
400
				*ptr++ ^= passbuf[i];
401
			}
402
			total_length += AUTH_PASS_LEN + 2;
403
404
#ifdef	KCHAP
405
		}
406
#endif	/* KCHAP */
407
	}
408
409
	/* Service Type */
410
	*ptr++ = PW_SERVICE_TYPE;
411
	*ptr++ = 2 + sizeof (UINT4);
412
	lvalue = htonl (ustype);
413
	memcpy ((char *) ptr, (char *) &lvalue, sizeof (UINT4));
414
	ptr = ptr + sizeof (UINT4);
415
	total_length += sizeof (UINT4) + 2;
416
417
	fptype = data->fptype;
418
	if (fptype > 0)			/* if -t [slip | ppp] */
419
	{
420
		/* Framed Protocol Type */
421
		*ptr++ = PW_FRAMED_PROTOCOL;
422
		*ptr++ = 2 + sizeof (UINT4);
423
		lvalue = htonl (fptype);
424
		memcpy ((char *) ptr, (char *) &lvalue, sizeof (UINT4));
425
		ptr = ptr + sizeof (UINT4);
426
		total_length += sizeof (UINT4) + 2;
427
	}
428
429
	/* Client IP Address */
430
	*ptr++ = PW_NAS_IP_ADDRESS;
431
	*ptr++ = 2 + sizeof (UINT4);
432
	myipaddr = htonl(data->client_id);
433
	memcpy ((char *) ptr, (char *) &myipaddr, sizeof (UINT4));
434
	ptr = ptr + sizeof (UINT4);
435
	total_length += sizeof (UINT4) + 2;
436
437
	/* Client Port Number */
438
	*ptr++ = PW_NAS_PORT;
439
	*ptr++ = 2 + sizeof (UINT4);
440
	port_num = htonl((UINT4) data->port_num);
441
	memcpy ((char *) ptr, (char *) &port_num, sizeof (UINT4));
442
	ptr = ptr + sizeof (UINT4);
443
	total_length += sizeof (UINT4) + 2;
444
445
	if (data->user_file != (char *) NULL) /* add a/v pairs from user_file */
446
	{
447
		sprintf (file, "%s.", data->user_file);
448
		check = (VALUE_PAIR *) NULL;
449
		if ((user_find (file, data->group, 0, &check, &reply, 1)) == 0)
450
		{
451
			total_length += (length = pack_list (check, ptr));
452
			ptr += length;
453
			total_length += (length = pack_list (reply, ptr));
454
			ptr += length;
455
		}
456
	}
457
458
	if (data->send_pairs != (VALUE_PAIR *) NULL) /* add more a/v pairs */
459
	{
460
		total_length += (length = pack_list (data->send_pairs, ptr));
461
		ptr += length;
462
	}
463
464
	auth->length = htons (total_length);
465
466
	sin = (struct sockaddr_in *) & saremote;
467
	memset ((char *) sin, '\0', sizeof (saremote));
468
	sin->sin_family = AF_INET;
469
	sin->sin_addr.s_addr = htonl (auth_ipaddr);
470
	sin->sin_port = htons (data->svc_port);
471
472
	for (;;)
473
	{
474
		sendto (sockfd, (char *) auth, (int) total_length, (int) 0,
475
			(struct sockaddr *) sin, sizeof (struct sockaddr_in));
476
477
		if (radsock)
478
		{		/* If non-blocking */
479
480
			/*
481
			 * Return stuff to be saved for evaluation of reply
482
			 * when it comes in
483
			 */
484
			strcpy (msg, secret);
485
			memcpy (msg + strlen (msg) + 1, (char *) vector,
486
				AUTH_VECTOR_LEN);
487
			memset (secret, '\0', sizeof (secret));
488
			return 1;	/* Pos. return means no error */
489
		}
490
		authtime.tv_usec = 0L;
491
		authtime.tv_sec = (long) timeout;
492
		FD_ZERO (&readfds);
493
		FD_SET (sockfd, &readfds);
494
		if (select (sockfd + 1, &readfds, NULL, NULL, &authtime) < 0)
495
		{
496
			if (errno == EINTR)
497
				continue;
498
			sprintf (msg, "select: %s\n", sys_errlist[errno]);
499
			memset (secret, '\0', sizeof (secret));
500
			close (sockfd);
501
			return (ERROR_RC);
502
		}
503
		if (FD_ISSET (sockfd, &readfds))
504
			break;
505
506
		/*
507
		 * Timed out waiting for response.  Retry "retry_max" times
508
		 * before giving up.  If retry_max = 0, don't retry at all.
509
		 */
510
		if (++(*retries) >= retry_max)
511
		{
512
			if (debug_flag > 0)
513
			{
514
				fprintf (stderr, "\n");
515
			}
516
			sprintf (msg,
517
				"No reply from RADIUS server \"%s(%u)\"\n",
518
				 ip_hostname (auth_ipaddr), data->svc_port);
519
			close (sockfd);
520
			memset (secret, '\0', sizeof (secret));
521
			return (TIMEOUT_RC);
522
		}
523
		else
524
		{
525
			if (debug_flag > 0)
526
			{
527
				fprintf (stderr, ".");
528
			}
529
		}
530
	}
531
	salen = sizeof (saremote);
532
	length = recvfrom (sockfd, (char *) recv_buffer,
533
			   (int) sizeof (recv_buffer),
534
			   (int) 0, &saremote, &salen);
535
536
	if (length <= 0)
537
	{
538
		sprintf (msg, "recvfrom: %s\n", sys_errlist[errno]);
539
		close (sockfd);
540
		memset (secret, '\0', sizeof (secret));
541
		return (ERROR_RC);
542
	}
543
	result = check_radius_reply (recv_buffer, secret, vector,
544
		(u_int) seq_nbr, msg);
545
	close (sockfd);
546
	memset (secret, '\0', sizeof (secret));
547
	return (result);
548
} /* end of send_server () */
549
550
/*************************************************************************
551
*
552
*	check_radius_reply - Verify items in returned packet.
553
*
554
*	Returns:	OK_RC       -- upon success,
555
*			BADRESP_RC  -- if anything looks funny.
556
*
557
*	Public entry point necessary for MINOS/MNET daemon.
558
*
559
**************************************************************************/
560
561
int 
562
check_radius_reply (buffer, secret, vector, seq_nbr, msg)
563
564
u_char         *buffer;
565
char           *secret;
566
u_char          vector[];
567
u_int           seq_nbr;
568
char           *msg;
569
570
{
571
	u_char          len;
572
	int             result;
573
	int             secretlen;
574
	int             totallen;
575
	AUTH_HDR       *auth;
576
	u_char         *next;
577
	u_char         *ptr;
578
	VALUE_PAIR     *vp;
579
	u_char          calc_digest[AUTH_VECTOR_LEN];
580
	u_char          reply_digest[AUTH_VECTOR_LEN];
581
582
	auth = (AUTH_HDR *) buffer;
583
	totallen = ntohs (auth->length);
584
585
	/* Verify that id (seq. number) matches what we sent */
586
	if (auth->id != (u_char) seq_nbr)
587
	{
588
		sprintf (msg, "Received non-matching id in server response\n");
589
		return (BADRESP_RC);
590
	}
591
592
	/* Verify the reply digest */
593
	memcpy ((char *) reply_digest, (char *) auth->vector, AUTH_VECTOR_LEN);
594
	memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
595
	secretlen = strlen (secret);
596
	memcpy ((char *) buffer + totallen, secret, secretlen);
597
	md5_calc (calc_digest, (char *) auth, totallen + secretlen);
598
599
	if (memcmp ((char *) reply_digest, (char *) calc_digest,
600
		    AUTH_VECTOR_LEN) != 0)
601
	{
602
		sprintf (msg, "Received invalid reply digest from server\n");
603
		return (BADRESP_RC);
604
	}
605
606
	if (debug_flag)
607
	{
608
		fprintf (stderr, "Received attribute/value pair(s):\n");
609
		vp = gen_valpairs (auth); /* just to print out in debug mode */
610
	}
611
612
	msg[0] = '\0';
613
	ptr = (u_char *) auth->data;
614
	totallen -= AUTH_HDR_LEN;
615
	while (totallen > 0)
616
	{
617
		len = ptr[1];
618
		totallen -= len;
619
		next = ptr + len;
620
		if (*ptr == '\0')
621
		{
622
			sprintf (msg, "Received bad attribute type from server\n");
623
			return (BADRESP_RC);
624
		}
625
626
		if (*ptr == PW_REPLY_MESSAGE)
627
		{
628
			ptr++;
629
			ptr++;
630
			strncat (msg, (char *) ptr, len - 2);
631
			strcat (msg, "\n");
632
		}
633
		ptr = next;
634
	}
635
636
	if ((auth->code == PW_ACCESS_ACCEPT) ||
637
		(auth->code == PW_PASSWORD_ACK) ||
638
		(auth->code == PW_ACCOUNTING_RESPONSE))
639
	{
640
		result = OK_RC;
641
	}
642
	else
643
	{
644
		result = BADRESP_RC;
645
	}
646
647
	return (result);
648
} /* end of check_radius_reply () */
649
650
/*************************************************************************
651
*
652
*	random_vector - Generates a random vector of AUTH_VECTOR_LEN octets.
653
*
654
*	Returns:	the vector (call by reference)
655
*
656
**************************************************************************/
657
658
void
659
random_vector (vector)
660
661
u_char         *vector;
662
663
{
664
	int             randno;
665
	int             i;
666
667
	srand (time (0));
668
	for (i = 0; i < AUTH_VECTOR_LEN;)
669
	{
670
		randno = rand ();
671
		memcpy ((char *) vector, (char *) &randno, sizeof (int));
672
		vector += sizeof (int);
673
		i += sizeof (int);
674
	}
675
	return;
676
} /* end of random_vector () */
677
678
/*************************************************************************
679
*
680
*	find_match - See if given IP address matches any address of hostname.
681
*
682
*	Returns:	 0 success
683
*			-1 failure
684
*
685
**************************************************************************/
686
687
static int 
688
find_match (ip_addr, hostname)
689
690
UINT4          *ip_addr;
691
char           *hostname;
692
693
{
694
	UINT4           addr;
695
	char          **paddr;
696
	struct hostent *hp;
697
698
	if (good_ipaddr (hostname) == 0)
699
	{
700
		if (*ip_addr == ntohl(inet_addr (hostname)))
701
		{
702
			return (0);
703
		}
704
	}
705
	else
706
	{
707
		if ((hp = gethostbyname (hostname)) == (struct hostent *) NULL)
708
		{
709
			return (-1);
710
		}
711
		if (hp->h_addr_list != (char **) NULL)
712
		{
713
			for (paddr = hp->h_addr_list; *paddr; paddr++)
714
			{
715
				addr = ** (UINT4 **) paddr;
716
				if (ntohl(addr) == *ip_addr)
717
				{
718
					return (0);
719
				}
720
			}
721
		}
722
	}
723
	return (-1);
724
} /* end of find_match */
725
726
/*************************************************************************
727
*
728
*	find_server - Look up the given server name in the clients file.
729
*
730
*	Returns:	 0 success
731
*			-1 failure
732
*
733
**************************************************************************/
734
735
static int 
736
find_server (server_name, ustype, ip_addr, secret, msg)
737
738
char           *server_name;
739
int             ustype;
740
UINT4          *ip_addr;
741
char           *secret;
742
char           *msg;
743
744
{
745
	static UINT4    myipaddr = 0;
746
	int             len;
747
	int             line_nbr = 0;
748
	int             result;
749
	FILE           *clientfd;
750
	char           *h;
751
	char           *s;
752
	char           *host2;
753
	char            buffer[128];
754
	char            fname[MAXPATHLEN];
755
	char            hostnm[AUTH_ID_LEN + 1];
756
757
	/* Get the IP address of the authentication server */
758
	if ((*ip_addr = get_ipaddr (server_name)) == (UINT4) 0)
759
	{
760
		sprintf (msg, "No such server: \"%s\"\n", server_name);
761
		return (-1);
762
	}
763
	/* Just use dummy secret for management polls */
764
	if (ustype == PW_ADMINISTRATIVE_USER) /* was old PW_MANAGEMENT_POLL */
765
	{
766
		strcpy (secret, MGMT_POLL_SECRET);
767
		return 0;
768
	}
769
	sprintf (fname, "%s/%s", radius_dir, RADIUS_CLIENTS);
770
	if ((clientfd = fopen (fname, "r")) == (FILE *) NULL)
771
	{
772
		sprintf (msg, "Couldn't open file \"%s\"\n", fname);
773
		return (-1);
774
	}
775
	if (!myipaddr)
776
	{
777
		if ((myipaddr = get_ipaddr (ourhostname)) == 0)
778
		{
779
			sprintf (msg, "Couldn't get our own ip address\n");
780
			fclose (clientfd);
781
			return (-1);
782
		}
783
	}
784
785
	result = 0;
786
	while (fgets (buffer, sizeof (buffer), clientfd) != (char *) NULL)
787
	{
788
		line_nbr++;
789
790
		if (*buffer == '#')
791
		{
792
			continue;
793
		}
794
795
		if ((h = strtok (buffer, " \t\n\r")) == NULL) /* 1st hostname */
796
		{
797
			continue;
798
		}
799
800
		memset (hostnm, '\0', AUTH_ID_LEN);
801
		len = strlen (h);
802
		if (len > AUTH_ID_LEN)
803
		{
804
			len = AUTH_ID_LEN;
805
		}
806
		strncpy (hostnm, h, len);
807
		hostnm[AUTH_ID_LEN] = '\0';
808
809
		if ((s = strtok (NULL, " \t\n\r")) == NULL) /* & secret field */
810
		{
811
			continue;
812
		}
813
814
		memset (secret, '\0', MAX_SECRET_LENGTH);
815
		len = strlen (s);
816
		if (len > MAX_SECRET_LENGTH)
817
		{
818
			len = MAX_SECRET_LENGTH;
819
		}
820
		strncpy (secret, s, len);
821
		secret[MAX_SECRET_LENGTH] = '\0';
822
823
		if (!strchr (hostnm, '/')) /* If single name form */
824
		{
825
			if (find_match (ip_addr, hostnm) == 0)
826
			{
827
				result++;
828
				break;
829
			}
830
		}
831
		else /* <name1>/<name2> "paired" form */
832
		{
833
			strtok (hostnm, "/"); /* replaces "/" with NULL char */
834
			host2 = strtok (NULL, " ");
835
			if (find_match (&myipaddr, hostnm) == 0)
836
			{	     /* If we're the 1st name, target is 2nd */
837
				if (find_match (ip_addr, host2) == 0)
838
				{
839
					result++;
840
					break;
841
				}
842
			}
843
			else	/* Check to see if we are the second name */
844
			{
845
				if (find_match (&myipaddr, host2) == 0)
846
				{ /* We are the 2nd name, target is 1st name */
847
					if (find_match (ip_addr, hostnm) == 0)
848
					{
849
						result++;
850
						break;
851
					}
852
				}
853
			}
854
		}
855
	}
856
	fclose (clientfd);
857
	if (result == 0)
858
	{
859
		memset (buffer, '\0', sizeof (buffer));
860
		memset (secret, '\0', sizeof (secret));
861
		sprintf (msg, "Couldn't find server in \"%s/%s\": \"%s\"\n",
862
			 radius_dir, RADIUS_CLIENTS, server_name);
863
		return (-1);
864
	}
865
	return 0;
866
} /* end of find_server () */
(-)pppd/rad_users.c (+3175 lines)
Line 0 Link Here
1
 /*
2
  * RADIUS -- Remote Authentication Dial In User Service
3
  * 
4
  * 
5
  * Livingston Enterprises, Inc. 6920 Koll Center Parkway Pleasanton, CA   94566
6
  * 
7
  * Copyright 1992 Livingston Enterprises, Inc.
8
  * 
9
  * Permission to use, copy, modify, and distribute this software for any
10
  * purpose and without fee is hereby granted, provided that this copyright
11
  * and permission notice appear on all copies and supporting documentation,
12
  * the name of Livingston Enterprises, Inc. not be used in advertising or
13
  * publicity pertaining to distribution of the program without specific
14
  * prior permission, and notice be given in supporting documentation that
15
  * copying and distribution is by permission of Livingston Enterprises, Inc.
16
  * 
17
  * Livingston Enterprises, Inc. makes no representations about the suitability
18
  * of this software for any purpose.  It is provided "as is" without express
19
  * or implied warranty.
20
  *
21
  * [C] The Regents of the University of Michigan and Merit Network, Inc. 1992,
22
  * 1993, 1994, 1995, 1996 All Rights Reserved
23
  *
24
  * Permission to use, copy, modify, and distribute this software and its
25
  * documentation for any purpose and without fee is hereby granted, provided
26
  * that the above copyright notice and this permission notice appear in all
27
  * copies of the software and derivative works or modified versions thereof,
28
  * and that both the copyright notice and this permission and disclaimer
29
  * notice appear in supporting documentation.
30
  *
31
  * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
32
  * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF
33
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE REGENTS OF THE
34
  * UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE
35
  * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR
36
  * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE.  The Regents of the
37
  * University of Michigan and Merit Network, Inc. shall not be liable for
38
  * any special, indirect, incidental or consequential damages with respect
39
  * to any claim by Licensee or any third party arising from use of the
40
  * software.
41
  *
42
  * Public entry points in this file:
43
  * 
44
  * add_file_list
45
  * config_init
46
  * config_files
47
  * config_fini
48
  * dns_recv
49
  * find_auth_type
50
  * find_auth_ent
51
  * find_client
52
  * find_client_by_name
53
  * find_host_by_name
54
  * free_user_ent
55
  * get_our_addr
56
  * ip_hostname
57
  * list_cat
58
  * list_copy
59
  * pair_parse
60
  * return_file_list
61
  * user_find
62
  * user_gettime
63
  * user_update
64
  * 
65
  */
66
67
static char     sccsid[] =
68
		"@(#)users.c 1.3 Copyright 1992 Livingston Enterprises Inc";
69
70
static char     rcsid[] = "$Id: users.c,v 1.89 1996/06/11 21:10:39 web Exp $";
71
72
#include	<sys/types.h>
73
#include	<sys/param.h>
74
#include	<sys/socket.h>
75
#include	<sys/time.h>
76
#include	<netinet/in.h>
77
#include	<arpa/inet.h>
78
79
#include	<stdio.h>
80
#include	<stdlib.h>
81
#include	<netdb.h>
82
#include	<time.h>
83
#include	<ctype.h>
84
#include	<dirent.h>
85
#include	<syslog.h>
86
87
#include	"radius.h"
88
89
static void          fieldcpy PROTO((char *, char **));
90
static FILE_LIST    *find_file_ent PROTO((char *));
91
static void          free_clients PROTO((CLIENT_ENTRY *));
92
static void          free_file_lists PROTO((void));
93
static int           host_is_us PROTO((char *));
94
static int           insert_client PROTO((char *, char *, char *));
95
static int           read_auth PROTO((FILE_LIST *, int));
96
static int           read_users PROTO((FILE_LIST *, int));
97
98
#if defined(ultrix) || defined(__hpux) || defined(__bsdi__) || defined(linux) || defined(SCO)
99
extern int           h_errno;
100
#endif	/* ultrix */
101
102
extern char          send_buffer[4096];
103
extern char          recv_buffer[4096];
104
extern char          ourhostname[MAXHOSTNAMELEN];
105
extern AATV         *authtype_tv[]; /* AATVs by authentication types */
106
extern int           debug_flag;
107
extern int           dumpcore;
108
extern char         *radius_dir;
109
extern FILE         *ddt;
110
extern int           authfile_cnt;
111
extern int           clients_cnt;
112
extern int           users_cnt;
113
extern int           file_logging; /*  0 => syslog, 1 => logfile, 2 => stderr */
114
extern AATV         *rad_ipc_aatv;
115
extern FILE         *msgfd;
116
117
int                  spawn_flag = 1;
118
int                  dnspid = 0;   /* PID of current DNS resolver process */
119
char                 default_radius_server[128] = DEFAULT_RADIUS_SERVER;
120
char                 default_tacacs_server[128] = DEFAULT_TACACS_SERVER;
121
int                  rad_ipc_port = 0;
122
123
static FILE_LIST    *file_list = (FILE_LIST *) NULL;
124
static CLIENT_ENTRY *client_list = (CLIENT_ENTRY *) NULL;
125
126
static UINT4         self_ip[11];	/* Used with multi-homed servers */
127
static int           is_engine = 0;	/* rlmadmin will not change this */
128
static CLIENT_ENTRY *old_clients;
129
130
/*************************************************************************
131
 *
132
 *	Function: add_file_list
133
 *
134
 *	Purpose: Find an existing FILE_LIST entry on file_list with the
135
 *		 specified prefix or add and init a new one if the
136
 *		 entry doesn't already exist.
137
 *
138
 *************************************************************************/
139
140
int
141
add_file_list (prefix)
142
143
char           *prefix;
144
145
{
146
	FILE_LIST      *file_ent;
147
	FILE_LIST     **fl_prev;
148
	static char    *func = "add_file_list";
149
150
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
151
152
	for (fl_prev = &file_list, file_ent = file_list;
153
		file_ent;
154
		fl_prev = &file_ent->next, file_ent = *fl_prev)
155
	{
156
		if (strcmp (file_ent->prefix, prefix) == 0)
157
		{
158
			return 0;
159
		}
160
	}
161
162
	if ((file_ent = (FILE_LIST *) malloc (sizeof (FILE_LIST)))
163
							== (FILE_LIST *) NULL)
164
	{
165
		logit (LOG_DAEMON, LOG_ALERT,
166
			"%s: Couldn't allocate FILE_ENTRY storage", func);
167
		return (-1);
168
	}
169
	file_ent->prefix = add_string (prefix, ASIS);
170
	file_ent->user_list = (USER_ENTRY *) NULL;
171
	file_ent->auth_list = (AUTH_ENTRY *) NULL;
172
	file_ent->next = (FILE_LIST *) NULL;
173
	*fl_prev = file_ent;
174
175
	return 0;
176
} /* end of add_file_list () */
177
178
/*************************************************************************
179
 *
180
 *	Function: config_init
181
 *
182
 *	Purpose: Setup environment for config_files() to run in.
183
 *
184
 *************************************************************************/
185
186
void
187
config_init ()
188
189
{
190
	is_engine = 1; /* flag set when engine calls us */
191
192
	/*
193
	 *	Set dnspid to defer the call to update_clients()
194
	 *	until the end of config_files().
195
	 */
196
	if (dnspid == 0)
197
	{
198
		dnspid = -1;
199
	}
200
201
	/*
202
	 *	Save the old clients list so we can pick up
203
	 *	the DNS addresses for the new list.
204
	 */
205
	old_clients = client_list;
206
	client_list = (CLIENT_ENTRY *) NULL;
207
	return;
208
} /* end of config_init () */
209
210
/*************************************************************************
211
 *
212
 *	Function: config_files
213
 *
214
 *	Purpose: Read database files into memory data structures.  Reads
215
 *		 "RADIUS_CLIENTS" and "RADIUS_AUTH" files unconditionally
216
 *		 and "RADIUS_USERS" file if users_flag is not zero.  Will
217
 * 		 read multiple users and authfiles if the "file_pfx" is
218
 *		 specified in a client entry (allowing use of different
219
 *		 files for different client NASes).
220
 *
221
 *		 If clear_flag is greater than zero, remove existing entries.
222
 *
223
 *		 A new CLIENT_ENTRY is added to the client_list for each
224
 *		 client appearing in the "RADIUS_CLIENTS" file.  A new
225
 *		 FILE_LIST entry is added for each unique file_pfx found
226
 *		 in the "RADIUS_CLIENTS" file.  Each FILE_LIST entry points
227
 *		 to a list of USER_ENTRYs containing the information read
228
 *		 from the "RADIUS_USERS" file with the corresponding
229
 *		 file_pfx.  Also each FILE_LIST entry contains a pointer to
230
 *		 the list of AUTH_ENTRYs containing realm information read
231
 *		 from the "RADIUS_AUTH" file with the corresponding file_pfx.
232
 *		 If either the "RADIUS_USERS" file or the "RADIUS_AUTH" file
233
 *		 with the given file_pfx did not exist, the default
234
 *		 (non-prefixed) file name entries are used instead.
235
 *
236
 *************************************************************************/
237
238
int
239
config_files (users_flag, clear_flag, dolog)
240
241
int             users_flag;
242
int             clear_flag;
243
int             dolog;
244
245
{
246
	int             i;
247
	int             ent_cnt = 0;
248
	int             line_nbr = 0;
249
	int             result;
250
	FILE_LIST      *file_ent;
251
	FILE           *clientfd;
252
	struct hostent *hp;
253
	char           *file_pfx;
254
	char           *host;
255
	char           *hostnm;
256
	char           *secret;
257
	char          **paddr;
258
	char            buffer[128];
259
	char            fname[MAXPATHLEN];
260
	static char    *func = "config_files";
261
262
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
263
264
	if (clear_flag > 0) /* Free current list, if already set up */
265
	{
266
		free_file_lists ();
267
	}
268
269
	/*
270
	 * Add default file_list entry - the entry for the "users" and
271
	 * "authfile" with no optional prefix
272
	 */
273
	add_file_list ("");
274
275
	/*
276
	 * Determine the IP address(es) of this machine
277
	 */
278
	if ((hp = gethostbyname (ourhostname)) == (struct hostent *) NULL)
279
	{
280
		logit (LOG_DAEMON, LOG_CRIT,
281
			"%s: Couldn't get our own IP address(es)", func);
282
		return (-1);
283
	}
284
285
	/*
286
	 *	First clear, then save our IP address(es)
287
	 *	leaving a zero entry at the end.
288
	 */
289
	memset ((char *) self_ip, '\0', sizeof (self_ip));
290
291
	if (hp->h_addr_list != (char **) NULL)
292
	{
293
		for (i = 0, paddr = hp->h_addr_list;
294
			(*paddr != (char *) NULL) &&
295
				(i < sizeof (self_ip) / 4 - 1);
296
			i++, paddr++)
297
		{
298
			memcpy ((char *) &self_ip[i], (char *) *paddr,
299
				hp->h_length);
300
			self_ip[i] = ntohl(self_ip[i]);
301
		}
302
	}
303
304
	/*
305
	 * Now read in all client file entries, adding a new "CLIENT_ENTRY"
306
	 * to client_list for each valid file entry found.  If there is more
307
	 * than one IP address for a given client DNS name, add an entry for
308
	 * each address.
309
	 */
310
	sprintf (fname, "%s/%s", radius_dir, RADIUS_CLIENTS);
311
	if ((clientfd = fopen (fname, "r")) == (FILE *) NULL)
312
	{
313
		logit (LOG_DAEMON, LOG_ERR, "%s: Couldn't open %s for reading",
314
			func, fname);
315
		return (-1);
316
	}
317
318
	clients_cnt = 0;
319
	result = -1;    /* Init result code */
320
321
	while (fgets (buffer, sizeof (buffer), clientfd) != (char *) NULL)
322
	{
323
		line_nbr++;
324
325
		if (*buffer == COMMENT)
326
		{
327
			continue;
328
		}
329
330
		/* first hostname */
331
		if ((hostnm = strtok (buffer, " \t\n\r")) == (char *) NULL)
332
		{
333
			continue;
334
		}
335
336
		/* and secret field */
337
		if ((secret = strtok (NULL, " \t\n\r")) == (char *) NULL)
338
		{
339
			logit (LOG_DAEMON, LOG_ERR,
340
				"%s: missing shared secret: %s line %d",
341
				func, fname, line_nbr);
342
			continue;
343
		}
344
345
		file_pfx = strtok (NULL, " \t\n\r"); /* optional prefix */
346
347
		/*
348
		 * Look for "paired" <name1>/<name2> entries.  This type of
349
		 * entry allows core RADIUS servers to share a common "clients"
350
		 * file.  If we're name1, name2 is the target name; if we are
351
		 * name2, then name1 is the target.  If we're neither name,
352
		 * then this entry isn't of interest to us and we ignore it.
353
		 */
354
		host = hostnm;  /* Assume just one name */
355
356
		if (strchr (hostnm, '/'))	/* If <name1>/<name2> form */
357
		{
358
			strtok (hostnm, "/");
359
			host = strtok (NULL, " ");
360
			if (host_is_us (hostnm))
361
			{
362
				/* We are 1st name - client is 2nd */
363
			}
364
			else
365
			{
366
				if (host_is_us (host))
367
				{
368
					/* We are 2nd - client is 1st */
369
					host = hostnm;
370
				}
371
				else /* We are neither - no match */
372
				{
373
					continue;
374
				}
375
			}
376
		}
377
378
		if ((result = insert_client (host, secret, file_pfx)) < 0)
379
		{
380
			break;
381
		}
382
		ent_cnt++;
383
	} /* end of while () */
384
	fclose (clientfd);
385
	if (dolog)
386
	{
387
		logit (LOG_DAEMON, LOG_INFO,
388
			"%s: %s (%u entries) read to memory",
389
			func, fname, ent_cnt);
390
	}
391
	clients_cnt = ent_cnt;
392
393
	/*
394
	 * Finally, go through all the file_list entries just added, reading
395
	 * in the "users" and "authfile" for each prefix found.
396
	 */
397
	for (file_ent = file_list; file_ent; file_ent = file_ent->next)
398
	{
399
400
#if !(defined(USE_DBM) || defined(USE_NDBM))
401
		if (users_flag)
402
			if (read_users (file_ent, dolog) != 0)
403
			{
404
				return (-1);
405
			}
406
#endif	/* USE_DBM || USE_NDBM */
407
408
		if (read_auth (file_ent, dolog) != 0)
409
		{
410
			return (-1);
411
		}
412
413
	}
414
415
	if (result < 0)
416
	{
417
		return (-1);
418
	}
419
420
	return 0;
421
} /* end of config_files () */
422
423
/*************************************************************************
424
 *
425
 *	Function: config_fini
426
 *
427
 *	Purpose: Cleanup environment after config_files() has run.
428
 *
429
 *************************************************************************/
430
431
void
432
config_fini ()
433
434
{
435
	free_clients (old_clients);
436
	old_clients = (CLIENT_ENTRY *) NULL;
437
438
	if ((file_logging == 1) && (msgfd != (FILE *) NULL))
439
	{
440
		fflush (msgfd);
441
	}
442
443
	if (dnspid == -1)
444
	{
445
		dnspid = 0;
446
	}
447
448
	update_clients ();       /* Start up the DNS resolver. */
449
450
	return;
451
} /* end of config_fini () */
452
453
/*************************************************************************
454
 *
455
 *      Function: dns_recv
456
 *
457
 *      Purpose: Process received DNS updates for clients database.
458
 *
459
 *************************************************************************/
460
461
void
462
dns_recv (sin, from_ipaddr, rcvlen)
463
464
struct sockaddr_in *sin;
465
UINT4               from_ipaddr;
466
int                 rcvlen;
467
468
{
469
	int              cnt;
470
	u_char           aliascnt;
471
	UINT4            temp;
472
	UINT4           *ourad;
473
	char            *ptr;
474
	IP_ADDRESS      *an_address;
475
	DNS_NAME        *a_name;
476
	CLIENT_ENTRY    *client_ent;
477
	static int       notify_count = 0;
478
	static char     *func = "dns_recv";
479
480
	notify_count ++;
481
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered (%d)",
482
		func, notify_count));
483
	 
484
	ptr = recv_buffer + 1;
485
486
	for (ourad = self_ip;
487
		(*ourad != (UINT4) 0) && (*ourad != from_ipaddr);
488
		ourad++)
489
	{
490
		continue;
491
	}
492
493
	if (*ourad == (UINT4) 0)
494
	{
495
		logit (LOG_DAEMON, LOG_INFO, "%s: from %s - Security Breach",
496
			func, ip_hostname (from_ipaddr));
497
		return;
498
	}
499
500
	for (client_ent = client_list;
501
		client_ent != (CLIENT_ENTRY *) NULL; 
502
		client_ent = client_ent->next)
503
	{
504
		if (strcmp (ptr, client_ent->hostname) == 0)
505
		{
506
			break;
507
		}
508
	}
509
510
	if (client_ent == (CLIENT_ENTRY *) NULL)
511
	{
512
		return;
513
	}		
514
515
	ptr += strlen (ptr) + 1;
516
	aliascnt = *ptr++;
517
518
	if (*ptr != '\0') /* If alias or IP address present, clear old ones */
519
	{
520
		/*
521
		 * Reset expire_time with some randomness (0 - 60 minutes)
522
		 * to avoid a burst of calls to gethostbyname().
523
		 */
524
		client_ent->expire_time = (time (0) + ADDRESS_AGING +
525
						(rand () & 3) * 60 * 20) & ~3;
526
		for (an_address = client_ent->addrs;
527
			an_address != (IP_ADDRESS *) NULL;
528
			an_address = client_ent->addrs)
529
		{
530
			client_ent->addrs = an_address->next;
531
			free (an_address);
532
		}
533
 
534
		for (a_name = client_ent->names;
535
			a_name != (DNS_NAME *) NULL;
536
			a_name = client_ent->names)
537
		{
538
			client_ent->names = a_name->next;
539
			free (a_name);
540
		}
541
	}
542
	else /* no alias or IP address present */
543
	{
544
		memcpy ((char *) &temp, ptr, sizeof (struct in_addr));
545
		if (temp == TRY_AGAIN) /* TRY_AGAIN is in netdb.h */
546
		{
547
			client_ent->expire_time = (time (0) + ADDRESS_AGING) 
548
									& ~3;
549
			logit (LOG_DAEMON, LOG_ALERT,
550
				"%s: DNS timeout on client or host '%s'",
551
				func, client_ent->hostname);
552
			return;
553
		}
554
		else
555
		{
556
			/*
557
			 *	Name couldn't be resolved -- log it and retry
558
			 *	shortly.  Cleverly (or foolishly) use the low
559
			 *	two bits of expire_time to control the logging
560
			 *	frequency.
561
			 */
562
			if ((cnt = client_ent->expire_time & 3) == 0)
563
			{
564
				/* Log every fourth time (or once per hour) */
565
				logit (LOG_DAEMON, LOG_ALERT,
566
				     "%s: DNS couldn't resolve name '%s' (%ld)",
567
					func, client_ent->hostname, temp);
568
			}
569
570
			client_ent->expire_time = ((time (0) + ADDRESS_AGING/4)
571
						 	& ~3) | (++cnt & 3);
572
			if (client_ent->addrs != (IP_ADDRESS *) NULL)
573
			{
574
				return;
575
			}
576
577
			/* Add invalid address to client_ent */
578
			memset (ptr, 255, sizeof (struct in_addr));
579
		}
580
	}
581
582
	/* Add alias names to client_ent structure */
583
	while (aliascnt-- > 0)
584
	{
585
		/* Note that DNS_NAME structure reserves one extra character. */
586
		if ((a_name =
587
			(DNS_NAME *) malloc (sizeof (DNS_NAME) + strlen (ptr)))
588
							== (DNS_NAME *) NULL)
589
		{
590
			logit (LOG_DAEMON, LOG_ALERT,
591
				"%s: FATAL Couldn't allocate DNS_NAME storage",
592
				func);
593
			abort ();
594
		}
595
596
		/* Note that type zero will always be last one. */
597
		strcpy (a_name->name, ptr); 
598
		ptr += strlen (ptr) + 1;
599
		a_name->type =  (u_char) *ptr++;
600
		a_name->next = client_ent->names;
601
		client_ent->names = a_name;
602
	}
603
604
	/*
605
	 * For each address in the list, add the address to the client_ent.
606
	 */
607
	while (*ptr != '\0')
608
	{
609
		if ((an_address = (IP_ADDRESS *) malloc (sizeof (IP_ADDRESS)))
610
							== (IP_ADDRESS *) NULL)
611
		{
612
			logit (LOG_DAEMON, LOG_ALERT,
613
				"%s: FATAL Couldn't allocate IP_ADDRESS storage",
614
				func);
615
			abort ();
616
		}
617
618
		an_address->next = client_ent->addrs;
619
		memcpy ((char *) &temp, ptr, sizeof (struct in_addr));
620
		an_address->ipaddr.s_addr = ntohl(temp);
621
		client_ent->addrs = an_address;
622
		ptr += sizeof (struct in_addr);
623
	}
624
625
	if (notify_count % DNS_SLEEP == DNS_SLEEP - 1)
626
	{
627
		logit (LOG_DAEMON, LOG_INFO, "%s: Notified of (%d) DNS changes",
628
			func, notify_count);
629
	}
630
631
	return;
632
} /* end of dns_recv () */
633
634
/*************************************************************************
635
 *
636
 *	Function: fieldcpy
637
 *
638
 *	Purpose: Copy a data field from the buffer.  Advance the buffer
639
 *		 past the data field.
640
 *
641
 *************************************************************************/
642
643
static void
644
fieldcpy (string, uptr)
645
646
char           *string;
647
char          **uptr;
648
649
{
650
	char           *ptr;
651
652
	ptr = *uptr;
653
	if (*ptr == '"')
654
	{
655
		ptr++;
656
		while (*ptr != '"' && *ptr != '\0' && *ptr != '\n')
657
		{
658
			*string++ = *ptr++;
659
		}
660
		*string = '\0';
661
		if (*ptr == '"')
662
		{
663
			ptr++;
664
		}
665
		*uptr = ptr;
666
		return;
667
	}
668
669
	while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0' && *ptr != '\n' &&
670
			*ptr != '=' && *ptr != ',')
671
	{
672
		*string++ = *ptr++;
673
	}
674
	*string = '\0';
675
	*uptr = ptr;
676
	return;
677
} /* end of fieldcpy () */
678
679
/*************************************************************************
680
 *
681
 *	Function: find_auth_ent
682
 *
683
 *	Purpose: Gives access to the private AUTH_ENT for the given realm.
684
 *
685
 *	Returns: pointer to the AUTH_ENT for the given realm,
686
 *		 or, NULL, if error.
687
 *
688
 *************************************************************************/
689
690
AUTH_ENTRY *
691
find_auth_ent (u_realm, prot, pfx)
692
693
char           *u_realm;
694
int             prot;
695
char           *pfx;
696
697
{
698
	int             head;
699
	int             pat_len;
700
	FILE_LIST      *file_ent;
701
	AUTH_ENTRY     *auth_ent;
702
	AUTH_ENTRY     *entry;
703
	char           *p;
704
	char           *realm_name;
705
	static char     temp[AUTH_ID_LEN + 1];
706
	static char    *func = "find_auth_ent";
707
708
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
709
710
	if (u_realm[0] == 0)	/* A null realm would match every line. */
711
	{
712
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: NULL realm", func));
713
		return (AUTH_ENTRY *) NULL;
714
	}
715
716
	if ((file_ent = find_file_ent (pfx)) == (FILE_LIST *) NULL)
717
	{
718
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: NULL file_ent", func));
719
		return (AUTH_ENTRY *) NULL;
720
	}
721
722
	if ((auth_ent = file_ent->auth_list) == (AUTH_ENTRY *) NULL)
723
	{
724
		/* If no auth_list for this prefix */
725
		file_ent = file_list;
726
		/* Default file_ent is first in file_list */
727
		if ((auth_ent = file_ent->auth_list) == (AUTH_ENTRY *) NULL)
728
		{
729
			logit (LOG_DAEMON, LOG_ERR,
730
				"%s: no default authfile data structure",
731
				func);
732
			return (AUTH_ENTRY *) NULL;
733
		}
734
	}
735
736
	/*
737
	 *	Match realm name (either exact match or substring match
738
	 *	based on *.realm syntax) with user supplied string.
739
	 */
740
	for ( ; auth_ent ; auth_ent = auth_ent->next )
741
	{
742
		realm_name = (char *) NULL;
743
		if (auth_ent->parent == (AUTH_ENTRY *) NULL) /* parent realm */
744
		{
745
			entry = auth_ent;
746
			/* Look for name match. */
747
			if (entry->name[0] == '*') /* this is wildcard realm */
748
			{
749
				p = &entry->name[1];
750
				pat_len = strlen (p);
751
				head = strlen (u_realm) - pat_len;
752
				if (strncmp ((char *) &u_realm[head],
753
					(char *) &entry->name[1], pat_len) == 0)
754
				{
755
					realm_name = u_realm;
756
				}
757
				else
758
				{
759
					realm_name = (char *) NULL;
760
				}
761
			}
762
			else /* not a wildcard realm */
763
			{
764
				if (strcasecmp (entry->name, u_realm) == 0)
765
				{
766
					realm_name = entry->name;
767
				}
768
			}
769
		}
770
		else /* this entry is an alias name for some real realm */
771
		{
772
			entry = auth_ent->parent;
773
			/* Look for name match. */
774
			if (entry->name[0] == '*') /* alias in wildcard realm */
775
			{
776
				p = &entry->name[1];
777
				pat_len = strlen (p);
778
				head = strlen (u_realm) - pat_len;
779
				if (strncmp ((char *) &u_realm[head],
780
					(char *) &entry->name[1], pat_len) == 0)
781
				{
782
					/* combine real prefix, parent suffix */
783
					strcpy (temp, u_realm);
784
					if (strtok (temp, ".") != (char *) NULL)
785
					{
786
						realm_name = strcat (temp,
787
							       &entry->name[1]);
788
					}
789
				}
790
				else
791
				{
792
					realm_name = (char *) NULL;
793
				}
794
			}
795
			else /* regular alias */
796
			{
797
				if (strcasecmp (auth_ent->name, u_realm) == 0)
798
				{
799
					realm_name = entry->name;
800
				}
801
			}
802
		}
803
804
		if (realm_name != (char *) NULL) /* then we have a name match */
805
		{
806
			if (!entry->prot || (entry->prot == prot))
807
			{
808
				break;
809
			}
810
		}
811
	}
812
813
	if (auth_ent == (AUTH_ENTRY *) NULL)
814
	{
815
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: realm not found", func));
816
		return (AUTH_ENTRY *) NULL;
817
	}
818
819
	return entry;
820
} /* end of find_auth_ent () */
821
822
/*************************************************************************
823
 *
824
 *	Function: find_auth_type
825
 *
826
 *	Purpose: Find the proper AUTH_ENTRY to use for the given authentication
827
 *		 realm name from the FILE_LIST entry with the given file_pfx.
828
 *
829
 *	Returns: The authentication type, name of the authentication agent to
830
 *		 use, the primary realm name and any optional packet filter
831
 *		 to be applied are returned.
832
 *
833
 *	Returns:  0 = normal return,
834
 *		 -1 = error return
835
 *
836
 *************************************************************************/
837
838
int
839
find_auth_type (u_realm, prot, pfx, type, agent, realm, filter)
840
841
char           *u_realm;
842
int             prot;
843
char           *pfx;
844
int            *type;	/* receives resultant authentication type value */
845
char          **agent;	/* receives resultant authentication agent name */
846
char          **realm;	/* receives resultant primary realm name */
847
char          **filter;	/* receives resultant authentication filter name */
848
849
{
850
	int             head;
851
	int             pat_len;
852
	FILE_LIST      *file_ent;
853
	AUTH_ENTRY     *auth_ent;
854
	AUTH_ENTRY     *entry;
855
	char           *p;
856
	char           *realm_name;
857
	static char     temp[AUTH_ID_LEN + 1];
858
	static char    *func = "find_auth_type";
859
860
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
861
862
	if (u_realm[0] == 0)	/* A null realm would match every line. */
863
	{
864
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: NULL realm", func));
865
		return (-1);
866
	}
867
868
	if ((file_ent = find_file_ent (pfx)) == (FILE_LIST *) NULL)
869
	{
870
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: NULL file_ent", func));
871
		return (-1);
872
	}
873
874
	if ((auth_ent = file_ent->auth_list) == (AUTH_ENTRY *) NULL)
875
	{
876
		/* If no auth_list for this prefix */
877
		file_ent = file_list;
878
		/* Default file_ent is first in file_list */
879
		if ((auth_ent = file_ent->auth_list) == (AUTH_ENTRY *) NULL)
880
		{
881
			logit (LOG_DAEMON, LOG_ERR,
882
				"%s: no default authfile data structure",
883
				func);
884
			return (-1);
885
		}
886
	}
887
888
	/*
889
	 *	Match realm name (either exact match or substring match
890
	 *	based on *.realm syntax) with user supplied string.
891
	 */
892
	for ( ; auth_ent ; auth_ent = auth_ent->next )
893
	{
894
		realm_name = (char *) NULL;
895
		if (auth_ent->parent == (AUTH_ENTRY *) NULL) /* parent realm */
896
		{
897
			entry = auth_ent;
898
			/* Look for name match. */
899
			if (entry->name[0] == '*') /* this is wildcard realm */
900
			{
901
				p = &entry->name[1];
902
				pat_len = strlen (p);
903
				head = strlen (u_realm) - pat_len;
904
				if (strncmp ((char *) &u_realm[head],
905
					(char *) &entry->name[1], pat_len) == 0)
906
				{
907
					realm_name = u_realm;
908
				}
909
				else
910
				{
911
					realm_name = (char *) NULL;
912
				}
913
			}
914
			else /* not a wildcard realm */
915
			{
916
				if (strcasecmp (entry->name, u_realm) == 0)
917
				{
918
					realm_name = entry->name;
919
				}
920
			}
921
		}
922
		else /* this entry is an alias name for some real realm */
923
		{
924
			entry = auth_ent->parent;
925
			/* Look for name match. */
926
			if (entry->name[0] == '*') /* alias in wildcard realm */
927
			{
928
				p = &entry->name[1];
929
				pat_len = strlen (p);
930
				head = strlen (u_realm) - pat_len;
931
				if (strncmp ((char *) &u_realm[head],
932
					(char *) &entry->name[1], pat_len) == 0)
933
				{
934
					/* combine real prefix, parent suffix */
935
					strcpy (temp, u_realm);
936
					if (strtok (temp, ".") != (char *) NULL)
937
					{
938
						realm_name = strcat (temp,
939
							       &entry->name[1]);
940
					}
941
				}
942
				else
943
				{
944
					realm_name = (char *) NULL;
945
				}
946
			}
947
			else /* regular alias */
948
			{
949
				if (strcasecmp (auth_ent->name, u_realm) == 0)
950
				{
951
					realm_name = entry->name;
952
				}
953
			}
954
		}
955
956
		if (realm_name != (char *) NULL) /* then we have a name match */
957
		{
958
			if (!entry->prot || (entry->prot == prot))
959
			{
960
				break;
961
			}
962
		}
963
	}
964
965
	if (auth_ent == (AUTH_ENTRY *) NULL)
966
	{
967
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: realm not found", func));
968
		return (-1);
969
	}
970
971
	*type = entry->type;
972
	*agent = entry->host;
973
	*realm = realm_name;
974
	*filter = entry->filter;
975
	dprintf(2, (LOG_AUTH, LOG_DEBUG,
976
		"%s: type %d, agent '%s', realm '%s' and filter '%s'",
977
		func, entry->type, entry->host, realm_name, entry->filter));
978
	return 0;
979
} /* end of find_auth_type () */
980
981
/*************************************************************************
982
 *
983
 *	Function: find_client
984
 *
985
 *	Purpose: Find the CLIENT_ENTRY in client_list for the client with
986
 *		 the given IP address.  If the entry is found, the secret
987
 *		 shared with this client, any configured file_pfx to be
988
 *		 used for this client and the client's name are returned.
989
 *
990
 *	Returns: 0 = found client entry,
991
 *		-1 = client not found.
992
 *
993
 *************************************************************************/
994
995
int
996
find_client (ipaddr, hostname, secret, pfx)
997
998
UINT4           ipaddr;
999
char          **hostname;	/* Receives resultant hostname, if found */
1000
char          **secret;		/* Receives resultant secret, if found */
1001
char          **pfx;		/* Receives resultant prefix, if found */
1002
1003
{
1004
	int             ud = 0;
1005
	CLIENT_ENTRY   *client_ent;
1006
	IP_ADDRESS     *an_address;
1007
	time_t          cur_time;
1008
	static char    *func = "find_client";
1009
1010
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1011
1012
	cur_time = time (0);
1013
	for (client_ent = client_list;
1014
		client_ent;
1015
		client_ent = client_ent->next)
1016
	{
1017
		if (cur_time > client_ent->expire_time)
1018
		{
1019
			ud = 1;
1020
		}
1021
1022
		for (an_address = client_ent->addrs;
1023
			an_address != (IP_ADDRESS *) NULL;
1024
			an_address = an_address->next)
1025
		{
1026
			if (an_address->ipaddr.s_addr == ipaddr)
1027
			{
1028
				break;
1029
			}
1030
		}
1031
1032
		if (an_address)
1033
		{
1034
			break;
1035
		}
1036
	}
1037
1038
	if (ud > 0)
1039
	{
1040
		update_clients ();
1041
	}
1042
1043
	/* Don't match host-only entries (those with a null secret) */
1044
	if (client_ent == (CLIENT_ENTRY *) NULL || *client_ent->secret == '\0')
1045
	{
1046
		return (-1);
1047
	}
1048
1049
	*hostname = client_ent->hostname;
1050
	*secret = client_ent->secret;
1051
	*pfx = client_ent->prefix;
1052
1053
	return (0);
1054
} /* end of find_client () */
1055
1056
/*************************************************************************
1057
 *
1058
 *	Function: find_client_by_name
1059
 *
1060
 *	Purpose: Find the CLIENT_ENTRY in client_list for the client with
1061
 *		 the given hostname.  If the entry is found, the secret
1062
 *		 shared with this client, any configured file_pfx to be
1063
 *		 used for this client and the client's name are returned.
1064
 *
1065
 *	Returns: 0 = found client entry and resolved IP address,
1066
 *		 1 = found client entry but no IP address,	
1067
 *		 2 = found host entry but IP address not obtained 
1068
 *		     (unresolvable DNS name),	
1069
 *		-1 = client not found.
1070
 *
1071
 *************************************************************************/
1072
1073
int
1074
find_client_by_name (ipaddr, hostname, secret, pfx)
1075
1076
UINT4          *ipaddr;		/* Receives resultant address, if found */
1077
char           *hostname;	/* Match this name */
1078
char          **secret;		/* Receives resultant secret, if found */
1079
char          **pfx;		/* Receives resultant prefix, if found */
1080
1081
{
1082
	int             ud = 0;
1083
	CLIENT_ENTRY   *client_ent;
1084
	DNS_NAME       *name_ent;
1085
	char           *name;
1086
	time_t          cur_time;
1087
	static char    *func = "find_client_by_name";
1088
1089
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1090
1091
	if (good_ipaddr (hostname) == 0)
1092
	{
1093
		/* name = address same as find_client() call */
1094
		*ipaddr = ntohl(inet_addr (hostname));
1095
		return find_client (*ipaddr, &name, secret, pfx);
1096
	}
1097
1098
	if (strcmp (hostname, RADIUS_LOCALSERVER) == 0)
1099
	{
1100
		hostname = ourhostname;
1101
	}
1102
1103
	cur_time = time (0);
1104
	for (client_ent = client_list;
1105
		client_ent != (CLIENT_ENTRY *) NULL;
1106
		client_ent = client_ent->next)
1107
	{
1108
		if (cur_time > client_ent->expire_time)
1109
		{
1110
			ud = 1;
1111
		}
1112
1113
		if (strcmp (client_ent->hostname, hostname) == 0)
1114
		{
1115
			break;
1116
		}
1117
1118
		for (name_ent = client_ent->names;
1119
			name_ent != (DNS_NAME *) NULL;
1120
			name_ent = name_ent->next)
1121
		{
1122
			if (strcmp (name_ent->name, hostname) == 0)
1123
			{
1124
				break;
1125
			}
1126
		}
1127
1128
		if (name_ent != (DNS_NAME *) NULL)
1129
		{
1130
			break;
1131
		}
1132
	}
1133
1134
	if (ud > 0)
1135
	{
1136
		update_clients ();
1137
	}
1138
1139
	/* Don't match host-only entries (those with a null secret) */
1140
	if (client_ent == (CLIENT_ENTRY *) NULL || *client_ent->secret == '\0')
1141
	{
1142
		return (-1);
1143
	}
1144
1145
	*secret = client_ent->secret;
1146
	*pfx = client_ent->prefix;
1147
1148
	if (client_ent->addrs == (IP_ADDRESS *) NULL)
1149
	{
1150
		*ipaddr = 0;
1151
		return (1);
1152
	}
1153
1154
	if ((*ipaddr = client_ent->addrs->ipaddr.s_addr) == -1)
1155
	{
1156
		return (2);
1157
	}
1158
1159
	return (0);
1160
} /* end of find_client_by_name () */
1161
1162
/*************************************************************************
1163
 *
1164
 *	Function: find_host_by_name
1165
 *
1166
 *	Purpose: Resolve the host address by looking in the client list.
1167
 *		 Non-clients (those with a null secret) in this list
1168
 *		 are matched as well as normal clients.
1169
 *
1170
 *	Returns: 0 = found host entry and resolved IP address,
1171
 *		 1 = found host entry but unresolved IP address,	
1172
 *		 2 = found host entry but IP address not obtained 
1173
 *		     (unresolvable DNS name - uses address 255.255.255.255),	
1174
 *		-1 = host not found.
1175
 *
1176
 *************************************************************************/
1177
1178
int
1179
find_host_by_name (ipaddr, hostname)
1180
1181
UINT4          *ipaddr;		/* receives resultant address if found */
1182
char           *hostname;	/* Match this name */
1183
1184
{
1185
	int             ud = 0;
1186
	char           *p;
1187
	char           *q;
1188
	CLIENT_ENTRY   *client_ent;
1189
	DNS_NAME       *name_ent;
1190
	time_t          cur_time;
1191
	static char    *func = "find_host_by_name";
1192
1193
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1194
1195
	if (good_ipaddr (hostname) == 0)
1196
	{
1197
		*ipaddr = ntohl(inet_addr (hostname));
1198
		return 0;
1199
	}
1200
1201
	if (strcmp (hostname, RADIUS_LOCALSERVER) == 0)
1202
	{
1203
		*ipaddr = self_ip[0];
1204
		return 0;
1205
	}
1206
1207
	/* See if it's us.  Match full name or up to "." of our name */
1208
	for (p = hostname, q = ourhostname; *p == *q; p++, q++)
1209
	{
1210
		if (*p == '\0')
1211
		{
1212
			break;
1213
		}
1214
	}
1215
1216
	if (*p == '\0' && (*q == '\0' || *q == '.'))
1217
	{
1218
		*ipaddr = self_ip[0];
1219
		return 0;
1220
	}
1221
1222
	cur_time = time (0);
1223
	for (client_ent = client_list;
1224
		client_ent != (CLIENT_ENTRY *) NULL;
1225
		client_ent = client_ent->next)
1226
	{
1227
		if (cur_time > client_ent->expire_time)
1228
		{
1229
			ud = 1;
1230
		}
1231
1232
		if (strcmp (client_ent->hostname, hostname) == 0)
1233
		{
1234
			break;
1235
		}
1236
1237
		for (name_ent = client_ent->names;
1238
			name_ent != (DNS_NAME *) NULL;
1239
			name_ent = name_ent->next)
1240
		{
1241
			if (strcmp (name_ent->name, hostname) == 0)
1242
			{
1243
				break;
1244
			}
1245
		}
1246
1247
		if (name_ent != (DNS_NAME *) NULL)
1248
		{
1249
			break;
1250
		}
1251
	}
1252
1253
	if (ud > 0)
1254
	{
1255
		update_clients ();
1256
	}
1257
1258
	if (client_ent == (CLIENT_ENTRY *) NULL)
1259
	{
1260
		*ipaddr = 0;
1261
		return (-1);
1262
	}
1263
1264
	if (client_ent->addrs == (struct ip_address *) NULL)
1265
	{
1266
		*ipaddr = 0;
1267
		return (1);
1268
	}
1269
1270
	if ((*ipaddr = client_ent->addrs->ipaddr.s_addr) == -1)
1271
	{
1272
		return (2);
1273
	}
1274
	return (0);
1275
} /* end of find_host_by_name () */
1276
1277
/*************************************************************************
1278
 *
1279
 *	Function: find_file_ent
1280
 *
1281
 *	Purpose: Find a FILE_LIST entry on file_list with the specified
1282
 *		 file_pfx.  The entry should be found as find_file_ent is
1283
 *		 only called for file_pfx's that were found in the "clients"
1284
 *		 file at initialization time.
1285
 *
1286
 *************************************************************************/
1287
1288
static FILE_LIST *
1289
find_file_ent (file_pfx)
1290
1291
char           *file_pfx;
1292
1293
{
1294
	FILE_LIST      *file_ent;
1295
	static char    *func = "find_file_ent";
1296
1297
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1298
1299
	if ((file_ent = file_list) == (FILE_LIST *) NULL)
1300
	{
1301
		logit (LOG_DAEMON, LOG_ERR,
1302
			"%s: No users/authfile data structure", func);
1303
		return (FILE_LIST *) NULL;
1304
	}
1305
	if (file_pfx && file_pfx[0])
1306
	{
1307
		while (strcmp (file_ent->prefix, file_pfx) != 0)
1308
		{
1309
			if ((file_ent = file_ent->next) == (FILE_LIST *) NULL)
1310
			{
1311
				logit (LOG_DAEMON, LOG_ERR,
1312
					"%s: Couldn't match %s in FILE_LIST",
1313
					func, file_pfx);
1314
				return (FILE_LIST *) NULL;
1315
			}
1316
		}
1317
	}
1318
	return file_ent;
1319
} /* end of find_file_ent () */
1320
1321
/*************************************************************************
1322
 *
1323
 *	Function: free_clients
1324
 *
1325
 *	Purpose: Toss client list entries and associated address structure.
1326
 *
1327
 *	Remark: Zap storage blocks to avoid leaving any secrets around.
1328
 *
1329
 *************************************************************************/
1330
1331
static void
1332
free_clients (client_list)
1333
1334
CLIENT_ENTRY   *client_list;
1335
1336
{
1337
	CLIENT_ENTRY      *client_ent;
1338
	IP_ADDRESS        *an_address;	
1339
	DNS_NAME          *a_name;
1340
	static char       *func = "free_clients";
1341
1342
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1343
1344
	for (client_ent = client_list;
1345
		client_ent != (CLIENT_ENTRY *) NULL;
1346
		client_ent = client_list)
1347
	{
1348
		client_list = client_ent->next;
1349
1350
		for (an_address = client_ent->addrs;
1351
			an_address != (IP_ADDRESS *) NULL;
1352
			an_address = client_ent->addrs)
1353
		{
1354
			client_ent->addrs = an_address->next;
1355
			free (an_address);
1356
		}
1357
1358
		for (a_name = client_ent->names;
1359
			a_name != (DNS_NAME *) NULL;
1360
			a_name = client_ent->names)
1361
		{
1362
			client_ent->names = a_name->next;
1363
			free (a_name);
1364
		}
1365
1366
		free (client_ent);
1367
	}
1368
	return;
1369
} /* end of free_clients () */
1370
1371
/*************************************************************************
1372
 *
1373
 *	Function: free_file_lists
1374
 *
1375
 *	Purpose: Free all the storage for the "users" and "authfile"
1376
 *		 memory resident data structures allocated by calling
1377
 *		 config_files().
1378
 *
1379
 *************************************************************************/
1380
1381
static void
1382
free_file_lists ()
1383
1384
{
1385
	FILE_LIST      *file_ent;
1386
	USER_ENTRY     *user_ent;
1387
	AUTH_ENTRY     *auth_ent;
1388
	static char    *func = "free_file_lists";
1389
1390
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1391
1392
	authfile_cnt = 0;
1393
	users_cnt = 0;
1394
1395
	for (file_ent = file_list; file_ent; file_ent = file_list)
1396
	{
1397
		for (user_ent = file_ent->user_list;
1398
			user_ent;
1399
			user_ent = file_ent->user_list)
1400
		{
1401
			file_ent->user_list = user_ent->next;
1402
			free_user_ent (user_ent);
1403
		}
1404
		for (auth_ent = file_ent->auth_list;
1405
			auth_ent;
1406
			auth_ent = file_ent->auth_list)
1407
		{
1408
			file_ent->auth_list = auth_ent->next;
1409
			free (auth_ent);
1410
		}
1411
		file_list = file_ent->next;
1412
		free (file_ent);
1413
	}
1414
1415
	return;
1416
} /* end of free_file_lists () */
1417
1418
/*************************************************************************
1419
 *
1420
 *	Function: free_user_ent
1421
 *
1422
 *	Purpose: Free all components of a USER_ENTRY structure.  Zap
1423
 *		 the USER_ENTRY storage.
1424
 *
1425
 *************************************************************************/
1426
1427
void
1428
free_user_ent (user_ent)
1429
1430
USER_ENTRY     *user_ent;
1431
1432
{
1433
	list_free (user_ent->check);
1434
	list_free (user_ent->reply);
1435
	memset ((char *) user_ent, '\0', sizeof (USER_ENTRY));
1436
	free (user_ent);
1437
	return;
1438
} /* end of free_user_ent () */
1439
1440
/*************************************************************************
1441
 *
1442
 *	Function: get_our_addr
1443
 *
1444
 *	Purpose: A global function to return a local variable (?)
1445
 *
1446
 *	Returns: (an) IP address of this machine.
1447
 *
1448
 *************************************************************************/
1449
1450
UINT4
1451
get_our_addr ()
1452
1453
{
1454
	return self_ip[0];
1455
} /* end of get_our_addr () */
1456
1457
/*************************************************************************
1458
 *
1459
 *	Function: host_is_us
1460
 *
1461
 *	Purpose: Determine if we are the given host.
1462
 *
1463
 *	Returns: 1 if the given hostname is the name of this host,
1464
 *		 0 otherwise.
1465
 *
1466
 *************************************************************************/
1467
1468
static int
1469
host_is_us (hostname)
1470
1471
char	       *hostname;
1472
1473
{
1474
	UINT4	        addr;
1475
	UINT4	       *adptr;
1476
1477
	if (find_host_by_name (&addr, hostname) == 0)
1478
	{
1479
		for (adptr = self_ip; *adptr > 0; adptr++)
1480
		{
1481
			if (*adptr == addr)
1482
			{
1483
				return 1;
1484
			}
1485
		}
1486
	}
1487
	return 0;
1488
} /* end of host_is_us () */
1489
1490
/*************************************************************************
1491
 *
1492
 *	Function: insert_client
1493
 *
1494
 *	Purpose: Inserts a CLIENT_ENTRY node into client_list for the
1495
 *		 given hostname.
1496
 *
1497
 *	Returns: 0 - inserted ok
1498
 *		-1 - bad news
1499
 *
1500
 *************************************************************************/
1501
1502
static int
1503
insert_client (hostname, secret, prefix)
1504
1505
char           *hostname;
1506
char           *secret;
1507
char           *prefix;
1508
1509
{
1510
	CLIENT_ENTRY   *client_ent = (CLIENT_ENTRY *) NULL;
1511
	CLIENT_ENTRY   *oldent;
1512
	CLIENT_ENTRY  **prev;
1513
	IP_ADDRESS     *ip_address;
1514
	struct in_addr  addr;
1515
	static char    *func = "insert_client";
1516
1517
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1518
1519
	/* Convert generic name for us to our real name */
1520
	if (strcmp (hostname, RADIUS_LOCALSERVER) == 0)
1521
	{
1522
		hostname = ourhostname;
1523
	}
1524
1525
	/* Look for entry from previous list (before HUP) */
1526
1527
	if (old_clients != (CLIENT_ENTRY *) NULL)
1528
	{
1529
		for (prev = &old_clients;
1530
			(oldent = *prev) != (CLIENT_ENTRY *) NULL;
1531
			prev = &oldent->next)
1532
		{
1533
			if (strcmp (hostname, oldent->hostname) == 0)
1534
			{
1535
				/* Matched - Remove from old list */
1536
				*prev = oldent->next;
1537
				client_ent = oldent;
1538
				break;
1539
			}
1540
		}
1541
	}
1542
1543
	if (client_ent == (CLIENT_ENTRY *) NULL)
1544
	{
1545
		if ((client_ent =
1546
			(CLIENT_ENTRY *) malloc ( sizeof (CLIENT_ENTRY)))
1547
						== (CLIENT_ENTRY *) NULL)
1548
		{
1549
			logit (LOG_DAEMON, LOG_ALERT,
1550
			     "%s: FATAL Couldn't allocate CLIENT_ENTRY storage",
1551
				 func);
1552
			abort ();
1553
		}
1554
		client_ent->hostname = add_string (hostname, ASIS);
1555
		client_ent->names = (DNS_NAME *) NULL;
1556
		client_ent->addrs = (IP_ADDRESS *) NULL;
1557
		client_ent->type = CE_DNS;
1558
1559
		/* Set constant addrs now so we don't have to wait for DNS */
1560
		if (good_ipaddr (hostname) == 0)
1561
		{
1562
			client_ent->type = CE_NUMERIC;
1563
			addr.s_addr = ntohl(inet_addr (hostname));
1564
		}
1565
		else
1566
		{
1567
			if (strcmp (hostname, ourhostname) == 0)
1568
			{
1569
				client_ent->type = CE_OURADDR;
1570
				addr.s_addr = self_ip[0];
1571
			}
1572
		}
1573
1574
		if (client_ent->type != CE_DNS)
1575
		{
1576
			if ((ip_address =
1577
				(IP_ADDRESS *) malloc (sizeof (CLIENT_ENTRY)))
1578
							== (IP_ADDRESS *) NULL)
1579
			{
1580
				logit (LOG_DAEMON, LOG_ALERT,
1581
			       "%s: FATAL Couldn't allocate IP_ADDRESS storage",
1582
					func);
1583
				abort ();
1584
			}
1585
1586
			ip_address->ipaddr = addr;
1587
			ip_address->next = (IP_ADDRESS *) NULL;
1588
			client_ent->addrs = ip_address;
1589
		}
1590
	}
1591
1592
	client_ent->secret = add_string (secret, ASIS);
1593
	client_ent->prefix = add_string (prefix, ASIS);
1594
	client_ent->expire_time = (time_t) 0;
1595
	client_ent->next = client_list;
1596
	client_list = client_ent;
1597
1598
	/*
1599
	 *	If the entry had an optional file prefix, add a new FILE_ENTRY
1600
	 *	to the file_list to handle this prefix.  Add_file_list() will
1601
	 *	not add duplicate entries.
1602
	 */
1603
	if (client_ent->prefix[0] != '\0')
1604
	{
1605
		add_file_list (client_ent->prefix);
1606
	}
1607
	return 0;
1608
} /* end of insert_client () */
1609
1610
#define	MAX_HOSTNAME_BUFFERS	20
1611
1612
/*************************************************************************
1613
 *
1614
 *	Function: ip_hostname
1615
 *
1616
 *	Purpose: Return a printable host name (or IP address in dotted quad
1617
 *		 notation) for the supplied IP address.
1618
 *
1619
 *************************************************************************/
1620
1621
char *
1622
ip_hostname (h_ipaddr)
1623
1624
UINT4           h_ipaddr;
1625
1626
{
1627
	UINT4          *ourad;
1628
	CLIENT_ENTRY   *client_ent;
1629
	IP_ADDRESS     *an_address;
1630
	DNS_NAME       *a_name;
1631
	struct hostent *hp;
1632
	struct in_addr  inad;
1633
	static char     buffers[MAX_HOSTNAME_BUFFERS][128];
1634
	static int      ndx = 0;
1635
	char           *hstname = buffers[ndx];
1636
1637
	for (client_ent = client_list;
1638
		client_ent != (CLIENT_ENTRY *) NULL;
1639
		client_ent = client_ent->next)
1640
	{
1641
		for (an_address = client_ent->addrs;
1642
			an_address != (IP_ADDRESS *) NULL;
1643
			an_address = an_address->next)
1644
		{
1645
			if (an_address->ipaddr.s_addr == h_ipaddr)
1646
			{
1647
				break;
1648
			}
1649
		}
1650
1651
		if (an_address != (IP_ADDRESS *) NULL)
1652
		{
1653
			break;
1654
		}
1655
	}
1656
1657
	if (client_ent != (CLIENT_ENTRY *) NULL)
1658
	{
1659
		/*
1660
		 *	We found something in our tables.
1661
		 *	Return a pointer to that instead of
1662
		 *	copying it to our own static area.
1663
		 */
1664
		if ((a_name = client_ent->names) == (DNS_NAME *) NULL ||
1665
			(a_name->type != 0))
1666
		{
1667
			return (client_ent->hostname);
1668
		}
1669
		else /* return official name if it's not in the main entry */
1670
		{
1671
			return (a_name->name);
1672
		}
1673
	}
1674
1675
	/* Didn't find it in our tables.  Keep looking... */
1676
	for (ourad = self_ip;
1677
		(*ourad > (UINT4) 0) && (*ourad != h_ipaddr);
1678
		ourad++)
1679
	{
1680
		continue;
1681
	}
1682
1683
	/* If it was our own address, return our hostname. */
1684
	if (*ourad > (UINT4) 0)
1685
	{
1686
		return (ourhostname);
1687
	}
1688
1689
	/* It wasn't us, so make something up. */
1690
	inad.s_addr = htonl(h_ipaddr);
1691
	strcpy (hstname, inet_ntoa (inad));	/* xxx.yyy.zzz.qqq */
1692
1693
	/*
1694
	 *	Special check for non-server use.
1695
	 *	Note: a server always will have at
1696
	 *	least one client.
1697
	 */
1698
	if (client_list == (CLIENT_ENTRY *) NULL)
1699
	{
1700
		if ((hp = gethostbyaddr ((char *) &inad.s_addr,
1701
					sizeof (struct in_addr),
1702
					AF_INET)) 
1703
				!= (struct hostent *) NULL)
1704
		{
1705
			strcpy (hstname, hp->h_name);
1706
		}
1707
	}
1708
1709
	/* Circulate through the buffers... */
1710
	ndx++;
1711
	if (ndx >= MAX_HOSTNAME_BUFFERS)
1712
	{
1713
		ndx = 0;
1714
	}
1715
1716
	return (hstname);
1717
1718
} /* end of ip_hostname () */
1719
1720
/*************************************************************************
1721
 *
1722
 *	Function: list_cat
1723
 *
1724
 *	Purpose: Given two lists, "a" and "b", place "b" at the end of "a"
1725
 *
1726
 *************************************************************************/
1727
1728
void
1729
list_cat (a, b)
1730
1731
VALUE_PAIR    **a;
1732
VALUE_PAIR     *b;
1733
1734
{
1735
	VALUE_PAIR    **last;
1736
	FILE           *debugout = stdout;
1737
	static char    *func = "list_cat";
1738
1739
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1740
1741
	if (debug_flag >= 4)
1742
	{
1743
		if (ddt)
1744
		{
1745
			debugout = ddt;
1746
		}
1747
		fprintf (debugout, "First list:\n");
1748
	}
1749
1750
	for (last = a; *last != (VALUE_PAIR *) NULL; last = &((*last)->next))
1751
	{
1752
		if (debug_flag >= 4)
1753
		{
1754
			debug_pair (debugout, *last);
1755
		}
1756
	}
1757
1758
	*last = b;
1759
1760
	if (debug_flag >= 4)
1761
	{
1762
		fprintf (debugout, "and Second list:\n");
1763
		debug_list (debugout, b);
1764
	}
1765
1766
	return;
1767
} /* end of list_cat () */
1768
1769
#define LIST_COPY_LIMIT 256   /* Limit the number of items we will copy. */
1770
1771
/*************************************************************************
1772
 *
1773
 *	Function: list_copy
1774
 *
1775
 *	Purpose: Make a copy of the entire list of value_pairs pointed to by
1776
 *		 from_list.  It is necessary to copy the check_items and
1777
 *		 reply_items from a USER_ENTRY before processing a request
1778
 *		 because they may be modified or freed.
1779
 *
1780
 *************************************************************************/
1781
1782
void
1783
list_copy (to_list, from_list)
1784
1785
VALUE_PAIR    **to_list;
1786
VALUE_PAIR     *from_list;
1787
1788
{
1789
	int             count = 0;      /* Count items we copy. */
1790
	VALUE_PAIR     *copy_item;
1791
	VALUE_PAIR     *new_item;
1792
	VALUE_PAIR    **last;
1793
	VALUE_PAIR    **old_end;
1794
	static char    *func = "list_copy";
1795
1796
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1797
1798
	if (to_list == (VALUE_PAIR **) NULL)
1799
	{
1800
		logit (LOG_DAEMON, LOG_ERR, "%s: NULL parameter", func);
1801
		exit (-13);
1802
	}
1803
1804
	copy_item = (VALUE_PAIR *) NULL;
1805
1806
	/* run to end of destination list */
1807
	for (last = to_list ;
1808
		*last != (VALUE_PAIR *) NULL ;
1809
		last = &((*last)->next))
1810
	{
1811
		if (*last == from_list)
1812
		{
1813
			logit (LOG_DAEMON, LOG_ALERT,
1814
			"%s: FATAL (0x%p->0x%p,0x%p) crosslinked at 0x%p->0x%p",
1815
			       func, to_list, *to_list, from_list, last, *last);
1816
			dumpcore = 1;
1817
			abort ();
1818
		}
1819
	}
1820
	old_end = last; /* Save old end-ptr for sanity checking. */
1821
1822
	new_item = (VALUE_PAIR *) NULL;
1823
1824
	dprintf(5, (LOG_AUTH, LOG_DEBUG,
1825
			"%s: copy from list 0x%p to end of list at 0x%p->0x%p",
1826
			func, from_list, to_list, *to_list));
1827
1828
	for (copy_item = from_list ;
1829
		copy_item != (VALUE_PAIR *) NULL ;
1830
		copy_item = copy_item->next)
1831
	{
1832
		if (count > LIST_COPY_LIMIT)
1833
		{
1834
			logit (LOG_DAEMON, LOG_ALERT,
1835
			 "%s: FATAL (0x%p->0x%p, 0x%p), count=%d, limit exceed",
1836
				func, to_list, *to_list, from_list, copy_item,
1837
				count);
1838
			dumpcore = 1;
1839
			abort ();
1840
		}
1841
1842
		if (copy_item == *old_end)
1843
		{
1844
			logit (LOG_DAEMON, LOG_ALERT,
1845
		 "%s: FATAL (0x%X->0x%X, 0x%X) list appended to itself at 0x%X",
1846
				func, to_list, *to_list, from_list, copy_item);
1847
			dumpcore = 1;
1848
			abort ();
1849
		}
1850
1851
		if ((new_item = (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
1852
							== (VALUE_PAIR *) NULL)
1853
		{
1854
			logit (LOG_DAEMON, LOG_ALERT, "%s: FATAL out of memory",
1855
				func);
1856
			abort ();
1857
		}
1858
		memcpy ((char *) new_item, (char *) copy_item,
1859
			sizeof (VALUE_PAIR));
1860
		new_item->next = (VALUE_PAIR *) NULL;
1861
1862
		*last = new_item; /* always put copy at end of to_list */
1863
		last = &(new_item->next); /* new end of to_list */
1864
		count++;
1865
	}
1866
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: copied %d items", func, count));
1867
	return;
1868
} /* end of list_copy () */
1869
1870
#define PARSE_MODE_NAME		0
1871
#define PARSE_MODE_EQUAL	1
1872
#define PARSE_MODE_VALUE	2
1873
#define PARSE_MODE_INVALID	3
1874
1875
/*************************************************************************
1876
 *
1877
 *	Function: pair_parse
1878
 *
1879
 *	Purpose: Parses the buffer to extract the attribute-value pairs.
1880
 *
1881
 *	Returns: 0 = successful parse of attribute-value pair,
1882
 *		-1 = syntax (or other) error detected.
1883
 *
1884
 *************************************************************************/
1885
1886
int
1887
pair_parse (buffer, first_pair)
1888
1889
char           *buffer;
1890
VALUE_PAIR    **first_pair;
1891
1892
{
1893
	int             mode;
1894
	int             rc;
1895
	char            attrstr[AUTH_ID_LEN];
1896
	char            valstr[AUTH_ID_LEN];
1897
	DICT_ATTR      *attr;
1898
	DICT_VALUE     *dval;
1899
	VALUE_PAIR     *pair;
1900
	VALUE_PAIR     *link;
1901
	struct tm      *tm;
1902
	time_t          timeval;
1903
	static char    *func = "pair_parse";
1904
1905
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
1906
1907
	mode = PARSE_MODE_NAME;
1908
	while (*buffer != '\n' && *buffer != '\0')
1909
	{
1910
		if (*buffer == ' ' || *buffer == '\t' || *buffer == ',')
1911
		{
1912
			buffer++;
1913
			continue;
1914
		}
1915
1916
		switch (mode)
1917
		{
1918
		    case PARSE_MODE_NAME:		/* Attribute Name */
1919
			fieldcpy (attrstr, &buffer);
1920
			if ((attr =
1921
				dict_attrfind (attrstr)) == (DICT_ATTR *) NULL)
1922
			{
1923
				return (-1);
1924
			}
1925
			mode = PARSE_MODE_EQUAL;
1926
			break;
1927
1928
		    case PARSE_MODE_EQUAL:		/* Equal sign */
1929
			if (*buffer == '=')
1930
			{
1931
				mode = PARSE_MODE_VALUE;
1932
				buffer++;
1933
			}
1934
			else
1935
			{
1936
				return (-1);
1937
			}
1938
			break;
1939
1940
		    case PARSE_MODE_VALUE:		/* Value */
1941
			fieldcpy (valstr, &buffer);
1942
1943
			if ((pair =
1944
				(VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
1945
							== (VALUE_PAIR *) NULL)
1946
			{
1947
				logit (LOG_DAEMON, LOG_ALERT,
1948
					"%s: FATAL out of memory", func);
1949
				abort ();
1950
			}
1951
			strcpy (pair->name, attr->name);
1952
			pair->attribute = attr->value;
1953
			pair->type = attr->type;
1954
1955
			switch (pair->type)
1956
			{
1957
1958
			    case PW_TYPE_STRING:
1959
				strcpy (pair->strvalue, valstr);
1960
				break;
1961
1962
			    case PW_TYPE_INTEGER:
1963
				if (isdigit (*valstr))
1964
				{
1965
					pair->lvalue = atoi (valstr);
1966
				}
1967
				else
1968
				{
1969
					if ((dval = dict_valfind (valstr))
1970
							== (DICT_VALUE *) NULL)
1971
					{
1972
						free (pair);
1973
						return (-1);
1974
					}
1975
					else
1976
					{
1977
						pair->lvalue = dval->value;
1978
					}
1979
				}
1980
				break;
1981
1982
			    case PW_TYPE_IPADDR:
1983
				rc = find_host_by_name (&pair->lvalue, valstr);
1984
				if (rc == -1)   /* Name not in our list yet */
1985
				{
1986
					insert_client (valstr, "", "");
1987
				}
1988
				else
1989
				{
1990
					if (rc == 2) /* Unresolvable DNS name */
1991
					{
1992
						free (pair);
1993
						return (-1);
1994
					}
1995
				}
1996
1997
				/* If DNS name given, store it in strvalue */
1998
				if (good_ipaddr (valstr) == 0)
1999
				{
2000
					*pair->strvalue = '\0';
2001
				}
2002
				else /* Now we can re-resolve these names */
2003
				{
2004
					strcpy (pair->strvalue, valstr);
2005
				}
2006
				break;
2007
2008
			    case PW_TYPE_DATE:
2009
				timeval = time (0);
2010
				tm = localtime (&timeval);
2011
				tm->tm_hour = 0;
2012
				tm->tm_min = 0;
2013
				tm->tm_sec = 0;
2014
				user_gettime (valstr, tm);
2015
#ifdef TIMELOCAL
2016
				pair->lvalue = (UINT4) timelocal (tm);
2017
#else	/* TIMELOCAL */
2018
				pair->lvalue = (UINT4) mktime (tm);
2019
#endif	/* TIMELOCAL */
2020
				break;
2021
2022
			    default:
2023
				free (pair);
2024
				return (-1);
2025
			}
2026
			pair->next = (VALUE_PAIR *) NULL;
2027
2028
			if (*first_pair == (VALUE_PAIR *) NULL)
2029
			{
2030
				*first_pair = pair;
2031
			}
2032
			else
2033
			{
2034
				link = *first_pair;
2035
				while (link->next != (VALUE_PAIR *) NULL)
2036
				{
2037
					link = link->next;
2038
				}
2039
				link->next = pair;
2040
			}
2041
2042
			mode = PARSE_MODE_NAME;
2043
			break;
2044
2045
		    default:
2046
			mode = PARSE_MODE_NAME;
2047
			break;
2048
		}
2049
	}
2050
	return (0);
2051
} /* end of pair_parse () */
2052
2053
/*************************************************************************
2054
 *
2055
 *	Function: read_auth
2056
 *
2057
 *	Purpose: Reads in the realm information from the "authfile" with
2058
 *	         file_pfx corresponding to the given file_ent.  The information
2059
 *		 read is copied to a data structure that is linked to the
2060
 *		 given file_ent.
2061
 *
2062
 *************************************************************************/
2063
2064
static int
2065
read_auth (file_ent, dolog)
2066
2067
FILE_LIST      *file_ent;
2068
int             dolog;
2069
2070
{
2071
	FILE             *authfd;
2072
	char             *name;
2073
	char             *prot;
2074
	char             *type;
2075
	char             *host;
2076
	char             *filter;
2077
	char             *alias_list;
2078
	int               line_no = 0;
2079
	int               ent_cnt = 0;
2080
	int               type_inx;
2081
	int               prot_inx;
2082
	int               error = 0;
2083
	AUTH_ENTRY       *auth_ent;
2084
	AUTH_ENTRY      **end_ent;
2085
	AUTH_ALIAS_ENTRY *alias_ent;
2086
	DICT_VALUE       *type_val;
2087
	static char      *auth_prots[] =
2088
	{
2089
		PW_PROTTYPES_DFLT,
2090
		PW_PROTTYPES_CHAP,
2091
		PW_PROTTYPES_PW,
2092
		NULL
2093
	};
2094
	char              buffer[128];
2095
	char              fname[MAXPATHLEN];
2096
	char             *func = "read_auth";
2097
2098
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
2099
2100
	sprintf (fname, "%s/%s%s", radius_dir, file_ent->prefix, RADIUS_AUTH);
2101
	if ((authfd = fopen (fname, "r")) == (FILE *) NULL)
2102
	{
2103
		/*
2104
		 * It's okay if a non-prefixed RADIUS_AUTH file doesn't exist,
2105
		 * as long as no CI_AUTHENTICATION_TYPE = REALM entries are
2106
		 * configured in the RADIUS_USERS file.  If <pfx>RADIUS_AUTH
2107
		 * doesn't exist, then the non-prefixed RADIUS_AUTH file will
2108
		 * be used instead.
2109
		 */
2110
		return (0);
2111
	}
2112
	end_ent = &file_ent->auth_list;
2113
	while (fgets (buffer, sizeof (buffer), authfd) != (char *) NULL)
2114
	{
2115
		line_no++;
2116
		if (isspace (*buffer) || (*buffer == COMMENT))
2117
		{
2118
			continue;
2119
		}
2120
		name = strtok (buffer, " ,\t\n\r");
2121
2122
		if (strcmp ("DEFAULT_RADIUS_SERVER", name) == 0)
2123
		{
2124
			if ((host = strtok (NULL, " \"\n\r")) != (char *) NULL)
2125
			{
2126
				strcpy (default_radius_server, host);
2127
			}
2128
			else
2129
			{
2130
				default_radius_server[0] = '\0';
2131
			}		
2132
			continue;
2133
		}
2134
		else
2135
		{
2136
			if (strcmp ("DEFAULT_TACACS_SERVER", name) == 0)
2137
			{
2138
				if ((host = strtok (NULL, " \"\n\r"))
2139
							!= (char *) NULL)
2140
				{
2141
					strcpy (default_tacacs_server, host);
2142
				}
2143
				else
2144
				{
2145
					default_tacacs_server[0] = '\0';
2146
				}		
2147
				continue;
2148
			}
2149
		}
2150
2151
		/* Scan for optional alias list or protocol indicator */
2152
2153
		prot_inx = 0;
2154
		alias_list = NULL;
2155
		type = NULL;
2156
2157
		while (type == NULL && !error)
2158
		{
2159
			prot = strtok (NULL, " ,\t\n\r");
2160
			if (prot == NULL)
2161
			{
2162
				error++;
2163
				continue;
2164
			}
2165
2166
2167
			switch (*prot)
2168
			{
2169
			    case '(': 	/* "(<aliases>)" */
2170
				alias_list = prot;
2171
				if (prot[strlen (prot) - 1] != ')')
2172
				{
2173
					if (strtok (NULL, ")") == NULL)
2174
					{
2175
						error++;
2176
					}
2177
				/* We don't want to break up alias list yet */
2178
					prot[strlen (prot)] = ' ';
2179
				}
2180
				break;
2181
2182
			    case ('-'):	/* "-<protocol>" */
2183
				if (*++prot == '\0')
2184
				{
2185
					error++;
2186
					break;
2187
				}
2188
2189
				for (prot_inx = 0;
2190
				     auth_prots[prot_inx] &&
2191
				       strcmp (prot, auth_prots[prot_inx]) != 0;
2192
				     prot_inx++)
2193
				{
2194
					;
2195
				}
2196
2197
				if (!auth_prots[prot_inx])
2198
				{
2199
					error++;
2200
				}
2201
				break;
2202
2203
			    default:
2204
				type = prot;
2205
				break;
2206
			}
2207
		}
2208
2209
		if (error)
2210
		{
2211
			logit (LOG_DAEMON, LOG_ERR,
2212
				"%s: Invalid entry in %s at line %d",
2213
				func, fname, line_no);
2214
			continue;
2215
		}
2216
2217
		type_val = dict_valfind (type);
2218
		if (type_val == (DICT_VALUE *) NULL)
2219
		{
2220
			logit (LOG_DAEMON, LOG_ERR,
2221
				"%s: Invalid TYPE '%s' in %s at line %d",
2222
				func, type, fname, line_no);
2223
			continue;
2224
		}
2225
		type_inx = type_val->value;
2226
2227
		host = strtok (NULL, " \t\n\r");
2228
		filter = strtok (NULL, " \t\n\r");
2229
2230
		if (host == NULL && type_inx != AA_UNIX)
2231
		{
2232
			logit (LOG_DAEMON, LOG_ERR,
2233
				"%s: Invalid entry in %s at line %d",
2234
				func, fname, line_no);
2235
			continue;
2236
		}
2237
2238
		if ((auth_ent = (AUTH_ENTRY *) malloc (sizeof (AUTH_ENTRY)))
2239
				== (AUTH_ENTRY *) NULL)
2240
		{
2241
			logit (LOG_DAEMON, LOG_ALERT,
2242
				"%s: No memory for auth_ent", func);
2243
			fclose (authfd);
2244
			return (-1);
2245
		}
2246
		auth_ent->parent = (AUTH_ENTRY *) NULL;
2247
		auth_ent->type = type_inx;
2248
2249
		if (is_engine == 1) /* then we are being called by the engine */
2250
		{
2251
			if (authtype_tv[type_inx] == (AATV *) NULL)
2252
			{
2253
				logit (LOG_DAEMON, LOG_ERR,
2254
				  "%s: Missing AATV for entry on line %d of %s",
2255
					func, line_no, fname);
2256
				fclose (authfd);
2257
				return (-1);
2258
			}
2259
		}
2260
2261
		auth_ent->prot = prot_inx;
2262
		auth_ent->name = add_string (name, ASIS);
2263
		auth_ent->host = add_string (host, ASIS);
2264
		auth_ent->filter = add_string (filter, ASIS);
2265
		auth_ent->next = (AUTH_ENTRY *) NULL;
2266
		*end_ent = auth_ent;
2267
		end_ent = &auth_ent->next;
2268
		ent_cnt++;
2269
2270
		/* Add alias entries if aliases given */
2271
		if (alias_list)
2272
		{
2273
			alias_list++;
2274
			name = strtok (alias_list, " ,)");
2275
			while (name)
2276
			{
2277
				if ((alias_ent = 
2278
					(AUTH_ALIAS_ENTRY *) malloc 
2279
						(sizeof(AUTH_ALIAS_ENTRY)) )
2280
						   == (AUTH_ALIAS_ENTRY *) NULL)
2281
				{
2282
					logit (LOG_DAEMON, LOG_ALERT,
2283
						"%s: No memory for auth_ent",
2284
						func);
2285
					fclose (authfd);
2286
					return (-1);
2287
				}
2288
				alias_ent->name = add_string (name, ASIS);
2289
				alias_ent->parent = auth_ent;
2290
				alias_ent->next = (AUTH_ENTRY *) NULL;
2291
				*end_ent = (AUTH_ENTRY *) alias_ent;
2292
				end_ent = &alias_ent->next;
2293
				name = strtok (NULL, " ,)");
2294
			}
2295
		}
2296
	}
2297
	fclose (authfd);
2298
	if (dolog)
2299
	{
2300
		logit (LOG_DAEMON, LOG_INFO,
2301
			"%s: %s (%u entries) read to memory",
2302
			func, fname, ent_cnt);
2303
	}
2304
	authfile_cnt += ent_cnt;
2305
2306
	return 0;
2307
} /* end of read_auth () */
2308
2309
#define FIND_MODE_NAME	0
2310
#define FIND_MODE_REPLY	1
2311
#define FIND_MODE_SKIP	2
2312
#define FIND_MODE_FLUSH	3
2313
2314
/*************************************************************************
2315
 *
2316
 *	Function: read_users
2317
 *
2318
 *	Purpose: For each entry in a "users" file (with the file_pfx
2319
 *		 corresponding to the given file_ent), read all check_items
2320
 *		 and reply_items into a data structure.  Each such
2321
 *		 data structure is linked to the given file_ent.
2322
 *
2323
 *	Returns:  0 = normal (successful) return,
2324
 *		 -1 = error return.
2325
 *
2326
 *************************************************************************/
2327
2328
static int
2329
read_users (file_ent, dolog)
2330
2331
FILE_LIST      *file_ent;
2332
int             dolog;
2333
2334
{
2335
	FILE           *userfd;
2336
	char           *ptr;
2337
	int             mode;
2338
	int             line_nbr = 0;
2339
	int             count = 0;
2340
	USER_ENTRY     *user_ent = (USER_ENTRY *) NULL;
2341
	USER_ENTRY    **end_ent;
2342
	char            buffer[256];
2343
	char            fname[MAXPATHLEN];
2344
	static char    *func = "read_users";
2345
2346
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
2347
2348
	/*
2349
	 * Open the user table
2350
	 */
2351
	sprintf (fname, "%s/%s%s", radius_dir, file_ent->prefix, RADIUS_USERS);
2352
	if ((userfd = fopen (fname, "r")) == (FILE *) NULL)
2353
	{
2354
		/*
2355
		 *  It's ok for prefixed user files to not exist, but
2356
		 *  non-prefixed user file has to exist.
2357
		 */
2358
		if (file_ent->prefix[0] == 0)
2359
		{
2360
			logit (LOG_DAEMON, LOG_ERR,
2361
				"%s: Couldn't open %s for reading",
2362
			 	func, fname);
2363
			return (-1);
2364
		}
2365
		return (0);
2366
	}
2367
2368
	end_ent = &file_ent->user_list;
2369
2370
	mode = FIND_MODE_NAME;
2371
	while (fgets (buffer, sizeof (buffer), userfd) != (char *) NULL)
2372
	{
2373
		line_nbr++;
2374
		if (*buffer == COMMENT)
2375
		{
2376
			continue;
2377
		}
2378
2379
		for (;;)
2380
		{
2381
			if (mode == FIND_MODE_NAME)
2382
			{
2383
				if (isspace (*buffer))
2384
				{
2385
					break;  /* to read another line */
2386
				}
2387
				if ((user_ent = (USER_ENTRY *)
2388
						malloc (sizeof (USER_ENTRY)))
2389
							== (USER_ENTRY *) NULL)
2390
				{
2391
					logit (LOG_DAEMON, LOG_ALERT,
2392
				     "%s: Couldn't allocate USER_ENTRY storage",
2393
						func);
2394
					return (-1);
2395
				}
2396
				ptr = strtok (buffer, " \t\n\r");
2397
				user_ent->name = add_string (ptr, ASIS);
2398
				user_ent->check = (VALUE_PAIR *) NULL;
2399
				user_ent->reply = (VALUE_PAIR *) NULL;
2400
				user_ent->next = (USER_ENTRY *) NULL;
2401
2402
				/*
2403
				 * Parse the check values
2404
				 */
2405
				ptr += strlen (ptr) + 1;
2406
				if (pair_parse (ptr, &user_ent->check) != 0)
2407
				{
2408
					logit (LOG_DAEMON, LOG_ERR,
2409
				      "%s: %d: Parse error for user %s (check)",
2410
					 	func, line_nbr, user_ent->name);
2411
					free_user_ent (user_ent);
2412
					user_ent = (USER_ENTRY *) NULL;
2413
				}
2414
				else
2415
				{
2416
					mode = FIND_MODE_REPLY;
2417
				}
2418
				break;  /* to read another line */
2419
			}
2420
2421
			/* Reading reply items */
2422
			if (isspace (*buffer))
2423
			{
2424
				/*
2425
				 * Parse the reply values
2426
				 */
2427
				if (pair_parse (buffer, &user_ent->reply) != 0)
2428
				{
2429
					logit (LOG_DAEMON, LOG_ERR,
2430
				      "%s: %d: Parse error for user %s (reply)",
2431
						func, line_nbr, user_ent->name);
2432
					free_user_ent (user_ent);
2433
					user_ent = (USER_ENTRY *) NULL;
2434
					mode = FIND_MODE_NAME;
2435
				}
2436
				break;
2437
			}
2438
2439
			/* Start of next entry */
2440
			*end_ent = user_ent;
2441
			end_ent = &user_ent->next;
2442
			user_ent = (USER_ENTRY *) NULL;
2443
			mode = FIND_MODE_NAME;
2444
			count++;
2445
			continue;       /* with same input */
2446
		}
2447
	}
2448
	fclose (userfd);
2449
	if (user_ent != (USER_ENTRY *) NULL)
2450
	{
2451
		*end_ent = user_ent;
2452
		count++;
2453
	}
2454
2455
	if (dolog)
2456
	{
2457
		logit (LOG_DAEMON, LOG_INFO,
2458
			"%s: %s (%u entries) read to memory",
2459
			func, fname, count);
2460
	}
2461
	users_cnt += count;
2462
2463
	return (0);
2464
} /* end of read_users () */
2465
2466
/*************************************************************************
2467
 *
2468
 *	Function: return_file_list
2469
 *
2470
 *	Purpose: Returns the private file_list pointer for clients in need.
2471
 *
2472
 *************************************************************************/
2473
2474
FILE_LIST *
2475
return_file_list ()
2476
2477
{
2478
	return (file_list);
2479
} /* end of return_file_list () */
2480
2481
/*************************************************************************
2482
 *
2483
 *	Function: update_clients
2484
 *
2485
 *	Purpose: Updates IP address(es) and expire_time in given
2486
 *		 CLIENT_ENTRY node.
2487
 *
2488
 *************************************************************************/
2489
2490
int
2491
update_clients ()
2492
2493
{
2494
	int                len;
2495
	int                notify_count = 0;
2496
	struct hostent    *hp;
2497
	struct in_addr   **addrlist;
2498
	char              *aliascnt;
2499
	char              *ptr;
2500
	char             **name;
2501
	CLIENT_ENTRY      *client_ent;
2502
	struct sockaddr_in send_sin;
2503
	time_t             cur_time;
2504
	static char       *func = "update_clients";
2505
2506
	dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
2507
2508
	if (dnspid != 0)	/* Already resolving addrs */
2509
	{
2510
		return 0;
2511
	}
2512
2513
	if (spawn_flag > 0)
2514
	{
2515
		if ((dnspid = (int) fork ()) < 0)	
2516
		{
2517
			dnspid = 0;
2518
			logit (LOG_DAEMON, LOG_ALERT, "%s: fork: %s",
2519
				func, get_errmsg ());
2520
			return (-1);
2521
		}
2522
2523
		if (dnspid != 0)	/* Parent */
2524
		{
2525
			return 0;
2526
		}
2527
	}
2528
	
2529
	/* ======= Child process code ======= */
2530
2531
	memset ((char *) &send_sin, '\0', sizeof (send_sin));
2532
	send_sin.sin_family = AF_INET;
2533
	send_sin.sin_addr.s_addr = htonl(self_ip[0]);
2534
	send_sin.sin_port = htons(rad_ipc_port);
2535
2536
	cur_time = time (0);
2537
	for (client_ent = client_list;
2538
		client_ent != (CLIENT_ENTRY *) NULL;
2539
		client_ent = client_ent->next)
2540
	{
2541
		if (cur_time < client_ent->expire_time)
2542
		{
2543
			continue;
2544
		}
2545
2546
		hp = gethostbyname (client_ent->hostname);
2547
		ptr = send_buffer;
2548
		*ptr++ = '\0';		/* Only one code for now */
2549
		strcpy (ptr, client_ent->hostname);
2550
		ptr += strlen (ptr) + 1;
2551
		*ptr = '\0';
2552
		aliascnt = ptr++;
2553
2554
		if (hp != (struct hostent *) NULL)
2555
		{
2556
			if (hp->h_aliases != (char **) NULL)
2557
			{
2558
				for (name = hp->h_aliases;
2559
					*name != (char *) NULL;
2560
					name++)  
2561
				{
2562
					if (strcmp (client_ent->hostname,
2563
						    *name) != 0)
2564
					{
2565
						(*aliascnt)++; 
2566
						strcpy (ptr, *name);
2567
						ptr += strlen (ptr) + 1; 
2568
2569
						/* Indicate just an alias */
2570
						*ptr++ = 1;
2571
					}
2572
				}
2573
			}
2574
2575
			/* Pass official name last */
2576
			if (strcmp (client_ent->hostname, hp->h_name) != 0)
2577
			{
2578
				(*aliascnt)++; 
2579
				strcpy (ptr, hp->h_name);
2580
				ptr += strlen (ptr) + 1; 
2581
				*ptr++ = 0;	/* Indicate official name */
2582
			}
2583
2584
			if (hp->h_addr_list != (char **) NULL)
2585
			{
2586
				addrlist = (struct in_addr **) hp->h_addr_list;
2587
				while (*addrlist)
2588
				{
2589
					memcpy (ptr, *(char **) addrlist,
2590
						sizeof (struct in_addr));
2591
					ptr += sizeof (struct in_addr);
2592
					addrlist++;
2593
				}
2594
			}
2595
			memset (ptr, '\0', sizeof (struct in_addr)); 
2596
		}
2597
		else /* Extra check for brain-dead gethostbyname() calls */
2598
		{
2599
			if (client_ent->type == CE_NUMERIC)
2600
			{
2601
				struct in_addr temp;
2602
2603
				temp.s_addr = ntohl(inet_addr (client_ent->hostname));
2604
				memcpy (ptr, (char *) &temp,
2605
					sizeof (struct in_addr));
2606
				ptr += sizeof (struct in_addr);
2607
				memset (ptr, '\0', sizeof (struct in_addr));
2608
			}
2609
			else
2610
			{
2611
				memset (ptr, '\0', sizeof (struct in_addr)); 
2612
				/* Pass error code in packet */
2613
				*(ptr + sizeof (struct in_addr) - 1) = h_errno;
2614
			}
2615
		}
2616
2617
		len = ptr - send_buffer + sizeof (struct in_addr);
2618
		notify_count++;
2619
2620
		dprintf (2, (LOG_DAEMON, LOG_DEBUG,
2621
			"%s: Sendto call number (%d) for client '%s'",
2622
			func, notify_count, client_ent->hostname));
2623
2624
		if (notify_count % DNS_SLEEP == 0)
2625
		{
2626
			sleep (1);
2627
		}
2628
2629
		/* Send it to main process */
2630
		sendto (rad_ipc_aatv->sockfd, send_buffer, len, (int) 0,
2631
			(struct sockaddr *) & send_sin, sizeof (send_sin));
2632
2633
	}
2634
2635
	if (spawn_flag > 0)
2636
	{
2637
		_exit (0);
2638
	}
2639
2640
	return 0;
2641
} /* end of update_clients () */
2642
2643
/*************************************************************************
2644
 *
2645
 *	Function: user_find
2646
 *
2647
 *	Purpose: Find the named user in the users database.  Create the
2648
 *		 set of attribute-value pairs to check and reply with
2649
 *		 for this user from the database.
2650
 *
2651
 *		 Note that the users database can be either in the file
2652
 *		 "RADIUS_USERS" (-u option), in memory (default), or in
2653
 *		 a dbm(3) database.
2654
 *
2655
 *************************************************************************/
2656
2657
int
2658
user_find (file_pfx, name, protocol, check_pairs, reply_pairs, not_user_file)
2659
2660
char           *file_pfx;        /* Selects which "users" file to use */
2661
char           *name;
2662
int             protocol;
2663
VALUE_PAIR    **check_pairs;
2664
VALUE_PAIR    **reply_pairs;
2665
int             not_user_file;   /* Look up user in a domain specific file */
2666
2667
{
2668
	int             mode;
2669
	int             namelen;
2670
	FILE           *userfd;
2671
	VALUE_PAIR     *check_first;
2672
	VALUE_PAIR     *reply_first;
2673
	VALUE_PAIR     *prot_ent;
2674
	FILE_LIST      *file_ent;
2675
	USER_ENTRY     *user_ent;
2676
	USER_ENTRY     *dflt_ent;
2677
	char           *ptr;
2678
	FILE           *debugout = stdout;
2679
	char            buffer[256];
2680
	char            fname[MAXPATHLEN];
2681
	static char    *func = "user_find";
2682
2683
#ifdef USE_NDBM
2684
	datum           named;
2685
	datum           contentd;
2686
	DBM            *db;
2687
#endif	/* USE_NDBM */
2688
2689
#ifdef USE_DBM
2690
	datum           named;
2691
	datum           contentd;
2692
#endif	/* USE_DBM */
2693
2694
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered name='%s'", func, name));
2695
2696
	*check_pairs = check_first = (VALUE_PAIR *) NULL;
2697
	*reply_pairs = reply_first = (VALUE_PAIR *) NULL;
2698
2699
	if ((namelen = strlen (name)) == 0)
2700
	{
2701
		return 1;	/* A null name would match every line. */
2702
	}
2703
2704
	/*
2705
	 *	First check what type of lookup to do.
2706
	 *	See if user file(s) have been cached in memory.
2707
	 */
2708
2709
	if (not_user_file == 0 &&
2710
		(dflt_ent = file_list->user_list) != (USER_ENTRY *) NULL)
2711
	{
2712
		if ((file_ent = find_file_ent (file_pfx)) == (FILE_LIST *) NULL)
2713
		{
2714
			return (-1);
2715
		}
2716
		if ((user_ent = file_ent->user_list) == (USER_ENTRY *) NULL)
2717
		{
2718
			/* If no user file for this prefix, ...  */
2719
			/* ... then use first entry in file_list as ... */
2720
			/* ... default file_ent. */
2721
			user_ent = dflt_ent;
2722
		}
2723
		for (; user_ent; user_ent = user_ent->next)
2724
		{
2725
			/* Allow match for entry specifying framed protocol
2726
			 * type specified in "protocol".  An entry with a 
2727
			 * matching name but no framed-protocol type check 
2728
			 * item matches unconditionally.  An entry with a 
2729
			 * matching name and a framed-protocol type check 
2730
			 * item must match value in "protocol".
2731
			 */
2732
2733
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: cache name='%s'", func, user_ent->name));
2734
2735
#ifndef REGNAMES
2736
			if (strcmp (user_ent->name, name) == 0)
2737
#else /* REGNAMES */
2738
			if (regimatch(user_ent->name, name))
2739
#endif /* REGNAMES */
2740
			{
2741
				if ((prot_ent =
2742
					get_vp (user_ent->check,
2743
						PW_FRAMED_PROTOCOL))
2744
							== (VALUE_PAIR *) NULL)
2745
				{
2746
					break;
2747
				}
2748
				if (prot_ent->lvalue == protocol)
2749
				{
2750
					break;
2751
				}
2752
			}
2753
		}
2754
		if (!user_ent)	/* rc 1 => User not found and no error */
2755
		{
2756
			return 1;
2757
		}
2758
		list_copy (&check_first, user_ent->check);
2759
		list_copy (&reply_first, user_ent->reply);
2760
		if (debug_flag >= 2)
2761
		{
2762
			if (ddt)
2763
			{
2764
				debugout = ddt;
2765
			}
2766
2767
			fprintf (debugout, "Check items:\n");
2768
			debug_list (debugout, user_ent->check);
2769
			fprintf (debugout, "Reply items:\n");
2770
			debug_list (debugout, user_ent->reply);
2771
		}
2772
		*check_pairs = check_first;
2773
		*reply_pairs = reply_first;
2774
		return (0);	/* rc 0 => User found */
2775
	} /* End of cached users file(s) lookup */
2776
2777
	/*
2778
	 * Open the user table.
2779
	 * If prefixed file doesn't exist, use default (non-prefixed) file.
2780
	 */
2781
	for (;;)
2782
	{
2783
		sprintf (fname, "%s/%s%s", radius_dir,
2784
			file_pfx ? file_pfx : "", RADIUS_USERS);
2785
2786
#if defined(USE_DBM) || defined(USE_NDBM)
2787
#ifdef USE_NDBM
2788
		if ((db = dbm_open (fname, O_RDONLY, 0)) == 0)
2789
		{
2790
#endif	/* USE_NDBM */
2791
#ifdef USE_DBM
2792
		if (dbminit (fname) != 0)
2793
		{
2794
#endif	/* USE_DBM */
2795
#else	/* USE_DBM || USE_NDBM */
2796
		if ((userfd = fopen (fname, "r")) == (FILE *) NULL)
2797
		{
2798
#endif	/* USE_DBM || USE_NDBM */
2799
2800
			if (not_user_file == 0 &&
2801
				file_pfx != NULL &&
2802
				file_pfx[0] != 0)
2803
			{
2804
				file_pfx = NULL;
2805
				continue;
2806
			}
2807
2808
			logit (LOG_DAEMON, LOG_ERR,
2809
				"%s: Couldn't open %s for reading",
2810
			 	func, fname);
2811
			return (-1);
2812
		}
2813
		break;
2814
	}
2815
2816
#if defined(USE_DBM) || defined(USE_NDBM)
2817
/*
2818
 * Note that the DBM feature currently does not support protocol specific user
2819
 * entry matching.  It could be done by appending a protocol type to the
2820
 * name when building the database and looking for that modified name here.
2821
 * This seems like a non-trivial task and we don't use the DBM feature
2822
 * here so I'll leave this to someone else to implement.
2823
 */
2824
	named.dptr = name;
2825
	named.dsize = namelen;
2826
2827
#ifdef	USE_NDBM
2828
	contentd = dbm_fetch (db, named);
2829
#else	/* USE_NDBM */
2830
	contentd = fetch (named);
2831
#endif	/* USE_NDBM */
2832
2833
	if (contentd.dsize == 0)
2834
	{
2835
		named.dptr = "DEFAULT";
2836
		named.dsize = strlen ("DEFAULT");
2837
2838
#ifdef	USE_NDBM
2839
		contentd = dbm_fetch (db, named);
2840
#else	/* USE_NDBM */
2841
		contentd = fetch (named);
2842
#endif	/* USE_NDBM */
2843
2844
		if (contentd.dsize == 0)
2845
		{
2846
#ifdef	USE_NDBM
2847
			dbm_close (db);
2848
#else	/* USE_NDBM */
2849
			dbmclose ();
2850
#endif	/* USE_NDBM */
2851
			return (-1);
2852
		}
2853
	}
2854
2855
	/*
2856
	 * Parse the check values
2857
	 */
2858
	ptr = contentd.dptr;
2859
	contentd.dptr[contentd.dsize] = '\0';
2860
2861
	if (pair_parse (ptr, &check_first) != 0)
2862
	{
2863
		logit (LOG_DAEMON, LOG_ERR,
2864
			"%s: Parse error for user %s in %s (check)",
2865
			func, name, fname);
2866
		list_free (check_first);
2867
#ifdef	USE_NDBM
2868
		dbm_close (db);
2869
#else	/* USE_NDBM */
2870
		dbmclose ();
2871
#endif	/* USE_NDBM */
2872
		return (-1);
2873
	}
2874
	while (*ptr != '\n' && *ptr != '\0')
2875
	{
2876
		ptr++;
2877
	}
2878
	if (*ptr != '\n')
2879
	{
2880
		list_free (check_first);
2881
#ifdef	USE_NDBM
2882
		dbm_close (db);
2883
#else	/* USE_NDBM */
2884
		dbmclose ();
2885
#endif	/* USE_NDBM */
2886
		return (-1);
2887
	}
2888
	ptr++;
2889
2890
	/*
2891
	 * Parse the reply values
2892
	 */
2893
	if (pair_parse (ptr, &reply_first) != 0)
2894
	{
2895
		logit (LOG_DAEMON, LOG_ERR,
2896
			"%s: Parse error for user %s in %s (reply)",
2897
			func, name, fname);
2898
		list_free (check_first);
2899
		list_free (reply_first);
2900
#ifdef	USE_NDBM
2901
		dbm_close (db);
2902
#else	/* USE_NDBM */
2903
		dbmclose ();
2904
#endif	/* USE_NDBM */
2905
		return (-1);
2906
	}
2907
#ifdef	USE_NDBM
2908
	dbm_close (db);
2909
#else	/* USE_NDBM */
2910
	dbmclose ();
2911
#endif	/* USE_NDBM */
2912
	*check_pairs = check_first;
2913
	*reply_pairs = reply_first;
2914
	return (0);
2915
2916
#else /* USE_DBM || USE_NBDM */
2917
2918
	mode = FIND_MODE_NAME;
2919
2920
	while (fgets (buffer, sizeof (buffer), userfd) != (char *) NULL)
2921
	{
2922
		if (*buffer == COMMENT)
2923
		{
2924
			continue;
2925
		}
2926
2927
		if (mode == FIND_MODE_NAME)
2928
		{
2929
			/*
2930
			 * Find the entry starting with the users name.
2931
			 */
2932
		dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: name='%s'", func, user_ent->name));
2933
2934
#ifndef REGNAMES
2935
			if (strncmp (buffer, name, namelen) == 0 &&
2936
			    (buffer[namelen] == ' ' || buffer[namelen] == '\t'))
2937
			{
2938
				ptr = &buffer[namelen];
2939
#else /* REGNAMES */
2940
			ptr = strtok(buffer, " \t\n");
2941
			fprintf(debugout, "name='%s'", ptr);
2942
			if (regimatch(ptr, name))
2943
			{
2944
				ptr = &buffer[strlen(ptr)+1];
2945
				fprintf(debugout, "name='%s'", ptr);
2946
#endif /* REGNAMES */
2947
				/*
2948
				 * Parse the check values
2949
				 */
2950
				if (pair_parse (ptr, &check_first) != 0)
2951
				{
2952
					logit (LOG_DAEMON, LOG_ERR,
2953
				"%s: Parse error for user %s in %s (DBM check)",
2954
						 func, name, fname);
2955
					list_free (check_first);
2956
					fclose (userfd);
2957
					return (-1);
2958
				}
2959
				/* Allow match for entry specifying framed
2960
				 * protocol type specified in "protocol".  An
2961
				 * entry with matching name but no
2962
				 * framed-protocol type check item matches
2963
				 * unconditionally.  An entry with matching
2964
				 * name and a framed-protocol type check item
2965
				 * must match value in "protocol".
2966
				 */
2967
				if ((prot_ent =
2968
					get_vp (check_first,
2969
						PW_FRAMED_PROTOCOL))
2970
							!= (VALUE_PAIR *) NULL)
2971
				{
2972
					if (prot_ent->lvalue != protocol)
2973
					{
2974
						list_free (check_first);
2975
						continue;
2976
					}
2977
				}
2978
				mode = FIND_MODE_REPLY;
2979
			}
2980
		}
2981
		else
2982
		{
2983
			if (*buffer == ' ' || *buffer == '\t')
2984
			{
2985
				/*
2986
				 * Parse the reply values
2987
				 */
2988
				if (pair_parse (buffer, &reply_first) != 0)
2989
				{
2990
					logit (LOG_DAEMON, LOG_ERR,
2991
				"%s: Parse error for user %s in %s (DBM reply)",
2992
						 func, name, fname);
2993
					list_free (check_first);
2994
					list_free (reply_first);
2995
					fclose (userfd);
2996
					return (-1);
2997
				}
2998
			}
2999
			else /* We are done */
3000
			{
3001
				break;
3002
			}
3003
		}
3004
	}
3005
	fclose (userfd);
3006
3007
	/* Update the callers pointers */
3008
	if (mode == FIND_MODE_NAME)
3009
	{
3010
		return 1;		/* No error and no match */
3011
	}
3012
	*check_pairs = check_first;
3013
	*reply_pairs = reply_first;
3014
	return (0);
3015
#endif	/* USE_DBM || USE_NBDM */
3016
} /* end of user_find () */
3017
3018
static char * months[] =
3019
		{
3020
			"Jan", "Feb", "Mar", "Apr", "May", "Jun",
3021
			"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3022
		};
3023
3024
/*************************************************************************
3025
 *
3026
 *	Function: user_gettime
3027
 *
3028
 *	Purpose: Turns printable string into correct tm struct entries.
3029
 *
3030
 *************************************************************************/
3031
3032
void
3033
user_gettime (valstr, tm)
3034
3035
char           *valstr;
3036
struct tm      *tm;
3037
3038
{
3039
	int             i;
3040
	static char    *func = "user_gettime";
3041
3042
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
3043
3044
	/* Get the month */
3045
	for (i = 0; i < 12; i++)
3046
	{
3047
		if (strncmp (months[i], valstr, 3) == 0)
3048
		{
3049
			tm->tm_mon = i;
3050
			i = 13;
3051
		}
3052
	}
3053
3054
	/* Get the Day */
3055
	tm->tm_mday = atoi (&valstr[4]);
3056
3057
	/* Now the year */
3058
	tm->tm_year = atoi (&valstr[7]) - 1900;
3059
} /* end of user_gettime () */
3060
3061
/*************************************************************************
3062
 *
3063
 *	Function: user_update
3064
 *
3065
 *	Purpose: Updates a user in the database.  Replaces the original
3066
 *		 entry with the name, the list of check items, and the
3067
 *		 list of reply items which are supplied.
3068
 *
3069
 *************************************************************************/
3070
3071
int
3072
user_update (name, user_check, user_reply)
3073
3074
char           *name;
3075
VALUE_PAIR     *user_check;
3076
VALUE_PAIR     *user_reply;
3077
3078
{
3079
	FILE           *oldfd;
3080
	FILE           *userfd;
3081
	char            buffer[256];
3082
	char            buffer1[256];
3083
	int             namelen;
3084
	int             mode;
3085
	static char    *func = "user_update";
3086
3087
	dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func));
3088
3089
	sprintf (buffer, "%s/%s", radius_dir, RADIUS_USERS);
3090
	sprintf (buffer1, "%s/%s", radius_dir, RADIUS_HOLD);
3091
3092
	/* Move the user table to a temporary location */
3093
	if (rename (buffer, buffer1) != 0)
3094
	{
3095
		logit (LOG_DAEMON, LOG_ERR, "%s: Couldn't rename %s",
3096
			func, buffer);
3097
		return (-1);
3098
	}
3099
3100
	/* Open the old user file (using the temporary name */
3101
	if ((oldfd = fopen (buffer1, "r")) == (FILE *) NULL)
3102
	{
3103
		logit (LOG_DAEMON, LOG_ERR, "%s: Couldn't open %s for reading",
3104
			func, buffer1);
3105
		exit (-9);
3106
	}
3107
3108
	/* Open the new user file */
3109
	if ((userfd = fopen (buffer, "w")) == (FILE *) NULL)
3110
	{
3111
		logit (LOG_DAEMON, LOG_ERR, "%s: Couldn't open %s for writing",
3112
			func, buffer);
3113
		exit (-9);
3114
	}
3115
3116
	mode = FIND_MODE_NAME;
3117
	namelen = strlen (name);
3118
3119
	/* Copy the old to the new, only recreating the changed user */
3120
	while (fgets (buffer, sizeof (buffer), oldfd) != (char *) NULL)
3121
	{
3122
		if (mode == FIND_MODE_NAME)
3123
		{
3124
			if ((strncmp (buffer, name, namelen) == 0 &&
3125
			   (buffer[namelen] == ' ' || buffer[namelen] == '\t')))
3126
			{
3127
3128
				/* Write our new information */
3129
				fprintf (userfd, "%s\t", name);
3130
				while (user_check != (VALUE_PAIR *) NULL)
3131
				{
3132
					fprint_attr_val (userfd, user_check);
3133
					if (user_check->next !=
3134
							(VALUE_PAIR *) NULL)
3135
					{
3136
						fprintf (userfd, ", ");
3137
					}
3138
					user_check = user_check->next;
3139
				}
3140
				fprintf (userfd, "\n\t");
3141
				while (user_reply != (VALUE_PAIR *) NULL)
3142
				{
3143
					fprint_attr_val (userfd, user_reply);
3144
					if (user_reply->next !=
3145
							(VALUE_PAIR *) NULL)
3146
					{
3147
						fprintf (userfd, ",\n\t");
3148
					}
3149
					user_reply = user_reply->next;
3150
				}
3151
				fprintf (userfd, "\n");
3152
				mode = FIND_MODE_SKIP;
3153
			}
3154
			else
3155
			{
3156
				fputs (buffer, userfd);
3157
			}
3158
		}
3159
		else if (mode == FIND_MODE_SKIP)
3160
		{
3161
			if (*buffer != ' ' && *buffer != '\t')
3162
			{
3163
				fputs (buffer, userfd);
3164
				mode = FIND_MODE_FLUSH;
3165
			}
3166
		}
3167
		else
3168
		{
3169
			fputs (buffer, userfd);
3170
		}
3171
	}
3172
	fclose (oldfd);
3173
	fclose (userfd);
3174
	return (0);
3175
} /* end of user_update () */
(-)pppd/rad_util.c (+178 lines)
Line 0 Link Here
1
/*
2
 *
3
 *	RADIUS   Remote Authentication Dial In User Service
4
 *
5
 *
6
 *	Livingston Enterprises, Inc.
7
 *	6920 Koll Center Parkway
8
 *	Pleasanton, CA   94566
9
 *
10
 *	Copyright 1992 Livingston Enterprises, Inc.
11
 *
12
 *	Permission to use, copy, modify, and distribute this software for any
13
 *	purpose and without fee is hereby granted, provided that this
14
 *	copyright and permission notice appear on all copies and supporting
15
 *	documentation, the name of Livingston Enterprises, Inc. not be used
16
 *	in advertising or publicity pertaining to distribution of the
17
 *	program without specific prior permission, and notice be given
18
 *	in supporting documentation that copying and distribution is by
19
 *	permission of Livingston Enterprises, Inc.
20
 *
21
 *	Livingston Enterprises, Inc. makes no representations about
22
 *	the suitability of this software for any purpose.  It is
23
 *	provided "as is" without express or implied warranty.
24
 *
25
 * [C] The Regents of the University of Michigan and Merit Network, Inc. 1992,
26
 * 1993, 1994, 1995, 1996 All Rights Reserved
27
 *
28
 * Permission to use, copy, modify, and distribute this software and its
29
 * documentation for any purpose and without fee is hereby granted, provided
30
 * that the above copyright notice and this permission notice appear in all
31
 * copies of the software and derivative works or modified versions thereof,
32
 * and that both the copyright notice and this permission and disclaimer
33
 * notice appear in supporting documentation.
34
 *
35
 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
36
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF
37
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE REGENTS OF THE
38
 * UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE
39
 * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR
40
 * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE.  The Regents of the
41
 * University of Michigan and Merit Network, Inc. shall not be liable for any
42
 * special, indirect, incidental or consequential damages with respect to any
43
 * claim by Licensee or any third party arising from use of the software.
44
 *
45
 *	Public entry points in this file:
46
 *
47
 *	get_ipaddr
48
 *	good_ipaddr
49
 *	list_free
50
 *
51
 */
52
53
static char     sccsid[] =
54
		"@(#)util.c 1.1 Copyright 1992 Livingston Enterprises Inc";
55
56
static char     rcsid[] = "$Id: util.c,v 1.9 1996/05/21 15:16:01 web Exp $";
57
58
#include	<sys/types.h>
59
#include	<sys/socket.h>
60
#include	<sys/time.h>
61
#include	<netinet/in.h>
62
#include	<arpa/inet.h>
63
64
#include	<stdio.h>
65
#include	<netdb.h>
66
#include	<ctype.h>
67
#include	<time.h>
68
69
#include	"radius.h"
70
71
/*************************************************************************
72
 *
73
 *	Function: get_ipaddr
74
 *
75
 *	Purpose: Return an IP address in host long notation from a host
76
 *		 name or address in dot notation.
77
 *
78
 *************************************************************************/
79
80
UINT4
81
get_ipaddr (host)
82
83
char           *host;
84
85
{
86
	struct hostent *hp;
87
88
	if (good_ipaddr (host) == 0)
89
	{
90
		return ntohl(inet_addr (host));
91
	}
92
	else if ((hp = gethostbyname (host)) == (struct hostent *) NULL)
93
	{
94
		return ((UINT4) 0);
95
	}
96
	return ntohl((*(UINT4 *) hp->h_addr));
97
} /* end of get_ipaddr () */
98
99
/*************************************************************************
100
 *
101
 *	Function: good_ipaddr
102
 *
103
 *	Purpose: Check for valid IP address in standard dot notation.
104
 *
105
 *************************************************************************/
106
107
int
108
good_ipaddr (addr)
109
110
char           *addr;
111
112
{
113
	int             dot_count;
114
	int             digit_count;
115
116
	if (addr == (char *) NULL)
117
	{
118
		return (-1);
119
	}
120
121
	dot_count = 0;
122
	digit_count = 0;
123
124
	while (*addr != '\0' && *addr != ' ')
125
	{
126
		if (*addr == '.')
127
		{
128
			dot_count++;
129
			digit_count = 0;
130
		}
131
		else if (!isdigit (*addr))
132
		{
133
			dot_count = 5;
134
		}
135
		else
136
		{
137
			digit_count++;
138
			if (digit_count > 3)
139
			{
140
				dot_count = 5;
141
			}
142
		}
143
		addr++;
144
	}
145
	if (dot_count != 3)
146
	{
147
		return (-1);
148
	}
149
	else
150
	{
151
		return (0);
152
	}
153
} /* end of good_ipaddr () */
154
155
/*************************************************************************
156
 *
157
 *	Function: list_free
158
 *
159
 *	Purpose: Release the memory used by a list of a/v pairs.
160
 *
161
 *************************************************************************/
162
163
void
164
list_free (pair)
165
166
VALUE_PAIR     *pair;
167
168
{
169
	VALUE_PAIR     *next;
170
171
	while (pair != (VALUE_PAIR *) NULL)
172
	{
173
		next = pair->next;
174
		free (pair);
175
		pair = next;
176
	}
177
	return;
178
} /* end of list_free () */
(-)pppd/radius.h (+1137 lines)
Line 0 Link Here
1
#ifndef RADIUS_H
2
#define RADIUS_H
3
4
/*
5
 *	RADIUS   Remote Authentication Dial In User Service
6
 *
7
 *	Livingston Enterprises, Inc.
8
 *	6920 Koll Center Parkway
9
 *	Pleasanton, CA   94566
10
 *
11
 *	Copyright 1992 Livingston Enterprises, Inc.
12
 *
13
 *	Permission to use, copy, modify, and distribute this software for any
14
 *	purpose and without fee is hereby granted, provided that this
15
 *	copyright and permission notice appear on all copies and supporting
16
 *	documentation, the name of Livingston Enterprises, Inc. not be used
17
 *	in advertising or publicity pertaining to distribution of the
18
 *	program without specific prior permission, and notice be given
19
 *	in supporting documentation that copying and distribution is by
20
 *	permission of Livingston Enterprises, Inc.
21
 *
22
 *	Livingston Enterprises, Inc. makes no representations about
23
 *	the suitability of this software for any purpose.  It is
24
 *	provided "as is" without express or implied warranty.
25
 *
26
 * [C] The Regents of the University of Michigan and Merit Network, Inc. 1992,
27
 * 1993, 1994, 1995, 1996 All Rights Reserved
28
 *
29
 * Permission to use, copy, modify, and distribute this software and its
30
 * documentation for any purpose and without fee is hereby granted, provided
31
 * that the above copyright notice and this permission notice appear in all
32
 * copies of the software and derivative works or modified versions thereof,
33
 * and that both the copyright notice and this permission and disclaimer
34
 * notice appear in supporting documentation.
35
 *
36
 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
37
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF
38
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE REGENTS OF THE
39
 * UNIVERSITY OF MICHIGAN AND MERIT NETWORK, INC. DO NOT WARRANT THAT THE
40
 * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR
41
 * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE.  The Regents of the
42
 * University of Michigan and Merit Network, Inc. shall not be liable for any
43
 * special, indirect, incidental or consequential damages with respect to any
44
 * claim by Licensee or any third party arising from use of the software.
45
 *
46
 *	@(#)radius.h	1.3 1/20/93
47
 *
48
 *	$Id: radius.h,v 2.64 1996/06/19 18:16:23 web Exp $
49
 */
50
51
#include "conf.h"
52
53
#define	COMMENT			'#'	/* comment char for config files */
54
55
#define AUTH_VECTOR_LEN		16
56
#define AUTH_PASS_LEN		64
57
#define AUTH_ID_LEN		64
58
#define AUTH_STRING_LEN		128	/* maximum of 253 */
59
60
#define FILTER_LEN		16
61
#define NAME_LENGTH		32
62
#define	MAX_FSMID_LEN		20	/* Maximum length of %FSMID string */
63
64
typedef struct pw_auth_hdr
65
{
66
	u_char          code;
67
	u_char          id;
68
	u_short         length;
69
	u_char          vector[AUTH_VECTOR_LEN];
70
	u_char          data[2];
71
} AUTH_HDR;
72
73
#define AUTH_HDR_LEN			20
74
#define MAX_SECRET_LENGTH		16
75
#define CHAP_VALUE_LENGTH		16
76
77
#if !defined(PW_AUTH_UDP_PORT)
78
#define PW_AUTH_UDP_PORT		1645
79
#endif
80
81
#if !defined(PW_ACCT_UDP_PORT)
82
#define PW_ACCT_UDP_PORT		1646
83
#endif
84
85
#define PW_TYPE_STRING			0
86
#define PW_TYPE_INTEGER			1
87
#define PW_TYPE_IPADDR			2
88
#define PW_TYPE_DATE			3
89
#define PW_TYPE_OCTETS			4
90
#define PW_TYPE_VENDOR			5
91
92
/* standard RADIUS codes */
93
94
#define	PW_ACCESS_REQUEST		1
95
#define	PW_ACCESS_ACCEPT		2
96
#define	PW_ACCESS_REJECT		3
97
#define	PW_ACCOUNTING_REQUEST		4
98
#define	PW_ACCOUNTING_RESPONSE		5
99
#define	PW_ACCOUNTING_STATUS		6
100
#define	PW_PASSWORD_REQUEST		7
101
#define	PW_PASSWORD_ACK			8
102
#define	PW_PASSWORD_REJECT		9
103
#define	PW_ACCOUNTING_MESSAGE		10
104
#define	PW_ACCESS_CHALLENGE		11
105
#define	PW_STATUS_SERVER		12
106
#define	PW_STATUS_CLIENT		13
107
#define	PW_FORWARDING			216
108
109
110
/* standard RADIUS attribute-value pairs */
111
112
#define	PW_USER_NAME			1	/* string */
113
#define	PW_USER_PASSWORD		2	/* string */
114
#define	PW_CHAP_PASSWORD		3	/* string */
115
#define	PW_NAS_IP_ADDRESS		4	/* ipaddr */
116
#define	PW_NAS_PORT			5	/* integer */
117
#define	PW_SERVICE_TYPE			6	/* integer */
118
#define	PW_FRAMED_PROTOCOL		7	/* integer */
119
#define	PW_FRAMED_IP_ADDRESS		8	/* ipaddr */
120
#define	PW_FRAMED_IP_NETMASK		9	/* ipaddr */
121
#define	PW_FRAMED_ROUTING		10	/* integer */
122
#define	PW_FILTER_ID		        11	/* string */
123
#define	PW_FRAMED_MTU			12	/* integer */
124
#define	PW_FRAMED_COMPRESSION		13	/* integer */
125
#define	PW_LOGIN_IP_HOST		14	/* ipaddr */
126
#define	PW_LOGIN_SERVICE		15	/* integer */
127
#define	PW_LOGIN_PORT			16	/* integer */
128
#define	PW_OLD_PASSWORD			17	/* string */ /* deprecated */
129
#define	PW_REPLY_MESSAGE		18	/* string */
130
#define	PW_LOGIN_CALLBACK_NUMBER	19	/* string */
131
#define	PW_FRAMED_CALLBACK_ID		20	/* string */
132
#define	PW_EXPIRATION			21	/* date */ /* deprecated */
133
#define	PW_FRAMED_ROUTE			22	/* string */
134
#define	PW_FRAMED_IPX_NETWORK		23	/* integer */
135
#define	PW_STATE			24	/* string */
136
#define	PW_CLASS			25	/* string */
137
#define	PW_VENDOR_SPECIFIC		26	/* string */
138
#define	PW_SESSION_TIMEOUT		27	/* integer */
139
#define	PW_IDLE_TIMEOUT			28	/* integer */
140
#define	PW_TERMINATION_ACTION		29	/* integer */
141
#define	PW_CALLED_STATION_ID		30	/* string */
142
#define	PW_CALLING_STATION_ID		31	/* string */
143
#define	PW_NAS_IDENTIFIER		32	/* string */
144
#define	PW_PROXY_STATE			33	/* string */
145
#define	PW_LOGIN_LAT_SERVICE		34	/* string */
146
#define	PW_LOGIN_LAT_NODE		35	/* string */
147
#define	PW_LOGIN_LAT_GROUP		36	/* string */
148
#define	PW_FRAMED_APPLETALK_LINK	37	/* integer */
149
#define	PW_FRAMED_APPLETALK_NETWORK	38	/* integer */
150
#define	PW_FRAMED_APPLETALK_ZONE	39	/* string */
151
#define	PW_CHAP_CHALLENGE		60	/* string */
152
#define	PW_NAS_PORT_TYPE		61	/* integer */
153
#define	PW_PORT_LIMIT			62	/* integer */
154
#define	PW_LOGIN_LAT_PORT		63	/* string */
155
156
/*	Accounting */
157
158
#define	PW_ACCT_STATUS_TYPE		40	/* integer */
159
#define	PW_ACCT_DELAY_TIME		41	/* integer */
160
#define	PW_ACCT_INPUT_OCTETS		42	/* integer */
161
#define	PW_ACCT_OUTPUT_OCTETS		43	/* integer */
162
#define	PW_ACCT_SESSION_ID		44	/* string */
163
#define	PW_ACCT_AUTHENTIC		45	/* integer */
164
#define	PW_ACCT_SESSION_TIME		46	/* integer */
165
#define	PW_ACCT_INPUT_PACKETS		47	/* integer */
166
#define	PW_ACCT_OUTPUT_PACKETS		48	/* integer */
167
#define	PW_ACCT_TERMINATE_CAUSE		49	/* integer */
168
#define	PW_ACCT_MULTI_SESSION_ID	50	/* string */
169
170
/*	Merit Experimental Extensions */
171
172
/*	Temporary assignment for LOG AATV session logging */
173
174
#define PW_LAS_START_TIME		145	/* integer */
175
#define PW_LAS_CODE			146	/* integer */
176
#define PW_LAS_DURATION			147	/* integer */
177
#define PW_LOCAL_DURATION		148	/* integer */
178
179
#define	PW_SERVICE_CLASS		149	/* string */
180
#define	PW_PORT_ENTRY			150	/* string */
181
#define	PW_PROXY_ACTION			211	/* string */
182
#define	PW_TOKEN			213	/* string */
183
#define	PW_HUNTGROUP_NAME		221	/* string */
184
#define	PW_USER_ID			222	/* string */
185
#define	PW_USER_REALM			223	/* string */
186
187
/*	Configuration Only Attributes (for check-items) */
188
189
#define	CI_COMMENT			1024	/* string */
190
#define	CI_XVALUE			1025	/* integer */
191
#define	CI_XSTRING			1026	/* string */
192
#define	CI_AUTHENTICATION_TYPE		1027	/* integer */
193
#define	CI_PROHIBIT			1028	/* integer */
194
#define	CI_USER_CATEGORY		1029	/* string */
195
#define	CI_GROUP_NAME			1030	/* string */
196
#define	CI_ENCRYPTED_PASSWORD		1031	/* string */
197
#define	CI_EXPIRATION			1032	/* date */
198
#define	CI_USER_PASSWORD		1033	/* string */
199
#define	CI_SIMULTANEOUS_USE		1034	/* integer */
200
#define	CI_SERVER_NAME			1035	/* string */
201
202
/*	Integer Translations */
203
204
/*	SERVICE TYPES	*/
205
206
#define	PW_LOGIN			1
207
#define	PW_FRAMED			2
208
#define	PW_CALLBACK_LOGIN		3
209
#define	PW_CALLBACK_FRAMED		4
210
#define	PW_OUTBOUND_USER		5
211
#define	PW_ADMINISTRATIVE_USER		6
212
#define	PW_SHELL_USER			7
213
#define PW_AUTHENTICATE_ONLY		8
214
#define PW_CALLBACK_ADMIN_USER		9
215
216
/*	FRAMED PROTOCOLS	*/
217
218
#define	PW_PPP				1
219
#define	PW_SLIP				2
220
#define	PW_ARA				3
221
#define	PW_GANDALF			4
222
223
/*	FRAMED ROUTING VALUES	*/
224
225
#define	PW_NONE				0
226
#define	PW_BROADCAST			1
227
#define	PW_LISTEN			2
228
#define	PW_BROADCAST_LISTEN		3
229
230
/*	FRAMED COMPRESSION TYPES	*/
231
232
#define	PW_VAN_JACOBSON_TCP_IP		1
233
#define	PW_IPX_HEADER_COMPRESSION	2
234
235
/*	LOGIN SERVICES	*/
236
237
#define	PW_TELNET			0
238
#define	PW_RLOGIN			1
239
#define	PW_TCP_CLEAR			2
240
#define	PW_PORTMASTER			3
241
#define	PW_LAT				4
242
243
/*	TERMINATION ACTIONS	*/
244
245
#define	PW_DEFAULT			0
246
#define	PW_RADIUS_REQUEST		1
247
248
/*	AUTHENTICATION TYPES */
249
250
#define AA_NONE		0	/* This is not a valid user id entry */
251
#define AA_UNIX		1	/* Use local Unix password file */
252
#define AA_AKRB		2	/* AFS Kerberos type authentication */
253
#define AA_MKRB		3	/* MIT Kerberos type authentication */
254
#define AA_RAD		4	/* Pass to remote RADIUS server */
255
#define AA_MNET		5	/* Do Merit specific authentication */
256
#define AA_KCHAP	6	/* Kerberos CHAP authentication */
257
#define AA_TACACS	7	/* Encrypted TACACS authentication */
258
#define AA_REALM	8	/* Find given realm in authfile */
259
#define AA_LOCAL	9
260
#define AA_FILE		10	/* ID/PW list in a file */
261
#define	AA_SCRIPT	11	/* External script */
262
263
#define PW_AUTH_MAX	11	/* Highest authentication type */
264
265
/*	PROHIBIT PROTOCOL  */
266
267
#define PW_DUMB		0	/* 1 and 2 are defined in FRAMED PROTOCOLS */
268
#define PW_AUTH_ONLY	3
269
#define PW_ALL		255
270
271
/*	ACCOUNTING STATUS TYPES    */
272
273
#define PW_STATUS_START		1
274
#define PW_STATUS_STOP		2
275
#define PW_STATUS_ALIVE		3
276
#define PW_STATUS_MODEM_START	4
277
#define PW_STATUS_MODEM_STOP	5
278
#define PW_STATUS_CANCEL	6
279
#define PW_ACCOUNTING_ON	7
280
#define PW_ACCOUNTING_OFF	8
281
282
/*	ACCOUNTING TERMINATION CAUSES    */
283
284
#define PW_USER_REQUEST		1
285
#define PW_LOST_CARRIER		2
286
#define PW_LOST_SERVICE		3
287
#define PW_ACCT_IDLE_TIMEOUT	4
288
#define PW_ACCT_SESSION_TIMEOUT	5
289
#define PW_ADMIN_RESET		6
290
#define PW_ADMIN_REBOOT		7
291
#define PW_PORT_ERROR		8
292
#define PW_NAS_ERROR		9
293
#define PW_NAS_REQUEST		10
294
#define PW_NAS_REBOOT		11
295
#define PW_PORT_UNNEEDED	12
296
#define PW_PORT_PREEMPTED	13
297
#define PW_PORT_SUSPENDED	14
298
#define PW_SERVICE_UNAVAILABLE	15
299
#define PW_CALLBACK		16
300
#define PW_USER_ERROR		17
301
#define PW_HOST_REQUEST		18
302
303
/*	NAS PORT TYPES    */
304
305
#define PW_ASYNC		0
306
#define PW_SYNC			1
307
#define PW_ISDN_SYNC		2
308
#define PW_ISDN_SYNC_V120	3
309
#define PW_ISDN_SYNC_V110	4
310
311
/* Default Database File Names */
312
313
#ifndef RADIUS_DIR
314
#define RADIUS_DIR		"/var/adm/raddb"
315
#endif
316
317
#ifndef RADACCT_DIR
318
#define RADACCT_DIR		"/var/adm/radacct"
319
#endif
320
321
#ifndef RADIUS_SCRIPT
322
#define RADIUS_SCRIPT		"/usr/local/adm/radauth"
323
#endif
324
325
#ifndef RADIUS_SCRIPT_ACCT
326
#define RADIUS_SCRIPT_ACCT	"/usr/local/adm/radacct"
327
#endif
328
329
/*
330
 *	Note:	To change where these files go, do not change the #defines
331
 *		below, instead change the RADIUS_DIR #define above.
332
 */
333
334
#define RADIUS_DICTIONARY	"dictionary"
335
#define RADIUS_CLIENTS		"clients"
336
#define RADIUS_USERS		"users"
337
#define RADIUS_HOLD		"holdusers"
338
#define RADIUS_LOG		"/var/adm/radius.log"
339
#define RADIUS_AUTH		"authfile"
340
#define RADIUS_PID		"radiusd.pid"
341
#define RADIUS_FSM		"radius.fsm"
342
#define RADIUS_DEBUG		"/tmp/radius.debug"
343
344
#ifndef RADIUS_COMPRESS
345
#define RADIUS_COMPRESS		"/usr/bin/gzip"  /* might be gzip, etc. */
346
#endif
347
348
#ifndef RADIUS_LOCALSERVER
349
#define RADIUS_LOCALSERVER	"localserver"
350
#endif
351
352
#ifndef DEFAULT_REALM
353
#define DEFAULT_REALM		"DEFAULT"
354
#endif
355
356
#ifndef NULL_REALM
357
#define NULL_REALM		"NULL"
358
#endif
359
360
/* Server data structures */
361
362
typedef struct dict_attr
363
{
364
	char              name[NAME_LENGTH + 1];	/* attribute name */
365
	int               value;			/* attribute index */
366
	int               type;				/* string, int, etc. */
367
	struct dict_attr *next;
368
} DICT_ATTR;
369
370
typedef struct dict_value
371
{
372
	char               attrname[NAME_LENGTH +1];
373
	char               name[NAME_LENGTH + 1];
374
	int                value;
375
	struct dict_value *next;
376
} DICT_VALUE;
377
378
typedef struct value_pair
379
{
380
	char               name[NAME_LENGTH + 1];
381
	int                attribute;
382
	int                type;
383
	UINT4              lvalue;
384
	char               strvalue[AUTH_STRING_LEN + 1];
385
	struct value_pair *next;
386
} VALUE_PAIR;
387
388
typedef struct auth_req
389
{
390
	UINT4             ipaddr;           /* IP address of requestor */
391
	u_short           udp_port;         /* UDP reply socket of requestor */
392
	u_char            id;               /* Original request seq. number */
393
	u_char            code;             /* Type of RADIUS packet */
394
	u_char            vector[AUTH_VECTOR_LEN];
395
	char             *secret;
396
	char             *file_pfx;
397
	char             *realm_filter;
398
	u_char            ttl;              /* Global queue time-to-live secs */
399
	u_char            timer;            /* General utility timer */
400
	u_char            reply_id;         /* RADIUS-to-RADIUS seq. number */
401
	u_char            retry_cnt;        /* Counter for duplicate requests */
402
	u_char            state;            /* State of current request */
403
	u_char            sws;              /* Switches, flags, etc. */
404
	int               result;           /* Result of previous action */
405
	int               cur_count;        /* Original number request pairs */
406
	struct aatv      *fsm_aatv;         /* Pointer to current FSM action */
407
	struct aatv      *direct_aatv;      /* Pointer to actual action */
408
	struct event_ent *event_q;          /* Pointer to active event queue */
409
	struct auth_req  *next;             /* Global request queue link */
410
	VALUE_PAIR       *request;          /* Original client a/v pairs */
411
	VALUE_PAIR       *cur_request;      /* Represents current a/v pairs */
412
	VALUE_PAIR       *user_check;       /* List of users file check items */
413
} AUTH_REQ;
414
415
typedef struct event_ent
416
{
417
	struct event_ent *next;
418
	AUTH_REQ         *auth_head; /* pointer back to the authreq structure */
419
	struct aatv      *fsm_aatv;  /* record action from FSM table */
420
	struct aatv      *sub_aatv;  /* record action when request was issued */
421
	u_char           *packet;    /* copy of request packet which was sent */
422
	int               len;       /* length of packet */
423
	pid_t             pid;       /* fork type: pid, socket type: == zero */
424
	struct sockaddr_in sin;      /* socket info for packet re-sending */
425
	int               evalue;    /* AATV act_func integer argument */
426
	u_char            state;     /* state in which the request was issued */
427
	char              action[NAME_LENGTH+1]; /* "cmd" arg to radius_send */
428
	char              estring[AUTH_ID_LEN]; /* AATV act_func string arg */
429
} EVENT_ENT;
430
431
typedef struct user_ent
432
{
433
	struct user_ent *next;
434
	char            *name;
435
	VALUE_PAIR      *check;
436
	VALUE_PAIR      *reply;
437
} USER_ENTRY;
438
439
#ifdef  MERIT_LAS
440
typedef struct lasrealm_ent *LAS_REALM;
441
#endif	/* MERIT_LAS */
442
443
typedef struct auth_ent
444
{
445
	struct auth_ent *next;
446
	char            *name;
447
	struct auth_ent *parent;
448
	int              prot;
449
	int              type;
450
	char            *host;
451
	char            *filter;
452
#ifdef  MERIT_LAS
453
	LAS_REALM        las_realm;
454
#endif	/* MERIT_LAS */
455
} AUTH_ENTRY;
456
457
/* The following must match the beginning of the auth_ent structure */
458
typedef struct auth_aent
459
{
460
	struct auth_ent *next;
461
	char            *name;
462
	struct auth_ent *parent;
463
} AUTH_ALIAS_ENTRY;
464
465
typedef struct linklist_entry
466
{
467
	struct linklist_entry *next;	/* pointer to next entry in list */
468
} LINKLIST_ENT;
469
470
#define	numbof(X)	(sizeof(X)/sizeof(X[0]))
471
472
typedef struct name_list
473
{
474
	struct name_list  *next;
475
	char              *name;
476
	u_char             flag;
477
	u_short            num;
478
} NAME_LIST;
479
480
/*	Binary port entry structure used in Port-Entry attribute */
481
482
#define	PORT_ENTRY_VERSION	0	/* increase if change structure here */
483
484
typedef struct bin_port_ent
485
{
486
	u_char             version;	/* be sure to use PORT_ENTRY_VERSION */
487
	u_char             port_source; /* zero => was HGAS, one => otherwise */
488
	time_t             start_time;	/* start time of session on this port */
489
	UINT4              port_nbr;	/* port number of this session */
490
	UINT4              duration;	/* session length (seconds) */
491
} BIN_PORT_ENT;
492
493
/*
494
 * Use the following to specify default "realm" names to use for
495
 * authentication-type entries of RADIUS or TACACS that may be
496
 * configured in the "users" file.  May be configured globally
497
 * in the Makefile or changed in the authfile on a running server.
498
 */
499
500
#ifndef DEFAULT_RADIUS_SERVER
501
#define DEFAULT_RADIUS_SERVER ""
502
#endif
503
504
#ifndef DEFAULT_TACACS_SERVER
505
#define DEFAULT_TACACS_SERVER ""
506
#endif
507
508
/******************************************************************
509
 *
510
 *      PW_PROTTYPE & PW_PROTTYPES - define authentication protocol allowed
511
 *                                   for particular realm entry in authfile.
512
 *
513
 *      The PW_PROTTYPE value is stored in the auth_ent.prot field.
514
 *      The PW_PROTTYPE value corresponds to the order of PW_PROTTYPES.
515
 *
516
 *****************************************************************/
517
518
#define PW_PROTTYPE_DFLT	0	/* Use this entry for any protocol */
519
#define PW_PROTTYPE_CHAP	1	/* Entry is for CHAP style authent. */
520
#define PW_PROTTYPE_PW		2	/* Entry is for id/pw style authent. */
521
522
#define PW_PROTTYPES_DFLT	"DEFAULT"
523
#define PW_PROTTYPES_CHAP	"CHAP"
524
#define PW_PROTTYPES_PW		"PW"
525
526
typedef struct file_list
527
{
528
	struct file_list       *next;
529
	char                   *prefix;
530
	USER_ENTRY             *user_list;
531
	AUTH_ENTRY             *auth_list;
532
} FILE_LIST;
533
534
typedef struct ip_address
535
{
536
	struct ip_address *next;
537
	struct in_addr     ipaddr;
538
} IP_ADDRESS;
539
540
typedef struct dns_name
541
{
542
	struct dns_name   *next;
543
	u_char             type;	/* 0 = official name, 1 = alias */
544
	char               name[1];
545
} DNS_NAME;
546
547
typedef struct client_ent
548
{
549
	struct client_ent *next;
550
	IP_ADDRESS        *addrs;
551
	char              *secret;
552
	char              *prefix;
553
	char              *hostname;
554
	DNS_NAME          *names;
555
	time_t             expire_time;
556
	enum {CE_DNS, CE_NUMERIC, CE_OURADDR} type;
557
} CLIENT_ENTRY;
558
559
#define dprintf(lev, args)	{ if (debug_flag >= lev) logit args; }
560
#define	ddumpx(lev, args)	{ if (debug_flag > lev) dumpit args; }
561
562
/* 	Define return codes from "SendServer" utility */
563
564
#define BADRESP_RC	-2
565
#define ERROR_RC	-1
566
#define OK_RC		0
567
#define TIMEOUT_RC	1
568
569
typedef struct send_data /* Used to pass information to sendserver() function */
570
{
571
	u_char          code;		/* RADIUS packet code */
572
	u_char          seq_nbr;	/* Packet sequence number */
573
	char           *user_name;
574
	char           *password;	/* Cleartext user password */
575
	u_char          ustype;		/* Service-Type attribute */
576
	u_char          fptype;		/* Framed-Protocol attribute */
577
	char           *server;		/* Name/addrress of RADIUS server */
578
	int             svc_port;	/* RADIUS protocol destination port */
579
	int             timeout;	/* Session timeout in seconds */
580
	UINT4           client_id;	/* IP address of client */
581
	int             port_num;	/* Port number on client */
582
	char           *user_file;	/* Users style file of a/v pairs */
583
	char           *group;
584
	VALUE_PAIR     *send_pairs;     /* More a/v pairs to send */
585
	VALUE_PAIR    **receive_pairs;  /* Where to place received a/v pairs */
586
} SEND_DATA;
587
588
/*
589
 *	Handle older syslog versions, too!
590
 */
591
592
#ifndef	LOG_CONS
593
#define	LOG_DAEMON		0
594
#define	LOG_AUTH		0
595
#endif
596
597
#define	MGMT_POLL_SECRET	"Hardlyasecret"
598
#define	MAX_REQUESTS		128
599
#define	MAX_REQUEST_TIME	30	/* Lifetime of a request */
600
#define	CLEANUP_DELAY		5	/* Hold onto old requests this long */
601
#define	DEFAULT_INETD_TIMEOUT	15	/* Fifteen minutes by default */
602
#define	DEFAULT_TIMER_VALUE	3	/* Three seconds by default */
603
#define	ADDRESS_AGING		60*60	/* One hour by default */
604
#define	DFLT_TACACS_UDP_PORT	49	/* Default TACACS server port */
605
#define	SESS_ID_LEN		8	/* session id length */
606
#define SECONDS_PER_DAY		86400
607
#define TRUNCATION_DAY		7   /* Sunday is zero (0), daily is seven (7) */
608
#define	DNS_SLEEP		100	/* Time which DNS sub-process sleeps. */
609
610
typedef enum				/* error code */
611
{
612
  EC_OK,				/* no error */
613
  EC_INTERNAL,				/* internal error */
614
  EC_CONFIG,				/* configuration error */
615
  EC_NO_MEMORY,				/* out of memory */
616
  EC_CREATE_FILE,			/* error creating file */
617
  EC_NO_TOKEN,				/* no token available */
618
  EC_NO_PORTS,				/* no ports available for guests */
619
  EC_TOO_MANY_SESSIONS,			/* user has too many sessions */
620
  EC_ABS_FAILURE,                       /* ABS failed (with message) */
621
  EC_NO_BALANCE,			/* error querying for balance */
622
  EC_BAD_BALANCE			/* balance too low */
623
} ERRORCODE;
624
625
typedef enum				/* accounting code */
626
{
627
	AC_ERROR	= -1,		/* no accounting code */
628
	AC_NORMAL,			/* normal disconnect */
629
	AC_REJECT,			/* rejected by this server */
630
	AC_CANCEL,			/* access rejected by someone */
631
	AC_NOCONFIRM,			/* no confirmation */
632
	AC_OVERTIME,			/* session over maximum time allowed */
633
	AC_UNKNOWN,			/* session ended for unknown reason */
634
	AC_NOTOKEN,			/* rejected because no token */
635
	AC_NOTLOCAL,			/* session not local */
636
	AC_SUSPEND,			/* session suspended */
637
	AC_FAILED,			/* authentication failed */
638
	AC_AUTHORIZED,			/* session authorized (for stats) */
639
	AC_NASREBOOT,			/* released due to NAS reboot */
640
	AC_REMOTE,			/* remote session, failed to forward */
641
	AC_NUMBOFCODE			/* number of accounting code */
642
} ACCTCODE;
643
644
#ifndef PROTO
645
#ifdef __STDC__
646
#define PROTO(x) x
647
#else
648
#define PROTO(x) ()
649
#define const
650
#endif /* !__STDC__ */
651
#endif /* !PROTO */
652
653
union action_u
654
{
655
	struct aatv    *aatv;	/* points to the id field of an AATV */
656
	char           *proxy;	/* pointer to a Proxy-Action string */
657
} UACTION;
658
659
/*	Define event structure (for events generated by AATV recv functions */
660
661
typedef struct ev
662
{
663
	u_char          state;
664
	union action_u  a;
665
	int             isproxy;	/* set to one if action "a" is proxy */
666
	int             value;
667
	char            xstring[AUTH_ID_LEN];
668
} EV;
669
670
/*	Define aatvfunc_type codes */ 
671
672
#define	AA_DIRECT	0	/* Function gives direct reply */
673
#define	AA_SOCKET	1	/* Deferred reply returned on socket */
674
#define	AA_FORK		2	/* Spawn a process to wait for reply */
675
#define	AA_FREPLY	3	/* Fork & get reply on server socket */
676
677
typedef struct aatv
678
{
679
	u_char       id[NAME_LENGTH + 1];
680
	char         authen_type; /* a -1 value indicates built-in AATV types */
681
	u_char       aatvfunc_type;
682
	void       (*init) PROTO((struct aatv *));
683
	int        (*timer) PROTO((void));
684
	int        (*act_func) PROTO((AUTH_REQ *, int, char *));
685
	AUTH_REQ * (*recv) PROTO((struct sockaddr_in *, UINT4, u_int, EV *));
686
	void       (*cleanup) PROTO((void));
687
	UINT4        sockfd;
688
} AATV, *AATVPTR;
689
690
extern AATV    *authtype_tv[];
691
692
#ifdef  MERIT_LAS
693
extern AATVPTR  rad_log_aatv;		/* For logging (selector) */
694
extern AATVPTR  rad_log_all_aatv;	/* For logging (debugging) */
695
extern AATVPTR  rad_log_brief_aatv;	/* For logging (logging) */
696
extern AATVPTR  rad_log_old_aatv;	/* For logging (logging) */
697
extern AATVPTR  rad_log_v1_0_aatv;	/* For logging (logging) */
698
extern AATVPTR  rad_log_v1_1_aatv;	/* For logging (logging) */
699
extern AATVPTR  rad_log_v2_0_aatv;	/* For logging (logging) */
700
extern AATVPTR  rad_log_v2_1_aatv;	/* For logging (logging) */
701
#endif	/* MERIT_LAS */
702
703
/*	Specify all authentication/authorization transfer vectors here. */
704
705
extern AATVPTR	rad_realm_aatv;		/* Needed for authtype = realm */
706
extern AATVPTR	rad_2rad_aatv;		/* Authtype = Radius */
707
extern AATVPTR	rad_tacs_aatv;		/* Authtype = TACACS */
708
extern AATVPTR	rad_unix_aatv;		/* Authtype = Unix-pw */
709
extern AATVPTR	rad_kchp_aatv;		/* Authtype = KCHAP */
710
extern AATVPTR	rad_mnet_aatv;		/* Authtype = mnet */
711
extern AATVPTR	rad_akrb_aatv;		/* Authtype = akerb */
712
extern AATVPTR	rad_mkrb_aatv;		/* Authtype = mkerb */
713
extern AATVPTR  rad_script_aatv;        /* Authtype = SCRIPT */
714
extern AATVPTR	rad_file_aatv;		/* Authtype = File */
715
extern AATVPTR	rad_authen_aatv;	/* Authentication begins here */
716
extern AATVPTR	rad_passwd_aatv;	/* Used for changing passwords */
717
718
#ifdef  MERIT_HUNTGROUP
719
#include	"huntgroup.h"
720
#define EN_HGAS1		"HGAS1"
721
#define EN_HGAS2		"HGAS2"
722
#define EN_HGAS3		"HGAS3"
723
#define EN_HGAS4		"HGAS4"
724
#define EN_BACCT		"BACCT"
725
extern AATVPTR	rad_hgas1_aatv;		/* Hg Authorization begins here */
726
extern AATVPTR	rad_hgas2_aatv;		/* Hg Authorization continues here */
727
extern AATVPTR	rad_hgas3_aatv;		/* Hg Accounting begins here */
728
extern AATVPTR	rad_hgas4_aatv; 	/* Hg Accounting continues here */
729
extern AATVPTR	rad_hgasrmt_aatv;	/* Hg forwarding to remote server */
730
extern AATVPTR	rad_hgacctrmt_aatv;	/* Hg accounting origination */
731
extern AATVPTR	rad_hgaslog_aatv;	/* Hg logging action (for HGAS1) */
732
733
#ifdef  MERIT_HUNTGROUP_DAC
734
extern AATVPTR	rad_hgdac1_aatv;	/* Hg DAC policy begins here */
735
extern AATVPTR	rad_hgdac2_aatv;	/* Hg DAC policy continues here */
736
extern AATVPTR	rad_hgdac3_aatv;	/* Hg DAC accounting begins here */
737
#define DACAATVS ,&rad_hgdac1_aatv,&rad_hgdac2_aatv,&rad_hgdac3_aatv
738
#else	/* MERIT_HUNTGROUP_DAC */
739
#define DACAATVS
740
#endif	/* MERIT_HUNTGROUP_DAC */
741
742
#ifdef  MERIT_HUNTGROUP_SHP
743
extern AATVPTR	rad_hgshp1_aatv;	/* Hg SHP policy begins here */
744
extern AATVPTR	rad_hgshp2_aatv;	/* Hg SHP policy continues here */
745
extern AATVPTR	rad_hgshp3_aatv;	/* Hg SHP accounting begins here */
746
#define SHPAATVS ,&rad_hgshp1_aatv,&rad_hgshp2_aatv,&rad_hgshp3_aatv
747
#else	/* MERIT_HUNTGROUP_SHP */
748
#define SHPAATVS
749
#endif	/* MERIT_HUNTGROUP_SHP */
750
751
#define HGAATVS	,&rad_hgas1_aatv,&rad_hgas2_aatv,&rad_hgas3_aatv,&rad_hgas4_aatv,&rad_hgasrmt_aatv,&rad_hgaslog_aatv,&rad_hgacctrmt_aatv DACAATVS SHPAATVS
752
#else	/* MERIT_HUNTGROUP */
753
#define HGAATVS
754
#define EN_HGAS1		""
755
#define EN_HGAS2		""
756
#define EN_HGAS3		""
757
#define EN_HGAS4		""
758
#define EN_BACCT		""
759
#endif	/* MERIT_HUNTGROUP */
760
761
#ifdef  MERIT_ORGANIZATION
762
#include	"oas.h"
763
#define EN_OAS			"OAS"
764
#define EN_OAS_ACCT		"OAS_ACCT"
765
extern AATVPTR	rad_oas_aatv;		/* Org Authorization begins here */
766
extern AATVPTR	rad_oasrem_aatv;	/* Org Authorization remote stuff */
767
extern AATVPTR	rad_oasloc_aatv;	/* Org Authorization local stuff */
768
extern AATVPTR	oas_acct_aatv;		/* Org Accounting begins here */
769
#define OASAATVS ,&rad_oas_aatv,&rad_oasrem_aatv,&rad_oasloc_aatv,&oas_acct_aatv
770
#else	/* MERIT_ORGANIZATION */
771
#define OASAATVS
772
#define EN_OAS			""
773
#define EN_OAS_ACCT		""
774
#endif	/* MERIT_ORGANIZATION */
775
776
#ifdef  MERIT_LAS
777
#include	"las.h"
778
#define EN_LAS			"AUTHENTICATE"
779
#define EN_LAS_ACCT		"LAS_ACCT"
780
extern AATVPTR	rad_las_aatv;		/* Local authorization */
781
extern AATVPTR	las_auth_subaatv;	/* Generic LAS authorization */
782
extern AATVPTR	las_acct_subaatv;	/* Generic LAS accounting */
783
extern AATVPTR	las_acct_aatv;		/* LAS accounting */
784
785
#ifdef	LAS_NO_HGAS
786
#define	LASCPAATV
787
#else	/* LAS_NO_HGAS */
788
extern AATVPTR	lascp_aatv;		/* LAS synchronizing */
789
#define	LASCPAATV	,&lascp_aatv
790
#endif	/* LAS_NO_HGAS */
791
792
#ifdef UOFM_LAS
793
#include	"umlas.h"
794
extern AATVPTR  las_um_aatv;		/* U of M LAS */
795
#define LASAATVS  ,&las_auth_subaatv,&las_acct_subaatv,&las_um_aatv, \
796
		&rad_las_aatv,&las_acct_aatv LASCPAATV
797
#else	/* UOFM_LAS */
798
#define LASAATVS  ,&las_auth_subaatv,&las_acct_subaatv, \
799
		&rad_las_aatv,&las_acct_aatv LASCPAATV
800
#endif	/* UOFM_LAS */
801
#else	/* MERIT_LAS */
802
#define LASAATVS
803
#define EN_LAS			""
804
#define EN_LAS_ACCT		""
805
#endif	/* MERIT_LAS */
806
807
#define AUTHENAATVS	&rad_realm_aatv,   &rad_unix_aatv,   &rad_2rad_aatv, \
808
			&rad_tacs_aatv,    &rad_kchp_aatv,   &rad_mnet_aatv, \
809
			&rad_akrb_aatv,    &rad_mkrb_aatv,   &rad_file_aatv, \
810
			&rad_authen_aatv,  &rad_passwd_aatv, &rad_script_aatv
811
812
813
#define AATVS	AUTHENAATVS HGAATVS OASAATVS LASAATVS
814
815
/*
816
 *	Event names (EN_*) in RADIUS   ###   see the NOTE in enum_event()
817
 */
818
819
#define EN_NAK			"NAK"
820
#define EN_ACK			"ACK"
821
#define EN_ERROR		"ERROR"
822
#define EN_WAIT			"WAIT"
823
#define EN_FATAL		"FATAL"
824
#define EN_DUP_REQ		"DUP"
825
#define EN_TIMER		"TIMER"
826
#define EN_TIMEOUT		"TIMEOUT"
827
#define EN_ABORT		"ABORT"
828
#define EN_NEW_AUTHEN		"AUTHEN"
829
#define EN_NEW_ACCT		"ACCT"
830
#define EN_NEW_PASSWD		"PASSWD"
831
#define EN_RE_ACCESS		"REACCESS"
832
#define EN_ACC_CHAL		"ACC_CHAL"
833
#define EN_MGT_POLL		"MGT_POLL"
834
#define EN_AUTH_ONLY		"AUTH_ONLY"
835
#define EN_ACCT_START		"ACCT_START"
836
#define EN_ACCT_STOP		"ACCT_STOP"
837
#define EN_ACCT_ALIVE		"ACCT_ALIVE"
838
#define EN_ACCT_MODEM_START	"ACCT_MSTART"
839
#define EN_ACCT_MODEM_STOP	"ACCT_MSTOP"
840
#define EN_ACCT_CANCEL		"ACCT_CANCEL"
841
#define EN_RC1			"RC1"
842
#define EN_RC2			"RC2"
843
#define EN_RC3			"RC3"
844
#define EN_RC4			"RC4"
845
#define EN_RC5			"RC5"
846
#define EN_RC6			"RC6"
847
#define EN_RC7			"RC7"
848
#define EN_RC8			"RC8"
849
#define EN_RC9			"RC9"
850
#define EN_RC10			"RC10"
851
#define EN_RC11			"RC11"
852
#define EN_RC12			"RC12"
853
#define EN_RC13			"RC13"
854
#define EN_RC14			"RC14"
855
#define EN_RC15			"RC15"
856
#define EN_RC16			"RC16"
857
#define EN_RC17			"RC17"
858
#define EN_RC18			"RC18"
859
#define EN_RC19			"RC19"
860
#define EN_RC20			"RC20"
861
#define EN_RC21			"RC21"
862
863
/*
864
 *	Event numbers in RADIUS   ###   see the NOTE in enum_event()
865
 */
866
typedef enum
867
{
868
	EV_NAK			= -1,
869
	EV_ACK			= 0,
870
	EV_ERROR		= 1,
871
	EV_WAIT			= 2,
872
	EV_FATAL		= 3,
873
	EV_DUP_REQ		= 4,
874
	EV_TIMER		= 5,
875
	EV_TIMEOUT		= 6,
876
	EV_ABORT		= 7,
877
878
	/* arbitrary return codes from AATV action functions */
879
880
	EV_RC1			= 8,
881
	EV_RC2			= 9,
882
	EV_RC3			= 10,
883
	EV_RC4			= 11,
884
	EV_RC5			= 12,
885
	EV_RC6			= 13,
886
	EV_RC7			= 14,
887
	EV_RC8			= 15,
888
	EV_RC9			= 16,
889
	EV_RC10			= 17,
890
	EV_RC11			= 18,
891
	EV_RC12			= 19,
892
	EV_RC13			= 20,
893
	EV_RC14			= 21,
894
	EV_RC15			= 22,
895
	EV_RC16			= 23,
896
	EV_RC17			= 24,
897
	EV_RC18			= 25,
898
	EV_RC19			= 26,
899
	EV_RC20			= 27,
900
	EV_RC21			= 28
901
} EVENT;
902
903
/* Request type events */
904
905
#define	EV_NEW_AUTHEN		EV_RC1
906
#define	EV_NEW_ACCT		EV_RC2
907
#define	EV_NEW_PASSWD		EV_RC3
908
#define	EV_RE_ACCESS		EV_RC4
909
#define	EV_ACC_CHAL		EV_RC5
910
#define	EV_MGT_POLL		EV_RC6
911
#define	EV_AUTH_ONLY		EV_RC7
912
#ifdef  MERIT_HUNTGROUP
913
#define	EV_HGAS1		EV_RC8
914
#define	EV_HGAS2		EV_RC9
915
#define	EV_HGAS3		EV_RC10
916
#define	EV_BACCT		EV_RC11
917
#else	/* MERIT_HUNTGROUP */
918
#define	EV_HGAS1		EV_ACK
919
#define	EV_HGAS2		EV_ACK
920
#define	EV_HGAS3		EV_ACK
921
#define	EV_BACCT		EV_ACK
922
#endif	/* MERIT_HUNTGROUP */
923
#define EV_ACCT_START		EV_RC12
924
#define EV_ACCT_STOP		EV_RC13
925
#define EV_ACCT_ALIVE		EV_RC14
926
#define EV_ACCT_MODEM_START	EV_RC15
927
#define EV_ACCT_MODEM_STOP	EV_RC16
928
#define EV_ACCT_CANCEL		EV_RC17
929
#ifdef  MERIT_ORGANIZATION
930
#define	EV_OAS			EV_RC18
931
#define	EV_OAS_ACCT		EV_RC19
932
#else	/* MERIT_ORGANIZATION */
933
#define	EV_OAS			EV_ACK
934
#define	EV_OAS_ACCT		EV_ACK
935
#endif	/* MERIT_ORGANIZATION */
936
#ifdef  MERIT_LAS
937
#define	EV_LAS			EV_RC20
938
#define	EV_LAS_ACCT		EV_RC21
939
#else	/* MERIT_LAS */
940
#define	EV_LAS			EV_ACK
941
#define	EV_LAS_ACCT		EV_ACK
942
#endif	/* MERIT_LAS */
943
944
typedef enum		/* Typedef for second add_string() argument */
945
{
946
	ASIS		= 0x0000,	/* No conversion on string */
947
	ASLC		= 0x0001,	/* Store as lower case sting */
948
	FINDONLY	= 0x0002	/* Find string only */
949
} AS_CONVERT;
950
951
/*
952
 *	The finite state machine (FSM) table is laid out as follows:
953
 *
954
 *	state0:
955
 *		event01         aatv01          nextstate01
956
 *		event02         aatv02          nextstate02
957
 *		...
958
 *	state1:
959
 *		event11         aatv11          nextstate11
960
 *		...
961
 */
962
963
#define NUMSTATES	32	/* initial maximum number of states */
964
965
#define ST_INIT		0	/* initial state */
966
967
#define ST_RESERVED	240	/* beginning of reserved state range */
968
#define ST_SEEN		241	/* flag for state seen before being defined */
969
#define ST_DEFINED	242	/* flag for state definition */
970
971
#define ST_RECV		251	/* to indicate state which receives requests */
972
#define ST_HOLD		252	/* to indicate dead requests */
973
#define ST_SAME		253	/* for default action table */
974
#define ST_ANY		254	/* for default action table */
975
#define ST_END		255	/* end of FSM table */
976
977
typedef struct statelist        /* list of all state names */
978
{
979
	int        maxst;	/* capacity of this list */
980
	int        nst;		/* number of states already there */
981
	NAME_LIST *states;	/* list of states found in the config file */
982
} STATELIST;
983
984
typedef struct fsm_entry	/* The Finite State Machine an array of these */
985
{
986
	struct fsm_entry *next;		/* list of entries for this state */
987
	EV                event;	/* (state.action.event) 3-tuple */
988
	AATV             *action;	/* what AATV (action) to invoke */
989
	int               xvalue;	/* miscellaneous integer from FSM */
990
	char             *xstring;	/* miscellaneous string from FSM */
991
	u_char            next_state;	/* the next state to visit */
992
} FSM_ENT;
993
994
typedef struct prun_rule /* Pruning data structure (from RADIUS DRAFT RFC) */
995
{
996
	int               value;	/* this is the attribute value */
997
	int               flags;	/* inclusive OR of PRUN_FLG values */
998
	int               count;	/* how many the RFC says to allow */
999
} PRUN_RULE;
1000
1001
typedef struct prun_list
1002
{
1003
	char              vendor[AUTH_ID_LEN + 1];
1004
	PRUN_RULE        *rules;
1005
	struct prun_list *next;
1006
} PRUN_LIST;
1007
1008
#define	PRUN_FLG1	1	/* this attribute allowable in Access_Accept */
1009
#define	PRUN_FLG2	2	/* this attribute allowable in Access_Reject */
1010
1011
#define AR_NO_LOG	0x01		    /* sws: Suppress logging flag */
1012
#define AR_FROM_PROXY	0x04		    /* sws: authreq came from NAS */
1013
1014
#define SAR_NO_LOG(authreq) (authreq->sws |= AR_NO_LOG)	      /* set flag */
1015
#define CAR_NO_LOG(authreq) (authreq->sws &= ~AR_NO_LOG)      /* clear flag */
1016
#define TAR_NO_LOG(authreq) ((authreq->sws & AR_NO_LOG) != 0) /* test flag */
1017
1018
#define SAR_FROM_PROXY(authreq) (authreq->sws |= AR_FROM_PROXY)   /* set flag */
1019
#define CAR_FROM_PROXY(authreq) (authreq->sws &= ~AR_FROM_PROXY)  /* clr flag */
1020
#define TAR_FROM_PROXY(authreq) ((authreq->sws & AR_FROM_PROXY) != 0) /* test */
1021
1022
#define AVPAIR_VTOA_QUOTE 0x0001 /* Quote strings with "'" */
1023
#define AVPAIR_VTOA_NULL  0x0002 /* Print "" instead of NULL for missing item */
1024
#define AVPAIR_VTOA_MASK  0x00ff /* Reserve fourteen more bits. */
1025
1026
#define LOG_VP_QUOTE	0x0001	/* Quote strings (same as AVPAIR_VTOA_QUOTE) */
1027
#define LOG_VP_NULL	0x0002  /* Use "" (incompatible with LOG_VP_NA) */
1028
#define LOG_VP_TAB	0x0100	/* Put tab after printing. */
1029
#define LOG_VP_NA	0x0200  /* fprintf ("NA") if no attr exists in list. */
1030
#define LOG_VP_LAST	0x0400	/* Log last value pair found. */
1031
#define LOG_VP_ALL	0x0800	/* Log all attributes found. */
1032
#define LOG_VP_MASK	0xFFFF	/* Switches available. */
1033
1034
/* dict.c */
1035
int dict_init PROTO((void));
1036
DICT_ATTR * dict_attrget PROTO((int));
1037
DICT_ATTR * dict_attrfind PROTO((char *));
1038
DICT_VALUE * dict_valfind PROTO((char *));
1039
DICT_VALUE * dict_valget PROTO((UINT4, char *));
1040
1041
/* fsm.c */
1042
/*AATV * find_aatv PROTO((char *));
1043
int init_fsm PROTO((int, AATVPTR **, int, char *, FSM_ENT ***, FSM_ENT ***));
1044
*/
1045
/* funcs.c */
1046
char * add_string PROTO((char *, int));
1047
char * authtype_toa PROTO((int));
1048
VALUE_PAIR * avpair_add PROTO((VALUE_PAIR **, int, void *, int));
1049
int avpair_assign PROTO((VALUE_PAIR *, void *, int));
1050
int avpair_copy PROTO((VALUE_PAIR **, VALUE_PAIR *, int));
1051
int avpair_get PROTO((void *, VALUE_PAIR *, int));
1052
VALUE_PAIR * avpair_new PROTO((int, void *, int));
1053
char * avpair_vtoa PROTO((VALUE_PAIR *, int));
1054
void compress_file PROTO((FILE **, char *));
1055
void debug_list PROTO((FILE *, VALUE_PAIR *));
1056
void debug_pair PROTO((FILE *, VALUE_PAIR *));
1057
int dumpit PROTO((/* int, int, void *, int, int, char *, ...*/));
1058
void fprint_attr_val PROTO((FILE *, VALUE_PAIR *));
1059
VALUE_PAIR * gen_valpairs PROTO((AUTH_HDR *));
1060
char * get_errmsg PROTO((void));
1061
int get_passwd PROTO((AUTH_REQ *, char *, char *, char *));
1062
VALUE_PAIR * get_vp PROTO((VALUE_PAIR *, UINT4));
1063
VALUE_PAIR * get_last_vp PROTO((VALUE_PAIR *, UINT4));
1064
int hex_dump PROTO((char *, char *, int, int));
1065
void insert_vp PROTO((VALUE_PAIR **, VALUE_PAIR *, VALUE_PAIR *));
1066
int loghead PROTO(( /* va_alist */ ));
1067
int logit PROTO(( /* int facility, int level, char *format, ... */ ));
1068
void missing_attribute PROTO((AUTH_REQ *, char *, int, char *));
1069
VALUE_PAIR * parse_realm PROTO((AUTH_REQ *));
1070
int prune_pairs PROTO((AUTH_REQ *, PRUN_LIST *, int));
1071
#define reply_message(authreq, msgno, msg) _reply_message(authreq, msgno, msg,__FILE__, __LINE__)
1072
int _reply_message PROTO((AUTH_REQ *, ERRORCODE, char *, char *, int));
1073
int reply_sprintf PROTO(( /* int logsw, AUTHREQ *, char *format, ... */ ));
1074
int setupsock PROTO((struct sockaddr_in *, int));
1075
void trunc_logfile PROTO((FILE **, char *));
1076
char * type_string PROTO((AUTH_REQ *, VALUE_PAIR *));
1077
1078
/* passchange.c */
1079
/*int pw_expired PROTO((UINT4));*/
1080
1081
/* radiusd.c */
1082
/*AUTH_REQ * build_acct_req PROTO((AUTH_REQ *, int, char *, int, VALUE_PAIR *));
1083
int call_action PROTO((AATV *, AUTH_REQ *, int, char *));
1084
AUTH_REQ * rad_2rad_recv PROTO((struct sockaddr_in *, UINT4, u_int, EV *));
1085
AUTH_REQ * rad_recv PROTO((struct sockaddr_in *, UINT4, u_int, EV *));
1086
int radius_send PROTO((char *, u_int, char *, AUTH_REQ *, int));
1087
void start_fsm PROTO((AUTH_REQ *, int, char *, char *));
1088
*/
1089
/* sesslog.c */
1090
/*VALUE_PAIR *log_vp PROTO((FILE *, VALUE_PAIR *, int, int));
1091
int logfmt_brief PROTO((FILE *, VALUE_PAIR *));
1092
int logfmt_old PROTO((FILE *, VALUE_PAIR *, int));
1093
int logfmt_v1_0 PROTO((FILE *, VALUE_PAIR *));
1094
int logfmt_v1_1 PROTO((FILE *, VALUE_PAIR *));
1095
int logfmt_v2_0 PROTO((FILE *, VALUE_PAIR *, int, u_short *));
1096
int logfmt_v2_1 PROTO((FILE *, VALUE_PAIR *, int));
1097
*/
1098
/* users.c */
1099
int add_file_list PROTO((char *));
1100
void config_init PROTO((void));
1101
int config_files PROTO((int, int, int));
1102
void config_fini PROTO((void));
1103
void dns_recv PROTO((struct sockaddr_in *, UINT4, int));
1104
AUTH_ENTRY * find_auth_ent PROTO((char *, int, char*));
1105
int find_auth_type PROTO((char *, int, char *, int *, char **, char **, char **));
1106
int find_client PROTO((UINT4, char **, char **, char **));
1107
int find_client_by_name PROTO((UINT4 *, char *, char **, char **));
1108
int find_host_by_name PROTO((UINT4 *, char *));
1109
void free_user_ent PROTO((USER_ENTRY *));
1110
UINT4 get_our_addr PROTO((void));
1111
char * ip_hostname PROTO((UINT4));
1112
void list_cat PROTO((VALUE_PAIR **, VALUE_PAIR *));
1113
void list_copy PROTO((VALUE_PAIR **, VALUE_PAIR *));
1114
int pair_parse PROTO((char *, VALUE_PAIR **));
1115
FILE_LIST * return_file_list PROTO((void));
1116
int update_clients PROTO((void));
1117
int user_find PROTO((char *, char *, int, VALUE_PAIR **, VALUE_PAIR **, int));
1118
void user_gettime PROTO((char *, struct tm *));
1119
int user_update PROTO((char *, VALUE_PAIR *, VALUE_PAIR*));
1120
1121
/* util.c */
1122
UINT4 get_ipaddr PROTO((char *));
1123
int good_ipaddr PROTO((char *));
1124
void list_free PROTO((VALUE_PAIR *));
1125
1126
/* version.c */
1127
/*char * version PROTO((void));
1128
*/
1129
/* pppradius.c */
1130
int rad_auth PROTO((char *, char *));
1131
int rad_acct_start PROTO((char *));
1132
int rad_acct_stop PROTO((char *));
1133
1134
int reqradius;
1135
char *RADIUS_name;
1136
1137
#endif /* RADIUS_H */
(-)pppd/sys-NeXT.c (+1703 lines)
Line 0 Link Here
1
/*
2
 * sys-next.c - System-dependent procedures for setting up
3
 * PPP interfaces on NeXT 3.2/3.3  systems
4
 *
5
 * Copyright (c) 1989 Carnegie Mellon University.
6
 * Copyright (c) 1994 Philippe-Andre Prindeville.
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms are permitted
10
 * provided that the above copyright notice and this paragraph are
11
 * duplicated in all such forms and that any documentation,
12
 * advertising materials, and other materials related to such
13
 * distribution and use acknowledge that the software was developed
14
 * by Carnegie Mellon University.  The name of the
15
 * University may not be used to endorse or promote products derived
16
 * from this software without specific prior written permission.
17
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20
 */
21
22
#ifndef lint
23
static char rcsid[] = "$Id: sys-NeXT.c,v 1.9 1998/03/25 02:17:23 paulus Exp $";
24
#endif
25
26
#include <stdio.h>
27
#include <syslog.h>
28
#include <termios.h>
29
#include <utmp.h>
30
#include <unistd.h>
31
#include <stdlib.h>
32
#include <libc.h>
33
#include <strings.h>
34
#include <sys/types.h>
35
#include <sys/file.h>
36
#include <sys/socket.h>
37
#include <sys/ioctl.h>
38
#include <sys/time.h>
39
#include <sys/errno.h>
40
#include <sys/stat.h>
41
#include <sys/fcntl.h>
42
43
#include <net/if.h>
44
#include <net/ppp_defs.h>
45
#include <net/if_ppp.h>
46
#include <netdb.h>
47
#include <netinet/in.h>
48
#include <netinet/in_systm.h>
49
#include <netinet/in_var.h>
50
#if !(NS_TARGET >= 40)
51
/* XXX get an error "duplicate member ip_v under 4.1 GAMMA */
52
#include <netinet/ip.h>
53
#endif /* NS_TARGET */
54
#include <netinet/if_ether.h>
55
#include <net/route.h>
56
#include <netinet/in.h>
57
58
#include <netinfo/ni.h>
59
60
#include "pppd.h"
61
62
static int initdisc = -1;	/* Initial TTY discipline */
63
static int initfdflags = -1;	/* Initial file descriptor flags for fd */
64
static int ppp_fd = -1;		/* fd which is set to PPP discipline */
65
static int loop_slave = -1;
66
static int loop_master;
67
static char loop_name[20];
68
69
extern int errno;
70
71
static int	restore_term;	/* 1 => we've munged the terminal */
72
static struct termios inittermios; /* Initial TTY termios */
73
74
static char *lock_file;
75
76
static int sockfd;		/* socket for doing interface ioctls */
77
static int pppdev;  /* +++ */
78
79
#if defined(i386) && defined(HAS_BROKEN_IOCTL)
80
#define	ioctl	myioctl
81
#endif
82
83
static int if_is_up;		/* the interface is currently up */
84
static u_int32_t default_route_gateway;	/* gateway addr for default route */
85
static u_int32_t proxy_arp_addr;	/* remote addr for proxy arp */
86
87
/* Prototypes for procedures local to this file. */
88
static int translate_speed __P((int));
89
static int baud_rate_of __P((int));
90
static int dodefaultroute __P((u_int32_t, int));
91
static int get_ether_addr __P((u_int32_t, struct sockaddr *));
92
static int ether_by_host __P((char *, struct ether_addr *));
93
94
95
/*
96
 * sys_init - System-dependent initialization.
97
 */
98
void
99
sys_init()
100
{
101
    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
102
    setlogmask(LOG_UPTO(LOG_INFO));
103
104
    /* Get an internet socket for doing socket ioctl's on. */
105
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
106
	syslog(LOG_ERR, "Couldn't create IP socket: %m");
107
	die(1);
108
    }
109
110
    if((pppdev = open("/dev/ppp0", O_RDWR, O_NONBLOCK)) == NULL)
111
      {
112
	syslog(LOG_ERR, "Couldn't open /dev/ppp0: %m");
113
	die(1);
114
      }
115
      
116
}
117
118
/*
119
 * sys_cleanup - restore any system state we modified before exiting:
120
 * mark the interface down, delete default route and/or proxy arp entry.
121
 * This should call die() because it's called from die().
122
 */
123
void
124
sys_cleanup()
125
{
126
    struct ifreq ifr;
127
128
    if (if_is_up) {
129
	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
130
	if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
131
	    && ((ifr.ifr_flags & IFF_UP) != 0)) {
132
	    ifr.ifr_flags &= ~IFF_UP;
133
	    ioctl(sockfd, SIOCSIFFLAGS, &ifr);
134
	}
135
    }
136
137
    if (default_route_gateway)
138
	cifdefaultroute(0, 0, default_route_gateway);
139
    if (proxy_arp_addr)
140
	cifproxyarp(0, proxy_arp_addr);
141
142
    close(pppdev);
143
}
144
145
/*
146
 * note_debug_level - note a change in the debug level.
147
 */
148
void
149
note_debug_level()
150
{
151
    if (debug) {
152
	syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
153
	setlogmask(LOG_UPTO(LOG_DEBUG));
154
    } else {
155
	setlogmask(LOG_UPTO(LOG_WARNING));
156
    }
157
}
158
159
/*
160
 * ppp_available - check whether the system has any ppp interfaces
161
 * (in fact we check whether we can do an ioctl on ppp0).
162
 */
163
int
164
ppp_available()
165
{
166
    int s, ok;
167
    struct ifreq ifr;
168
    extern char *no_ppp_msg;
169
170
    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
171
	return 1;		/* can't tell - maybe we're not root */
172
173
    strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
174
    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
175
    close(s);
176
177
    no_ppp_msg = "\
178
This system lacks kernel support for PPP.  To include PPP support\n\
179
in the kernel, please follow the steps detailed in the README.NeXT\n\
180
file in the ppp-2.2 distribution.\n";
181
182
    return ok;
183
}
184
185
/*
186
 * establish_ppp - Turn the serial port into a ppp interface.
187
 */
188
void
189
establish_ppp(fd)
190
    int fd;
191
{
192
    int pppdisc = PPPDISC;
193
    int x;
194
195
    if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
196
	syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
197
	die(1);
198
    }
199
    if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
200
	syslog(LOG_ERR, "ioctl(establish TIOCSETD): %m");
201
	die(1);
202
    }
203
204
    /*
205
     * Find out which interface we were given.
206
     */
207
    if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {	
208
	syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
209
	die(1);
210
    }
211
212
    /*
213
     * Enable debug in the driver if requested.
214
     */
215
    if (kdebugflag) {
216
	if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
217
	    syslog(LOG_WARNING, "ioctl(PPPIOCGFLAGS): %m");
218
	} else {
219
	    x |= (kdebugflag & 0xFF) * SC_DEBUG;
220
	    if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
221
		syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
222
	}
223
    }
224
225
    /*
226
     * Set device for non-blocking reads so PPPD can poll for
227
     * input from the kernel.
228
     */
229
    if ((initfdflags = fcntl(fd, F_GETFL)) == -1
230
	|| fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
231
	syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
232
    }
233
234
}
235
236
237
/*
238
 * disestablish_ppp - Restore the serial port to normal operation.
239
 * This shouldn't call die() because it's called from die().
240
 */
241
void
242
disestablish_ppp(fd)
243
    int fd;
244
{
245
    /* Reset non-blocking mode on fd. */
246
    if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
247
	syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
248
    initfdflags = -1;
249
250
    /* Restore old line discipline. */
251
    if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
252
	syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
253
    initdisc = -1;
254
}
255
256
/*
257
 * Check whether the link seems not to be 8-bit clean.
258
 */
259
void
260
clean_check()
261
{
262
    int x;
263
    char *s;
264
265
    if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
266
	s = NULL;
267
	switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
268
	case SC_RCV_B7_0:
269
	    s = "bit 7 set to 1";
270
	    break;
271
	case SC_RCV_B7_1:
272
	    s = "bit 7 set to 0";
273
	    break;
274
	case SC_RCV_EVNP:
275
	    s = "odd parity";
276
	    break;
277
	case SC_RCV_ODDP:
278
	    s = "even parity";
279
	    break;
280
	}
281
	if (s != NULL) {
282
	    syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
283
	    syslog(LOG_WARNING, "All received characters had %s", s);
284
	}
285
    }
286
}
287
288
/*
289
 * List of valid speeds.
290
 */
291
struct speed {
292
    int speed_int, speed_val;
293
} speeds[] = {
294
#ifdef B50
295
    { 50, B50 },
296
#endif
297
#ifdef B75
298
    { 75, B75 },
299
#endif
300
#ifdef B110
301
    { 110, B110 },
302
#endif
303
#ifdef B134
304
    { 134, B134 },
305
#endif
306
#ifdef B150
307
    { 150, B150 },
308
#endif
309
#ifdef B200
310
    { 200, B200 },
311
#endif
312
#ifdef B300
313
    { 300, B300 },
314
#endif
315
#ifdef B600
316
    { 600, B600 },
317
#endif
318
#ifdef B1200
319
    { 1200, B1200 },
320
#endif
321
#ifdef B1800
322
    { 1800, B1800 },
323
#endif
324
#ifdef B2000
325
    { 2000, B2000 },
326
#endif
327
#ifdef B2400
328
    { 2400, B2400 },
329
#endif
330
#ifdef B3600
331
    { 3600, B3600 },
332
#endif
333
#ifdef B4800
334
    { 4800, B4800 },
335
#endif
336
#ifdef B7200
337
    { 7200, B7200 },
338
#endif
339
#ifdef B9600
340
    { 9600, B9600 },
341
#endif
342
#ifdef B19200
343
    { 19200, B19200 },
344
#endif
345
#ifdef B38400
346
    { 38400, B38400 },
347
#endif
348
#ifdef EXTA
349
    { 19200, EXTA },
350
#endif
351
#ifdef EXTB
352
    { 38400, EXTB },
353
#endif
354
#ifdef B14400
355
    { 14400, B14400 },
356
#endif
357
#ifdef B28800
358
    { 28800, B28800 },
359
#endif
360
#ifdef B43200
361
    { 43200, B43200 },
362
#endif
363
#ifdef B57600
364
    { 57600, B57600 },
365
#endif
366
/*
367
#ifndef B115200
368
#warning Defining B115200
369
#define B115200 20
370
#endif
371
*/
372
#ifdef B115200
373
    { 115200, B115200 },
374
#endif
375
    { 0, 0 }
376
};
377
378
/*
379
 * Translate from bits/second to a speed_t.
380
 */
381
int
382
translate_speed(bps)
383
    int bps;
384
{
385
    struct speed *speedp;
386
387
    if (bps == 0)
388
	return 0;
389
    for (speedp = speeds; speedp->speed_int; speedp++)
390
	if (bps == speedp->speed_int)
391
	    return speedp->speed_val;
392
    syslog(LOG_WARNING, "speed %d not supported", bps);
393
    return 0;
394
}
395
396
/*
397
 * Translate from a speed_t to bits/second.
398
 */
399
static int
400
baud_rate_of(speed)
401
    int speed;
402
{
403
    struct speed *speedp;
404
405
    if (speed == 0)
406
	return 0;
407
    for (speedp = speeds; speedp->speed_int; speedp++)
408
	if (speed == speedp->speed_val)
409
	    return speedp->speed_int;
410
    return 0;
411
}
412
413
414
/*
415
 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
416
 * at the requested speed, etc.  If `local' is true, set CLOCAL
417
 * regardless of whether the modem option was specified.
418
 */
419
void
420
set_up_tty(fd, local)
421
    int fd, local;
422
{
423
    int speed, x, modembits;
424
    struct termios tios;
425
426
    if (tcgetattr(fd, &tios) < 0) {
427
	syslog(LOG_ERR, "tcgetattr: %m");
428
	die(1);
429
    }
430
431
    if (!restore_term)
432
	inittermios = tios;
433
434
    tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
435
436
    tios.c_cflag |= CS8 | CREAD | HUPCL;
437
    if (local || !modem)
438
	tios.c_cflag |= CLOCAL;
439
440
    tios.c_iflag = IGNBRK | IGNPAR;
441
    tios.c_oflag = 0;
442
    tios.c_lflag = 0;
443
    tios.c_cc[VMIN] = 1;
444
    tios.c_cc[VTIME] = 0;
445
446
    if (crtscts == -2) {
447
	tios.c_iflag |= IXON | IXOFF;
448
	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
449
	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
450
    }
451
452
    speed = translate_speed(inspeed);
453
    if (speed) {
454
	cfsetospeed(&tios, speed);
455
	cfsetispeed(&tios, speed);
456
    } else {
457
	speed = cfgetospeed(&tios);
458
	/*
459
	 * We can't proceed if the serial port speed is B0,
460
	 * since that implies that the serial port is disabled.
461
	 */
462
	if (speed == B0) {
463
	    syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
464
		   devnam);
465
	    die(1);
466
	}
467
    }
468
469
    if (modem) {
470
      modembits = TIOCM_RTS | TIOCM_CTS;
471
      if (ioctl(fd, (crtscts ? TIOCMBIS : TIOCMBIC), &modembits) < 0)
472
	syslog(LOG_ERR, "ioctl: TIOCMBIS/BIC: %m");
473
    }
474
475
    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
476
	syslog(LOG_ERR, "tcsetattr: %m");
477
	die(1);
478
    }
479
480
   baud_rate = inspeed = baud_rate_of(speed);
481
   restore_term = 1;
482
}
483
484
/*
485
 * restore_tty - restore the terminal to the saved settings.
486
 */
487
void
488
restore_tty(fd)
489
    int fd;
490
{
491
    if (restore_term) {
492
	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
493
	    if (errno != ENXIO)
494
		syslog(LOG_WARNING, "tcsetattr: %m");
495
	restore_term = 0;
496
    }
497
}
498
499
/*
500
 * setdtr - control the DTR line on the serial port.
501
 * This is called from die(), so it shouldn't call die().
502
 *
503
 * The write hack is to get NXFax to recognize that there is
504
 * activity on the port.  Not using the write nukes
505
 * NXFax's capability to determine port usage.
506
 *
507
 */
508
void
509
setdtr(fd, on)
510
int fd, on;
511
{
512
    int modembits = TIOCM_DTR;
513
514
    if (!on)
515
      {
516
	write(fd, " ", 1);
517
	sleep(1);
518
      }
519
520
/*    ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); */
521
    ioctl(fd, (on? TIOCSDTR: TIOCCDTR), 0);
522
}
523
524
525
/*
526
 * output - Output PPP packet.
527
 */
528
void
529
output(unit, p, len)
530
    int unit;
531
    u_char *p;
532
    int len;
533
{
534
    if (debug)
535
	log_packet(p, len, "sent ", LOG_DEBUG);
536
537
    if (write(ttyfd, p, len) < 0) {
538
	if (errno == EWOULDBLOCK || errno == ENOBUFS
539
	    || errno == ENXIO || errno == EIO) {
540
	    syslog(LOG_WARNING, "write: warning: %m");
541
	} else {
542
	    syslog(LOG_ERR, "write: %m");
543
	    die(1);
544
	}
545
    }
546
}
547
548
549
/*
550
 * wait_input - wait until there is data available on ttyfd,
551
 * for the length of time specified by *timo (indefinite
552
 * if timo is NULL).
553
 */
554
void
555
wait_input(timo)
556
    struct timeval *timo;
557
{
558
    fd_set ready;
559
    int n;
560
561
    FD_ZERO(&ready);
562
    FD_SET(ttyfd, &ready);
563
    n = select(ttyfd+1, &ready, NULL, &ready, timo);
564
    if (n < 0 && errno != EINTR) {
565
	syslog(LOG_ERR, "select: %m");
566
	die(1);
567
    }
568
}
569
570
571
/*
572
 * read_packet - get a PPP packet from the serial device.
573
 */
574
int
575
read_packet(buf)
576
    u_char *buf;
577
{
578
    int len;
579
580
    if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
581
	if (errno == EWOULDBLOCK || errno == EINTR) {
582
	    MAINDEBUG((LOG_DEBUG, "read: %m"));
583
	    return -1;
584
	}
585
	syslog(LOG_ERR, "read: %m");
586
	die(1);
587
    }
588
    return len;
589
}
590
591
592
/*
593
 * ppp_send_config - configure the transmit characteristics of
594
 * the ppp interface.
595
 */
596
void
597
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
598
    int unit, mtu;
599
    u_int32_t asyncmap;
600
    int pcomp, accomp;
601
{
602
    u_int x;
603
    struct ifreq ifr;
604
605
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
606
    ifr.ifr_mtu = mtu;
607
    if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
608
	syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
609
	quit();
610
    }
611
612
    if (ioctl(ttyfd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
613
	syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
614
	quit();
615
    }
616
617
    if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
618
	syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
619
	quit();
620
    }
621
    x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
622
    x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
623
    if (ioctl(ttyfd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
624
	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
625
	quit();
626
    }
627
}
628
629
630
/*
631
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
632
 */
633
void
634
ppp_set_xaccm(unit, accm)
635
    int unit;
636
    ext_accm accm;
637
{
638
    if (ioctl(ttyfd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
639
	syslog(LOG_WARNING, "ioctl(PPPIOCSXASYNCMAP): %m");
640
}
641
642
643
/*
644
 * ppp_recv_config - configure the receive-side characteristics of
645
 * the ppp interface.
646
 */
647
void
648
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
649
    int unit, mru;
650
    u_int32_t asyncmap;
651
    int pcomp, accomp;
652
{
653
    int x;
654
655
    if (ioctl(ttyfd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
656
	syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
657
	quit();
658
    }
659
    if (ioctl(ttyfd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
660
	syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
661
	quit();
662
    }
663
    if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
664
	syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
665
	quit();
666
    }
667
    x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
668
    if (ioctl(ttyfd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
669
	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
670
	quit();
671
    }
672
}
673
674
/*
675
 * ccp_test - ask kernel whether a given compression method
676
 * is acceptable for use.
677
 */
678
int
679
ccp_test(unit, opt_ptr, opt_len, for_transmit)
680
    int unit, opt_len, for_transmit;
681
    u_char *opt_ptr;
682
{
683
    struct ppp_option_data data;
684
685
    data.ptr = opt_ptr;
686
    data.length = opt_len;
687
    data.transmit = for_transmit;
688
    if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
689
	return 1;
690
    return (errno == ENOBUFS)? 0: -1;
691
}
692
693
/*
694
 * ccp_flags_set - inform kernel about the current state of CCP.
695
 */
696
void
697
ccp_flags_set(unit, isopen, isup)
698
    int unit, isopen, isup;
699
{
700
    int x;
701
702
    if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
703
	syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
704
	return;
705
    }
706
    x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
707
    x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
708
    if (ioctl(ttyfd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
709
	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
710
}
711
712
/*
713
 * ccp_fatal_error - returns 1 if decompression was disabled as a
714
 * result of an error detected after decompression of a packet,
715
 * 0 otherwise.  This is necessary because of patent nonsense.
716
 */
717
int
718
ccp_fatal_error(unit)
719
    int unit;
720
{
721
    int x;
722
723
    if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
724
	syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
725
	return 0;
726
    }
727
    return x & SC_DC_FERROR;
728
}
729
730
/*
731
 * sifvjcomp - config tcp header compression
732
 */
733
int
734
sifvjcomp(u, vjcomp, cidcomp, maxcid)
735
    int u, vjcomp, cidcomp, maxcid;
736
{
737
    u_int x;
738
739
    if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
740
	syslog(LOG_ERR, "ioctl(PPIOCGFLAGS): %m");
741
	return 0;
742
    }
743
    x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
744
    x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
745
    if (ioctl(ttyfd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
746
	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
747
	return 0;
748
    }
749
    if (ioctl(ttyfd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
750
	syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
751
	return 0;
752
    }
753
    return 1;
754
}
755
756
/*
757
 * sifup - Config the interface up and enable IP packets to pass.
758
 */
759
#ifndef SC_ENABLE_IP
760
#define SC_ENABLE_IP	0x100	/* compat for old versions of kernel code */
761
#endif
762
763
int
764
sifup(u)
765
    int u;
766
{
767
    struct ifreq ifr;
768
    u_int x;
769
    struct npioctl npi;
770
771
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
772
    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
773
	syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
774
	return 0;
775
    }
776
    ifr.ifr_flags |= IFF_UP;
777
    if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
778
	syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
779
	return 0;
780
    }
781
    if_is_up = 1;
782
    npi.protocol = PPP_IP;
783
    npi.mode = NPMODE_PASS;
784
    if (ioctl(ttyfd, PPPIOCSNPMODE, &npi) < 0) {
785
	if (errno != ENOTTY) {
786
	    syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
787
	    return 0;
788
	}
789
	/* for backwards compatibility */
790
	if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
791
	    syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
792
	    return 0;
793
	}
794
	x |= SC_ENABLE_IP;
795
	if (ioctl(ttyfd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
796
	    syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
797
	    return 0;
798
	}
799
    }
800
    return 1;
801
}
802
803
/*
804
 * sifdown - Config the interface down and disable IP.
805
 */
806
int
807
sifdown(u)
808
    int u;
809
{
810
    struct ifreq ifr;
811
    u_int x;
812
    int rv;
813
    struct npioctl npi;
814
815
    rv = 1;
816
    npi.protocol = PPP_IP;
817
    npi.mode = NPMODE_ERROR;
818
    ioctl(ttyfd, PPPIOCSNPMODE, (caddr_t) &npi);
819
    /* ignore errors, because ttyfd might have been closed by now. */
820
821
822
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
823
    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
824
	syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
825
	rv = 0;
826
    } else {
827
	ifr.ifr_flags &= ~IFF_UP;
828
	if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
829
	    syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
830
	    rv = 0;
831
	} else
832
	    if_is_up = 0;
833
    }
834
    return rv;
835
}
836
837
/*
838
 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
839
 * if it exists.
840
 */
841
#define SET_SA_FAMILY(addr, family)		\
842
    BZERO((char *) &(addr), sizeof(addr));	\
843
    addr.sa_family = (family); 
844
845
/*
846
 * sifaddr - Config the interface IP addresses and netmask.
847
 */
848
int
849
sifaddr(u, o, h, m)
850
    int u;
851
    u_int32_t o, h, m;
852
{
853
    int ret;
854
    struct ifreq ifr;
855
856
    ret = 1;
857
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
858
    SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
859
    ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
860
    if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
861
	syslog(LOG_ERR, "ioctl(SIOCAIFADDR): %m");
862
	ret = 0;
863
    }
864
    ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
865
    if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
866
	syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
867
	ret = 0;
868
    }
869
    if (m != 0) {
870
	((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
871
	syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
872
	if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
873
	    syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
874
	    ret = 0;
875
	}
876
    }
877
    return ret;
878
}
879
880
/*
881
 * cifaddr - Clear the interface IP addresses, and delete routes
882
 * through the interface if possible.
883
 *
884
 * N.B.: under NextStep, you can't *delete* an address on an interface,
885
 * so we change it to 0.0.0.0...  A real hack.  But it simplifies
886
 * reconnection on the server side.
887
 */
888
int
889
cifaddr(u, o, h)
890
    int u;
891
    u_int32_t o, h;
892
{
893
    struct rtentry rt;
894
895
#if 1
896
    h = o = 0L;
897
    (void) sifaddr(u, o, h, 0L);
898
#endif
899
    SET_SA_FAMILY(rt.rt_dst, AF_INET);
900
    ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
901
    SET_SA_FAMILY(rt.rt_gateway, AF_INET);
902
    ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
903
    rt.rt_flags = RTF_HOST;
904
    if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
905
	syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
906
	return 0;
907
    }
908
    return 1;
909
}
910
911
/*
912
 * sifdefaultroute - assign a default route through the address given.
913
 */
914
int
915
sifdefaultroute(u, l, g)
916
    int u;
917
    u_int32_t l, g;
918
{
919
    return dodefaultroute(g, 's');
920
}
921
922
/*
923
 * cifdefaultroute - delete a default route through the address given.
924
 */
925
int
926
cifdefaultroute(u, l, g)
927
    int u;
928
    u_int32_t l, g;
929
{
930
    return dodefaultroute(g, 'c');
931
}
932
933
/*
934
 * dodefaultroute - talk to a routing socket to add/delete a default route.
935
 */
936
int
937
dodefaultroute(g, cmd)
938
    u_int32_t g;
939
    int cmd;
940
{
941
    struct rtentry rt;
942
943
    SET_SA_FAMILY(rt.rt_dst, AF_INET);
944
    ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = 0L;
945
    SET_SA_FAMILY(rt.rt_gateway, AF_INET);
946
    ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
947
    rt.rt_flags = RTF_GATEWAY;
948
    if (ioctl(sockfd, (cmd == 's') ? SIOCADDRT : SIOCDELRT, &rt) < 0) {
949
	syslog(LOG_ERR, "%cifdefaultroute: ioctl(%s): %m", cmd,
950
	       (cmd == 's') ? "SIOCADDRT" : "SIOCDELRT");
951
	return 0;
952
    }
953
    default_route_gateway = (cmd == 's')? g: 0;
954
    return 1;
955
}
956
957
/*
958
 * sifproxyarp - Make a proxy ARP entry for the peer.
959
 */
960
int
961
sifproxyarp(unit, hisaddr)
962
    int unit;
963
    u_int32_t hisaddr;
964
{
965
    struct arpreq arpreq;
966
967
    BZERO(&arpreq, sizeof(arpreq));
968
969
    /*
970
     * Get the hardware address of an interface on the same subnet
971
     * as our local address.
972
     */
973
    if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
974
	syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
975
	return 0;
976
    }
977
978
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
979
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
980
    arpreq.arp_flags = ATF_PERM | ATF_PUBL;
981
    if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
982
	syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
983
	return 0;
984
    }
985
986
    proxy_arp_addr = hisaddr;
987
    return 1;
988
}
989
990
/*
991
 * cifproxyarp - Delete the proxy ARP entry for the peer.
992
 */
993
int
994
cifproxyarp(unit, hisaddr)
995
    int unit;
996
    u_int32_t hisaddr;
997
{
998
    struct arpreq arpreq;
999
1000
    BZERO(&arpreq, sizeof(arpreq));
1001
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1002
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1003
    if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1004
	syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1005
	return 0;
1006
    }
1007
    proxy_arp_addr = 0;
1008
    return 1;
1009
}
1010
1011
/*
1012
 * get_ether_addr - get the hardware address of an interface on the
1013
 * the same subnet as ipaddr.
1014
 */
1015
#define MAX_IFS		32
1016
1017
int
1018
get_ether_addr(ipaddr, hwaddr)
1019
    u_int32_t ipaddr;
1020
    struct sockaddr *hwaddr;
1021
{
1022
    struct ifreq *ifr, *ifend, *ifp;
1023
    u_int32_t ina, mask;
1024
    struct ether_addr dla;
1025
    struct ifreq ifreq;
1026
    struct ifconf ifc;
1027
    struct ifreq ifs[MAX_IFS];
1028
    struct hostent *hostent;
1029
1030
    ifc.ifc_len = sizeof(ifs);
1031
    ifc.ifc_req = ifs;
1032
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1033
	syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1034
	return 0;
1035
    }
1036
1037
    /*
1038
     * Scan through looking for an interface with an Internet
1039
     * address on the same subnet as `ipaddr'.
1040
     */
1041
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1042
    for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1043
		((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1044
	if (ifr->ifr_addr.sa_family == AF_INET) {
1045
	    ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1046
	    strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1047
	    /*
1048
	     * Check that the interface is up, and not point-to-point
1049
	     * or loopback.
1050
	     */
1051
	    if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1052
		continue;
1053
	    if ((ifreq.ifr_flags &
1054
		 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1055
		 != (IFF_UP|IFF_BROADCAST))
1056
		continue;
1057
	    /*
1058
	     * Get its netmask and check that it's on the right subnet.
1059
	     */
1060
	    if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1061
		continue;
1062
	    mask = ((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr.s_addr;
1063
	    if ((ipaddr & mask) != (ina & mask))
1064
		continue;
1065
1066
	    break;
1067
	}
1068
    }
1069
1070
    if (ifr >= ifend)
1071
	return 0;
1072
    syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1073
1074
    /*
1075
     * Get the hostname and look for an entry using the ethers database.
1076
     * Under NeXTStep this is the best we can do for now.
1077
     */
1078
    if ((hostent = gethostbyaddr((char*)&ina, sizeof(ina), AF_INET)) == NULL)
1079
	return 0;
1080
1081
    if (ether_by_host(hostent->h_name, &dla)) {
1082
	syslog(LOG_INFO, "Add entry for %s in /etc/ethers", hostent->h_name);
1083
	return 0;	/* it's not there */
1084
    }
1085
    hwaddr->sa_family = AF_UNSPEC;
1086
    BCOPY(&dla, hwaddr->sa_data, sizeof(dla));
1087
    return 1;
1088
}
1089
1090
static int
1091
ether_by_host(hostname, etherptr)
1092
    char *hostname;
1093
    struct ether_addr *etherptr;
1094
{
1095
    struct ether_addr *thisptr;
1096
    void *conn;
1097
    ni_id root;
1098
    ni_namelist val;
1099
    char path[256];
1100
1101
    if (!ether_hostton(hostname, etherptr))
1102
	return 0;
1103
    /*
1104
     * We shall now try and
1105
     * find the address in the
1106
     * top domain of netinfo.
1107
     */
1108
    strcat(strcpy(path, "/machines/"), hostname);
1109
1110
    if (ni_open((void *)0, "/", &conn)
1111
     || ni_root(conn, &root)
1112
     || ni_pathsearch(conn, &root, path)
1113
     || ni_lookupprop(conn, &root, "en_address", &val))
1114
	return 1;
1115
1116
    /*
1117
     * Now we can convert the returned string into an ethernet address.
1118
     */
1119
    strcpy(path, val.ni_namelist_val[0]);
1120
    ni_free(conn);
1121
    if ((thisptr = (struct ether_addr*)ether_aton(path)) == NULL)
1122
	return 1;
1123
    BCOPY(thisptr, etherptr, sizeof(struct ether_addr));
1124
    return 0;
1125
}
1126
1127
1128
1129
/*
1130
 * Return user specified netmask, modified by any mask we might determine
1131
 * for address `addr' (in network byte order).
1132
 * Here we scan through the system's list of interfaces, looking for
1133
 * any non-point-to-point interfaces which might appear to be on the same
1134
 * network as `addr'.  If we find any, we OR in their netmask to the
1135
 * user-specified netmask.
1136
 */
1137
u_int32_t
1138
GetMask(addr)
1139
    u_int32_t addr;
1140
{
1141
    u_int32_t mask, nmask, ina;
1142
    struct ifreq *ifr, *ifend, ifreq;
1143
    struct ifconf ifc;
1144
    struct ifreq ifs[MAX_IFS];
1145
1146
    addr = ntohl(addr);
1147
    if (IN_CLASSA(addr))	/* determine network mask for address class */
1148
	nmask = IN_CLASSA_NET;
1149
    else if (IN_CLASSB(addr))
1150
	nmask = IN_CLASSB_NET;
1151
    else
1152
	nmask = IN_CLASSC_NET;
1153
    /* class D nets are disallowed by bad_ip_adrs */
1154
    mask = netmask | htonl(nmask);
1155
1156
    /*
1157
     * Scan through the system's network interfaces.
1158
     */
1159
    ifc.ifc_len = sizeof(ifs);
1160
    ifc.ifc_req = ifs;
1161
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1162
	syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1163
	return mask;
1164
    }
1165
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1166
    for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1167
	 	((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1168
	/*
1169
	 * Check the interface's internet address.
1170
	 */
1171
	if (ifr->ifr_addr.sa_family != AF_INET)
1172
	    continue;
1173
	ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1174
	if ((ntohl(ina) & nmask) != (addr & nmask))
1175
	    continue;
1176
	/*
1177
	 * Check that the interface is up, and not point-to-point or loopback.
1178
	 */
1179
	strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1180
	if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1181
	    continue;
1182
	if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1183
	    != IFF_UP)
1184
	    continue;
1185
	/*
1186
	 * Get its netmask and OR it into our mask.
1187
	 */
1188
	if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1189
	    continue;
1190
	mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1191
    }
1192
1193
    return mask;
1194
}
1195
1196
1197
1198
/*
1199
 * daemon - Detach us from the terminal session.
1200
 */
1201
int
1202
daemon(nochdir, noclose)
1203
    int nochdir, noclose;
1204
{
1205
    int pid;
1206
1207
    if ((pid = fork()) < 0)
1208
	return -1;
1209
    if (pid != 0)
1210
	exit(0);		/* parent dies */
1211
    (void)setsid();
1212
    if (!nochdir)
1213
	chdir("/");
1214
    if (!noclose) {
1215
	fclose(stdin);		/* don't need stdin, stdout, stderr */
1216
	fclose(stdout);
1217
	fclose(stderr);
1218
    }
1219
    return 0;
1220
}
1221
1222
1223
char *
1224
strdup(s)
1225
    const char *s;
1226
{
1227
    char *d = malloc(strlen(s) + 1);
1228
1229
    if (d) strcpy(d, s);
1230
    return d;
1231
}
1232
1233
/*
1234
 * This logwtmp() implementation is subject to the following copyright:
1235
 *
1236
 * Copyright (c) 1988 The Regents of the University of California.
1237
 * All rights reserved.
1238
 *
1239
 * Redistribution and use in source and binary forms are permitted
1240
 * provided that the above copyright notice and this paragraph are
1241
 * duplicated in all such forms and that any documentation,
1242
 * advertising materials, and other materials related to such
1243
 * distribution and use acknowledge that the software was developed
1244
 * by the University of California, Berkeley.  The name of the
1245
 * University may not be used to endorse or promote products derived
1246
 * from this software without specific prior written permission.
1247
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1248
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1249
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1250
 */
1251
1252
#define WTMPFILE        "/usr/adm/wtmp"
1253
1254
void
1255
logwtmp(line, name, host)
1256
    const char *line, *name, *host;
1257
{
1258
    int fd;
1259
    struct stat buf;
1260
    struct utmp ut;
1261
1262
    if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1263
	return;
1264
    if (!fstat(fd, &buf)) {
1265
	(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1266
	(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1267
	(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1268
	(void)time(&ut.ut_time);
1269
	if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1270
	    (void)ftruncate(fd, buf.st_size);
1271
    }
1272
    close(fd);
1273
}
1274
1275
/*
1276
 * Routines for locking and unlocking the serial device, moved here
1277
 * from chat.c.
1278
 */
1279
1280
#define LOCK_PREFIX	"/usr/spool/uucp/LCK/LCK.."
1281
1282
/*
1283
 * lock - create a lock file for the named device
1284
 */
1285
int
1286
lock(dev)
1287
    char *dev;
1288
{
1289
    int fd, pid, n;
1290
    char *p;
1291
1292
    if ((p = strrchr(dev, '/')) != NULL)
1293
	dev = p + 1;
1294
    lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1295
    if (lock_file == NULL)
1296
	novm("lock file name");
1297
    strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1298
1299
    while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1300
	if (errno == EEXIST
1301
	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1302
	    /* Read the lock file to find out who has the device locked */
1303
	    n = read(fd, &pid, sizeof(pid));
1304
	    if (n <= 0) {
1305
		syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1306
		close(fd);
1307
	    } else {
1308
		if (kill(pid, 0) == -1 && errno == ESRCH) {
1309
		    /* pid no longer exists - remove the lock file */
1310
		    if (unlink(lock_file) == 0) {
1311
			close(fd);
1312
			syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1313
			       dev, pid);
1314
			continue;
1315
		    } else
1316
			syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1317
			       dev);
1318
		} else
1319
		    syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1320
			   dev, pid);
1321
	    }
1322
	    close(fd);
1323
	} else
1324
	    syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1325
	free(lock_file);
1326
	lock_file = NULL;
1327
	return -1;
1328
    }
1329
1330
    pid = getpid();
1331
    write(fd, &pid, sizeof pid);
1332
1333
    close(fd);
1334
    return 0;
1335
}
1336
1337
/*
1338
 * unlock - remove our lockfile
1339
 */
1340
void
1341
unlock()
1342
{
1343
    if (lock_file) {
1344
	unlink(lock_file);
1345
	free(lock_file);
1346
	lock_file = NULL;
1347
    }
1348
}
1349
1350
#if defined(i386) && defined(HAS_BROKEN_IOCTL)
1351
int
1352
ioctl(fd, cmd, c)
1353
    int fd, cmd;
1354
    caddr_t c;
1355
{
1356
#undef	ioctl
1357
    int ret;
1358
1359
#ifdef DEBUGIOCTL
1360
    int serrno;
1361
    u_char let, code, size;
1362
1363
    size = (cmd >> 16) & IOCPARM_MASK;
1364
    let = (cmd >> 8);
1365
    code = cmd;
1366
1367
    if (let == 't' && (75 <= code && code <= 90))
1368
    syslog(LOG_INFO, "ioctl(%d, 0x%x ('%c', %d, %d), 0x%x)\n", fd, cmd,
1369
	   let, code, size, c);
1370
#endif
1371
1372
    ret = ioctl(fd, cmd, c);
1373
1374
#ifdef DEBUGIOCTL
1375
    serrno = errno;
1376
    if (ret == -1)
1377
	syslog(LOG_INFO, "ioctl('%c', %d, %d) errno = %d (%m)\n",
1378
		let, code, size, errno);
1379
    if (let == 't' && (75 <= code && code <= 90) && (cmd & IOC_OUT)) {
1380
	int i, len = ((cmd >> 16) & IOCPARM_MASK);
1381
	for (i = 0; i < len / 4; ++i)
1382
		syslog(LOG_INFO, "word[%d] @ 0x%06x = 0x%x\n",
1383
		       i, &((int *) c)[i],((int *)c)[i]);
1384
    }
1385
    errno = serrno;
1386
#endif
1387
1388
    if (ret == -1 && errno == EPERM)
1389
	errno = ret = 0;
1390
    return ret;
1391
}
1392
#endif	/* HAS_BROKEN_IOCTL */
1393
1394
1395
#if defined(FIXSIGS) && (defined (hppa) || defined(sparc))
1396
1397
/*
1398
 * These redefinitions of Posix functions are necessary
1399
 * because HPPA systems have an OS bug that causes 
1400
 * sigaction to core dump:
1401
 *
1402
 * AlainF 9-Nov-1994	HACK FOR HP-PA/NEXTSTEP
1403
 *			sigaction(3) seems broken in the HP-PA NeXTSTEP 3.2
1404
 *			Posix lib. This causes pppd to SIGBUS at the expiration
1405
 *			of the first timeout (_sigtramp seems to invoke
1406
 *			the SIGALRM handler at an unreasonably low address).
1407
 *			All calls so sigaction(3) have been changed to calls
1408
 *			to sigvec(2) and sigprocmask(SIG_BLOCK,...) to
1409
 *			sigblock(2).
1410
 *			This is kind of a hack, especially since there are
1411
 *			other routines of the Posix lib still used, but
1412
 *			it worked for me.
1413
 *
1414
 * Dave Hess <David-Hess@net.tamu.edu> noted that 3.3 Sparc seems to
1415
 * have the same bug.  Thus this fix has been enabled for SPARC also.
1416
 *
1417
 *
1418
 */
1419
1420
int sigemptyset(sigset_t *mask)
1421
{
1422
  *mask = 0;
1423
}
1424
1425
sigaddset(sigset_t *mask, int which_sig)
1426
{
1427
  *mask |= sigmask(which_sig);
1428
}
1429
1430
1431
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
1432
{
1433
   struct sigvec sv;
1434
   static int in = 0;
1435
1436
   sv.sv_handler = act->sa_handler;
1437
   sv.sv_mask = act->sa_mask;
1438
   sv.sv_flags = 0;
1439
1440
   if (!in)
1441
     {
1442
       in = 1;
1443
       syslog(LOG_WARNING, "PPPD: Inside modified HP and SPARC sigaction\n");
1444
     }
1445
1446
   return sigvec(sig, &sv, NULL);
1447
}
1448
1449
#endif
1450
1451
1452
/*
1453
 * Code following is added for 2.3 compatibility
1454
 */
1455
1456
/*
1457
 * get_idle_time - return how long the link has been idle.
1458
 */
1459
int
1460
get_idle_time(u, ip)
1461
    int u;
1462
    struct ppp_idle *ip;
1463
{
1464
  return (ioctl(ttyfd, PPPIOCGIDLE, ip) >= 0); 
1465
}
1466
1467
1468
/*
1469
 * get_loop_output - read characters from the loopback, form them
1470
 * into frames, and detect when we want to bring the real link up.
1471
 * Return value is 1 if we need to bring up the link, 0 otherwise.
1472
 */
1473
int
1474
get_loop_output()
1475
{
1476
1477
#if 0
1478
    int rv = 0;
1479
    int n;
1480
1481
    while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
1482
	if (loop_chars(inbuf, n))
1483
	    rv = 1;
1484
    }
1485
1486
    if (n == 0) {
1487
	syslog(LOG_ERR, "eof on loopback");
1488
	die(1);
1489
    } else if (errno != EWOULDBLOCK){
1490
	syslog(LOG_ERR, "read from loopback: %m");
1491
	die(1);
1492
    }
1493
1494
    return rv;
1495
#endif
1496
1497
    return 0;
1498
}
1499
1500
/*
1501
 * sifnpmode - Set the mode for handling packets for a given NP.
1502
 */
1503
int
1504
sifnpmode(u, proto, mode)
1505
    int u;
1506
    int proto;
1507
    enum NPmode mode;
1508
{
1509
    struct npioctl npi;
1510
1511
    npi.protocol = proto;
1512
    npi.mode = mode;
1513
    if (ioctl(ttyfd, PPPIOCSNPMODE, &npi) < 0) {
1514
	syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
1515
	return 0;
1516
    }
1517
    return 1;
1518
}
1519
1520
1521
/*
1522
 * open_ppp_loopback - open the device we use for getting
1523
 * packets in demand mode, and connect it to a ppp interface.
1524
 * Here we use a pty.
1525
 */
1526
void
1527
open_ppp_loopback()
1528
{
1529
1530
#if 0
1531
    int flags;
1532
    struct termios tios;
1533
    int pppdisc = PPPDISC;
1534
1535
    syslog(LOG_ERR, "open_ppp_loopback called!");
1536
    die(1);
1537
1538
    if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) {
1539
	syslog(LOG_ERR, "No free pty for loopback");
1540
	die(1);
1541
    }
1542
    SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
1543
1544
    if (tcgetattr(loop_slave, &tios) == 0) {
1545
	tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
1546
	tios.c_cflag |= CS8 | CREAD;
1547
	tios.c_iflag = IGNPAR;
1548
	tios.c_oflag = 0;
1549
	tios.c_lflag = 0;
1550
	if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
1551
	    syslog(LOG_WARNING, "couldn't set attributes on loopback: %m");
1552
    }
1553
1554
    if ((flags = fcntl(loop_master, F_GETFL)) != -1) 
1555
	if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
1556
	    syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m");
1557
1558
    ttyfd = loop_slave;
1559
    if (ioctl(ttyfd, TIOCSETD, &pppdisc) < 0) {
1560
	syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1561
	die(1);
1562
    }
1563
1564
    /*
1565
     * Find out which interface we were given.
1566
     */
1567
    if (ioctl(ttyfd, PPPIOCGUNIT, &ifunit) < 0) {	
1568
	syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
1569
	die(1);
1570
    }
1571
1572
    /*
1573
     * Enable debug in the driver if requested.
1574
     */
1575
    if (kdebugflag) {
1576
	if (ioctl(ttyfd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
1577
	    syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
1578
	} else {
1579
	    flags |= (kdebugflag & 0xFF) * SC_DEBUG;
1580
	    if (ioctl(ttyfd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
1581
		syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
1582
	}
1583
    }
1584
1585
#endif
1586
1587
}
1588
1589
/*
1590
 * restore_loop - reattach the ppp unit to the loopback.
1591
 */
1592
void
1593
restore_loop()
1594
{
1595
    int x;
1596
1597
    /*
1598
     * Transfer the ppp interface back to the loopback.
1599
     */
1600
    if (ioctl(ttyfd, PPPIOCXFERUNIT, 0) < 0) {
1601
	syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
1602
	die(1);
1603
    }
1604
    x = PPPDISC;
1605
    if (ioctl(loop_slave, TIOCSETD, &x) < 0) {
1606
	syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1607
	die(1);
1608
    }
1609
1610
    /*
1611
     * Check that we got the same unit again.
1612
     */
1613
    if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) {	
1614
	syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
1615
	die(1);
1616
    }
1617
    if (x != ifunit) {
1618
	syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
1619
	       ifunit, x);
1620
	die(1);
1621
    }
1622
    ttyfd = loop_slave;
1623
}
1624
1625
1626
/*
1627
 * Use the hostid as part of the random number seed.
1628
 */
1629
int
1630
get_host_seed()
1631
{
1632
    return gethostid();
1633
}
1634
1635
1636
/*
1637
 * sys_check_options - check the options that the user specified
1638
 */
1639
void
1640
sys_check_options()
1641
{
1642
  /*
1643
   * We don't support demand dialing yet.
1644
   */
1645
  if(demand)
1646
    {
1647
      syslog(LOG_WARNING, "PPP-2.3 for NeXTSTEP does not yet support demand dialing\n");
1648
      demand = 0;
1649
    }
1650
}
1651
1652
1653
/*
1654
 * sys_close - Clean up in a child process before execing.
1655
 */
1656
void
1657
sys_close()
1658
{
1659
    close(sockfd);
1660
    if (loop_slave >= 0) {
1661
	close(loop_slave);
1662
	close(loop_master);
1663
    }
1664
    closelog();
1665
}
1666
1667
1668
/*
1669
 * wait_loop_output - wait until there is data available on the
1670
 * loopback, for the length of time specified by *timo (indefinite
1671
 * if timo is NULL).
1672
 */
1673
void wait_loop_output(timo)
1674
    struct timeval *timo;
1675
{
1676
    fd_set ready;
1677
    int n;
1678
1679
    FD_ZERO(&ready);
1680
    FD_SET(loop_master, &ready);
1681
    n = select(loop_master + 1, &ready, NULL, &ready, timo);
1682
    if (n < 0 && errno != EINTR) {
1683
	syslog(LOG_ERR, "select: %m");
1684
	die(1);
1685
    }
1686
}
1687
1688
1689
/*
1690
 * wait_time - wait for a given length of time or until a
1691
 * signal is received.
1692
 */
1693
void wait_time(timo)
1694
    struct timeval *timo;
1695
{
1696
    int n;
1697
1698
    n = select(0, NULL, NULL, NULL, timo);
1699
    if (n < 0 && errno != EINTR) {
1700
	syslog(LOG_ERR, "select: %m");
1701
	die(1);
1702
    }
1703
}
(-)pppd/sys-osf.c (+1661 lines)
Line 0 Link Here
1
/*
2
 * System-dependent procedures for pppd under Digital UNIX (OSF/1).
3
 *
4
 * Copyright (c) 1994 The Australian National University.
5
 * All rights reserved.
6
 *
7
 * Permission to use, copy, modify, and distribute this software and its
8
 * documentation is hereby granted, provided that the above copyright
9
 * notice appears in all copies.  This software is provided without any
10
 * warranty, express or implied. The Australian National University
11
 * makes no representations about the suitability of this software for
12
 * any purpose.
13
 *
14
 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17
 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
18
 * OF SUCH DAMAGE.
19
 *
20
 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23
 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25
 * OR MODIFICATIONS.
26
 */
27
28
#ifndef lint
29
static char rcsid[] = "$Id: sys-osf.c,v 1.13 1998/03/25 02:19:27 paulus Exp $";
30
#endif
31
32
#include <stdio.h>
33
#include <stddef.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <ctype.h>
37
#include <errno.h>
38
#include <fcntl.h>
39
#include <unistd.h>
40
#include <termios.h>
41
#include <signal.h>
42
#include <malloc.h>
43
#include <utmp.h>
44
#include <sys/types.h>
45
#include <sys/param.h>
46
#include <sys/socket.h>
47
#include <sys/stream.h>
48
#include <sys/stropts.h>
49
#include <sys/syslog.h>
50
#include <sys/stat.h>
51
#include <sys/time.h>
52
#include <sys/poll.h>
53
#include <net/if.h>
54
#include <net/if_arp.h>
55
#include <net/route.h>
56
#include <net/ppp_defs.h>
57
#include <net/pppio.h>
58
#include <netinet/in.h>
59
60
#include "pppd.h"
61
62
static int	pppfd;
63
static int	fdmuxid = -1;
64
static int	iffd;
65
static int	sockfd;
66
67
static int	restore_term;
68
static struct termios inittermios;
69
static struct winsize wsinfo;	/* Initial window size info */
70
static pid_t	tty_sid;	/* PID of our session leader */
71
72
extern u_char	inpacket_buf[];	/* borrowed from main.c */
73
74
static int	link_mtu, link_mru;
75
76
#define NMODULES	32
77
static int	tty_nmodules;
78
static char	tty_modules[NMODULES][FMNAMESZ+1];
79
80
static int closed_stdio;
81
static int initfdflags = -1;
82
static int orig_ttyfd = -1;
83
84
static int	if_is_up;	/* Interface has been marked up */
85
static u_int32_t ifaddrs[2];	/* local and remote addresses */
86
static u_int32_t default_route_gateway;	/* Gateway for default route added */
87
static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
88
89
/* Prototypes for procedures local to this file. */
90
static int translate_speed __P((int));
91
static int baud_rate_of __P((int));
92
static int get_ether_addr __P((u_int32_t, struct sockaddr *));
93
static int strioctl __P((int, int, void *, int, int));
94
95
96
/*
97
 * sys_init - System-dependent initialization.
98
 */
99
void
100
sys_init()
101
{
102
    int x;
103
104
    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
105
    setlogmask(LOG_UPTO(LOG_INFO));
106
    if (debug)
107
	setlogmask(LOG_UPTO(LOG_DEBUG));
108
109
    /* Get an internet socket for doing socket ioctl's on. */
110
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
111
	syslog(LOG_ERR, "Couldn't create IP socket: %m");
112
	die(1);
113
    }
114
115
    if (default_device)
116
	tty_sid = getsid((pid_t)0);
117
118
    /*
119
     * Open the ppp device.
120
     */
121
    pppfd = open("/dev/streams/ppp", O_RDWR | O_NONBLOCK, 0);
122
    if (pppfd < 0) {
123
	syslog(LOG_ERR, "Can't open /dev/streams/ppp: %m");
124
	die(1);
125
    }
126
    if (kdebugflag) {
127
	x = PPPDBG_LOG + PPPDBG_DRIVER;
128
	strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
129
    }
130
131
    /* Assign a new PPA and get its unit number. */
132
    if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
133
	syslog(LOG_ERR, "Can't create new PPP interface: %m");
134
	die(1);
135
    }
136
137
    /*
138
     * Open the ppp device again and push the if_ppp module on it.
139
     */
140
    iffd = open("/dev/streams/ppp", O_RDWR, 0);
141
    if (iffd < 0) {
142
	syslog(LOG_ERR, "Can't open /dev/streams/ppp (2): %m");
143
	die(1);
144
    }
145
    if (kdebugflag) {
146
	x = PPPDBG_LOG + PPPDBG_DRIVER;
147
	strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
148
    }
149
    if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) {
150
	syslog(LOG_ERR, "Couldn't attach ppp interface to device: %m");
151
	die(1);
152
    }
153
    if (ioctl(iffd, I_PUSH, "if_ppp") < 0) {
154
	syslog(LOG_ERR, "Can't push ppp interface module: %m");
155
	die(1);
156
    }
157
    if (kdebugflag) {
158
	x = PPPDBG_LOG + PPPDBG_IF;
159
	strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
160
    }
161
    if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) {
162
	syslog(LOG_ERR, "Couldn't create ppp interface unit: %m");
163
	die(1);
164
    }
165
    x = PPP_IP;
166
    if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) {
167
	syslog(LOG_ERR, "Couldn't bind ppp interface to IP SAP: %m");
168
	die(1);
169
    }
170
}
171
172
/*
173
 * sys_cleanup - restore any system state we modified before exiting:
174
 * mark the interface down, delete default route and/or proxy arp entry.
175
 * This shouldn't call die() because it's called from die().
176
 */
177
void
178
sys_cleanup()
179
{
180
    if (if_is_up)
181
	sifdown(0);
182
    if (ifaddrs[0])
183
	cifaddr(0, ifaddrs[0], ifaddrs[1]);
184
    if (default_route_gateway)
185
	cifdefaultroute(0, 0, default_route_gateway);
186
    if (proxy_arp_addr)
187
	cifproxyarp(0, proxy_arp_addr);
188
}
189
190
/*
191
 * sys_close - Clean up in a child process before execing.
192
 */
193
void
194
sys_close()
195
{
196
    close(iffd);
197
    close(pppfd);
198
    close(sockfd);
199
    closelog();
200
}
201
202
/*
203
 * sys_check_options - check the options that the user specified
204
 */
205
void
206
sys_check_options()
207
{
208
}
209
210
211
/*
212
 * daemon - Detach us from controlling terminal session.
213
 */
214
int
215
daemon(nochdir, noclose)
216
    int nochdir, noclose;
217
{
218
    int pid;
219
220
    if ((pid = fork()) < 0)
221
	return -1;
222
    if (pid != 0)
223
	exit(0);		/* parent dies */
224
    setsid();
225
    if (!nochdir)
226
	chdir("/");
227
    if (!noclose) {
228
	fclose(stdin);		/* don't need stdin, stdout, stderr */
229
	fclose(stdout);
230
	fclose(stderr);
231
    }
232
    return 0;
233
}
234
235
/*
236
 * note_debug_level - note a change in the debug level.
237
 */
238
void
239
note_debug_level()
240
{
241
    if (debug) {
242
	setlogmask(LOG_UPTO(LOG_DEBUG));
243
    } else {
244
	setlogmask(LOG_UPTO(LOG_WARNING));
245
    }
246
}
247
248
/*
249
 * ppp_available - check whether the system has any ppp interfaces
250
 */
251
int
252
ppp_available()
253
{
254
    struct stat buf;
255
256
    return stat("/dev/streams/ppp", &buf) >= 0;
257
}
258
259
char pipename[] = "/dev/streams/pipe";
260
261
/*
262
 *  streampipe -- Opens a STREAMS based pipe.  Used by streamify().
263
 */
264
265
int 
266
streampipe(int fd[2])
267
{
268
    if ((fd[0]=open(pipename, O_RDWR)) == -1)
269
	return(-1);
270
    else if ((fd[1]=open(pipename, O_RDWR)) == -1) {
271
	close(fd[0]);
272
	return(-1);
273
    } else if (ioctl(fd[0], I_PIPE, fd[1]) != 0) {
274
	close(fd[0]);
275
	close(fd[1]);
276
	return(-1);
277
    } else {
278
	return(ioctl(fd[0], I_PUSH, "pipemod"));
279
    }
280
}
281
282
/*
283
 *  streamify -- Needed for Digital UNIX, since some tty devices are not STREAMS
284
 *               modules (but ptys are, and pipes can be).
285
 */
286
287
#define BUFFSIZE 1000     /*  Size of buffer for streamify()  */
288
289
int 
290
streamify(int fd)
291
{
292
    int fdes[2];
293
    fd_set readfds;
294
    int ret, fret, rret, maxfd;
295
    static char buffer[BUFFSIZE];
296
    struct sigaction sa;
297
298
    if (streampipe(fdes) != 0)
299
	syslog(LOG_ERR, "streampipe(): %m\n");
300
    else if (isastream(fdes[0]) == 1) {
301
	if ((fret=fork()) < 0) {
302
	    syslog(LOG_ERR, "fork(): %m\n");
303
	} else if (fret == 0) {
304
	    /*  Process to forward things from pipe to tty  */
305
            sigemptyset(&(sa.sa_mask));
306
	    sa.sa_handler = SIG_DFL;
307
	    sa.sa_flags = 0;
308
	    sigaction(SIGHUP, &sa, NULL);   /*  Go back to default actions */
309
	    sigaction(SIGINT, &sa, NULL);   /*  for changed signals.  */
310
	    sigaction(SIGTERM, &sa, NULL);
311
	    sigaction(SIGCHLD, &sa, NULL);
312
	    sigaction(SIGUSR1, &sa, NULL);
313
	    sigaction(SIGUSR2, &sa, NULL);
314
	    close(fdes[0]);
315
316
	    maxfd = (fdes[1]>fd)?fdes[1]:fd;
317
	    while (1) {
318
		FD_ZERO(&readfds);
319
		FD_SET(fdes[1], &readfds);
320
		FD_SET(fd, &readfds);
321
		ret = select(maxfd+1, &readfds, NULL, NULL, NULL);
322
		if (FD_ISSET(fd, &readfds)) {
323
		    rret = read(fd, buffer, BUFFSIZE);
324
		    if (rret == 0) {
325
			MAINDEBUG((LOG_DEBUG, "slave died:  EOF on tty."));
326
			exit(0);
327
		    } else {
328
			write(fdes[1], buffer, rret);
329
		    }
330
		}
331
		if (FD_ISSET(fdes[1], &readfds)) {
332
		    rret = read(fdes[1], buffer, BUFFSIZE);
333
		    if (rret == 0) {
334
			MAINDEBUG((LOG_DEBUG, "slave died:  EOF on pipe."));
335
			exit(0);
336
		    } else {
337
			write(fd, buffer, rret);
338
		    }
339
		}
340
	    }
341
	} else {
342
	    close(fdes[1]);
343
	    orig_ttyfd = fd;
344
	    return(fdes[0]);
345
        }
346
    }
347
348
    return(-1);
349
}
350
351
/*
352
 * establish_ppp - Turn the serial port into a ppp interface.
353
 */
354
void
355
establish_ppp(fd)
356
    int fd;
357
{
358
    int i;
359
360
    if (isastream(fd) != 1) {
361
	if ((ttyfd = fd = streamify(fd)) < 0) {
362
	    syslog(LOG_ERR, "Couldn't get a STREAMS module!\n");
363
	    die(1);
364
	}
365
    }
366
367
    /* Pop any existing modules off the tty stream. */
368
    for (i = 0;; ++i) {
369
	if (ioctl(fd, I_LOOK, tty_modules[i]) < 0
370
	    || ioctl(fd, I_POP, 0) < 0)
371
	    break;
372
        syslog(LOG_ERR, "popping module %s\n", tty_modules[i]);
373
    }
374
375
    tty_nmodules = i;
376
377
    /* Push the async hdlc module and the compressor module. */
378
    if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) {
379
	syslog(LOG_ERR, "Couldn't push PPP Async HDLC module: %m");
380
	die(1);
381
    }
382
    if (ioctl(fd, I_PUSH, "ppp_comp") < 0) {
383
	syslog(LOG_ERR, "Couldn't push PPP compression module: %m");
384
/*	die(1); */
385
    }
386
387
    /* read mode, message non-discard mode */
388
    if (ioctl(fd, I_SRDOPT, RMSGN|RPROTNORM) < 0) {
389
        syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m");
390
        die(1);
391
    }
392
393
    /* Link the serial port under the PPP multiplexor. */
394
    if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) {
395
	syslog(LOG_ERR, "Can't link tty to PPP mux: %m");
396
	die(1);
397
    }
398
399
    /* close stdin, stdout, stderr if they might refer to the device */
400
    if (default_device && !closed_stdio) {
401
        int i;
402
403
        for (i = 0; i <= 2; ++i)
404
            if (i != fd && i != sockfd)
405
                close(i);
406
        closed_stdio = 1;
407
    }
408
409
    /*
410
     * Set device for non-blocking reads.
411
     */
412
    if ((initfdflags = fcntl(fd, F_GETFL)) == -1
413
        || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
414
        syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
415
    }
416
}
417
418
/*
419
 * restore_loop - reattach the ppp unit to the loopback.
420
 * This doesn't need to do anything because disestablish_ppp does it.
421
 */
422
void
423
restore_loop()
424
{
425
}
426
427
/*
428
 * disestablish_ppp - Restore the serial port to normal operation.
429
 * It attempts to reconstruct the stream with the previously popped
430
 * modules.  This shouldn't call die() because it's called from die().
431
 */
432
void
433
disestablish_ppp(fd)
434
    int fd;
435
{
436
    int i;
437
438
    if (fdmuxid >= 0) {
439
	if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) {
440
	    if (!hungup)
441
		syslog(LOG_ERR, "Can't unlink tty from PPP mux: %m");
442
	}
443
	fdmuxid = -1;
444
445
        /* Reset non-blocking mode on the file descriptor. */
446
        if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
447
            syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
448
        initfdflags = -1;
449
450
	if (!hungup) {
451
	    while (ioctl(fd, I_POP, 0) >= 0)
452
		;
453
	    for (i = tty_nmodules - 1; i >= 0; --i)
454
		if (ioctl(fd, I_PUSH, tty_modules[i]) < 0)
455
		    syslog(LOG_ERR, "Couldn't restore tty module %s: %m",
456
			   tty_modules[i]);
457
	}
458
459
	if (hungup && default_device && tty_sid > 0) {
460
	    /*
461
	     * If we have received a hangup, we need to send a SIGHUP
462
	     * to the terminal's controlling process.  The reason is
463
	     * that the original stream head for the terminal hasn't
464
	     * seen the M_HANGUP message (it went up through the ppp
465
	     * driver to the stream head for our fd to /dev/ppp).
466
	     */
467
	    syslog(LOG_DEBUG, "sending hangup to %d", tty_sid);
468
	    if (kill(tty_sid, SIGHUP) < 0)
469
		syslog(LOG_ERR, "couldn't kill pgrp: %m");
470
	}
471
	if (orig_ttyfd >= 0) {
472
	    close(fd);
473
	    (void)wait((void *)0);
474
	    ttyfd = orig_ttyfd;
475
	    orig_ttyfd = -1;
476
	}
477
    }
478
}
479
480
/*
481
 * Check whether the link seems not to be 8-bit clean.
482
 */
483
void
484
clean_check()
485
{
486
    int x;
487
    char *s;
488
489
    if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0)
490
	return;
491
    s = NULL;
492
    switch (~x) {
493
    case RCV_B7_0:
494
	s = "bit 7 set to 1";
495
	break;
496
    case RCV_B7_1:
497
	s = "bit 7 set to 0";
498
	break;
499
    case RCV_EVNP:
500
	s = "odd parity";
501
	break;
502
    case RCV_ODDP:
503
	s = "even parity";
504
	break;
505
    }
506
    if (s != NULL) {
507
	syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
508
	syslog(LOG_WARNING, "All received characters had %s", s);
509
    }
510
}
511
512
/*
513
 * List of valid speeds.
514
 */
515
struct speed {
516
    int speed_int, speed_val;
517
} speeds[] = {
518
#ifdef B50
519
    { 50, B50 },
520
#endif
521
#ifdef B75
522
    { 75, B75 },
523
#endif
524
#ifdef B110
525
    { 110, B110 },
526
#endif
527
#ifdef B134
528
    { 134, B134 },
529
#endif
530
#ifdef B150
531
    { 150, B150 },
532
#endif
533
#ifdef B200
534
    { 200, B200 },
535
#endif
536
#ifdef B300
537
    { 300, B300 },
538
#endif
539
#ifdef B600
540
    { 600, B600 },
541
#endif
542
#ifdef B1200
543
    { 1200, B1200 },
544
#endif
545
#ifdef B1800
546
    { 1800, B1800 },
547
#endif
548
#ifdef B2000
549
    { 2000, B2000 },
550
#endif
551
#ifdef B2400
552
    { 2400, B2400 },
553
#endif
554
#ifdef B3600
555
    { 3600, B3600 },
556
#endif
557
#ifdef B4800
558
    { 4800, B4800 },
559
#endif
560
#ifdef B7200
561
    { 7200, B7200 },
562
#endif
563
#ifdef B9600
564
    { 9600, B9600 },
565
#endif
566
#ifdef B19200
567
    { 19200, B19200 },
568
#endif
569
#ifdef B38400
570
    { 38400, B38400 },
571
#endif
572
#ifdef EXTA
573
    { 19200, EXTA },
574
#endif
575
#ifdef EXTB
576
    { 38400, EXTB },
577
#endif
578
#ifdef B57600
579
    { 57600, B57600 },
580
#endif
581
#ifdef B115200
582
    { 115200, B115200 },
583
#endif
584
    { 0, 0 }
585
};
586
587
/*
588
 * Translate from bits/second to a speed_t.
589
 */
590
static int
591
translate_speed(bps)
592
    int bps;
593
{
594
    struct speed *speedp;
595
596
    if (bps == 0)
597
	return 0;
598
    for (speedp = speeds; speedp->speed_int; speedp++)
599
	if (bps == speedp->speed_int)
600
	    return speedp->speed_val;
601
    syslog(LOG_WARNING, "speed %d not supported", bps);
602
    return 0;
603
}
604
605
/*
606
 * Translate from a speed_t to bits/second.
607
 */
608
static int
609
baud_rate_of(speed)
610
    int speed;
611
{
612
    struct speed *speedp;
613
614
    if (speed == 0)
615
	return 0;
616
    for (speedp = speeds; speedp->speed_int; speedp++)
617
	if (speed == speedp->speed_val)
618
	    return speedp->speed_int;
619
    return 0;
620
}
621
622
/*
623
 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
624
 * at the requested speed, etc.  If `local' is true, set CLOCAL
625
 * regardless of whether the modem option was specified.
626
 */
627
void
628
set_up_tty(fd, local)
629
    int fd, local;
630
{
631
    int speed;
632
    struct termios tios;
633
634
    if (tcgetattr(fd, &tios) < 0) {
635
	syslog(LOG_ERR, "tcgetattr: %m");
636
	die(1);
637
    }
638
639
    if (!restore_term) {
640
	inittermios = tios;
641
	ioctl(fd, TIOCGWINSZ, &wsinfo);
642
    }
643
644
    tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
645
    if (crtscts > 0)
646
	tios.c_cflag |= CRTSCTS;
647
    else if (crtscts < 0)
648
	tios.c_cflag &= ~CRTSCTS;
649
650
    tios.c_cflag |= CS8 | CREAD | HUPCL;
651
    if (local || !modem)
652
	tios.c_cflag |= CLOCAL;
653
    tios.c_iflag = IGNBRK | IGNPAR;
654
    tios.c_oflag = 0;
655
    tios.c_lflag = 0;
656
    tios.c_cc[VMIN] = 1;
657
    tios.c_cc[VTIME] = 0;
658
659
    if (crtscts == -2) {
660
	tios.c_iflag |= IXON | IXOFF;
661
	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
662
	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
663
    }
664
665
    speed = translate_speed(inspeed);
666
    if (speed) {
667
	cfsetospeed(&tios, speed);
668
	cfsetispeed(&tios, speed);
669
    } else {
670
	speed = cfgetospeed(&tios);
671
	/*
672
	 * We can't proceed if the serial port speed is 0,
673
	 * since that implies that the serial port is disabled.
674
	 */
675
	if (speed == B0) {
676
	    syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
677
		   devnam);
678
	    die(1);
679
	}
680
    }
681
682
    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
683
	syslog(LOG_ERR, "tcsetattr: %m");
684
	die(1);
685
    }
686
687
    baud_rate = inspeed = baud_rate_of(speed);
688
    restore_term = 1;
689
}
690
691
/*
692
 * restore_tty - restore the terminal to the saved settings.
693
 */
694
void
695
restore_tty(fd)
696
    int fd;
697
{
698
    if (restore_term) {
699
	if (!default_device) {
700
	    /*
701
	     * Turn off echoing, because otherwise we can get into
702
	     * a loop with the tty and the modem echoing to each other.
703
	     * We presume we are the sole user of this tty device, so
704
	     * when we close it, it will revert to its defaults anyway.
705
	     */
706
	    inittermios.c_lflag &= ~(ECHO | ECHONL);
707
	}
708
	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
709
	    if (!hungup && errno != ENXIO)
710
		syslog(LOG_WARNING, "tcsetattr: %m");
711
	ioctl(fd, TIOCSWINSZ, &wsinfo);
712
	restore_term = 0;
713
    }
714
}
715
716
/*
717
 * setdtr - control the DTR line on the serial port.
718
 * This is called from die(), so it shouldn't call die().
719
 */
720
void
721
setdtr(fd, on)
722
int fd, on;
723
{
724
    int modembits = TIOCM_DTR;
725
726
    ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
727
}
728
729
/*
730
 * open_loopback - open the device we use for getting packets
731
 * in demand mode.  Under Solaris 2, we use our existing fd
732
 * to the ppp driver.
733
 */
734
void
735
open_ppp_loopback()
736
{
737
}
738
739
/*
740
 * output - Output PPP packet.
741
 */
742
void
743
output(unit, p, len)
744
    int unit;
745
    u_char *p;
746
    int len;
747
{
748
    struct strbuf data;
749
    int retries;
750
    struct pollfd pfd;
751
752
    if (debug)
753
	log_packet(p, len, "sent ", LOG_DEBUG);
754
755
    data.len = len;
756
    data.buf = (caddr_t) p;
757
    retries = 4;
758
    while (putmsg(pppfd, NULL, &data, 0) < 0) {
759
	if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
760
	    if (errno != ENXIO)
761
		syslog(LOG_ERR, "Couldn't send packet: %m");
762
	    break;
763
	}
764
	pfd.fd = pppfd;
765
	pfd.events = POLLOUT;
766
	poll(&pfd, 1, 250);	/* wait for up to 0.25 seconds */
767
    }
768
}
769
770
771
/*
772
 * wait_input - wait until there is data available on fd,
773
 * for the length of time specified by *timo (indefinite
774
 * if timo is NULL).
775
 */
776
void
777
wait_input(timo)
778
    struct timeval *timo;
779
{
780
    int t;
781
    struct pollfd pfd;
782
783
    t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
784
    pfd.fd = pppfd;
785
    pfd.events = POLLIN | POLLPRI | POLLHUP;
786
    if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
787
	syslog(LOG_ERR, "poll: %m");
788
	die(1);
789
    }
790
}
791
792
/*
793
 * wait_loop_output - wait until there is data available on the
794
 * loopback, for the length of time specified by *timo (indefinite
795
 * if timo is NULL).
796
 */
797
void
798
wait_loop_output(timo)
799
    struct timeval *timo;
800
{
801
    wait_input(timo);
802
}
803
804
/*
805
 * wait_time - wait for a given length of time or until a
806
 * signal is received.
807
 */
808
void
809
wait_time(timo)
810
    struct timeval *timo;
811
{
812
    int n;
813
814
    n = select(0, NULL, NULL, NULL, timo);
815
    if (n < 0 && errno != EINTR) {
816
	syslog(LOG_ERR, "select: %m");
817
	die(1);
818
    }
819
}
820
821
822
/*
823
 * read_packet - get a PPP packet from the serial device.
824
 */
825
int
826
read_packet(buf)
827
    u_char *buf;
828
{
829
    struct strbuf ctrl, data;
830
    int flags, len;
831
    unsigned char ctrlbuf[64];
832
833
    for (;;) {
834
	data.maxlen = PPP_MRU + PPP_HDRLEN;
835
	data.buf = (caddr_t) buf;
836
	ctrl.maxlen = sizeof(ctrlbuf);
837
	ctrl.buf = (caddr_t) ctrlbuf;
838
	flags = 0;
839
	len = getmsg(pppfd, &ctrl, &data, &flags);
840
	if (len < 0) {
841
	    if (errno = EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
842
		return -1;
843
	    syslog(LOG_ERR, "Error reading packet: %m");
844
	    die(1);
845
	}
846
847
	if (ctrl.len <= 0)
848
	    return data.len;
849
850
	/*
851
	 * Got a M_PROTO or M_PCPROTO message.  Huh?
852
	 */
853
	if (debug)
854
	    syslog(LOG_DEBUG, "got ctrl msg len=%d", ctrl.len);
855
856
    }
857
}
858
859
/*
860
 * get_loop_output - get outgoing packets from the ppp device,
861
 * and detect when we want to bring the real link up.
862
 * Return value is 1 if we need to bring up the link, 0 otherwise.
863
 */
864
int
865
get_loop_output()
866
{
867
    int len;
868
    int rv = 0;
869
870
    while ((len = read_packet(inpacket_buf)) > 0) {
871
	if (loop_frame(inpacket_buf, len))
872
	    rv = 1;
873
    }
874
    return rv;
875
}
876
877
/*
878
 * ppp_send_config - configure the transmit characteristics of
879
 * the ppp interface.
880
 */
881
void
882
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
883
    int unit, mtu;
884
    u_int32_t asyncmap;
885
    int pcomp, accomp;
886
{
887
    int cf[2];
888
889
    link_mtu = mtu;
890
    if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
891
	if (hungup && errno == ENXIO)
892
	    return;
893
	syslog(LOG_ERR, "Couldn't set MTU: %m");
894
    }
895
    if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
896
	syslog(LOG_ERR, "Couldn't set transmit ACCM: %m");
897
    }
898
    cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
899
    cf[1] = COMP_PROT | COMP_AC;
900
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
901
	syslog(LOG_ERR, "Couldn't set prot/AC compression: %m");
902
    }
903
}
904
905
/*
906
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
907
 */
908
void
909
ppp_set_xaccm(unit, accm)
910
    int unit;
911
    ext_accm accm;
912
{
913
    if (strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
914
	if (!hungup || errno != ENXIO)
915
	    syslog(LOG_WARNING, "Couldn't set extended ACCM: %m");
916
    }
917
}
918
919
/*
920
 * ppp_recv_config - configure the receive-side characteristics of
921
 * the ppp interface.
922
 */
923
void
924
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
925
    int unit, mru;
926
    u_int32_t asyncmap;
927
    int pcomp, accomp;
928
{
929
    int cf[2];
930
931
    link_mru = mru;
932
    if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
933
	if (hungup && errno == ENXIO)
934
	    return;
935
	syslog(LOG_ERR, "Couldn't set MRU: %m");
936
    }
937
    if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
938
	syslog(LOG_ERR, "Couldn't set receive ACCM: %m");
939
    }
940
    cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
941
    cf[1] = DECOMP_PROT | DECOMP_AC;
942
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
943
	syslog(LOG_ERR, "Couldn't set prot/AC decompression: %m");
944
    }
945
}
946
947
/*
948
 * ccp_test - ask kernel whether a given compression method
949
 * is acceptable for use.
950
 *
951
 * In Digital UNIX the memory buckets for chunks >16K are not
952
 * primed when the system comes up.  That means we're not
953
 * likely to get the memory needed for the compressor on
954
 * the first try.  The way we work around this is to have
955
 * the driver spin off a thread to go get the memory for us
956
 * (we can't block at that point in a streams context.)
957
 *
958
 * This code synchronizes with the thread when it has returned
959
 * with the memory we need.  The driver will continue to return
960
 * with EAGAIN until the thread comes back.  We give up here
961
 * if after 10 attempts in one second we still don't have memory.
962
 * It's up to the driver to not lose track of that memory if
963
 * thread takes too long to return.
964
 */
965
int
966
ccp_test(unit, opt_ptr, opt_len, for_transmit)
967
    int unit, opt_len, for_transmit;
968
    u_char *opt_ptr;
969
{
970
    struct timeval tval;
971
    int i;
972
973
    tval.tv_sec = 0;
974
    tval.tv_usec = 100000;
975
    for (i = 0; i < 10; ++i) {
976
        if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
977
	    opt_ptr, opt_len, 0) >= 0) {
978
	    return 1;
979
	}
980
	if (errno != EAGAIN)
981
	    break;
982
        wait_time(&tval);
983
    }
984
    if (errno != 0)
985
	syslog(LOG_ERR, "hard failure trying to get memory for a compressor: %m");
986
    return (errno == ENOSR)? 0: -1;
987
}
988
989
/*
990
 * ccp_flags_set - inform kernel about the current state of CCP.
991
 */
992
void
993
ccp_flags_set(unit, isopen, isup)
994
    int unit, isopen, isup;
995
{
996
    int cf[2];
997
998
    cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
999
    cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
1000
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1001
	if (!hungup || errno != ENXIO)
1002
	    syslog(LOG_ERR, "Couldn't set kernel CCP state: %m");
1003
    }
1004
}
1005
1006
/*
1007
 * get_idle_time - return how long the link has been idle.
1008
 */
1009
int
1010
get_idle_time(u, ip)
1011
    int u;
1012
    struct ppp_idle *ip;
1013
{
1014
    return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
1015
}
1016
1017
1018
/*
1019
 * ccp_fatal_error - returns 1 if decompression was disabled as a
1020
 * result of an error detected after decompression of a packet,
1021
 * 0 otherwise.  This is necessary because of patent nonsense.
1022
 */
1023
int
1024
ccp_fatal_error(unit)
1025
    int unit;
1026
{
1027
    int cf[2];
1028
1029
    cf[0] = cf[1] = 0;
1030
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1031
	if (errno != ENXIO && errno != EINVAL)
1032
	    syslog(LOG_ERR, "Couldn't get compression flags: %m");
1033
	return 0;
1034
    }
1035
    return cf[0] & CCP_FATALERROR;
1036
}
1037
1038
/*
1039
 * sifvjcomp - config tcp header compression
1040
 */
1041
int
1042
sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
1043
    int u, vjcomp, xcidcomp, xmaxcid;
1044
{
1045
    int cf[2];
1046
    char maxcid[2];
1047
1048
    if (vjcomp) {
1049
	maxcid[0] = xcidcomp;
1050
	maxcid[1] = 15;		/* XXX should be rmaxcid */
1051
	if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
1052
	    syslog(LOG_ERR, "Couldn't initialize VJ compression: %m");
1053
	}
1054
    }
1055
1056
    cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)	/* XXX this is wrong */
1057
	+ (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
1058
    cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
1059
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
1060
	if (vjcomp)
1061
	    syslog(LOG_ERR, "Couldn't enable VJ compression: %m");
1062
    }
1063
1064
    return 1;
1065
}
1066
1067
/*
1068
 * sifup - Config the interface up and enable IP packets to pass.
1069
 */
1070
int
1071
sifup(u)
1072
    int u;
1073
{
1074
    struct ifreq ifr;
1075
1076
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1077
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
1078
	syslog(LOG_ERR, "Couldn't mark interface up (get): %m");
1079
	return 0;
1080
    }
1081
    ifr.ifr_flags |= IFF_UP;
1082
    if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
1083
	syslog(LOG_ERR, "Couldn't mark interface up (set): %m");
1084
	return 0;
1085
    }
1086
    if_is_up = 1;
1087
    return 1;
1088
}
1089
1090
/*
1091
 * sifdown - Config the interface down and disable IP.
1092
 */
1093
int
1094
sifdown(u)
1095
    int u;
1096
{
1097
    struct ifreq ifr;
1098
1099
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1100
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
1101
	syslog(LOG_ERR, "Couldn't mark interface down (get): %m");
1102
	return 0;
1103
    }
1104
    if ((ifr.ifr_flags & IFF_UP) != 0) {
1105
	ifr.ifr_flags &= ~IFF_UP;
1106
	if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
1107
	    syslog(LOG_ERR, "Couldn't mark interface down (set): %m");
1108
	    return 0;
1109
	}
1110
    }
1111
    if_is_up = 0;
1112
    return 1;
1113
}
1114
1115
/*
1116
 * sifnpmode - Set the mode for handling packets for a given NP.
1117
 */
1118
int
1119
sifnpmode(u, proto, mode)
1120
    int u;
1121
    int proto;
1122
    enum NPmode mode;
1123
{
1124
    int npi[2];
1125
1126
    npi[0] = proto;
1127
    npi[1] = (int) mode;
1128
    if (strioctl(pppfd, PPPIO_NPMODE, npi, 2 * sizeof(int), 0) < 0) {
1129
	syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
1130
	return 0;
1131
    }
1132
    return 1;
1133
}
1134
1135
#define INET_ADDR(x)	(((struct sockaddr_in *) &(x))->sin_addr.s_addr)
1136
1137
/*
1138
 * SET_SA_FAMILY - initialize a struct sockaddr, setting the sa_family field.
1139
 */
1140
#define SET_SA_FAMILY(addr, family)             \
1141
    BZERO((char *) &(addr), sizeof(addr));      \
1142
    addr.sa_family = (family);                  \
1143
    addr.sa_len = sizeof ((addr))
1144
1145
/*
1146
 * sifaddr - Config the interface IP addresses and netmask.
1147
 */
1148
int
1149
sifaddr(u, o, h, m)
1150
    int u;
1151
    u_int32_t o, h, m;
1152
{
1153
    struct ifreq ifr;
1154
    struct ifaliasreq addreq;
1155
    int ret;
1156
1157
    ret = 1;
1158
1159
    /* flush old address, if any
1160
     */
1161
    bzero(&ifr, sizeof (ifr));
1162
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1163
    SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1164
    ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1165
    if ((ioctl(sockfd, (int)SIOCDIFADDR, (caddr_t) &ifr) < 0)
1166
        && errno != EADDRNOTAVAIL) {
1167
        syslog(LOG_ERR, "ioctl(SIOCDIFADDR): %m");
1168
        ret = 0;
1169
    }
1170
1171
    bzero(&addreq, sizeof (addreq));
1172
    strncpy(addreq.ifra_name, ifname, sizeof (addreq.ifra_name));
1173
    SET_SA_FAMILY(addreq.ifra_addr, AF_INET);
1174
    SET_SA_FAMILY(addreq.ifra_broadaddr, AF_INET);
1175
    ((struct sockaddr_in *)&addreq.ifra_addr)->sin_addr.s_addr = o;
1176
    ((struct sockaddr_in *)&addreq.ifra_broadaddr)->sin_addr.s_addr = h;
1177
1178
    if (m != 0) {
1179
        ((struct sockaddr_in *)&addreq.ifra_mask)->sin_addr.s_addr = m;
1180
        addreq.ifra_mask.sa_len = sizeof (struct sockaddr);
1181
        syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
1182
    }
1183
1184
    /* install new src/dst and (possibly) netmask
1185
     */
1186
    if (ioctl(sockfd, SIOCPIFADDR, &addreq) < 0) {
1187
        syslog(LOG_ERR, "ioctl(SIOCPIFADDR): %m");
1188
        ret = 0;
1189
    }
1190
1191
    ifr.ifr_metric = link_mtu;
1192
    if (ioctl(sockfd, SIOCSIPMTU, &ifr) < 0) {
1193
	syslog(LOG_ERR, "Couldn't set IP MTU: %m");
1194
        ret = 0;
1195
    }
1196
1197
    ifaddrs[0] = o;
1198
    ifaddrs[1] = h;
1199
    return (ret);
1200
}
1201
1202
1203
/*
1204
 * cifaddr - Clear the interface IP addresses, and delete routes
1205
 * through the interface if possible.
1206
 */
1207
int
1208
cifaddr(u, o, h)
1209
    int u;
1210
    u_int32_t o, h;
1211
{
1212
    struct ifreq ifr;
1213
1214
    ifaddrs[0] = 0;
1215
    bzero(&ifr, sizeof (ifr));
1216
    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1217
    SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1218
    ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1219
    if (ioctl(sockfd, (int)SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1220
        syslog(LOG_ERR, "ioctl(SIOCDIFADDR): %m");
1221
        return 0;
1222
    }
1223
    return 1;
1224
}
1225
1226
1227
/*
1228
 * sifdefaultroute - assign a default route through the address given.
1229
 */
1230
int
1231
sifdefaultroute(u, l, g)
1232
    int u;
1233
    u_int32_t l, g;
1234
{
1235
    struct ortentry rt;
1236
1237
    BZERO(&rt, sizeof(rt));
1238
    SET_SA_FAMILY(rt.rt_dst, AF_INET);
1239
    SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1240
    ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1241
    rt.rt_flags = RTF_GATEWAY;
1242
    if (ioctl(sockfd, (int)SIOCADDRT, &rt) < 0) {
1243
        syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
1244
        return 0;
1245
    }
1246
    default_route_gateway = g;
1247
    return 1;
1248
}
1249
1250
1251
/*
1252
 * cifdefaultroute - delete a default route through the address given.
1253
 */
1254
int
1255
cifdefaultroute(u, l, g)
1256
    int u;
1257
    u_int32_t l, g;
1258
{
1259
    struct ortentry rt;
1260
1261
    BZERO(&rt, sizeof(rt));
1262
    SET_SA_FAMILY(rt.rt_dst, AF_INET);
1263
    SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1264
    ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1265
    rt.rt_flags = RTF_GATEWAY;
1266
    if (ioctl(sockfd, (int)SIOCDELRT, &rt) < 0) {
1267
        syslog(LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1268
        return 0;
1269
    }
1270
    default_route_gateway = 0;
1271
    return 1;
1272
}
1273
1274
/*
1275
 * sifproxyarp - Make a proxy ARP entry for the peer.
1276
 */
1277
int
1278
sifproxyarp(unit, hisaddr)
1279
    int unit;
1280
    u_int32_t hisaddr;
1281
{
1282
    struct arpreq arpreq;
1283
1284
    BZERO(&arpreq, sizeof(arpreq));
1285
1286
    /*
1287
     * Get the hardware address of an interface on the same subnet
1288
     * as our local address.
1289
     */
1290
    if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
1291
        syslog(LOG_WARNING, "Cannot determine ethernet address for proxy ARP");
1292
        return 0;
1293
    }
1294
1295
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1296
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1297
    arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1298
    if (ioctl(sockfd, (int)SIOCSARP, (caddr_t)&arpreq) < 0) {
1299
        syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1300
        return 0;
1301
    }
1302
1303
    proxy_arp_addr = hisaddr;
1304
    return 1;
1305
}
1306
1307
1308
/*
1309
 * cifproxyarp - Delete the proxy ARP entry for the peer.
1310
 */
1311
int
1312
cifproxyarp(unit, hisaddr)
1313
    int unit;
1314
    u_int32_t hisaddr;
1315
{
1316
    struct arpreq arpreq;
1317
1318
    BZERO(&arpreq, sizeof(arpreq));
1319
    SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1320
    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1321
    if (ioctl(sockfd, (int)SIOCDARP, (caddr_t)&arpreq) < 0) {
1322
        syslog(LOG_ERR, "ioctl(SIOCDARP): %m");
1323
        return 0;
1324
    }
1325
    proxy_arp_addr = 0;
1326
    return 1;
1327
}
1328
1329
/*
1330
 * get_ether_addr - get the hardware address of an interface on the
1331
 * the same subnet as ipaddr.
1332
 */
1333
#define MAX_IFS		32
1334
1335
static int
1336
get_ether_addr(ipaddr, hwaddr)
1337
    u_int32_t ipaddr;
1338
    struct sockaddr *hwaddr;
1339
{
1340
    struct ifreq *ifr, *ifend;
1341
    u_int32_t ina, mask;
1342
    struct ifreq ifreq;
1343
    struct ifconf ifc;
1344
    struct ifreq ifs[MAX_IFS];
1345
    struct ifdevea ifdevreq;
1346
1347
    ifc.ifc_len = sizeof(ifs);
1348
    ifc.ifc_req = ifs;
1349
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1350
	syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1351
	return 0;
1352
    }
1353
1354
    /*
1355
     * Scan through looking for an interface with an Internet
1356
     * address on the same subnet as `ipaddr'.
1357
     */
1358
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1359
    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1360
        if (ifr->ifr_addr.sa_family == AF_INET) {
1361
1362
            /*
1363
             * Check that the interface is up, and not point-to-point
1364
             * or loopback.
1365
             */
1366
            strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1367
            if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1368
                continue;
1369
            if ((ifreq.ifr_flags &
1370
                 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1371
                 != (IFF_UP|IFF_BROADCAST))
1372
                continue;
1373
1374
            /*
1375
             * Get its netmask and check that it's on the right subnet.
1376
             */
1377
            if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1378
                continue;
1379
            ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1380
            mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1381
            if ((ipaddr & mask) != (ina & mask))
1382
                continue;
1383
1384
            break;
1385
        } else {
1386
	    if (ifr->ifr_addr.sa_len > sizeof (ifr->ifr_addr))
1387
		ifr = (struct ifreq *)((caddr_t)ifr + (ifr->ifr_addr.sa_len - sizeof (ifr->ifr_addr)));
1388
	}
1389
    }
1390
1391
    if (ifr >= ifend)
1392
	return 0;
1393
    syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1394
1395
    strncpy(ifdevreq.ifr_name, ifr->ifr_name, sizeof(ifdevreq.ifr_name));
1396
1397
    if (ioctl(sockfd, (int)SIOCRPHYSADDR, &ifdevreq) < 0) {
1398
        perror("ioctl(SIOCRPHYSADDR)");
1399
        return(0);
1400
    }
1401
1402
    hwaddr->sa_family = AF_UNSPEC;
1403
    memcpy(hwaddr->sa_data, ifdevreq.current_pa, sizeof(ifdevreq.current_pa));
1404
    return 1;
1405
}
1406
1407
#define	WTMPFILE	"/usr/adm/wtmp"
1408
1409
void
1410
logwtmp(line, name, host)
1411
    const char *line, *name, *host;
1412
{
1413
    int fd;
1414
    struct stat buf;
1415
    struct utmp ut;
1416
1417
    if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1418
	return;
1419
    if (!fstat(fd, &buf)) {
1420
	(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1421
	(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1422
	(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1423
	(void)time(&ut.ut_time);
1424
	if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1425
	    (void)ftruncate(fd, buf.st_size);
1426
    }
1427
    close(fd);
1428
}
1429
1430
/*
1431
 * Return user specified netmask, modified by any mask we might determine
1432
 * for address `addr' (in network byte order).
1433
 * Here we scan through the system's list of interfaces, looking for
1434
 * any non-point-to-point interfaces which might appear to be on the same
1435
 * network as `addr'.  If we find any, we OR in their netmask to the
1436
 * user-specified netmask.
1437
 */
1438
u_int32_t
1439
GetMask(addr)
1440
    u_int32_t addr;
1441
{
1442
    u_int32_t mask, nmask, ina;
1443
    struct ifreq *ifr, *ifend, ifreq;
1444
    struct ifconf ifc;
1445
1446
    addr = ntohl(addr);
1447
    if (IN_CLASSA(addr))	/* determine network mask for address class */
1448
	nmask = IN_CLASSA_NET;
1449
    else if (IN_CLASSB(addr))
1450
	nmask = IN_CLASSB_NET;
1451
    else
1452
	nmask = IN_CLASSC_NET;
1453
    /* class D nets are disallowed by bad_ip_adrs */
1454
    mask = netmask | htonl(nmask);
1455
1456
    /*
1457
     * Scan through the system's network interfaces.
1458
     */
1459
    ifc.ifc_len = MAX_IFS * sizeof(struct ifreq);
1460
    ifc.ifc_req = (struct ifreq *)alloca(ifc.ifc_len);
1461
    if (ifc.ifc_req == 0)
1462
	return mask;
1463
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1464
	syslog(LOG_WARNING, "Couldn't get system interface list: %m");
1465
	return mask;
1466
    }
1467
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1468
    for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1469
	/*
1470
	 * Check the interface's internet address.
1471
	 */
1472
	if (ifr->ifr_addr.sa_family == AF_INET) {
1473
	    ina = INET_ADDR(ifr->ifr_addr);
1474
	    if ((ntohl(ina) & nmask) != (addr & nmask))
1475
	        continue;
1476
	    /*
1477
	     * Check that the interface is up, and not point-to-point or loopback.
1478
	     */
1479
	    strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1480
	    if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1481
	        continue;
1482
	    if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1483
	        != IFF_UP)
1484
	        continue;
1485
	    /*
1486
	     * Get its netmask and OR it into our mask.
1487
	     */
1488
	    if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1489
	        continue;
1490
	    mask |= INET_ADDR(ifreq.ifr_addr);
1491
	    break;
1492
	} else {
1493
	    if (ifr->ifr_addr.sa_len > sizeof (ifr->ifr_addr))
1494
		ifr = (struct ifreq *)((caddr_t)ifr + (ifr->ifr_addr.sa_len - sizeof (ifr->ifr_addr)));
1495
	}
1496
    }
1497
1498
    return mask;
1499
}
1500
1501
static int
1502
strioctl(fd, cmd, ptr, ilen, olen)
1503
    int fd, cmd, ilen, olen;
1504
    void *ptr;
1505
{
1506
    struct strioctl str;
1507
1508
    str.ic_cmd = cmd;
1509
    str.ic_timout = 0;
1510
    str.ic_len = ilen;
1511
    str.ic_dp = ptr;
1512
    if (ioctl(fd, I_STR, &str) == -1)
1513
	return -1;
1514
    if (str.ic_len != olen)
1515
	syslog(LOG_DEBUG, "strioctl: expected %d bytes, got %d for cmd %x\n",
1516
	       olen, str.ic_len, cmd);
1517
    return 0;
1518
}
1519
1520
/*
1521
 * Use the hostid as part of the random number seed.
1522
 */
1523
int
1524
get_host_seed()
1525
{
1526
    return gethostid();
1527
}
1528
1529
/*
1530
 * Code for locking/unlocking the serial device.
1531
 * This code is derived from chat.c.
1532
 */
1533
1534
#if !defined(HDB) && !defined(SUNOS3)
1535
#define	HDB	1		/* ascii lock files are the default */
1536
#endif
1537
1538
#ifndef LOCK_DIR
1539
# if HDB
1540
#  define	PIDSTRING
1541
#  define	LOCK_PREFIX	"/usr/spool/locks/LCK.."
1542
# else /* HDB */
1543
#  define	LOCK_PREFIX	"/usr/spool/uucp/LCK.."
1544
# endif /* HDB */
1545
#endif /* LOCK_DIR */
1546
1547
static char *lock_file;		/* name of lock file created */
1548
1549
/*
1550
 * lock - create a lock file for the named device.
1551
 */
1552
int
1553
lock(dev)
1554
    char *dev;
1555
{
1556
    char hdb_lock_buffer[12];
1557
    int fd, pid, n;
1558
    char *p;
1559
1560
    if ((p = strrchr(dev, '/')) != NULL)
1561
	dev = p + 1;
1562
    lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1563
    if (lock_file == NULL)
1564
	novm("lock file name");
1565
    strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1566
1567
    while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1568
	if (errno == EEXIST
1569
	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1570
	    /* Read the lock file to find out who has the device locked */
1571
#ifdef PIDSTRING
1572
	    n = read(fd, hdb_lock_buffer, 11);
1573
	    if (n > 0) {
1574
		hdb_lock_buffer[n] = 0;
1575
		pid = atoi(hdb_lock_buffer);
1576
	    }
1577
#else
1578
	    n = read(fd, &pid, sizeof(pid));
1579
#endif
1580
	    if (n <= 0) {
1581
		syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1582
		close(fd);
1583
	    } else {
1584
		if (kill(pid, 0) == -1 && errno == ESRCH) {
1585
		    /* pid no longer exists - remove the lock file */
1586
		    if (unlink(lock_file) == 0) {
1587
			close(fd);
1588
			syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1589
			       dev, pid);
1590
			continue;
1591
		    } else
1592
			syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1593
			       dev);
1594
		} else
1595
		    syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1596
			   dev, pid);
1597
	    }
1598
	    close(fd);
1599
	} else
1600
	    syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1601
	free(lock_file);
1602
	lock_file = NULL;
1603
	return -1;
1604
    }
1605
1606
#ifdef PIDSTRING
1607
    sprintf(hdb_lock_buffer, "%10d\n", getpid());
1608
    write(fd, hdb_lock_buffer, 11);
1609
#else
1610
    pid = getpid();
1611
    write(fd, &pid, sizeof pid);
1612
#endif
1613
1614
    close(fd);
1615
    return 0;
1616
}
1617
1618
/*
1619
 * unlock - remove our lockfile
1620
 */
1621
void
1622
unlock()
1623
{
1624
    if (lock_file) {
1625
	unlink(lock_file);
1626
	free(lock_file);
1627
	lock_file = NULL;
1628
    }
1629
}
1630
1631
int
1632
set_filters(pass, active)
1633
    struct bpf_program *pass, *active;
1634
{
1635
    return 1;
1636
}
1637
1638
int
1639
bpf_compile(program, buf, optimize)
1640
    struct bpf_program *program;
1641
    char *buf;
1642
    int optimize;
1643
{
1644
    return 0;
1645
}
1646
1647
char *
1648
bpf_geterr()
1649
{
1650
    return 0;
1651
}
1652
1653
u_int
1654
bpf_filter(pc, p, wirelen, buflen)
1655
    struct bpf_insn *pc;
1656
    u_char *p;
1657
    u_int wirelen;
1658
    u_int buflen;
1659
{
1660
    return 0;
1661
}
(-)pppd/sys-sunos4.c (+1467 lines)
Line 0 Link Here
1
/*
2
 * System-dependent procedures for pppd under SunOS 4.
3
 *
4
 * Copyright (c) 1994 The Australian National University.
5
 * All rights reserved.
6
 *
7
 * Permission to use, copy, modify, and distribute this software and its
8
 * documentation is hereby granted, provided that the above copyright
9
 * notice appears in all copies.  This software is provided without any
10
 * warranty, express or implied. The Australian National University
11
 * makes no representations about the suitability of this software for
12
 * any purpose.
13
 *
14
 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17
 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
18
 * OF SUCH DAMAGE.
19
 *
20
 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23
 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25
 * OR MODIFICATIONS.
26
 */
27
28
#ifndef lint
29
static char rcsid[] = "$Id: sys-sunos4.c,v 1.9 1998/03/25 02:19:29 paulus Exp $";
30
#endif
31
32
#include <stdio.h>
33
#include <stddef.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <ctype.h>
37
#include <errno.h>
38
#include <fcntl.h>
39
#include <unistd.h>
40
#include <termios.h>
41
#include <signal.h>
42
#include <malloc.h>
43
#include <utmp.h>
44
#include <sys/types.h>
45
#include <sys/param.h>
46
#include <sys/socket.h>
47
#include <sys/sockio.h>
48
#include <sys/stream.h>
49
#include <sys/stropts.h>
50
#include <sys/syslog.h>
51
#include <sys/stat.h>
52
#include <sys/time.h>
53
#include <sys/poll.h>
54
#include <net/if.h>
55
#include <net/if_arp.h>
56
#include <net/nit_if.h>
57
#include <net/route.h>
58
#include <net/ppp_defs.h>
59
#include <net/pppio.h>
60
#include <netinet/in.h>
61
62
#include "pppd.h"
63
64
#if defined(sun) && defined(sparc)
65
#include <alloca.h>
66
#ifndef __GNUC__
67
extern void *alloca();
68
#endif
69
#endif /*sparc*/
70
71
static int	pppfd;
72
static int	fdmuxid = -1;
73
static int	iffd;
74
static int	sockfd;
75
76
static int	restore_term;
77
static struct termios inittermios;
78
static struct winsize wsinfo;	/* Initial window size info */
79
static pid_t	parent_pid;	/* PID of our parent */
80
81
extern u_char	inpacket_buf[];	/* borrowed from main.c */
82
83
static int	link_mtu, link_mru;
84
85
#define NMODULES	32
86
static int	tty_nmodules;
87
static char	tty_modules[NMODULES][FMNAMESZ+1];
88
89
static int	if_is_up;	/* Interface has been marked up */
90
static u_int32_t ifaddrs[2];	/* local and remote addresses */
91
static u_int32_t default_route_gateway;	/* Gateway for default route added */
92
static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
93
94
/* Prototypes for procedures local to this file. */
95
static int translate_speed __P((int));
96
static int baud_rate_of __P((int));
97
static int get_ether_addr __P((u_int32_t, struct sockaddr *));
98
static int strioctl __P((int, int, void *, int, int));
99
100
101
/*
102
 * sys_init - System-dependent initialization.
103
 */
104
void
105
sys_init()
106
{
107
    int x;
108
109
    /* Get an internet socket for doing socket ioctl's on. */
110
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
111
	syslog(LOG_ERR, "Couldn't create IP socket: %m");
112
	die(1);
113
    }
114
115
    /*
116
     * We may want to send a SIGHUP to the session leader associated
117
     * with our controlling terminal later.  Because SunOS doesn't
118
     * have getsid(), we make do with sending the signal to our
119
     * parent process.
120
     */
121
    parent_pid = getppid();
122
123
    /*
124
     * Open the ppp device.
125
     */
126
    pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
127
    if (pppfd < 0) {
128
	syslog(LOG_ERR, "Can't open /dev/ppp: %m");
129
	die(1);
130
    }
131
    if (kdebugflag) {
132
	x = PPPDBG_LOG + PPPDBG_DRIVER;
133
	strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
134
    }
135
136
    /* Assign a new PPA and get its unit number. */
137
    if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
138
	syslog(LOG_ERR, "Can't create new PPP interface: %m");
139
	die(1);
140
    }
141
142
    /*
143
     * Open the ppp device again and push the if_ppp module on it.
144
     */
145
    iffd = open("/dev/ppp", O_RDWR, 0);
146
    if (iffd < 0) {
147
	syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
148
	die(1);
149
    }
150
    if (kdebugflag) {
151
	x = PPPDBG_LOG + PPPDBG_DRIVER;
152
	strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
153
    }
154
    if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) {
155
	syslog(LOG_ERR, "Couldn't attach ppp interface to device: %m");
156
	die(1);
157
    }
158
    if (ioctl(iffd, I_PUSH, "if_ppp") < 0) {
159
	syslog(LOG_ERR, "Can't push ppp interface module: %m");
160
	die(1);
161
    }
162
    if (kdebugflag) {
163
	x = PPPDBG_LOG + PPPDBG_IF;
164
	strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
165
    }
166
    if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) {
167
	syslog(LOG_ERR, "Couldn't create ppp interface unit: %m");
168
	die(1);
169
    }
170
    x = PPP_IP;
171
    if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) {
172
	syslog(LOG_ERR, "Couldn't bind ppp interface to IP SAP: %m");
173
	die(1);
174
    }
175
}
176
177
/*
178
 * sys_cleanup - restore any system state we modified before exiting:
179
 * mark the interface down, delete default route and/or proxy arp entry.
180
 * This shouldn't call die() because it's called from die().
181
 */
182
void
183
sys_cleanup()
184
{
185
    if (if_is_up)
186
	sifdown(0);
187
    if (ifaddrs[0])
188
	cifaddr(0, ifaddrs[0], ifaddrs[1]);
189
    if (default_route_gateway)
190
	cifdefaultroute(0, 0, default_route_gateway);
191
    if (proxy_arp_addr)
192
	cifproxyarp(0, proxy_arp_addr);
193
}
194
195
/*
196
 * sys_close - Clean up in a child process before execing.
197
 */
198
void
199
sys_close()
200
{
201
    close(iffd);
202
    close(pppfd);
203
    close(sockfd);
204
}
205
206
/*
207
 * sys_check_options - check the options that the user specified
208
 */
209
void
210
sys_check_options()
211
{
212
}
213
214
215
/*
216
 * daemon - Detach us from controlling terminal session.
217
 */
218
int
219
daemon(nochdir, noclose)
220
    int nochdir, noclose;
221
{
222
    int pid;
223
224
    if ((pid = fork()) < 0)
225
	return -1;
226
    if (pid != 0)
227
	exit(0);		/* parent dies */
228
    setsid();
229
    if (!nochdir)
230
	chdir("/");
231
    if (!noclose) {
232
	fclose(stdin);		/* don't need stdin, stdout, stderr */
233
	fclose(stdout);
234
	fclose(stderr);
235
    }
236
    return 0;
237
}
238
239
/*
240
 * ppp_available - check whether the system has any ppp interfaces
241
 */
242
int
243
ppp_available()
244
{
245
    struct stat buf;
246
247
    return stat("/dev/ppp", &buf) >= 0;
248
}
249
250
/*
251
 * establish_ppp - Turn the serial port into a ppp interface.
252
 */
253
void
254
establish_ppp(fd)
255
    int fd;
256
{
257
    int i;
258
259
    /* Pop any existing modules off the tty stream. */
260
    for (i = 0;; ++i)
261
	if (ioctl(fd, I_LOOK, tty_modules[i]) < 0
262
	    || ioctl(fd, I_POP, 0) < 0)
263
	    break;
264
    tty_nmodules = i;
265
266
    /* Push the async hdlc module and the compressor module. */
267
    if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) {
268
	syslog(LOG_ERR, "Couldn't push PPP Async HDLC module: %m");
269
	die(1);
270
    }
271
    if (ioctl(fd, I_PUSH, "ppp_comp") < 0) {
272
	syslog(LOG_ERR, "Couldn't push PPP compression module: %m");
273
/*	die(1); */
274
    }
275
276
    /* Link the serial port under the PPP multiplexor. */
277
    if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) {
278
	syslog(LOG_ERR, "Can't link tty to PPP mux: %m");
279
	die(1);
280
    }
281
}
282
283
/*
284
 * restore_loop - reattach the ppp unit to the loopback.
285
 * This doesn't need to do anything because disestablish_ppp does it.
286
 */
287
void
288
restore_loop()
289
{
290
}
291
292
/*
293
 * disestablish_ppp - Restore the serial port to normal operation.
294
 * It attempts to reconstruct the stream with the previously popped
295
 * modules.  This shouldn't call die() because it's called from die().
296
 */
297
void
298
disestablish_ppp(fd)
299
    int fd;
300
{
301
    int i;
302
303
    if (fdmuxid >= 0) {
304
	if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) {
305
	    if (!hungup)
306
		syslog(LOG_ERR, "Can't unlink tty from PPP mux: %m");
307
	}
308
	fdmuxid = -1;
309
310
	if (!hungup) {
311
	    while (ioctl(fd, I_POP, 0) >= 0)
312
		;
313
	    for (i = tty_nmodules - 1; i >= 0; --i)
314
		if (ioctl(fd, I_PUSH, tty_modules[i]) < 0)
315
		    syslog(LOG_ERR, "Couldn't restore tty module %s: %m",
316
			   tty_modules[i]);
317
	}
318
	if (hungup && default_device && parent_pid > 0) {
319
	    /*
320
	     * If we have received a hangup, we need to send a SIGHUP
321
	     * to the terminal's controlling process.  The reason is
322
	     * that the original stream head for the terminal hasn't
323
	     * seen the M_HANGUP message (it went up through the ppp
324
	     * driver to the stream head for our fd to /dev/ppp).
325
	     * Actually we send the signal to the process that invoked
326
	     * pppd, since SunOS doesn't have getsid().
327
	     */
328
	    kill(parent_pid, SIGHUP);
329
	}
330
    }
331
}
332
333
/*
334
 * Check whether the link seems not to be 8-bit clean.
335
 */
336
void
337
clean_check()
338
{
339
    int x;
340
    char *s;
341
342
    if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0)
343
	return;
344
    s = NULL;
345
    switch (~x) {
346
    case RCV_B7_0:
347
	s = "bit 7 set to 1";
348
	break;
349
    case RCV_B7_1:
350
	s = "bit 7 set to 0";
351
	break;
352
    case RCV_EVNP:
353
	s = "odd parity";
354
	break;
355
    case RCV_ODDP:
356
	s = "even parity";
357
	break;
358
    }
359
    if (s != NULL) {
360
	syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
361
	syslog(LOG_WARNING, "All received characters had %s", s);
362
    }
363
}
364
365
/*
366
 * List of valid speeds.
367
 */
368
struct speed {
369
    int speed_int, speed_val;
370
} speeds[] = {
371
#ifdef B50
372
    { 50, B50 },
373
#endif
374
#ifdef B75
375
    { 75, B75 },
376
#endif
377
#ifdef B110
378
    { 110, B110 },
379
#endif
380
#ifdef B134
381
    { 134, B134 },
382
#endif
383
#ifdef B150
384
    { 150, B150 },
385
#endif
386
#ifdef B200
387
    { 200, B200 },
388
#endif
389
#ifdef B300
390
    { 300, B300 },
391
#endif
392
#ifdef B600
393
    { 600, B600 },
394
#endif
395
#ifdef B1200
396
    { 1200, B1200 },
397
#endif
398
#ifdef B1800
399
    { 1800, B1800 },
400
#endif
401
#ifdef B2000
402
    { 2000, B2000 },
403
#endif
404
#ifdef B2400
405
    { 2400, B2400 },
406
#endif
407
#ifdef B3600
408
    { 3600, B3600 },
409
#endif
410
#ifdef B4800
411
    { 4800, B4800 },
412
#endif
413
#ifdef B7200
414
    { 7200, B7200 },
415
#endif
416
#ifdef B9600
417
    { 9600, B9600 },
418
#endif
419
#ifdef B19200
420
    { 19200, B19200 },
421
#endif
422
#ifdef B38400
423
    { 38400, B38400 },
424
#endif
425
#ifdef EXTA
426
    { 19200, EXTA },
427
#endif
428
#ifdef EXTB
429
    { 38400, EXTB },
430
#endif
431
#ifdef B57600
432
    { 57600, B57600 },
433
#endif
434
#ifdef B115200
435
    { 115200, B115200 },
436
#endif
437
    { 0, 0 }
438
};
439
440
/*
441
 * Translate from bits/second to a speed_t.
442
 */
443
static int
444
translate_speed(bps)
445
    int bps;
446
{
447
    struct speed *speedp;
448
449
    if (bps == 0)
450
	return 0;
451
    for (speedp = speeds; speedp->speed_int; speedp++)
452
	if (bps == speedp->speed_int)
453
	    return speedp->speed_val;
454
    syslog(LOG_WARNING, "speed %d not supported", bps);
455
    return 0;
456
}
457
458
/*
459
 * Translate from a speed_t to bits/second.
460
 */
461
static int
462
baud_rate_of(speed)
463
    int speed;
464
{
465
    struct speed *speedp;
466
467
    if (speed == 0)
468
	return 0;
469
    for (speedp = speeds; speedp->speed_int; speedp++)
470
	if (speed == speedp->speed_val)
471
	    return speedp->speed_int;
472
    return 0;
473
}
474
475
/*
476
 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
477
 * at the requested speed, etc.  If `local' is true, set CLOCAL
478
 * regardless of whether the modem option was specified.
479
 */
480
void
481
set_up_tty(fd, local)
482
    int fd, local;
483
{
484
    int speed;
485
    struct termios tios;
486
487
    if (tcgetattr(fd, &tios) < 0) {
488
	syslog(LOG_ERR, "tcgetattr: %m");
489
	die(1);
490
    }
491
492
    if (!restore_term) {
493
	inittermios = tios;
494
	ioctl(fd, TIOCGWINSZ, &wsinfo);
495
    }
496
497
    tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
498
    if (crtscts > 0)
499
	tios.c_cflag |= CRTSCTS;
500
    else if (crtscts < 0)
501
	tios.c_cflag &= ~CRTSCTS;
502
503
    tios.c_cflag |= CS8 | CREAD | HUPCL;
504
    if (local || !modem)
505
	tios.c_cflag |= CLOCAL;
506
    tios.c_iflag = IGNBRK | IGNPAR;
507
    tios.c_oflag = 0;
508
    tios.c_lflag = 0;
509
    tios.c_cc[VMIN] = 1;
510
    tios.c_cc[VTIME] = 0;
511
512
    if (crtscts == -2) {
513
	tios.c_iflag |= IXON | IXOFF;
514
	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
515
	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
516
    }
517
518
    speed = translate_speed(inspeed);
519
    if (speed) {
520
	cfsetospeed(&tios, speed);
521
	cfsetispeed(&tios, speed);
522
    } else {
523
	speed = cfgetospeed(&tios);
524
	/*
525
	 * We can't proceed if the serial port speed is 0,
526
	 * since that implies that the serial port is disabled.
527
	 */
528
	if (speed == B0) {
529
	    syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
530
		   devnam);
531
	    die(1);
532
	}
533
    }
534
535
    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
536
	syslog(LOG_ERR, "tcsetattr: %m");
537
	die(1);
538
    }
539
540
    baud_rate = inspeed = baud_rate_of(speed);
541
    restore_term = 1;
542
}
543
544
/*
545
 * restore_tty - restore the terminal to the saved settings.
546
 */
547
void
548
restore_tty(fd)
549
    int fd;
550
{
551
    if (restore_term) {
552
	if (!default_device) {
553
	    /*
554
	     * Turn off echoing, because otherwise we can get into
555
	     * a loop with the tty and the modem echoing to each other.
556
	     * We presume we are the sole user of this tty device, so
557
	     * when we close it, it will revert to its defaults anyway.
558
	     */
559
	    inittermios.c_lflag &= ~(ECHO | ECHONL);
560
	}
561
	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
562
	    if (!hungup && errno != ENXIO)
563
		syslog(LOG_WARNING, "tcsetattr: %m");
564
	ioctl(fd, TIOCSWINSZ, &wsinfo);
565
	restore_term = 0;
566
    }
567
}
568
569
/*
570
 * setdtr - control the DTR line on the serial port.
571
 * This is called from die(), so it shouldn't call die().
572
 */
573
void
574
setdtr(fd, on)
575
int fd, on;
576
{
577
    int modembits = TIOCM_DTR;
578
579
    ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
580
}
581
582
/*
583
 * open_loopback - open the device we use for getting packets
584
 * in demand mode.  Under Solaris 2, we use our existing fd
585
 * to the ppp driver.
586
 */
587
void
588
open_ppp_loopback()
589
{
590
}
591
592
/*
593
 * output - Output PPP packet.
594
 */
595
void
596
output(unit, p, len)
597
    int unit;
598
    u_char *p;
599
    int len;
600
{
601
    struct strbuf data;
602
    int retries;
603
    struct pollfd pfd;
604
605
    if (debug)
606
	log_packet(p, len, "sent ", LOG_DEBUG);
607
608
    data.len = len;
609
    data.buf = (caddr_t) p;
610
    retries = 4;
611
    while (putmsg(pppfd, NULL, &data, 0) < 0) {
612
	if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
613
	    if (errno != ENXIO)
614
		syslog(LOG_ERR, "Couldn't send packet: %m");
615
	    break;
616
	}
617
	pfd.fd = pppfd;
618
	pfd.events = POLLOUT;
619
	poll(&pfd, 1, 250);	/* wait for up to 0.25 seconds */
620
    }
621
}
622
623
624
/*
625
 * wait_input - wait until there is data available on fd,
626
 * for the length of time specified by *timo (indefinite
627
 * if timo is NULL).
628
 */
629
void
630
wait_input(timo)
631
    struct timeval *timo;
632
{
633
    int t;
634
    struct pollfd pfd;
635
636
    t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
637
    pfd.fd = pppfd;
638
    pfd.events = POLLIN | POLLPRI | POLLHUP;
639
    if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
640
	syslog(LOG_ERR, "poll: %m");
641
	die(1);
642
    }
643
}
644
645
/*
646
 * wait_loop_output - wait until there is data available on the
647
 * loopback, for the length of time specified by *timo (indefinite
648
 * if timo is NULL).
649
 */
650
void
651
wait_loop_output(timo)
652
    struct timeval *timo;
653
{
654
    wait_input(timo);
655
}
656
657
/*
658
 * wait_time - wait for a given length of time or until a
659
 * signal is received.
660
 */
661
void
662
wait_time(timo)
663
    struct timeval *timo;
664
{
665
    int n;
666
667
    n = select(0, NULL, NULL, NULL, timo);
668
    if (n < 0 && errno != EINTR) {
669
	syslog(LOG_ERR, "select: %m");
670
	die(1);
671
    }
672
}
673
674
675
/*
676
 * read_packet - get a PPP packet from the serial device.
677
 */
678
int
679
read_packet(buf)
680
    u_char *buf;
681
{
682
    struct strbuf ctrl, data;
683
    int flags, len;
684
    unsigned char ctrlbuf[64];
685
686
    for (;;) {
687
	data.maxlen = PPP_MRU + PPP_HDRLEN;
688
	data.buf = (caddr_t) buf;
689
	ctrl.maxlen = sizeof(ctrlbuf);
690
	ctrl.buf = (caddr_t) ctrlbuf;
691
	flags = 0;
692
	len = getmsg(pppfd, &ctrl, &data, &flags);
693
	if (len < 0) {
694
	    if (errno = EAGAIN || errno == EINTR)
695
		return -1;
696
	    syslog(LOG_ERR, "Error reading packet: %m");
697
	    die(1);
698
	}
699
700
	if (ctrl.len <= 0)
701
	    return data.len;
702
703
	/*
704
	 * Got a M_PROTO or M_PCPROTO message.  Huh?
705
	 */
706
	if (debug)
707
	    syslog(LOG_DEBUG, "got ctrl msg len=%d", ctrl.len);
708
709
    }
710
}
711
712
/*
713
 * get_loop_output - get outgoing packets from the ppp device,
714
 * and detect when we want to bring the real link up.
715
 * Return value is 1 if we need to bring up the link, 0 otherwise.
716
 */
717
int
718
get_loop_output()
719
{
720
    int len;
721
    int rv = 0;
722
723
    while ((len = read_packet(inpacket_buf)) > 0) {
724
	if (loop_frame(inpacket_buf, len))
725
	    rv = 1;
726
    }
727
    return rv;
728
}
729
730
/*
731
 * ppp_send_config - configure the transmit characteristics of
732
 * the ppp interface.
733
 */
734
void
735
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
736
    int unit, mtu;
737
    u_int32_t asyncmap;
738
    int pcomp, accomp;
739
{
740
    int cf[2];
741
    struct ifreq ifr;
742
743
    link_mtu = mtu;
744
    if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
745
	if (hungup && errno == ENXIO)
746
	    return;
747
	syslog(LOG_ERR, "Couldn't set MTU: %m");
748
    }
749
    if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
750
	syslog(LOG_ERR, "Couldn't set transmit ACCM: %m");
751
    }
752
    cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
753
    cf[1] = COMP_PROT | COMP_AC;
754
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
755
	syslog(LOG_ERR, "Couldn't set prot/AC compression: %m");
756
    }
757
758
    /* set mtu for ip as well */
759
    memset(&ifr, 0, sizeof(ifr));
760
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
761
    ifr.ifr_metric = link_mtu;
762
    if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
763
	syslog(LOG_ERR, "Couldn't set IP MTU: %m");
764
    }
765
}
766
767
/*
768
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
769
 */
770
void
771
ppp_set_xaccm(unit, accm)
772
    int unit;
773
    ext_accm accm;
774
{
775
    if (strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
776
	if (!hungup || errno != ENXIO)
777
	    syslog(LOG_WARNING, "Couldn't set extended ACCM: %m");
778
    }
779
}
780
781
/*
782
 * ppp_recv_config - configure the receive-side characteristics of
783
 * the ppp interface.
784
 */
785
void
786
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
787
    int unit, mru;
788
    u_int32_t asyncmap;
789
    int pcomp, accomp;
790
{
791
    int cf[2];
792
793
    link_mru = mru;
794
    if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
795
	if (hungup && errno == ENXIO)
796
	    return;
797
	syslog(LOG_ERR, "Couldn't set MRU: %m");
798
    }
799
    if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
800
	syslog(LOG_ERR, "Couldn't set receive ACCM: %m");
801
    }
802
    cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
803
    cf[1] = DECOMP_PROT | DECOMP_AC;
804
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
805
	syslog(LOG_ERR, "Couldn't set prot/AC decompression: %m");
806
    }
807
}
808
809
/*
810
 * ccp_test - ask kernel whether a given compression method
811
 * is acceptable for use.
812
 */
813
int
814
ccp_test(unit, opt_ptr, opt_len, for_transmit)
815
    int unit, opt_len, for_transmit;
816
    u_char *opt_ptr;
817
{
818
    if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
819
		 opt_ptr, opt_len, 0) >= 0)
820
	return 1;
821
    return (errno == ENOSR)? 0: -1;
822
}
823
824
/*
825
 * ccp_flags_set - inform kernel about the current state of CCP.
826
 */
827
void
828
ccp_flags_set(unit, isopen, isup)
829
    int unit, isopen, isup;
830
{
831
    int cf[2];
832
833
    cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
834
    cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
835
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
836
	if (!hungup || errno != ENXIO)
837
	    syslog(LOG_ERR, "Couldn't set kernel CCP state: %m");
838
    }
839
}
840
841
/*
842
 * get_idle_time - return how long the link has been idle.
843
 */
844
int
845
get_idle_time(u, ip)
846
    int u;
847
    struct ppp_idle *ip;
848
{
849
    return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
850
}
851
852
853
/*
854
 * ccp_fatal_error - returns 1 if decompression was disabled as a
855
 * result of an error detected after decompression of a packet,
856
 * 0 otherwise.  This is necessary because of patent nonsense.
857
 */
858
int
859
ccp_fatal_error(unit)
860
    int unit;
861
{
862
    int cf[2];
863
864
    cf[0] = cf[1] = 0;
865
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
866
	if (errno != ENXIO && errno != EINVAL)
867
	    syslog(LOG_ERR, "Couldn't get compression flags: %m");
868
	return 0;
869
    }
870
    return cf[0] & CCP_FATALERROR;
871
}
872
873
/*
874
 * sifvjcomp - config tcp header compression
875
 */
876
int
877
sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
878
    int u, vjcomp, xcidcomp, xmaxcid;
879
{
880
    int cf[2];
881
    char maxcid[2];
882
883
    if (vjcomp) {
884
	maxcid[0] = xcidcomp;
885
	maxcid[1] = 15;		/* XXX should be rmaxcid */
886
	if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
887
	    syslog(LOG_ERR, "Couldn't initialize VJ compression: %m");
888
	}
889
    }
890
891
    cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)	/* XXX this is wrong */
892
	+ (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
893
    cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
894
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
895
	if (vjcomp)
896
	    syslog(LOG_ERR, "Couldn't enable VJ compression: %m");
897
    }
898
899
    return 1;
900
}
901
902
/*
903
 * sifup - Config the interface up and enable IP packets to pass.
904
 */
905
int
906
sifup(u)
907
    int u;
908
{
909
    struct ifreq ifr;
910
911
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
912
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
913
	syslog(LOG_ERR, "Couldn't mark interface up (get): %m");
914
	return 0;
915
    }
916
    ifr.ifr_flags |= IFF_UP;
917
    if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
918
	syslog(LOG_ERR, "Couldn't mark interface up (set): %m");
919
	return 0;
920
    }
921
    if_is_up = 1;
922
    return 1;
923
}
924
925
/*
926
 * sifdown - Config the interface down and disable IP.
927
 */
928
int
929
sifdown(u)
930
    int u;
931
{
932
    struct ifreq ifr;
933
934
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
935
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
936
	syslog(LOG_ERR, "Couldn't mark interface down (get): %m");
937
	return 0;
938
    }
939
    if ((ifr.ifr_flags & IFF_UP) != 0) {
940
	ifr.ifr_flags &= ~IFF_UP;
941
	if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
942
	    syslog(LOG_ERR, "Couldn't mark interface down (set): %m");
943
	    return 0;
944
	}
945
    }
946
    if_is_up = 0;
947
    return 1;
948
}
949
950
/*
951
 * sifnpmode - Set the mode for handling packets for a given NP.
952
 */
953
int
954
sifnpmode(u, proto, mode)
955
    int u;
956
    int proto;
957
    enum NPmode mode;
958
{
959
    int npi[2];
960
961
    npi[0] = proto;
962
    npi[1] = (int) mode;
963
    if (strioctl(pppfd, PPPIO_NPMODE, npi, 2 * sizeof(int), 0) < 0) {
964
	syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
965
	return 0;
966
    }
967
    return 1;
968
}
969
970
#define INET_ADDR(x)	(((struct sockaddr_in *) &(x))->sin_addr.s_addr)
971
972
/*
973
 * sifaddr - Config the interface IP addresses and netmask.
974
 */
975
int
976
sifaddr(u, o, h, m)
977
    int u;
978
    u_int32_t o, h, m;
979
{
980
    struct ifreq ifr;
981
982
    memset(&ifr, 0, sizeof(ifr));
983
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
984
    ifr.ifr_addr.sa_family = AF_INET;
985
    INET_ADDR(ifr.ifr_addr) = m;
986
    if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
987
	syslog(LOG_ERR, "Couldn't set IP netmask: %m");
988
    }
989
    ifr.ifr_addr.sa_family = AF_INET;
990
    INET_ADDR(ifr.ifr_addr) = o;
991
    if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
992
	syslog(LOG_ERR, "Couldn't set local IP address: %m");
993
    }
994
    ifr.ifr_dstaddr.sa_family = AF_INET;
995
    INET_ADDR(ifr.ifr_dstaddr) = h;
996
    if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
997
	syslog(LOG_ERR, "Couldn't set remote IP address: %m");
998
    }
999
#if 0	/* now done in ppp_send_config */
1000
    ifr.ifr_metric = link_mtu;
1001
    if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
1002
	syslog(LOG_ERR, "Couldn't set IP MTU: %m");
1003
    }
1004
#endif
1005
    ifaddrs[0] = o;
1006
    ifaddrs[1] = h;
1007
1008
    return 1;
1009
}
1010
1011
/*
1012
 * cifaddr - Clear the interface IP addresses, and delete routes
1013
 * through the interface if possible.
1014
 */
1015
int
1016
cifaddr(u, o, h)
1017
    int u;
1018
    u_int32_t o, h;
1019
{
1020
    struct rtentry rt;
1021
1022
    bzero(&rt, sizeof(rt));
1023
    rt.rt_dst.sa_family = AF_INET;
1024
    INET_ADDR(rt.rt_dst) = h;
1025
    rt.rt_gateway.sa_family = AF_INET;
1026
    INET_ADDR(rt.rt_gateway) = o;
1027
    rt.rt_flags = RTF_HOST;
1028
    if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
1029
	syslog(LOG_ERR, "Couldn't delete route through interface: %m");
1030
    ifaddrs[0] = 0;
1031
    return 1;
1032
}
1033
1034
/*
1035
 * sifdefaultroute - assign a default route through the address given.
1036
 */
1037
int
1038
sifdefaultroute(u, l, g)
1039
    int u;
1040
    u_int32_t l, g;
1041
{
1042
    struct rtentry rt;
1043
1044
    bzero(&rt, sizeof(rt));
1045
    rt.rt_dst.sa_family = AF_INET;
1046
    INET_ADDR(rt.rt_dst) = 0;
1047
    rt.rt_gateway.sa_family = AF_INET;
1048
    INET_ADDR(rt.rt_gateway) = g;
1049
    rt.rt_flags = RTF_GATEWAY;
1050
1051
    if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
1052
	syslog(LOG_ERR, "Can't add default route: %m");
1053
	return 0;
1054
    }
1055
1056
    default_route_gateway = g;
1057
    return 1;
1058
}
1059
1060
/*
1061
 * cifdefaultroute - delete a default route through the address given.
1062
 */
1063
int
1064
cifdefaultroute(u, l, g)
1065
    int u;
1066
    u_int32_t l, g;
1067
{
1068
    struct rtentry rt;
1069
1070
    bzero(&rt, sizeof(rt));
1071
    rt.rt_dst.sa_family = AF_INET;
1072
    INET_ADDR(rt.rt_dst) = 0;
1073
    rt.rt_gateway.sa_family = AF_INET;
1074
    INET_ADDR(rt.rt_gateway) = g;
1075
    rt.rt_flags = RTF_GATEWAY;
1076
1077
    if (ioctl(sockfd, SIOCDELRT, &rt) < 0) {
1078
	syslog(LOG_ERR, "Can't delete default route: %m");
1079
	return 0;
1080
    }
1081
1082
    default_route_gateway = 0;
1083
    return 1;
1084
}
1085
1086
/*
1087
 * sifproxyarp - Make a proxy ARP entry for the peer.
1088
 */
1089
int
1090
sifproxyarp(unit, hisaddr)
1091
    int unit;
1092
    u_int32_t hisaddr;
1093
{
1094
    struct arpreq arpreq;
1095
1096
    bzero(&arpreq, sizeof(arpreq));
1097
    if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
1098
	return 0;
1099
1100
    arpreq.arp_pa.sa_family = AF_INET;
1101
    INET_ADDR(arpreq.arp_pa) = hisaddr;
1102
    arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1103
    if (ioctl(sockfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
1104
	syslog(LOG_ERR, "Couldn't set proxy ARP entry: %m");
1105
	return 0;
1106
    }
1107
1108
    proxy_arp_addr = hisaddr;
1109
    return 1;
1110
}
1111
1112
/*
1113
 * cifproxyarp - Delete the proxy ARP entry for the peer.
1114
 */
1115
int
1116
cifproxyarp(unit, hisaddr)
1117
    int unit;
1118
    u_int32_t hisaddr;
1119
{
1120
    struct arpreq arpreq;
1121
1122
    bzero(&arpreq, sizeof(arpreq));
1123
    arpreq.arp_pa.sa_family = AF_INET;
1124
    INET_ADDR(arpreq.arp_pa) = hisaddr;
1125
    if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1126
	syslog(LOG_ERR, "Couldn't delete proxy ARP entry: %m");
1127
	return 0;
1128
    }
1129
1130
    proxy_arp_addr = 0;
1131
    return 1;
1132
}
1133
1134
/*
1135
 * get_ether_addr - get the hardware address of an interface on the
1136
 * the same subnet as ipaddr.
1137
 */
1138
#define MAX_IFS		32
1139
1140
static int
1141
get_ether_addr(ipaddr, hwaddr)
1142
    u_int32_t ipaddr;
1143
    struct sockaddr *hwaddr;
1144
{
1145
    struct ifreq *ifr, *ifend;
1146
    u_int32_t ina, mask;
1147
    struct ifreq ifreq;
1148
    struct ifconf ifc;
1149
    struct ifreq ifs[MAX_IFS];
1150
    int nit_fd;
1151
1152
    ifc.ifc_len = sizeof(ifs);
1153
    ifc.ifc_req = ifs;
1154
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1155
	syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1156
	return 0;
1157
    }
1158
1159
    /*
1160
     * Scan through looking for an interface with an Internet
1161
     * address on the same subnet as `ipaddr'.
1162
     */
1163
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1164
    for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
1165
	    ((char *)&ifr->ifr_addr + sizeof(struct sockaddr))) {
1166
        if (ifr->ifr_addr.sa_family == AF_INET) {
1167
1168
            /*
1169
             * Check that the interface is up, and not point-to-point
1170
             * or loopback.
1171
             */
1172
            strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1173
            if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1174
                continue;
1175
            if ((ifreq.ifr_flags &
1176
                 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1177
                 != (IFF_UP|IFF_BROADCAST))
1178
                continue;
1179
1180
            /*
1181
             * Get its netmask and check that it's on the right subnet.
1182
             */
1183
            if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1184
                continue;
1185
            ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1186
            mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1187
            if ((ipaddr & mask) != (ina & mask))
1188
                continue;
1189
1190
            break;
1191
        }
1192
    }
1193
1194
    if (ifr >= ifend)
1195
	return 0;
1196
    syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1197
1198
    /*
1199
     * Grab the physical address for this interface.
1200
     */
1201
    if ((nit_fd = open("/dev/nit", O_RDONLY)) < 0) {
1202
	syslog(LOG_ERR, "Couldn't open /dev/nit: %m");
1203
	return 0;
1204
    }
1205
    strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1206
    if (ioctl(nit_fd, NIOCBIND, &ifreq) < 0
1207
	|| ioctl(nit_fd, SIOCGIFADDR, &ifreq) < 0) {
1208
	syslog(LOG_ERR, "Couldn't get hardware address for %s: %m",
1209
	       ifreq.ifr_name);
1210
	close(nit_fd);
1211
	return 0;
1212
    }
1213
1214
    hwaddr->sa_family = AF_UNSPEC;
1215
    memcpy(hwaddr->sa_data, ifreq.ifr_addr.sa_data, 6);
1216
    close(nit_fd);
1217
    return 1;
1218
}
1219
1220
#define	WTMPFILE	"/usr/adm/wtmp"
1221
1222
void
1223
logwtmp(line, name, host)
1224
    const char *line, *name, *host;
1225
{
1226
    int fd;
1227
    struct stat buf;
1228
    struct utmp ut;
1229
1230
    if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1231
	return;
1232
    if (!fstat(fd, &buf)) {
1233
	(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1234
	(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1235
	(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1236
	(void)time(&ut.ut_time);
1237
	if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1238
	    (void)ftruncate(fd, buf.st_size);
1239
    }
1240
    close(fd);
1241
}
1242
1243
/*
1244
 * Return user specified netmask, modified by any mask we might determine
1245
 * for address `addr' (in network byte order).
1246
 * Here we scan through the system's list of interfaces, looking for
1247
 * any non-point-to-point interfaces which might appear to be on the same
1248
 * network as `addr'.  If we find any, we OR in their netmask to the
1249
 * user-specified netmask.
1250
 */
1251
u_int32_t
1252
GetMask(addr)
1253
    u_int32_t addr;
1254
{
1255
    u_int32_t mask, nmask, ina;
1256
    struct ifreq *ifr, *ifend, ifreq;
1257
    struct ifconf ifc;
1258
1259
    addr = ntohl(addr);
1260
    if (IN_CLASSA(addr))	/* determine network mask for address class */
1261
	nmask = IN_CLASSA_NET;
1262
    else if (IN_CLASSB(addr))
1263
	nmask = IN_CLASSB_NET;
1264
    else
1265
	nmask = IN_CLASSC_NET;
1266
    /* class D nets are disallowed by bad_ip_adrs */
1267
    mask = netmask | htonl(nmask);
1268
1269
    /*
1270
     * Scan through the system's network interfaces.
1271
     */
1272
    ifc.ifc_len = MAX_IFS * sizeof(struct ifreq);
1273
    ifc.ifc_req = alloca(ifc.ifc_len);
1274
    if (ifc.ifc_req == 0)
1275
	return mask;
1276
    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1277
	syslog(LOG_WARNING, "Couldn't get system interface list: %m");
1278
	return mask;
1279
    }
1280
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1281
    for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1282
	/*
1283
	 * Check the interface's internet address.
1284
	 */
1285
	if (ifr->ifr_addr.sa_family != AF_INET)
1286
	    continue;
1287
	ina = INET_ADDR(ifr->ifr_addr);
1288
	if ((ntohl(ina) & nmask) != (addr & nmask))
1289
	    continue;
1290
	/*
1291
	 * Check that the interface is up, and not point-to-point or loopback.
1292
	 */
1293
	strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1294
	if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1295
	    continue;
1296
	if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1297
	    != IFF_UP)
1298
	    continue;
1299
	/*
1300
	 * Get its netmask and OR it into our mask.
1301
	 */
1302
	if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1303
	    continue;
1304
	mask |= INET_ADDR(ifreq.ifr_addr);
1305
    }
1306
1307
    return mask;
1308
}
1309
1310
static int
1311
strioctl(fd, cmd, ptr, ilen, olen)
1312
    int fd, cmd, ilen, olen;
1313
    void *ptr;
1314
{
1315
    struct strioctl str;
1316
1317
    str.ic_cmd = cmd;
1318
    str.ic_timout = 0;
1319
    str.ic_len = ilen;
1320
    str.ic_dp = ptr;
1321
    if (ioctl(fd, I_STR, &str) == -1)
1322
	return -1;
1323
    if (str.ic_len != olen)
1324
	syslog(LOG_DEBUG, "strioctl: expected %d bytes, got %d for cmd %x\n",
1325
	       olen, str.ic_len, cmd);
1326
    return 0;
1327
}
1328
1329
/*
1330
 * Use the hostid as part of the random number seed.
1331
 */
1332
int
1333
get_host_seed()
1334
{
1335
    return gethostid();
1336
}
1337
1338
/*
1339
 * Code for locking/unlocking the serial device.
1340
 * This code is derived from chat.c.
1341
 */
1342
1343
#if !defined(HDB) && !defined(SUNOS3)
1344
#define	HDB	1		/* ascii lock files are the default */
1345
#endif
1346
1347
#ifndef LOCK_DIR
1348
# if HDB
1349
#  define	PIDSTRING
1350
#  define	LOCK_PREFIX	"/usr/spool/locks/LCK.."
1351
# else /* HDB */
1352
#  define	LOCK_PREFIX	"/usr/spool/uucp/LCK.."
1353
# endif /* HDB */
1354
#endif /* LOCK_DIR */
1355
1356
static char *lock_file;		/* name of lock file created */
1357
1358
/*
1359
 * lock - create a lock file for the named device.
1360
 */
1361
int
1362
lock(dev)
1363
    char *dev;
1364
{
1365
    char hdb_lock_buffer[12];
1366
    int fd, pid, n;
1367
    char *p;
1368
1369
    if ((p = strrchr(dev, '/')) != NULL)
1370
	dev = p + 1;
1371
    lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1372
    if (lock_file == NULL)
1373
	novm("lock file name");
1374
    strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1375
1376
    while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1377
	if (errno == EEXIST
1378
	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1379
	    /* Read the lock file to find out who has the device locked */
1380
#ifdef PIDSTRING
1381
	    n = read(fd, hdb_lock_buffer, 11);
1382
	    if (n > 0) {
1383
		hdb_lock_buffer[n] = 0;
1384
		pid = atoi(hdb_lock_buffer);
1385
	    }
1386
#else
1387
	    n = read(fd, &pid, sizeof(pid));
1388
#endif
1389
	    if (n <= 0) {
1390
		syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1391
		close(fd);
1392
	    } else {
1393
		if (kill(pid, 0) == -1 && errno == ESRCH) {
1394
		    /* pid no longer exists - remove the lock file */
1395
		    if (unlink(lock_file) == 0) {
1396
			close(fd);
1397
			syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1398
			       dev, pid);
1399
			continue;
1400
		    } else
1401
			syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1402
			       dev);
1403
		} else
1404
		    syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1405
			   dev, pid);
1406
	    }
1407
	    close(fd);
1408
	} else
1409
	    syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1410
	free(lock_file);
1411
	lock_file = NULL;
1412
	return -1;
1413
    }
1414
1415
#ifdef PIDSTRING
1416
    sprintf(hdb_lock_buffer, "%10d\n", getpid());
1417
    write(fd, hdb_lock_buffer, 11);
1418
#else
1419
    pid = getpid();
1420
    write(fd, &pid, sizeof pid);
1421
#endif
1422
1423
    close(fd);
1424
    return 0;
1425
}
1426
1427
/*
1428
 * unlock - remove our lockfile
1429
 */
1430
void
1431
unlock()
1432
{
1433
    if (lock_file) {
1434
	unlink(lock_file);
1435
	free(lock_file);
1436
	lock_file = NULL;
1437
    }
1438
}
1439
1440
/*
1441
 * SunOS doesn't have strtoul :-(
1442
 */
1443
unsigned long
1444
strtoul(str, ptr, base)
1445
    char *str, **ptr;
1446
    int base;
1447
{
1448
    return (unsigned long) strtol(str, ptr, base);
1449
}
1450
1451
/*
1452
 * Or strerror :-(
1453
 */
1454
extern char *sys_errlist[];
1455
extern int sys_nerr;
1456
1457
char *
1458
strerror(n)
1459
    int n;
1460
{
1461
    static char unknown[32];
1462
1463
    if (n > 0 && n < sys_nerr)
1464
	return sys_errlist[n];
1465
    sprintf(unknown, "Error %d", n);
1466
    return unknown;
1467
}
(-)pppd/sys-svr4.c (+1690 lines)
Line 0 Link Here
1
/*
2
 * System-dependent procedures for pppd under Solaris 2.
3
 *
4
 * Copyright (c) 1994 The Australian National University.
5
 * All rights reserved.
6
 *
7
 * Permission to use, copy, modify, and distribute this software and its
8
 * documentation is hereby granted, provided that the above copyright
9
 * notice appears in all copies.  This software is provided without any
10
 * warranty, express or implied. The Australian National University
11
 * makes no representations about the suitability of this software for
12
 * any purpose.
13
 *
14
 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17
 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
18
 * OF SUCH DAMAGE.
19
 *
20
 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23
 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25
 * OR MODIFICATIONS.
26
 */
27
28
#ifndef lint
29
static char rcsid[] = "$Id: sys-svr4.c,v 1.17 1998/03/25 02:19:31 paulus Exp $";
30
#endif
31
32
#include <limits.h>
33
#include <stdio.h>
34
#include <stddef.h>
35
#include <stdlib.h>
36
#include <ctype.h>
37
#include <errno.h>
38
#include <fcntl.h>
39
#include <unistd.h>
40
#include <termios.h>
41
#ifndef CRTSCTS
42
#include <sys/termiox.h>
43
#endif
44
#include <signal.h>
45
#include <utmpx.h>
46
#include <sys/types.h>
47
#include <sys/ioccom.h>
48
#include <sys/stream.h>
49
#include <sys/stropts.h>
50
#include <sys/socket.h>
51
#include <sys/sockio.h>
52
#include <sys/syslog.h>
53
#include <sys/sysmacros.h>
54
#include <sys/systeminfo.h>
55
#include <sys/dlpi.h>
56
#include <sys/stat.h>
57
#include <sys/mkdev.h>
58
#include <net/if.h>
59
#include <net/if_arp.h>
60
#include <net/route.h>
61
#include <net/ppp_defs.h>
62
#include <net/pppio.h>
63
#include <netinet/in.h>
64
65
#include "pppd.h"
66
67
static int	pppfd;
68
static int	fdmuxid = -1;
69
static int	ipfd;
70
static int	ipmuxid = -1;
71
72
static int	restore_term;
73
static struct termios inittermios;
74
#ifndef CRTSCTS
75
static struct termiox inittermiox;
76
static int	termiox_ok;
77
#endif
78
static struct winsize wsinfo;	/* Initial window size info */
79
static pid_t	tty_sid;	/* original session ID for terminal */
80
81
extern u_char	inpacket_buf[];	/* borrowed from main.c */
82
83
static int	link_mtu, link_mru;
84
85
#define NMODULES	32
86
static int	tty_nmodules;
87
static char	tty_modules[NMODULES][FMNAMESZ+1];
88
89
static int	if_is_up;	/* Interface has been marked up */
90
static u_int32_t default_route_gateway;	/* Gateway for default route added */
91
static u_int32_t proxy_arp_addr;	/* Addr for proxy arp entry added */
92
93
/* Prototypes for procedures local to this file. */
94
static int translate_speed __P((int));
95
static int baud_rate_of __P((int));
96
static int get_ether_addr __P((u_int32_t, struct sockaddr *));
97
static int get_hw_addr __P((char *, struct sockaddr *));
98
static int dlpi_attach __P((int, int));
99
static int dlpi_info_req __P((int));
100
static int dlpi_get_reply __P((int, union DL_primitives *, int, int));
101
static int strioctl __P((int, int, void *, int, int));
102
103
104
/*
105
 * sys_init - System-dependent initialization.
106
 */
107
void
108
sys_init()
109
{
110
    int ifd, x;
111
#ifndef sun
112
    struct ifreq ifr;
113
    struct {
114
	union DL_primitives prim;
115
	char space[64];
116
    } reply;
117
#endif
118
119
    ipfd = open("/dev/ip", O_RDWR, 0);
120
    if (ipfd < 0) {
121
	syslog(LOG_ERR, "Couldn't open IP device: %m");
122
	die(1);
123
    }
124
125
    if (default_device)
126
	tty_sid = getsid((pid_t)0);
127
128
    pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
129
    if (pppfd < 0) {
130
	syslog(LOG_ERR, "Can't open /dev/ppp: %m");
131
	die(1);
132
    }
133
    if (kdebugflag & 1) {
134
	x = PPPDBG_LOG + PPPDBG_DRIVER;
135
	strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
136
    }
137
138
    /* Assign a new PPA and get its unit number. */
139
    if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
140
	syslog(LOG_ERR, "Can't create new PPP interface: %m");
141
	die(1);
142
    }
143
144
    /*
145
     * Open the ppp device again and link it under the ip multiplexor.
146
     * IP will assign a unit number which hopefully is the same as ifunit.
147
     * I don't know any way to be certain they will be the same. :-(
148
     */
149
    ifd = open("/dev/ppp", O_RDWR, 0);
150
    if (ifd < 0) {
151
	syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
152
	die(1);
153
    }
154
    if (kdebugflag & 1) {
155
	x = PPPDBG_LOG + PPPDBG_DRIVER;
156
	strioctl(ifd, PPPIO_DEBUG, &x, sizeof(int), 0);
157
    }
158
#ifdef sun
159
    if (ioctl(ifd, I_PUSH, "ip") < 0) {
160
	syslog(LOG_ERR, "Can't push IP module: %m");
161
	close(ifd);
162
	die(1);
163
    }
164
#else
165
    if (dlpi_attach(ifd, ifunit) < 0 ||
166
	dlpi_get_reply(ifd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0) {
167
	syslog(LOG_ERR, "Can't attach to ppp%d: %m", ifunit);
168
	close(ifd);
169
	die(1);
170
    }
171
#endif
172
    ipmuxid = ioctl(ipfd, I_LINK, ifd);
173
    close(ifd);
174
    if (ipmuxid < 0) {
175
	syslog(LOG_ERR, "Can't link PPP device to IP: %m");
176
	die(1);
177
    }
178
179
#ifndef sun
180
    /* Set the interface name for the link. */
181
    (void) sprintf (ifr.ifr_name, "ppp%d", ifunit);
182
    ifr.ifr_metric = ipmuxid;
183
    if (strioctl(ipfd, SIOCSIFNAME, (char *)&ifr, sizeof ifr, 0) < 0) {
184
	syslog(LOG_ERR, "Can't set interface name %s: %m", ifr.ifr_name);
185
	die(1);
186
    }
187
#endif
188
}
189
190
/*
191
 * sys_cleanup - restore any system state we modified before exiting:
192
 * mark the interface down, delete default route and/or proxy arp entry.
193
 * This should call die() because it's called from die().
194
 */
195
void
196
sys_cleanup()
197
{
198
    struct ifreq ifr;
199
200
    if (if_is_up)
201
	sifdown(0);
202
    if (default_route_gateway)
203
	cifdefaultroute(0, default_route_gateway, default_route_gateway);
204
    if (proxy_arp_addr)
205
	cifproxyarp(0, proxy_arp_addr);
206
}
207
208
/*
209
 * sys_close - Clean up in a child process before execing.
210
 */
211
void
212
sys_close()
213
{
214
    close(ipfd);
215
    if (pppfd >= 0)
216
	close(pppfd);
217
}
218
219
/*
220
 * sys_check_options - check the options that the user specified
221
 */
222
void
223
sys_check_options()
224
{
225
}
226
227
228
/*
229
 * daemon - Detach us from controlling terminal session.
230
 */
231
int
232
daemon(nochdir, noclose)
233
    int nochdir, noclose;
234
{
235
    int pid;
236
237
    if ((pid = fork()) < 0)
238
	return -1;
239
    if (pid != 0)
240
	exit(0);		/* parent dies */
241
    setsid();
242
    if (!nochdir)
243
	chdir("/");
244
    if (!noclose) {
245
	fclose(stdin);		/* don't need stdin, stdout, stderr */
246
	fclose(stdout);
247
	fclose(stderr);
248
    }
249
    return 0;
250
}
251
252
/*
253
 * ppp_available - check whether the system has any ppp interfaces
254
 */
255
int
256
ppp_available()
257
{
258
    struct stat buf;
259
260
    return stat("/dev/ppp", &buf) >= 0;
261
}
262
263
/*
264
 * establish_ppp - Turn the serial port into a ppp interface.
265
 */
266
void
267
establish_ppp(fd)
268
    int fd;
269
{
270
    int i;
271
272
    /* Pop any existing modules off the tty stream. */
273
    for (i = 0;; ++i)
274
	if (ioctl(fd, I_LOOK, tty_modules[i]) < 0
275
	    || ioctl(fd, I_POP, 0) < 0)
276
	    break;
277
    tty_nmodules = i;
278
279
    /* Push the async hdlc module and the compressor module. */
280
    if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) {
281
	syslog(LOG_ERR, "Couldn't push PPP Async HDLC module: %m");
282
	die(1);
283
    }
284
    if (kdebugflag & 4) {
285
	i = PPPDBG_LOG + PPPDBG_AHDLC;
286
	strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
287
    }
288
    if (ioctl(fd, I_PUSH, "ppp_comp") < 0) {
289
	syslog(LOG_ERR, "Couldn't push PPP compression module: %m");
290
/*	die(1); */
291
    }
292
    if (kdebugflag & 2) {
293
	i = PPPDBG_LOG + PPPDBG_COMP;
294
	strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
295
    }
296
297
    /* Link the serial port under the PPP multiplexor. */
298
    if ((fdmuxid = ioctl(pppfd, I_LINK, fd)) < 0) {
299
	syslog(LOG_ERR, "Can't link tty to PPP mux: %m");
300
	die(1);
301
    }
302
}
303
304
/*
305
 * restore_loop - reattach the ppp unit to the loopback.
306
 * This doesn't need to do anything because disestablish_ppp does it.
307
 */
308
void
309
restore_loop()
310
{
311
}
312
313
/*
314
 * disestablish_ppp - Restore the serial port to normal operation.
315
 * It attempts to reconstruct the stream with the previously popped
316
 * modules.  This shouldn't call die() because it's called from die().
317
 */
318
void
319
disestablish_ppp(fd)
320
    int fd;
321
{
322
    int i;
323
324
    if (fdmuxid >= 0) {
325
	if (ioctl(pppfd, I_UNLINK, fdmuxid) < 0) {
326
	    if (!hungup)
327
		syslog(LOG_ERR, "Can't unlink tty from PPP mux: %m");
328
	}
329
	fdmuxid = -1;
330
331
	if (!hungup) {
332
	    while (ioctl(fd, I_POP, 0) >= 0)
333
		;
334
	    for (i = tty_nmodules - 1; i >= 0; --i)
335
		if (ioctl(fd, I_PUSH, tty_modules[i]) < 0)
336
		    syslog(LOG_ERR, "Couldn't restore tty module %s: %m",
337
			   tty_modules[i]);
338
	}
339
	if (hungup && default_device && tty_sid > 0) {
340
	    /*
341
	     * If we have received a hangup, we need to send a SIGHUP
342
	     * to the terminal's controlling process.  The reason is
343
	     * that the original stream head for the terminal hasn't
344
	     * seen the M_HANGUP message (it went up through the ppp
345
	     * driver to the stream head for our fd to /dev/ppp).
346
	     */
347
	    kill(tty_sid, SIGHUP);
348
	}
349
    }
350
}
351
352
/*
353
 * Check whether the link seems not to be 8-bit clean.
354
 */
355
void
356
clean_check()
357
{
358
    int x;
359
    char *s;
360
361
    if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0)
362
	return;
363
    s = NULL;
364
    switch (~x) {
365
    case RCV_B7_0:
366
	s = "bit 7 set to 1";
367
	break;
368
    case RCV_B7_1:
369
	s = "bit 7 set to 0";
370
	break;
371
    case RCV_EVNP:
372
	s = "odd parity";
373
	break;
374
    case RCV_ODDP:
375
	s = "even parity";
376
	break;
377
    }
378
    if (s != NULL) {
379
	syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
380
	syslog(LOG_WARNING, "All received characters had %s", s);
381
    }
382
}
383
384
/*
385
 * List of valid speeds.
386
 */
387
struct speed {
388
    int speed_int, speed_val;
389
} speeds[] = {
390
#ifdef B50
391
    { 50, B50 },
392
#endif
393
#ifdef B75
394
    { 75, B75 },
395
#endif
396
#ifdef B110
397
    { 110, B110 },
398
#endif
399
#ifdef B134
400
    { 134, B134 },
401
#endif
402
#ifdef B150
403
    { 150, B150 },
404
#endif
405
#ifdef B200
406
    { 200, B200 },
407
#endif
408
#ifdef B300
409
    { 300, B300 },
410
#endif
411
#ifdef B600
412
    { 600, B600 },
413
#endif
414
#ifdef B1200
415
    { 1200, B1200 },
416
#endif
417
#ifdef B1800
418
    { 1800, B1800 },
419
#endif
420
#ifdef B2000
421
    { 2000, B2000 },
422
#endif
423
#ifdef B2400
424
    { 2400, B2400 },
425
#endif
426
#ifdef B3600
427
    { 3600, B3600 },
428
#endif
429
#ifdef B4800
430
    { 4800, B4800 },
431
#endif
432
#ifdef B7200
433
    { 7200, B7200 },
434
#endif
435
#ifdef B9600
436
    { 9600, B9600 },
437
#endif
438
#ifdef B19200
439
    { 19200, B19200 },
440
#endif
441
#ifdef B38400
442
    { 38400, B38400 },
443
#endif
444
#ifdef EXTA
445
    { 19200, EXTA },
446
#endif
447
#ifdef EXTB
448
    { 38400, EXTB },
449
#endif
450
#ifdef B57600
451
    { 57600, B57600 },
452
#endif
453
#ifdef B115200
454
    { 115200, B115200 },
455
#endif
456
    { 0, 0 }
457
};
458
459
/*
460
 * Translate from bits/second to a speed_t.
461
 */
462
static int
463
translate_speed(bps)
464
    int bps;
465
{
466
    struct speed *speedp;
467
468
    if (bps == 0)
469
	return 0;
470
    for (speedp = speeds; speedp->speed_int; speedp++)
471
	if (bps == speedp->speed_int)
472
	    return speedp->speed_val;
473
    syslog(LOG_WARNING, "speed %d not supported", bps);
474
    return 0;
475
}
476
477
/*
478
 * Translate from a speed_t to bits/second.
479
 */
480
static int
481
baud_rate_of(speed)
482
    int speed;
483
{
484
    struct speed *speedp;
485
486
    if (speed == 0)
487
	return 0;
488
    for (speedp = speeds; speedp->speed_int; speedp++)
489
	if (speed == speedp->speed_val)
490
	    return speedp->speed_int;
491
    return 0;
492
}
493
494
/*
495
 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
496
 * at the requested speed, etc.  If `local' is true, set CLOCAL
497
 * regardless of whether the modem option was specified.
498
 */
499
void
500
set_up_tty(fd, local)
501
    int fd, local;
502
{
503
    int speed;
504
    struct termios tios;
505
#if !defined (CRTSCTS)
506
    struct termiox tiox;
507
#endif
508
509
    if (tcgetattr(fd, &tios) < 0) {
510
	syslog(LOG_ERR, "tcgetattr: %m");
511
	die(1);
512
    }
513
514
#ifndef CRTSCTS
515
    termiox_ok = 1;
516
    if (ioctl (fd, TCGETX, &tiox) < 0) {
517
	termiox_ok = 0;
518
	if (errno != ENOTTY)
519
	    syslog (LOG_ERR, "TCGETX: %m");
520
    }
521
#endif
522
523
    if (!restore_term) {
524
	inittermios = tios;
525
#ifndef CRTSCTS
526
	inittermiox = tiox;
527
#endif
528
	ioctl(fd, TIOCGWINSZ, &wsinfo);
529
    }
530
531
    tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
532
#ifdef CRTSCTS
533
    if (crtscts > 0)
534
	tios.c_cflag |= CRTSCTS;
535
    else if (crtscts < 0)
536
	tios.c_cflag &= ~CRTSCTS;
537
#else
538
    if (crtscts != 0 && !termiox_ok) {
539
	syslog(LOG_ERR, "Can't set RTS/CTS flow control");
540
    } else if (crtscts > 0) {
541
	tiox.x_hflag |= RTSXOFF|CTSXON;
542
    } else if (crtscts < 0) {
543
	tiox.x_hflag &= ~(RTSXOFF|CTSXON);
544
    }
545
#endif
546
547
    tios.c_cflag |= CS8 | CREAD | HUPCL;
548
    if (local || !modem)
549
	tios.c_cflag |= CLOCAL;
550
    tios.c_iflag = IGNBRK | IGNPAR;
551
    tios.c_oflag = 0;
552
    tios.c_lflag = 0;
553
    tios.c_cc[VMIN] = 1;
554
    tios.c_cc[VTIME] = 0;
555
556
    if (crtscts == -2) {
557
	tios.c_iflag |= IXON | IXOFF;
558
	tios.c_cc[VSTOP] = 0x13;	/* DC3 = XOFF = ^S */
559
	tios.c_cc[VSTART] = 0x11;	/* DC1 = XON  = ^Q */
560
    }
561
562
    speed = translate_speed(inspeed);
563
    if (speed) {
564
	cfsetospeed(&tios, speed);
565
	cfsetispeed(&tios, speed);
566
    } else {
567
	speed = cfgetospeed(&tios);
568
	/*
569
	 * We can't proceed if the serial port speed is 0,
570
	 * since that implies that the serial port is disabled.
571
	 */
572
	if (speed == B0) {
573
	    syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
574
		   devnam);
575
	    die(1);
576
	}
577
    }
578
579
    if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
580
	syslog(LOG_ERR, "tcsetattr: %m");
581
	die(1);
582
    }
583
584
#ifndef CRTSCTS
585
    if (termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){
586
	syslog (LOG_ERR, "TCSETXF: %m");
587
    }
588
#endif
589
590
    baud_rate = inspeed = baud_rate_of(speed);
591
    restore_term = 1;
592
}
593
594
/*
595
 * restore_tty - restore the terminal to the saved settings.
596
 */
597
void
598
restore_tty(fd)
599
    int fd;
600
{
601
    if (restore_term) {
602
	if (!default_device) {
603
	    /*
604
	     * Turn off echoing, because otherwise we can get into
605
	     * a loop with the tty and the modem echoing to each other.
606
	     * We presume we are the sole user of this tty device, so
607
	     * when we close it, it will revert to its defaults anyway.
608
	     */
609
	    inittermios.c_lflag &= ~(ECHO | ECHONL);
610
	}
611
	if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
612
	    if (!hungup && errno != ENXIO)
613
		syslog(LOG_WARNING, "tcsetattr: %m");
614
#ifndef CRTSCTS
615
	if (ioctl (fd, TCSETXF, &inittermiox) < 0){
616
	    if (!hungup && errno != ENXIO)
617
		syslog (LOG_ERR, "TCSETXF: %m");
618
	}
619
#endif
620
	ioctl(fd, TIOCSWINSZ, &wsinfo);
621
	restore_term = 0;
622
    }
623
}
624
625
/*
626
 * setdtr - control the DTR line on the serial port.
627
 * This is called from die(), so it shouldn't call die().
628
 */
629
void
630
setdtr(fd, on)
631
int fd, on;
632
{
633
    int modembits = TIOCM_DTR;
634
635
    ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
636
}
637
638
/*
639
 * open_loopback - open the device we use for getting packets
640
 * in demand mode.  Under Solaris 2, we use our existing fd
641
 * to the ppp driver.
642
 */
643
void
644
open_ppp_loopback()
645
{
646
}
647
648
/*
649
 * output - Output PPP packet.
650
 */
651
void
652
output(unit, p, len)
653
    int unit;
654
    u_char *p;
655
    int len;
656
{
657
    struct strbuf data;
658
    int retries;
659
    struct pollfd pfd;
660
661
    if (debug)
662
	log_packet(p, len, "sent ", LOG_DEBUG);
663
664
    data.len = len;
665
    data.buf = (caddr_t) p;
666
    retries = 4;
667
    while (putmsg(pppfd, NULL, &data, 0) < 0) {
668
	if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
669
	    if (errno != ENXIO)
670
		syslog(LOG_ERR, "Couldn't send packet: %m");
671
	    break;
672
	}
673
	pfd.fd = pppfd;
674
	pfd.events = POLLOUT;
675
	poll(&pfd, 1, 250);	/* wait for up to 0.25 seconds */
676
    }
677
}
678
679
680
/*
681
 * wait_input - wait until there is data available on fd,
682
 * for the length of time specified by *timo (indefinite
683
 * if timo is NULL).
684
 */
685
void
686
wait_input(timo)
687
    struct timeval *timo;
688
{
689
    int t;
690
    struct pollfd pfd;
691
692
    t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
693
    pfd.fd = pppfd;
694
    pfd.events = POLLIN | POLLPRI | POLLHUP;
695
    if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
696
	syslog(LOG_ERR, "poll: %m");
697
	die(1);
698
    }
699
}
700
701
/*
702
 * wait_loop_output - wait until there is data available on the
703
 * loopback, for the length of time specified by *timo (indefinite
704
 * if timo is NULL).
705
 */
706
void
707
wait_loop_output(timo)
708
    struct timeval *timo;
709
{
710
    wait_input(timo);
711
}
712
713
/*
714
 * wait_time - wait for a given length of time or until a
715
 * signal is received.
716
 */
717
void
718
wait_time(timo)
719
    struct timeval *timo;
720
{
721
    int n;
722
723
    n = select(0, NULL, NULL, NULL, timo);
724
    if (n < 0 && errno != EINTR) {
725
	syslog(LOG_ERR, "select: %m");
726
	die(1);
727
    }
728
}
729
730
731
/*
732
 * read_packet - get a PPP packet from the serial device.
733
 */
734
int
735
read_packet(buf)
736
    u_char *buf;
737
{
738
    struct strbuf ctrl, data;
739
    int flags, len;
740
    unsigned char ctrlbuf[sizeof(union DL_primitives) + 64];
741
742
    for (;;) {
743
	data.maxlen = PPP_MRU + PPP_HDRLEN;
744
	data.buf = (caddr_t) buf;
745
	ctrl.maxlen = sizeof(ctrlbuf);
746
	ctrl.buf = (caddr_t) ctrlbuf;
747
	flags = 0;
748
	len = getmsg(pppfd, &ctrl, &data, &flags);
749
	if (len < 0) {
750
	    if (errno = EAGAIN || errno == EINTR)
751
		return -1;
752
	    syslog(LOG_ERR, "Error reading packet: %m");
753
	    die(1);
754
	}
755
756
	if (ctrl.len <= 0)
757
	    return data.len;
758
759
	/*
760
	 * Got a M_PROTO or M_PCPROTO message.  Interpret it
761
	 * as a DLPI primitive??
762
	 */
763
	if (debug)
764
	    syslog(LOG_DEBUG, "got dlpi prim 0x%x, len=%d",
765
		   ((union DL_primitives *)ctrlbuf)->dl_primitive, ctrl.len);
766
767
    }
768
}
769
770
/*
771
 * get_loop_output - get outgoing packets from the ppp device,
772
 * and detect when we want to bring the real link up.
773
 * Return value is 1 if we need to bring up the link, 0 otherwise.
774
 */
775
int
776
get_loop_output()
777
{
778
    int len;
779
    int rv = 0;
780
781
    while ((len = read_packet(inpacket_buf)) > 0) {
782
	if (loop_frame(inpacket_buf, len))
783
	    rv = 1;
784
    }
785
    return rv;
786
}
787
788
/*
789
 * ppp_send_config - configure the transmit characteristics of
790
 * the ppp interface.
791
 */
792
void
793
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
794
    int unit, mtu;
795
    u_int32_t asyncmap;
796
    int pcomp, accomp;
797
{
798
    int cf[2];
799
    struct ifreq ifr;
800
801
    link_mtu = mtu;
802
    if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
803
	if (hungup && errno == ENXIO)
804
	    return;
805
	syslog(LOG_ERR, "Couldn't set MTU: %m");
806
    }
807
    if (fdmuxid >= 0) {
808
	/* can't set these if we don't have a stream attached below /dev/ppp */
809
	if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
810
	    syslog(LOG_ERR, "Couldn't set transmit ACCM: %m");
811
	}
812
	cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
813
	cf[1] = COMP_PROT | COMP_AC;
814
	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
815
	    syslog(LOG_ERR, "Couldn't set prot/AC compression: %m");
816
	}
817
    }
818
819
    /* set the MTU for IP as well */
820
    memset(&ifr, 0, sizeof(ifr));
821
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
822
    ifr.ifr_metric = link_mtu;
823
    if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
824
	syslog(LOG_ERR, "Couldn't set IP MTU: %m");
825
    }
826
}
827
828
/*
829
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
830
 */
831
void
832
ppp_set_xaccm(unit, accm)
833
    int unit;
834
    ext_accm accm;
835
{
836
    if (fdmuxid >= 0
837
	&& strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
838
	if (!hungup || errno != ENXIO)
839
	    syslog(LOG_WARNING, "Couldn't set extended ACCM: %m");
840
    }
841
}
842
843
/*
844
 * ppp_recv_config - configure the receive-side characteristics of
845
 * the ppp interface.
846
 */
847
void
848
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
849
    int unit, mru;
850
    u_int32_t asyncmap;
851
    int pcomp, accomp;
852
{
853
    int cf[2];
854
855
    link_mru = mru;
856
    if (strioctl(pppfd, PPPIO_MRU, &mru, sizeof(mru), 0) < 0) {
857
	if (hungup && errno == ENXIO)
858
	    return;
859
	syslog(LOG_ERR, "Couldn't set MRU: %m");
860
    }
861
    if (fdmuxid >= 0) {
862
	/* can't set these if we don't have a stream attached below /dev/ppp */
863
	if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
864
	    syslog(LOG_ERR, "Couldn't set receive ACCM: %m");
865
	}
866
	cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
867
	cf[1] = DECOMP_PROT | DECOMP_AC;
868
	if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
869
	    syslog(LOG_ERR, "Couldn't set prot/AC decompression: %m");
870
	}
871
    }
872
}
873
874
/*
875
 * ccp_test - ask kernel whether a given compression method
876
 * is acceptable for use.
877
 */
878
int
879
ccp_test(unit, opt_ptr, opt_len, for_transmit)
880
    int unit, opt_len, for_transmit;
881
    u_char *opt_ptr;
882
{
883
    if (strioctl(pppfd, (for_transmit? PPPIO_XCOMP: PPPIO_RCOMP),
884
		 opt_ptr, opt_len, 0) >= 0)
885
	return 1;
886
    return (errno == ENOSR)? 0: -1;
887
}
888
889
/*
890
 * ccp_flags_set - inform kernel about the current state of CCP.
891
 */
892
void
893
ccp_flags_set(unit, isopen, isup)
894
    int unit, isopen, isup;
895
{
896
    int cf[2];
897
898
    cf[0] = (isopen? CCP_ISOPEN: 0) + (isup? CCP_ISUP: 0);
899
    cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR;
900
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
901
	if (!hungup || errno != ENXIO)
902
	    syslog(LOG_ERR, "Couldn't set kernel CCP state: %m");
903
    }
904
}
905
906
/*
907
 * get_idle_time - return how long the link has been idle.
908
 */
909
int
910
get_idle_time(u, ip)
911
    int u;
912
    struct ppp_idle *ip;
913
{
914
    return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
915
}
916
917
#if 0
918
/*
919
 * set_filters - transfer the pass and active filters to the kernel.
920
 */
921
int
922
set_filters(pass, active)
923
    struct bpf_program *pass, *active;
924
{
925
    int ret = 1;
926
927
    if (pass->bf_len > 0) {
928
	if (strioctl(pppfd, PPPIO_PASSFILT, pass,
929
		     sizeof(struct bpf_program), 0) < 0) {
930
	    syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
931
	    ret = 0;
932
	}
933
    }
934
    if (active->bf_len > 0) {
935
	if (strioctl(pppfd, PPPIO_ACTIVEFILT, active,
936
		     sizeof(struct bpf_program), 0) < 0) {
937
	    syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
938
	    ret = 0;
939
	}
940
    }
941
    return ret;
942
}
943
#endif
944
945
/*
946
 * ccp_fatal_error - returns 1 if decompression was disabled as a
947
 * result of an error detected after decompression of a packet,
948
 * 0 otherwise.  This is necessary because of patent nonsense.
949
 */
950
int
951
ccp_fatal_error(unit)
952
    int unit;
953
{
954
    int cf[2];
955
956
    cf[0] = cf[1] = 0;
957
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
958
	if (errno != ENXIO && errno != EINVAL)
959
	    syslog(LOG_ERR, "Couldn't get compression flags: %m");
960
	return 0;
961
    }
962
    return cf[0] & CCP_FATALERROR;
963
}
964
965
/*
966
 * sifvjcomp - config tcp header compression
967
 */
968
int
969
sifvjcomp(u, vjcomp, xcidcomp, xmaxcid)
970
    int u, vjcomp, xcidcomp, xmaxcid;
971
{
972
    int cf[2];
973
    char maxcid[2];
974
975
    if (vjcomp) {
976
	maxcid[0] = xcidcomp;
977
	maxcid[1] = 15;		/* XXX should be rmaxcid */
978
	if (strioctl(pppfd, PPPIO_VJINIT, maxcid, sizeof(maxcid), 0) < 0) {
979
	    syslog(LOG_ERR, "Couldn't initialize VJ compression: %m");
980
	}
981
    }
982
983
    cf[0] = (vjcomp? COMP_VJC + DECOMP_VJC: 0)	/* XXX this is wrong */
984
	+ (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0);
985
    cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID;
986
    if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
987
	if (vjcomp)
988
	    syslog(LOG_ERR, "Couldn't enable VJ compression: %m");
989
    }
990
991
    return 1;
992
}
993
994
/*
995
 * sifup - Config the interface up and enable IP packets to pass.
996
 */
997
int
998
sifup(u)
999
    int u;
1000
{
1001
    struct ifreq ifr;
1002
1003
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1004
    if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1005
	syslog(LOG_ERR, "Couldn't mark interface up (get): %m");
1006
	return 0;
1007
    }
1008
    ifr.ifr_flags |= IFF_UP;
1009
    if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1010
	syslog(LOG_ERR, "Couldn't mark interface up (set): %m");
1011
	return 0;
1012
    }
1013
    if_is_up = 1;
1014
    return 1;
1015
}
1016
1017
/*
1018
 * sifdown - Config the interface down and disable IP.
1019
 */
1020
int
1021
sifdown(u)
1022
    int u;
1023
{
1024
    struct ifreq ifr;
1025
1026
    if (ipmuxid < 0)
1027
	return 1;
1028
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1029
    if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
1030
	syslog(LOG_ERR, "Couldn't mark interface down (get): %m");
1031
	return 0;
1032
    }
1033
    ifr.ifr_flags &= ~IFF_UP;
1034
    if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1035
	syslog(LOG_ERR, "Couldn't mark interface down (set): %m");
1036
	return 0;
1037
    }
1038
    if_is_up = 0;
1039
    return 1;
1040
}
1041
1042
/*
1043
 * sifnpmode - Set the mode for handling packets for a given NP.
1044
 */
1045
int
1046
sifnpmode(u, proto, mode)
1047
    int u;
1048
    int proto;
1049
    enum NPmode mode;
1050
{
1051
    int npi[2];
1052
1053
    npi[0] = proto;
1054
    npi[1] = (int) mode;
1055
    if (strioctl(pppfd, PPPIO_NPMODE, &npi, 2 * sizeof(int), 0) < 0) {
1056
	syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
1057
	return 0;
1058
    }
1059
    return 1;
1060
}
1061
1062
#define INET_ADDR(x)	(((struct sockaddr_in *) &(x))->sin_addr.s_addr)
1063
1064
/*
1065
 * sifaddr - Config the interface IP addresses and netmask.
1066
 */
1067
int
1068
sifaddr(u, o, h, m)
1069
    int u;
1070
    u_int32_t o, h, m;
1071
{
1072
    struct ifreq ifr;
1073
    int ret = 1;
1074
1075
    memset(&ifr, 0, sizeof(ifr));
1076
    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1077
    ifr.ifr_addr.sa_family = AF_INET;
1078
    INET_ADDR(ifr.ifr_addr) = m;
1079
    if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
1080
	syslog(LOG_ERR, "Couldn't set IP netmask: %m");
1081
	ret = 0;
1082
    }
1083
    ifr.ifr_addr.sa_family = AF_INET;
1084
    INET_ADDR(ifr.ifr_addr) = o;
1085
    if (ioctl(ipfd, SIOCSIFADDR, &ifr) < 0) {
1086
	syslog(LOG_ERR, "Couldn't set local IP address: %m");
1087
	ret = 0;
1088
    }
1089
1090
    /*
1091
     * On some systems, we have to explicitly set the point-to-point
1092
     * flag bit before we can set a destination address.
1093
     */
1094
    if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) >= 0
1095
	&& (ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
1096
	ifr.ifr_flags |= IFF_POINTOPOINT;
1097
	if (ioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) {
1098
	    syslog(LOG_ERR, "Couldn't mark interface pt-to-pt: %m");
1099
	    ret = 0;
1100
	}
1101
    }
1102
    ifr.ifr_dstaddr.sa_family = AF_INET;
1103
    INET_ADDR(ifr.ifr_dstaddr) = h;
1104
    if (ioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) {
1105
	syslog(LOG_ERR, "Couldn't set remote IP address: %m");
1106
	ret = 0;
1107
    }
1108
#if 0	/* now done in ppp_send_config */
1109
    ifr.ifr_metric = link_mtu;
1110
    if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
1111
	syslog(LOG_ERR, "Couldn't set IP MTU: %m");
1112
    }
1113
#endif
1114
1115
    return ret;
1116
}
1117
1118
/*
1119
 * cifaddr - Clear the interface IP addresses, and delete routes
1120
 * through the interface if possible.
1121
 */
1122
int
1123
cifaddr(u, o, h)
1124
    int u;
1125
    u_int32_t o, h;
1126
{
1127
#if defined(__USLC__)		/* was: #if 0 */
1128
    cifroute(unit, ouraddr, hisaddr);
1129
    if (ipmuxid >= 0) {
1130
	syslog(LOG_NOTICE, "Removing ppp interface unit");
1131
	if (ioctl(ipfd, I_UNLINK, ipmuxid) < 0) {
1132
	    syslog(LOG_ERR, "Can't remove ppp interface unit: %m");
1133
	    return 0;
1134
	}
1135
	ipmuxid = -1;
1136
    }
1137
#endif
1138
    return 1;
1139
}
1140
1141
/*
1142
 * sifdefaultroute - assign a default route through the address given.
1143
 */
1144
int
1145
sifdefaultroute(u, l, g)
1146
    int u;
1147
    u_int32_t l, g;
1148
{
1149
    struct rtentry rt;
1150
1151
#if defined(__USLC__)
1152
    g = l;			/* use the local address as gateway */
1153
#endif
1154
    memset(&rt, 0, sizeof(rt));
1155
    rt.rt_dst.sa_family = AF_INET;
1156
    INET_ADDR(rt.rt_dst) = 0;
1157
    rt.rt_gateway.sa_family = AF_INET;
1158
    INET_ADDR(rt.rt_gateway) = g;
1159
    rt.rt_flags = RTF_GATEWAY;
1160
1161
    if (ioctl(ipfd, SIOCADDRT, &rt) < 0) {
1162
	syslog(LOG_ERR, "Can't add default route: %m");
1163
	return 0;
1164
    }
1165
1166
    default_route_gateway = g;
1167
    return 1;
1168
}
1169
1170
/*
1171
 * cifdefaultroute - delete a default route through the address given.
1172
 */
1173
int
1174
cifdefaultroute(u, l, g)
1175
    int u;
1176
    u_int32_t l, g;
1177
{
1178
    struct rtentry rt;
1179
1180
#if defined(__USLC__)
1181
    g = l;			/* use the local address as gateway */
1182
#endif
1183
    memset(&rt, 0, sizeof(rt));
1184
    rt.rt_dst.sa_family = AF_INET;
1185
    INET_ADDR(rt.rt_dst) = 0;
1186
    rt.rt_gateway.sa_family = AF_INET;
1187
    INET_ADDR(rt.rt_gateway) = g;
1188
    rt.rt_flags = RTF_GATEWAY;
1189
1190
    if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
1191
	syslog(LOG_ERR, "Can't delete default route: %m");
1192
	return 0;
1193
    }
1194
1195
    default_route_gateway = 0;
1196
    return 1;
1197
}
1198
1199
/*
1200
 * sifproxyarp - Make a proxy ARP entry for the peer.
1201
 */
1202
int
1203
sifproxyarp(unit, hisaddr)
1204
    int unit;
1205
    u_int32_t hisaddr;
1206
{
1207
    struct arpreq arpreq;
1208
1209
    memset(&arpreq, 0, sizeof(arpreq));
1210
    if (!get_ether_addr(hisaddr, &arpreq.arp_ha))
1211
	return 0;
1212
1213
    arpreq.arp_pa.sa_family = AF_INET;
1214
    INET_ADDR(arpreq.arp_pa) = hisaddr;
1215
    arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1216
    if (ioctl(ipfd, SIOCSARP, (caddr_t) &arpreq) < 0) {
1217
	syslog(LOG_ERR, "Couldn't set proxy ARP entry: %m");
1218
	return 0;
1219
    }
1220
1221
    proxy_arp_addr = hisaddr;
1222
    return 1;
1223
}
1224
1225
/*
1226
 * cifproxyarp - Delete the proxy ARP entry for the peer.
1227
 */
1228
int
1229
cifproxyarp(unit, hisaddr)
1230
    int unit;
1231
    u_int32_t hisaddr;
1232
{
1233
    struct arpreq arpreq;
1234
1235
    memset(&arpreq, 0, sizeof(arpreq));
1236
    arpreq.arp_pa.sa_family = AF_INET;
1237
    INET_ADDR(arpreq.arp_pa) = hisaddr;
1238
    if (ioctl(ipfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1239
	syslog(LOG_ERR, "Couldn't delete proxy ARP entry: %m");
1240
	return 0;
1241
    }
1242
1243
    proxy_arp_addr = 0;
1244
    return 1;
1245
}
1246
1247
/*
1248
 * get_ether_addr - get the hardware address of an interface on the
1249
 * the same subnet as ipaddr.
1250
 */
1251
#define MAX_IFS		32
1252
1253
static int
1254
get_ether_addr(ipaddr, hwaddr)
1255
    u_int32_t ipaddr;
1256
    struct sockaddr *hwaddr;
1257
{
1258
    struct ifreq *ifr, *ifend, ifreq;
1259
    int nif;
1260
    struct ifconf ifc;
1261
    u_int32_t ina, mask;
1262
1263
    /*
1264
     * Scan through the system's network interfaces.
1265
     */
1266
#ifdef SIOCGIFNUM
1267
    if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
1268
#endif
1269
	nif = MAX_IFS;
1270
    ifc.ifc_len = nif * sizeof(struct ifreq);
1271
    ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
1272
    if (ifc.ifc_buf == 0)
1273
	return 0;
1274
    if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
1275
	syslog(LOG_WARNING, "Couldn't get system interface list: %m");
1276
	free(ifc.ifc_buf);
1277
	return 0;
1278
    }
1279
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1280
    for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1281
	if (ifr->ifr_addr.sa_family != AF_INET)
1282
	    continue;
1283
	/*
1284
	 * Check that the interface is up, and not point-to-point or loopback.
1285
	 */
1286
	strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1287
	if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
1288
	    continue;
1289
	if ((ifreq.ifr_flags &
1290
	     (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1291
	    != (IFF_UP|IFF_BROADCAST))
1292
	    continue;
1293
	/*
1294
	 * Get its netmask and check that it's on the right subnet.
1295
	 */
1296
	if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
1297
	    continue;
1298
	ina = INET_ADDR(ifr->ifr_addr);
1299
	mask = INET_ADDR(ifreq.ifr_addr);
1300
	if ((ipaddr & mask) == (ina & mask))
1301
	    break;
1302
    }
1303
1304
    if (ifr >= ifend) {
1305
	syslog(LOG_WARNING, "No suitable interface found for proxy ARP");
1306
	free(ifc.ifc_buf);
1307
	return 0;
1308
    }
1309
1310
    syslog(LOG_INFO, "found interface %s for proxy ARP", ifr->ifr_name);
1311
    if (!get_hw_addr(ifr->ifr_name, hwaddr)) {
1312
	syslog(LOG_ERR, "Couldn't get hardware address for %s", ifr->ifr_name);
1313
	free(ifc.ifc_buf);
1314
	return 0;
1315
    }
1316
1317
    free(ifc.ifc_buf);
1318
    return 1;
1319
}
1320
1321
/*
1322
 * get_hw_addr - obtain the hardware address for a named interface.
1323
 */
1324
static int
1325
get_hw_addr(name, hwaddr)
1326
    char *name;
1327
    struct sockaddr *hwaddr;
1328
{
1329
    char *p, *q;
1330
    int unit, iffd, adrlen;
1331
    unsigned char *adrp;
1332
    char ifdev[24];
1333
    struct {
1334
	union DL_primitives prim;
1335
	char space[64];
1336
    } reply;
1337
1338
    /*
1339
     * We have to open the device and ask it for its hardware address.
1340
     * First split apart the device name and unit.
1341
     */
1342
    strcpy(ifdev, "/dev/");
1343
    q = ifdev + 5;		/* strlen("/dev/") */
1344
    while (*name != 0 && !isdigit(*name))
1345
	*q++ = *name++;
1346
    *q = 0;
1347
    unit = atoi(name);
1348
1349
    /*
1350
     * Open the device and do a DLPI attach and phys_addr_req.
1351
     */
1352
    iffd = open(ifdev, O_RDWR);
1353
    if (iffd < 0) {
1354
	syslog(LOG_ERR, "Can't open %s: %m", ifdev);
1355
	return 0;
1356
    }
1357
    if (dlpi_attach(iffd, unit) < 0
1358
	|| dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0
1359
	|| dlpi_info_req(iffd) < 0
1360
	|| dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) {
1361
	close(iffd);
1362
	return 0;
1363
    }
1364
1365
    adrlen = reply.prim.info_ack.dl_addr_length;
1366
    adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;
1367
#if DL_CURRENT_VERSION >= 2
1368
    if (reply.prim.info_ack.dl_sap_length < 0)
1369
	adrlen += reply.prim.info_ack.dl_sap_length;
1370
    else
1371
	adrp += reply.prim.info_ack.dl_sap_length;
1372
#endif
1373
    hwaddr->sa_family = AF_UNSPEC;
1374
    memcpy(hwaddr->sa_data, adrp, adrlen);
1375
1376
    return 1;
1377
}
1378
1379
static int
1380
dlpi_attach(fd, ppa)
1381
    int fd, ppa;
1382
{
1383
    dl_attach_req_t req;
1384
    struct strbuf buf;
1385
1386
    req.dl_primitive = DL_ATTACH_REQ;
1387
    req.dl_ppa = ppa;
1388
    buf.len = sizeof(req);
1389
    buf.buf = (void *) &req;
1390
    return putmsg(fd, &buf, NULL, RS_HIPRI);
1391
}
1392
1393
static int
1394
dlpi_info_req(fd)
1395
    int fd;
1396
{
1397
    dl_info_req_t req;
1398
    struct strbuf buf;
1399
1400
    req.dl_primitive = DL_INFO_REQ;
1401
    buf.len = sizeof(req);
1402
    buf.buf = (void *) &req;
1403
    return putmsg(fd, &buf, NULL, RS_HIPRI);
1404
}
1405
1406
static int
1407
dlpi_get_reply(fd, reply, expected_prim, maxlen)
1408
    union DL_primitives *reply;
1409
    int fd, expected_prim, maxlen;
1410
{
1411
    struct strbuf buf;
1412
    int flags, n;
1413
    struct pollfd pfd;
1414
1415
    /*
1416
     * Use poll to wait for a message with a timeout.
1417
     */
1418
    pfd.fd = fd;
1419
    pfd.events = POLLIN | POLLPRI;
1420
    do {
1421
	n = poll(&pfd, 1, 1000);
1422
    } while (n == -1 && errno == EINTR);
1423
    if (n <= 0)
1424
	return -1;
1425
1426
    /*
1427
     * Get the reply.
1428
     */
1429
    buf.maxlen = maxlen;
1430
    buf.buf = (void *) reply;
1431
    flags = 0;
1432
    if (getmsg(fd, &buf, NULL, &flags) < 0)
1433
	return -1;
1434
1435
    if (buf.len < sizeof(ulong)) {
1436
	if (debug)
1437
	    syslog(LOG_DEBUG, "dlpi response short (len=%d)\n", buf.len);
1438
	return -1;
1439
    }
1440
1441
    if (reply->dl_primitive == expected_prim)
1442
	return 0;
1443
1444
    if (debug) {
1445
	if (reply->dl_primitive == DL_ERROR_ACK) {
1446
	    syslog(LOG_DEBUG, "dlpi error %d (unix errno %d) for prim %x\n",
1447
		   reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno,
1448
		   reply->error_ack.dl_error_primitive);
1449
	} else {
1450
	    syslog(LOG_DEBUG, "dlpi unexpected response prim %x\n",
1451
		   reply->dl_primitive);
1452
	}
1453
    }
1454
1455
    return -1;
1456
}
1457
1458
/*
1459
 * Return user specified netmask, modified by any mask we might determine
1460
 * for address `addr' (in network byte order).
1461
 * Here we scan through the system's list of interfaces, looking for
1462
 * any non-point-to-point interfaces which might appear to be on the same
1463
 * network as `addr'.  If we find any, we OR in their netmask to the
1464
 * user-specified netmask.
1465
 */
1466
u_int32_t
1467
GetMask(addr)
1468
    u_int32_t addr;
1469
{
1470
    u_int32_t mask, nmask, ina;
1471
    struct ifreq *ifr, *ifend, ifreq;
1472
    int nif;
1473
    struct ifconf ifc;
1474
1475
    addr = ntohl(addr);
1476
    if (IN_CLASSA(addr))	/* determine network mask for address class */
1477
	nmask = IN_CLASSA_NET;
1478
    else if (IN_CLASSB(addr))
1479
	nmask = IN_CLASSB_NET;
1480
    else
1481
	nmask = IN_CLASSC_NET;
1482
    /* class D nets are disallowed by bad_ip_adrs */
1483
    mask = netmask | htonl(nmask);
1484
1485
    /*
1486
     * Scan through the system's network interfaces.
1487
     */
1488
#ifdef SIOCGIFNUM
1489
    if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)
1490
#endif
1491
	nif = MAX_IFS;
1492
    ifc.ifc_len = nif * sizeof(struct ifreq);
1493
    ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len);
1494
    if (ifc.ifc_buf == 0)
1495
	return mask;
1496
    if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) {
1497
	syslog(LOG_WARNING, "Couldn't get system interface list: %m");
1498
	free(ifc.ifc_buf);
1499
	return mask;
1500
    }
1501
    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1502
    for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1503
	/*
1504
	 * Check the interface's internet address.
1505
	 */
1506
	if (ifr->ifr_addr.sa_family != AF_INET)
1507
	    continue;
1508
	ina = INET_ADDR(ifr->ifr_addr);
1509
	if ((ntohl(ina) & nmask) != (addr & nmask))
1510
	    continue;
1511
	/*
1512
	 * Check that the interface is up, and not point-to-point or loopback.
1513
	 */
1514
	strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1515
	if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
1516
	    continue;
1517
	if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1518
	    != IFF_UP)
1519
	    continue;
1520
	/*
1521
	 * Get its netmask and OR it into our mask.
1522
	 */
1523
	if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0)
1524
	    continue;
1525
	mask |= INET_ADDR(ifreq.ifr_addr);
1526
    }
1527
1528
    free(ifc.ifc_buf);
1529
    return mask;
1530
}
1531
1532
/*
1533
 * logwtmp - write an accounting record to the /var/adm/wtmp file.
1534
 */
1535
void
1536
logwtmp(line, name, host)
1537
    const char *line, *name, *host;
1538
{
1539
    static struct utmpx utmpx;
1540
1541
    if (name[0] != 0) {
1542
	/* logging in */
1543
	strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
1544
	strncpy(utmpx.ut_id, ifname, sizeof(utmpx.ut_id));
1545
	strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
1546
	utmpx.ut_pid = getpid();
1547
	utmpx.ut_type = USER_PROCESS;
1548
    } else {
1549
	utmpx.ut_type = DEAD_PROCESS;
1550
    }
1551
    gettimeofday(&utmpx.ut_tv, NULL);
1552
    updwtmpx("/var/adm/wtmpx", &utmpx);
1553
}
1554
1555
/*
1556
 * get_host_seed - return the serial number of this machine.
1557
 */
1558
int
1559
get_host_seed()
1560
{
1561
    char buf[32];
1562
1563
    if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) {
1564
	syslog(LOG_ERR, "sysinfo: %m");
1565
	return 0;
1566
    }
1567
    return (int) strtoul(buf, NULL, 16);
1568
}
1569
1570
static int
1571
strioctl(fd, cmd, ptr, ilen, olen)
1572
    int fd, cmd, ilen, olen;
1573
    void *ptr;
1574
{
1575
    struct strioctl str;
1576
1577
    str.ic_cmd = cmd;
1578
    str.ic_timout = 0;
1579
    str.ic_len = ilen;
1580
    str.ic_dp = ptr;
1581
    if (ioctl(fd, I_STR, &str) == -1)
1582
	return -1;
1583
    if (str.ic_len != olen)
1584
	syslog(LOG_DEBUG, "strioctl: expected %d bytes, got %d for cmd %x\n",
1585
	       olen, str.ic_len, cmd);
1586
    return 0;
1587
}
1588
1589
/*
1590
 * lock - create a lock file for the named lock device
1591
 */
1592
1593
#define LOCK_PREFIX	"/var/spool/locks/LK."
1594
static char lock_file[40];	/* name of lock file created */
1595
1596
int
1597
lock(dev)
1598
    char *dev;
1599
{
1600
    int n, fd, pid;
1601
    struct stat sbuf;
1602
    char ascii_pid[12];
1603
1604
    if (stat(dev, &sbuf) < 0) {
1605
	syslog(LOG_ERR, "Can't get device number for %s: %m", dev);
1606
	return -1;
1607
    }
1608
    if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
1609
	syslog(LOG_ERR, "Can't lock %s: not a character device", dev);
1610
	return -1;
1611
    }
1612
    sprintf(lock_file, "%s%03d.%03d.%03d", LOCK_PREFIX, major(sbuf.st_dev),
1613
	    major(sbuf.st_rdev), minor(sbuf.st_rdev));
1614
1615
    while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1616
	if (errno == EEXIST
1617
	    && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1618
	    /* Read the lock file to find out who has the device locked */
1619
	    n = read(fd, ascii_pid, 11);
1620
	    if (n <= 0) {
1621
		syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1622
		close(fd);
1623
	    } else {
1624
		ascii_pid[n] = 0;
1625
		pid = atoi(ascii_pid);
1626
		if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) {
1627
		    /* pid no longer exists - remove the lock file */
1628
		    if (unlink(lock_file) == 0) {
1629
			close(fd);
1630
			syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1631
			       dev, pid);
1632
			continue;
1633
		    } else
1634
			syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1635
			       dev);
1636
		} else
1637
		    syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1638
			   dev, pid);
1639
	    }
1640
	    close(fd);
1641
	} else
1642
	    syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1643
	lock_file[0] = 0;
1644
	return -1;
1645
    }
1646
1647
    sprintf(ascii_pid, "%10d\n", getpid());
1648
    write(fd, ascii_pid, 11);
1649
1650
    close(fd);
1651
    return 1;
1652
}
1653
1654
/*
1655
 * unlock - remove our lockfile
1656
 */
1657
void
1658
unlock()
1659
{
1660
    if (lock_file[0]) {
1661
	unlink(lock_file);
1662
	lock_file[0] = 0;
1663
    }
1664
}
1665
1666
1667
/*
1668
 * cifroute - delete a route through the addresses given.
1669
 */
1670
int
1671
cifroute(u, our, his)
1672
    int u;
1673
    u_int32_t our, his;
1674
{
1675
    struct rtentry rt;
1676
1677
    memset(&rt, 0, sizeof(rt));
1678
    rt.rt_dst.sa_family = AF_INET;
1679
    INET_ADDR(rt.rt_dst) = his;
1680
    rt.rt_gateway.sa_family = AF_INET;
1681
    INET_ADDR(rt.rt_gateway) = our;
1682
    rt.rt_flags = RTF_HOST;
1683
1684
    if (ioctl(ipfd, SIOCDELRT, &rt) < 0) {
1685
	syslog(LOG_ERR, "Can't delete route: %m");
1686
	return 0;
1687
    }
1688
1689
    return 1;
1690
}

Return to bug 15619