1*5d5fbe79SDavid van Moolenbroek /*
2*5d5fbe79SDavid van Moolenbroek * utils.c - various utility functions used in pppd.
3*5d5fbe79SDavid van Moolenbroek *
4*5d5fbe79SDavid van Moolenbroek * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved.
5*5d5fbe79SDavid van Moolenbroek *
6*5d5fbe79SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
7*5d5fbe79SDavid van Moolenbroek * modification, are permitted provided that the following conditions
8*5d5fbe79SDavid van Moolenbroek * are met:
9*5d5fbe79SDavid van Moolenbroek *
10*5d5fbe79SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*5d5fbe79SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
12*5d5fbe79SDavid van Moolenbroek *
13*5d5fbe79SDavid van Moolenbroek * 2. The name(s) of the authors of this software must not be used to
14*5d5fbe79SDavid van Moolenbroek * endorse or promote products derived from this software without
15*5d5fbe79SDavid van Moolenbroek * prior written permission.
16*5d5fbe79SDavid van Moolenbroek *
17*5d5fbe79SDavid van Moolenbroek * 3. Redistributions of any form whatsoever must retain the following
18*5d5fbe79SDavid van Moolenbroek * acknowledgment:
19*5d5fbe79SDavid van Moolenbroek * "This product includes software developed by Paul Mackerras
20*5d5fbe79SDavid van Moolenbroek * <paulus@samba.org>".
21*5d5fbe79SDavid van Moolenbroek *
22*5d5fbe79SDavid van Moolenbroek * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23*5d5fbe79SDavid van Moolenbroek * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24*5d5fbe79SDavid van Moolenbroek * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25*5d5fbe79SDavid van Moolenbroek * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26*5d5fbe79SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27*5d5fbe79SDavid van Moolenbroek * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28*5d5fbe79SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29*5d5fbe79SDavid van Moolenbroek */
30*5d5fbe79SDavid van Moolenbroek
31*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/ppp_opts.h"
32*5d5fbe79SDavid van Moolenbroek #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
33*5d5fbe79SDavid van Moolenbroek
34*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
35*5d5fbe79SDavid van Moolenbroek #include <stdio.h>
36*5d5fbe79SDavid van Moolenbroek #include <ctype.h>
37*5d5fbe79SDavid van Moolenbroek #include <stdlib.h>
38*5d5fbe79SDavid van Moolenbroek #include <string.h>
39*5d5fbe79SDavid van Moolenbroek #include <unistd.h>
40*5d5fbe79SDavid van Moolenbroek #include <signal.h>
41*5d5fbe79SDavid van Moolenbroek #include <errno.h>
42*5d5fbe79SDavid van Moolenbroek #include <fcntl.h>
43*5d5fbe79SDavid van Moolenbroek #include <syslog.h>
44*5d5fbe79SDavid van Moolenbroek #include <netdb.h>
45*5d5fbe79SDavid van Moolenbroek #include <time.h>
46*5d5fbe79SDavid van Moolenbroek #include <utmp.h>
47*5d5fbe79SDavid van Moolenbroek #include <pwd.h>
48*5d5fbe79SDavid van Moolenbroek #include <sys/param.h>
49*5d5fbe79SDavid van Moolenbroek #include <sys/types.h>
50*5d5fbe79SDavid van Moolenbroek #include <sys/wait.h>
51*5d5fbe79SDavid van Moolenbroek #include <sys/time.h>
52*5d5fbe79SDavid van Moolenbroek #include <sys/resource.h>
53*5d5fbe79SDavid van Moolenbroek #include <sys/stat.h>
54*5d5fbe79SDavid van Moolenbroek #include <sys/socket.h>
55*5d5fbe79SDavid van Moolenbroek #include <netinet/in.h>
56*5d5fbe79SDavid van Moolenbroek #ifdef SVR4
57*5d5fbe79SDavid van Moolenbroek #include <sys/mkdev.h>
58*5d5fbe79SDavid van Moolenbroek #endif
59*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
60*5d5fbe79SDavid van Moolenbroek
61*5d5fbe79SDavid van Moolenbroek #include <ctype.h> /* isdigit() */
62*5d5fbe79SDavid van Moolenbroek
63*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/ppp_impl.h"
64*5d5fbe79SDavid van Moolenbroek
65*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/fsm.h"
66*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/lcp.h"
67*5d5fbe79SDavid van Moolenbroek
68*5d5fbe79SDavid van Moolenbroek #if defined(SUNOS4)
69*5d5fbe79SDavid van Moolenbroek extern char *strerror();
70*5d5fbe79SDavid van Moolenbroek #endif
71*5d5fbe79SDavid van Moolenbroek
72*5d5fbe79SDavid van Moolenbroek static void ppp_logit(int level, const char *fmt, va_list args);
73*5d5fbe79SDavid van Moolenbroek static void ppp_log_write(int level, char *buf);
74*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
75*5d5fbe79SDavid van Moolenbroek static void ppp_vslp_printer(void *arg, const char *fmt, ...);
76*5d5fbe79SDavid van Moolenbroek static void ppp_format_packet(const u_char *p, int len,
77*5d5fbe79SDavid van Moolenbroek void (*printer) (void *, const char *, ...), void *arg);
78*5d5fbe79SDavid van Moolenbroek
79*5d5fbe79SDavid van Moolenbroek struct buffer_info {
80*5d5fbe79SDavid van Moolenbroek char *ptr;
81*5d5fbe79SDavid van Moolenbroek int len;
82*5d5fbe79SDavid van Moolenbroek };
83*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
84*5d5fbe79SDavid van Moolenbroek
85*5d5fbe79SDavid van Moolenbroek /*
86*5d5fbe79SDavid van Moolenbroek * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
87*5d5fbe79SDavid van Moolenbroek * always leaves destination null-terminated (for len > 0).
88*5d5fbe79SDavid van Moolenbroek */
ppp_strlcpy(char * dest,const char * src,size_t len)89*5d5fbe79SDavid van Moolenbroek size_t ppp_strlcpy(char *dest, const char *src, size_t len) {
90*5d5fbe79SDavid van Moolenbroek size_t ret = strlen(src);
91*5d5fbe79SDavid van Moolenbroek
92*5d5fbe79SDavid van Moolenbroek if (len != 0) {
93*5d5fbe79SDavid van Moolenbroek if (ret < len)
94*5d5fbe79SDavid van Moolenbroek strcpy(dest, src);
95*5d5fbe79SDavid van Moolenbroek else {
96*5d5fbe79SDavid van Moolenbroek strncpy(dest, src, len - 1);
97*5d5fbe79SDavid van Moolenbroek dest[len-1] = 0;
98*5d5fbe79SDavid van Moolenbroek }
99*5d5fbe79SDavid van Moolenbroek }
100*5d5fbe79SDavid van Moolenbroek return ret;
101*5d5fbe79SDavid van Moolenbroek }
102*5d5fbe79SDavid van Moolenbroek
103*5d5fbe79SDavid van Moolenbroek /*
104*5d5fbe79SDavid van Moolenbroek * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer,
105*5d5fbe79SDavid van Moolenbroek * always leaves destination null-terminated (for len > 0).
106*5d5fbe79SDavid van Moolenbroek */
ppp_strlcat(char * dest,const char * src,size_t len)107*5d5fbe79SDavid van Moolenbroek size_t ppp_strlcat(char *dest, const char *src, size_t len) {
108*5d5fbe79SDavid van Moolenbroek size_t dlen = strlen(dest);
109*5d5fbe79SDavid van Moolenbroek
110*5d5fbe79SDavid van Moolenbroek return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
111*5d5fbe79SDavid van Moolenbroek }
112*5d5fbe79SDavid van Moolenbroek
113*5d5fbe79SDavid van Moolenbroek
114*5d5fbe79SDavid van Moolenbroek /*
115*5d5fbe79SDavid van Moolenbroek * ppp_slprintf - format a message into a buffer. Like sprintf except we
116*5d5fbe79SDavid van Moolenbroek * also specify the length of the output buffer, and we handle
117*5d5fbe79SDavid van Moolenbroek * %m (error message), %v (visible string),
118*5d5fbe79SDavid van Moolenbroek * %q (quoted string), %t (current time) and %I (IP address) formats.
119*5d5fbe79SDavid van Moolenbroek * Doesn't do floating-point formats.
120*5d5fbe79SDavid van Moolenbroek * Returns the number of chars put into buf.
121*5d5fbe79SDavid van Moolenbroek */
ppp_slprintf(char * buf,int buflen,const char * fmt,...)122*5d5fbe79SDavid van Moolenbroek int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) {
123*5d5fbe79SDavid van Moolenbroek va_list args;
124*5d5fbe79SDavid van Moolenbroek int n;
125*5d5fbe79SDavid van Moolenbroek
126*5d5fbe79SDavid van Moolenbroek va_start(args, fmt);
127*5d5fbe79SDavid van Moolenbroek n = ppp_vslprintf(buf, buflen, fmt, args);
128*5d5fbe79SDavid van Moolenbroek va_end(args);
129*5d5fbe79SDavid van Moolenbroek return n;
130*5d5fbe79SDavid van Moolenbroek }
131*5d5fbe79SDavid van Moolenbroek
132*5d5fbe79SDavid van Moolenbroek /*
133*5d5fbe79SDavid van Moolenbroek * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args.
134*5d5fbe79SDavid van Moolenbroek */
135*5d5fbe79SDavid van Moolenbroek #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
136*5d5fbe79SDavid van Moolenbroek
ppp_vslprintf(char * buf,int buflen,const char * fmt,va_list args)137*5d5fbe79SDavid van Moolenbroek int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) {
138*5d5fbe79SDavid van Moolenbroek int c, i, n;
139*5d5fbe79SDavid van Moolenbroek int width, prec, fillch;
140*5d5fbe79SDavid van Moolenbroek int base, len, neg, quoted;
141*5d5fbe79SDavid van Moolenbroek unsigned long val = 0;
142*5d5fbe79SDavid van Moolenbroek const char *f;
143*5d5fbe79SDavid van Moolenbroek char *str, *buf0;
144*5d5fbe79SDavid van Moolenbroek const unsigned char *p;
145*5d5fbe79SDavid van Moolenbroek char num[32];
146*5d5fbe79SDavid van Moolenbroek #if 0 /* need port */
147*5d5fbe79SDavid van Moolenbroek time_t t;
148*5d5fbe79SDavid van Moolenbroek #endif /* need port */
149*5d5fbe79SDavid van Moolenbroek u32_t ip;
150*5d5fbe79SDavid van Moolenbroek static char hexchars[] = "0123456789abcdef";
151*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
152*5d5fbe79SDavid van Moolenbroek struct buffer_info bufinfo;
153*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
154*5d5fbe79SDavid van Moolenbroek
155*5d5fbe79SDavid van Moolenbroek buf0 = buf;
156*5d5fbe79SDavid van Moolenbroek --buflen;
157*5d5fbe79SDavid van Moolenbroek while (buflen > 0) {
158*5d5fbe79SDavid van Moolenbroek for (f = fmt; *f != '%' && *f != 0; ++f)
159*5d5fbe79SDavid van Moolenbroek ;
160*5d5fbe79SDavid van Moolenbroek if (f > fmt) {
161*5d5fbe79SDavid van Moolenbroek len = f - fmt;
162*5d5fbe79SDavid van Moolenbroek if (len > buflen)
163*5d5fbe79SDavid van Moolenbroek len = buflen;
164*5d5fbe79SDavid van Moolenbroek memcpy(buf, fmt, len);
165*5d5fbe79SDavid van Moolenbroek buf += len;
166*5d5fbe79SDavid van Moolenbroek buflen -= len;
167*5d5fbe79SDavid van Moolenbroek fmt = f;
168*5d5fbe79SDavid van Moolenbroek }
169*5d5fbe79SDavid van Moolenbroek if (*fmt == 0)
170*5d5fbe79SDavid van Moolenbroek break;
171*5d5fbe79SDavid van Moolenbroek c = *++fmt;
172*5d5fbe79SDavid van Moolenbroek width = 0;
173*5d5fbe79SDavid van Moolenbroek prec = -1;
174*5d5fbe79SDavid van Moolenbroek fillch = ' ';
175*5d5fbe79SDavid van Moolenbroek if (c == '0') {
176*5d5fbe79SDavid van Moolenbroek fillch = '0';
177*5d5fbe79SDavid van Moolenbroek c = *++fmt;
178*5d5fbe79SDavid van Moolenbroek }
179*5d5fbe79SDavid van Moolenbroek if (c == '*') {
180*5d5fbe79SDavid van Moolenbroek width = va_arg(args, int);
181*5d5fbe79SDavid van Moolenbroek c = *++fmt;
182*5d5fbe79SDavid van Moolenbroek } else {
183*5d5fbe79SDavid van Moolenbroek while (isdigit(c)) {
184*5d5fbe79SDavid van Moolenbroek width = width * 10 + c - '0';
185*5d5fbe79SDavid van Moolenbroek c = *++fmt;
186*5d5fbe79SDavid van Moolenbroek }
187*5d5fbe79SDavid van Moolenbroek }
188*5d5fbe79SDavid van Moolenbroek if (c == '.') {
189*5d5fbe79SDavid van Moolenbroek c = *++fmt;
190*5d5fbe79SDavid van Moolenbroek if (c == '*') {
191*5d5fbe79SDavid van Moolenbroek prec = va_arg(args, int);
192*5d5fbe79SDavid van Moolenbroek c = *++fmt;
193*5d5fbe79SDavid van Moolenbroek } else {
194*5d5fbe79SDavid van Moolenbroek prec = 0;
195*5d5fbe79SDavid van Moolenbroek while (isdigit(c)) {
196*5d5fbe79SDavid van Moolenbroek prec = prec * 10 + c - '0';
197*5d5fbe79SDavid van Moolenbroek c = *++fmt;
198*5d5fbe79SDavid van Moolenbroek }
199*5d5fbe79SDavid van Moolenbroek }
200*5d5fbe79SDavid van Moolenbroek }
201*5d5fbe79SDavid van Moolenbroek str = 0;
202*5d5fbe79SDavid van Moolenbroek base = 0;
203*5d5fbe79SDavid van Moolenbroek neg = 0;
204*5d5fbe79SDavid van Moolenbroek ++fmt;
205*5d5fbe79SDavid van Moolenbroek switch (c) {
206*5d5fbe79SDavid van Moolenbroek case 'l':
207*5d5fbe79SDavid van Moolenbroek c = *fmt++;
208*5d5fbe79SDavid van Moolenbroek switch (c) {
209*5d5fbe79SDavid van Moolenbroek case 'd':
210*5d5fbe79SDavid van Moolenbroek val = va_arg(args, long);
211*5d5fbe79SDavid van Moolenbroek if ((long)val < 0) {
212*5d5fbe79SDavid van Moolenbroek neg = 1;
213*5d5fbe79SDavid van Moolenbroek val = (unsigned long)-(long)val;
214*5d5fbe79SDavid van Moolenbroek }
215*5d5fbe79SDavid van Moolenbroek base = 10;
216*5d5fbe79SDavid van Moolenbroek break;
217*5d5fbe79SDavid van Moolenbroek case 'u':
218*5d5fbe79SDavid van Moolenbroek val = va_arg(args, unsigned long);
219*5d5fbe79SDavid van Moolenbroek base = 10;
220*5d5fbe79SDavid van Moolenbroek break;
221*5d5fbe79SDavid van Moolenbroek default:
222*5d5fbe79SDavid van Moolenbroek OUTCHAR('%');
223*5d5fbe79SDavid van Moolenbroek OUTCHAR('l');
224*5d5fbe79SDavid van Moolenbroek --fmt; /* so %lz outputs %lz etc. */
225*5d5fbe79SDavid van Moolenbroek continue;
226*5d5fbe79SDavid van Moolenbroek }
227*5d5fbe79SDavid van Moolenbroek break;
228*5d5fbe79SDavid van Moolenbroek case 'd':
229*5d5fbe79SDavid van Moolenbroek i = va_arg(args, int);
230*5d5fbe79SDavid van Moolenbroek if (i < 0) {
231*5d5fbe79SDavid van Moolenbroek neg = 1;
232*5d5fbe79SDavid van Moolenbroek val = -i;
233*5d5fbe79SDavid van Moolenbroek } else
234*5d5fbe79SDavid van Moolenbroek val = i;
235*5d5fbe79SDavid van Moolenbroek base = 10;
236*5d5fbe79SDavid van Moolenbroek break;
237*5d5fbe79SDavid van Moolenbroek case 'u':
238*5d5fbe79SDavid van Moolenbroek val = va_arg(args, unsigned int);
239*5d5fbe79SDavid van Moolenbroek base = 10;
240*5d5fbe79SDavid van Moolenbroek break;
241*5d5fbe79SDavid van Moolenbroek case 'o':
242*5d5fbe79SDavid van Moolenbroek val = va_arg(args, unsigned int);
243*5d5fbe79SDavid van Moolenbroek base = 8;
244*5d5fbe79SDavid van Moolenbroek break;
245*5d5fbe79SDavid van Moolenbroek case 'x':
246*5d5fbe79SDavid van Moolenbroek case 'X':
247*5d5fbe79SDavid van Moolenbroek val = va_arg(args, unsigned int);
248*5d5fbe79SDavid van Moolenbroek base = 16;
249*5d5fbe79SDavid van Moolenbroek break;
250*5d5fbe79SDavid van Moolenbroek #if 0 /* unused (and wrong on LLP64 systems) */
251*5d5fbe79SDavid van Moolenbroek case 'p':
252*5d5fbe79SDavid van Moolenbroek val = (unsigned long) va_arg(args, void *);
253*5d5fbe79SDavid van Moolenbroek base = 16;
254*5d5fbe79SDavid van Moolenbroek neg = 2;
255*5d5fbe79SDavid van Moolenbroek break;
256*5d5fbe79SDavid van Moolenbroek #endif /* unused (and wrong on LLP64 systems) */
257*5d5fbe79SDavid van Moolenbroek case 's':
258*5d5fbe79SDavid van Moolenbroek str = va_arg(args, char *);
259*5d5fbe79SDavid van Moolenbroek break;
260*5d5fbe79SDavid van Moolenbroek case 'c':
261*5d5fbe79SDavid van Moolenbroek num[0] = va_arg(args, int);
262*5d5fbe79SDavid van Moolenbroek num[1] = 0;
263*5d5fbe79SDavid van Moolenbroek str = num;
264*5d5fbe79SDavid van Moolenbroek break;
265*5d5fbe79SDavid van Moolenbroek #if 0 /* do we always have strerror() in embedded ? */
266*5d5fbe79SDavid van Moolenbroek case 'm':
267*5d5fbe79SDavid van Moolenbroek str = strerror(errno);
268*5d5fbe79SDavid van Moolenbroek break;
269*5d5fbe79SDavid van Moolenbroek #endif /* do we always have strerror() in embedded ? */
270*5d5fbe79SDavid van Moolenbroek case 'I':
271*5d5fbe79SDavid van Moolenbroek ip = va_arg(args, u32_t);
272*5d5fbe79SDavid van Moolenbroek ip = lwip_ntohl(ip);
273*5d5fbe79SDavid van Moolenbroek ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
274*5d5fbe79SDavid van Moolenbroek (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
275*5d5fbe79SDavid van Moolenbroek str = num;
276*5d5fbe79SDavid van Moolenbroek break;
277*5d5fbe79SDavid van Moolenbroek #if 0 /* need port */
278*5d5fbe79SDavid van Moolenbroek case 't':
279*5d5fbe79SDavid van Moolenbroek time(&t);
280*5d5fbe79SDavid van Moolenbroek str = ctime(&t);
281*5d5fbe79SDavid van Moolenbroek str += 4; /* chop off the day name */
282*5d5fbe79SDavid van Moolenbroek str[15] = 0; /* chop off year and newline */
283*5d5fbe79SDavid van Moolenbroek break;
284*5d5fbe79SDavid van Moolenbroek #endif /* need port */
285*5d5fbe79SDavid van Moolenbroek case 'v': /* "visible" string */
286*5d5fbe79SDavid van Moolenbroek case 'q': /* quoted string */
287*5d5fbe79SDavid van Moolenbroek quoted = c == 'q';
288*5d5fbe79SDavid van Moolenbroek p = va_arg(args, unsigned char *);
289*5d5fbe79SDavid van Moolenbroek if (p == NULL)
290*5d5fbe79SDavid van Moolenbroek p = (const unsigned char *)"<NULL>";
291*5d5fbe79SDavid van Moolenbroek if (fillch == '0' && prec >= 0) {
292*5d5fbe79SDavid van Moolenbroek n = prec;
293*5d5fbe79SDavid van Moolenbroek } else {
294*5d5fbe79SDavid van Moolenbroek n = strlen((const char *)p);
295*5d5fbe79SDavid van Moolenbroek if (prec >= 0 && n > prec)
296*5d5fbe79SDavid van Moolenbroek n = prec;
297*5d5fbe79SDavid van Moolenbroek }
298*5d5fbe79SDavid van Moolenbroek while (n > 0 && buflen > 0) {
299*5d5fbe79SDavid van Moolenbroek c = *p++;
300*5d5fbe79SDavid van Moolenbroek --n;
301*5d5fbe79SDavid van Moolenbroek if (!quoted && c >= 0x80) {
302*5d5fbe79SDavid van Moolenbroek OUTCHAR('M');
303*5d5fbe79SDavid van Moolenbroek OUTCHAR('-');
304*5d5fbe79SDavid van Moolenbroek c -= 0x80;
305*5d5fbe79SDavid van Moolenbroek }
306*5d5fbe79SDavid van Moolenbroek if (quoted && (c == '"' || c == '\\'))
307*5d5fbe79SDavid van Moolenbroek OUTCHAR('\\');
308*5d5fbe79SDavid van Moolenbroek if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
309*5d5fbe79SDavid van Moolenbroek if (quoted) {
310*5d5fbe79SDavid van Moolenbroek OUTCHAR('\\');
311*5d5fbe79SDavid van Moolenbroek switch (c) {
312*5d5fbe79SDavid van Moolenbroek case '\t': OUTCHAR('t'); break;
313*5d5fbe79SDavid van Moolenbroek case '\n': OUTCHAR('n'); break;
314*5d5fbe79SDavid van Moolenbroek case '\b': OUTCHAR('b'); break;
315*5d5fbe79SDavid van Moolenbroek case '\f': OUTCHAR('f'); break;
316*5d5fbe79SDavid van Moolenbroek default:
317*5d5fbe79SDavid van Moolenbroek OUTCHAR('x');
318*5d5fbe79SDavid van Moolenbroek OUTCHAR(hexchars[c >> 4]);
319*5d5fbe79SDavid van Moolenbroek OUTCHAR(hexchars[c & 0xf]);
320*5d5fbe79SDavid van Moolenbroek }
321*5d5fbe79SDavid van Moolenbroek } else {
322*5d5fbe79SDavid van Moolenbroek if (c == '\t')
323*5d5fbe79SDavid van Moolenbroek OUTCHAR(c);
324*5d5fbe79SDavid van Moolenbroek else {
325*5d5fbe79SDavid van Moolenbroek OUTCHAR('^');
326*5d5fbe79SDavid van Moolenbroek OUTCHAR(c ^ 0x40);
327*5d5fbe79SDavid van Moolenbroek }
328*5d5fbe79SDavid van Moolenbroek }
329*5d5fbe79SDavid van Moolenbroek } else
330*5d5fbe79SDavid van Moolenbroek OUTCHAR(c);
331*5d5fbe79SDavid van Moolenbroek }
332*5d5fbe79SDavid van Moolenbroek continue;
333*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
334*5d5fbe79SDavid van Moolenbroek case 'P': /* print PPP packet */
335*5d5fbe79SDavid van Moolenbroek bufinfo.ptr = buf;
336*5d5fbe79SDavid van Moolenbroek bufinfo.len = buflen + 1;
337*5d5fbe79SDavid van Moolenbroek p = va_arg(args, unsigned char *);
338*5d5fbe79SDavid van Moolenbroek n = va_arg(args, int);
339*5d5fbe79SDavid van Moolenbroek ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo);
340*5d5fbe79SDavid van Moolenbroek buf = bufinfo.ptr;
341*5d5fbe79SDavid van Moolenbroek buflen = bufinfo.len - 1;
342*5d5fbe79SDavid van Moolenbroek continue;
343*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
344*5d5fbe79SDavid van Moolenbroek case 'B':
345*5d5fbe79SDavid van Moolenbroek p = va_arg(args, unsigned char *);
346*5d5fbe79SDavid van Moolenbroek for (n = prec; n > 0; --n) {
347*5d5fbe79SDavid van Moolenbroek c = *p++;
348*5d5fbe79SDavid van Moolenbroek if (fillch == ' ')
349*5d5fbe79SDavid van Moolenbroek OUTCHAR(' ');
350*5d5fbe79SDavid van Moolenbroek OUTCHAR(hexchars[(c >> 4) & 0xf]);
351*5d5fbe79SDavid van Moolenbroek OUTCHAR(hexchars[c & 0xf]);
352*5d5fbe79SDavid van Moolenbroek }
353*5d5fbe79SDavid van Moolenbroek continue;
354*5d5fbe79SDavid van Moolenbroek default:
355*5d5fbe79SDavid van Moolenbroek *buf++ = '%';
356*5d5fbe79SDavid van Moolenbroek if (c != '%')
357*5d5fbe79SDavid van Moolenbroek --fmt; /* so %z outputs %z etc. */
358*5d5fbe79SDavid van Moolenbroek --buflen;
359*5d5fbe79SDavid van Moolenbroek continue;
360*5d5fbe79SDavid van Moolenbroek }
361*5d5fbe79SDavid van Moolenbroek if (base != 0) {
362*5d5fbe79SDavid van Moolenbroek str = num + sizeof(num);
363*5d5fbe79SDavid van Moolenbroek *--str = 0;
364*5d5fbe79SDavid van Moolenbroek while (str > num + neg) {
365*5d5fbe79SDavid van Moolenbroek *--str = hexchars[val % base];
366*5d5fbe79SDavid van Moolenbroek val = val / base;
367*5d5fbe79SDavid van Moolenbroek if (--prec <= 0 && val == 0)
368*5d5fbe79SDavid van Moolenbroek break;
369*5d5fbe79SDavid van Moolenbroek }
370*5d5fbe79SDavid van Moolenbroek switch (neg) {
371*5d5fbe79SDavid van Moolenbroek case 1:
372*5d5fbe79SDavid van Moolenbroek *--str = '-';
373*5d5fbe79SDavid van Moolenbroek break;
374*5d5fbe79SDavid van Moolenbroek case 2:
375*5d5fbe79SDavid van Moolenbroek *--str = 'x';
376*5d5fbe79SDavid van Moolenbroek *--str = '0';
377*5d5fbe79SDavid van Moolenbroek break;
378*5d5fbe79SDavid van Moolenbroek default:
379*5d5fbe79SDavid van Moolenbroek break;
380*5d5fbe79SDavid van Moolenbroek }
381*5d5fbe79SDavid van Moolenbroek len = num + sizeof(num) - 1 - str;
382*5d5fbe79SDavid van Moolenbroek } else {
383*5d5fbe79SDavid van Moolenbroek len = strlen(str);
384*5d5fbe79SDavid van Moolenbroek if (prec >= 0 && len > prec)
385*5d5fbe79SDavid van Moolenbroek len = prec;
386*5d5fbe79SDavid van Moolenbroek }
387*5d5fbe79SDavid van Moolenbroek if (width > 0) {
388*5d5fbe79SDavid van Moolenbroek if (width > buflen)
389*5d5fbe79SDavid van Moolenbroek width = buflen;
390*5d5fbe79SDavid van Moolenbroek if ((n = width - len) > 0) {
391*5d5fbe79SDavid van Moolenbroek buflen -= n;
392*5d5fbe79SDavid van Moolenbroek for (; n > 0; --n)
393*5d5fbe79SDavid van Moolenbroek *buf++ = fillch;
394*5d5fbe79SDavid van Moolenbroek }
395*5d5fbe79SDavid van Moolenbroek }
396*5d5fbe79SDavid van Moolenbroek if (len > buflen)
397*5d5fbe79SDavid van Moolenbroek len = buflen;
398*5d5fbe79SDavid van Moolenbroek memcpy(buf, str, len);
399*5d5fbe79SDavid van Moolenbroek buf += len;
400*5d5fbe79SDavid van Moolenbroek buflen -= len;
401*5d5fbe79SDavid van Moolenbroek }
402*5d5fbe79SDavid van Moolenbroek *buf = 0;
403*5d5fbe79SDavid van Moolenbroek return buf - buf0;
404*5d5fbe79SDavid van Moolenbroek }
405*5d5fbe79SDavid van Moolenbroek
406*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
407*5d5fbe79SDavid van Moolenbroek /*
408*5d5fbe79SDavid van Moolenbroek * vslp_printer - used in processing a %P format
409*5d5fbe79SDavid van Moolenbroek */
ppp_vslp_printer(void * arg,const char * fmt,...)410*5d5fbe79SDavid van Moolenbroek static void ppp_vslp_printer(void *arg, const char *fmt, ...) {
411*5d5fbe79SDavid van Moolenbroek int n;
412*5d5fbe79SDavid van Moolenbroek va_list pvar;
413*5d5fbe79SDavid van Moolenbroek struct buffer_info *bi;
414*5d5fbe79SDavid van Moolenbroek
415*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
416*5d5fbe79SDavid van Moolenbroek bi = (struct buffer_info *) arg;
417*5d5fbe79SDavid van Moolenbroek n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar);
418*5d5fbe79SDavid van Moolenbroek va_end(pvar);
419*5d5fbe79SDavid van Moolenbroek
420*5d5fbe79SDavid van Moolenbroek bi->ptr += n;
421*5d5fbe79SDavid van Moolenbroek bi->len -= n;
422*5d5fbe79SDavid van Moolenbroek }
423*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
424*5d5fbe79SDavid van Moolenbroek
425*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
426*5d5fbe79SDavid van Moolenbroek /*
427*5d5fbe79SDavid van Moolenbroek * log_packet - format a packet and log it.
428*5d5fbe79SDavid van Moolenbroek */
429*5d5fbe79SDavid van Moolenbroek
430*5d5fbe79SDavid van Moolenbroek void
431*5d5fbe79SDavid van Moolenbroek log_packet(p, len, prefix, level)
432*5d5fbe79SDavid van Moolenbroek u_char *p;
433*5d5fbe79SDavid van Moolenbroek int len;
434*5d5fbe79SDavid van Moolenbroek char *prefix;
435*5d5fbe79SDavid van Moolenbroek int level;
436*5d5fbe79SDavid van Moolenbroek {
437*5d5fbe79SDavid van Moolenbroek init_pr_log(prefix, level);
438*5d5fbe79SDavid van Moolenbroek ppp_format_packet(p, len, pr_log, &level);
439*5d5fbe79SDavid van Moolenbroek end_pr_log();
440*5d5fbe79SDavid van Moolenbroek }
441*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
442*5d5fbe79SDavid van Moolenbroek
443*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
444*5d5fbe79SDavid van Moolenbroek /*
445*5d5fbe79SDavid van Moolenbroek * ppp_format_packet - make a readable representation of a packet,
446*5d5fbe79SDavid van Moolenbroek * calling `printer(arg, format, ...)' to output it.
447*5d5fbe79SDavid van Moolenbroek */
ppp_format_packet(const u_char * p,int len,void (* printer)(void *,const char *,...),void * arg)448*5d5fbe79SDavid van Moolenbroek static void ppp_format_packet(const u_char *p, int len,
449*5d5fbe79SDavid van Moolenbroek void (*printer) (void *, const char *, ...), void *arg) {
450*5d5fbe79SDavid van Moolenbroek int i, n;
451*5d5fbe79SDavid van Moolenbroek u_short proto;
452*5d5fbe79SDavid van Moolenbroek const struct protent *protp;
453*5d5fbe79SDavid van Moolenbroek
454*5d5fbe79SDavid van Moolenbroek if (len >= 2) {
455*5d5fbe79SDavid van Moolenbroek GETSHORT(proto, p);
456*5d5fbe79SDavid van Moolenbroek len -= 2;
457*5d5fbe79SDavid van Moolenbroek for (i = 0; (protp = protocols[i]) != NULL; ++i)
458*5d5fbe79SDavid van Moolenbroek if (proto == protp->protocol)
459*5d5fbe79SDavid van Moolenbroek break;
460*5d5fbe79SDavid van Moolenbroek if (protp != NULL) {
461*5d5fbe79SDavid van Moolenbroek printer(arg, "[%s", protp->name);
462*5d5fbe79SDavid van Moolenbroek n = (*protp->printpkt)(p, len, printer, arg);
463*5d5fbe79SDavid van Moolenbroek printer(arg, "]");
464*5d5fbe79SDavid van Moolenbroek p += n;
465*5d5fbe79SDavid van Moolenbroek len -= n;
466*5d5fbe79SDavid van Moolenbroek } else {
467*5d5fbe79SDavid van Moolenbroek for (i = 0; (protp = protocols[i]) != NULL; ++i)
468*5d5fbe79SDavid van Moolenbroek if (proto == (protp->protocol & ~0x8000))
469*5d5fbe79SDavid van Moolenbroek break;
470*5d5fbe79SDavid van Moolenbroek if (protp != 0 && protp->data_name != 0) {
471*5d5fbe79SDavid van Moolenbroek printer(arg, "[%s data]", protp->data_name);
472*5d5fbe79SDavid van Moolenbroek if (len > 8)
473*5d5fbe79SDavid van Moolenbroek printer(arg, "%.8B ...", p);
474*5d5fbe79SDavid van Moolenbroek else
475*5d5fbe79SDavid van Moolenbroek printer(arg, "%.*B", len, p);
476*5d5fbe79SDavid van Moolenbroek len = 0;
477*5d5fbe79SDavid van Moolenbroek } else
478*5d5fbe79SDavid van Moolenbroek printer(arg, "[proto=0x%x]", proto);
479*5d5fbe79SDavid van Moolenbroek }
480*5d5fbe79SDavid van Moolenbroek }
481*5d5fbe79SDavid van Moolenbroek
482*5d5fbe79SDavid van Moolenbroek if (len > 32)
483*5d5fbe79SDavid van Moolenbroek printer(arg, "%.32B ...", p);
484*5d5fbe79SDavid van Moolenbroek else
485*5d5fbe79SDavid van Moolenbroek printer(arg, "%.*B", len, p);
486*5d5fbe79SDavid van Moolenbroek }
487*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
488*5d5fbe79SDavid van Moolenbroek
489*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
490*5d5fbe79SDavid van Moolenbroek /*
491*5d5fbe79SDavid van Moolenbroek * init_pr_log, end_pr_log - initialize and finish use of pr_log.
492*5d5fbe79SDavid van Moolenbroek */
493*5d5fbe79SDavid van Moolenbroek
494*5d5fbe79SDavid van Moolenbroek static char line[256]; /* line to be logged accumulated here */
495*5d5fbe79SDavid van Moolenbroek static char *linep; /* current pointer within line */
496*5d5fbe79SDavid van Moolenbroek static int llevel; /* level for logging */
497*5d5fbe79SDavid van Moolenbroek
498*5d5fbe79SDavid van Moolenbroek void
499*5d5fbe79SDavid van Moolenbroek init_pr_log(prefix, level)
500*5d5fbe79SDavid van Moolenbroek const char *prefix;
501*5d5fbe79SDavid van Moolenbroek int level;
502*5d5fbe79SDavid van Moolenbroek {
503*5d5fbe79SDavid van Moolenbroek linep = line;
504*5d5fbe79SDavid van Moolenbroek if (prefix != NULL) {
505*5d5fbe79SDavid van Moolenbroek ppp_strlcpy(line, prefix, sizeof(line));
506*5d5fbe79SDavid van Moolenbroek linep = line + strlen(line);
507*5d5fbe79SDavid van Moolenbroek }
508*5d5fbe79SDavid van Moolenbroek llevel = level;
509*5d5fbe79SDavid van Moolenbroek }
510*5d5fbe79SDavid van Moolenbroek
511*5d5fbe79SDavid van Moolenbroek void
512*5d5fbe79SDavid van Moolenbroek end_pr_log()
513*5d5fbe79SDavid van Moolenbroek {
514*5d5fbe79SDavid van Moolenbroek if (linep != line) {
515*5d5fbe79SDavid van Moolenbroek *linep = 0;
516*5d5fbe79SDavid van Moolenbroek ppp_log_write(llevel, line);
517*5d5fbe79SDavid van Moolenbroek }
518*5d5fbe79SDavid van Moolenbroek }
519*5d5fbe79SDavid van Moolenbroek
520*5d5fbe79SDavid van Moolenbroek /*
521*5d5fbe79SDavid van Moolenbroek * pr_log - printer routine for outputting to log
522*5d5fbe79SDavid van Moolenbroek */
523*5d5fbe79SDavid van Moolenbroek void
524*5d5fbe79SDavid van Moolenbroek pr_log (void *arg, const char *fmt, ...)
525*5d5fbe79SDavid van Moolenbroek {
526*5d5fbe79SDavid van Moolenbroek int l, n;
527*5d5fbe79SDavid van Moolenbroek va_list pvar;
528*5d5fbe79SDavid van Moolenbroek char *p, *eol;
529*5d5fbe79SDavid van Moolenbroek char buf[256];
530*5d5fbe79SDavid van Moolenbroek
531*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
532*5d5fbe79SDavid van Moolenbroek n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar);
533*5d5fbe79SDavid van Moolenbroek va_end(pvar);
534*5d5fbe79SDavid van Moolenbroek
535*5d5fbe79SDavid van Moolenbroek p = buf;
536*5d5fbe79SDavid van Moolenbroek eol = strchr(buf, '\n');
537*5d5fbe79SDavid van Moolenbroek if (linep != line) {
538*5d5fbe79SDavid van Moolenbroek l = (eol == NULL)? n: eol - buf;
539*5d5fbe79SDavid van Moolenbroek if (linep + l < line + sizeof(line)) {
540*5d5fbe79SDavid van Moolenbroek if (l > 0) {
541*5d5fbe79SDavid van Moolenbroek memcpy(linep, buf, l);
542*5d5fbe79SDavid van Moolenbroek linep += l;
543*5d5fbe79SDavid van Moolenbroek }
544*5d5fbe79SDavid van Moolenbroek if (eol == NULL)
545*5d5fbe79SDavid van Moolenbroek return;
546*5d5fbe79SDavid van Moolenbroek p = eol + 1;
547*5d5fbe79SDavid van Moolenbroek eol = strchr(p, '\n');
548*5d5fbe79SDavid van Moolenbroek }
549*5d5fbe79SDavid van Moolenbroek *linep = 0;
550*5d5fbe79SDavid van Moolenbroek ppp_log_write(llevel, line);
551*5d5fbe79SDavid van Moolenbroek linep = line;
552*5d5fbe79SDavid van Moolenbroek }
553*5d5fbe79SDavid van Moolenbroek
554*5d5fbe79SDavid van Moolenbroek while (eol != NULL) {
555*5d5fbe79SDavid van Moolenbroek *eol = 0;
556*5d5fbe79SDavid van Moolenbroek ppp_log_write(llevel, p);
557*5d5fbe79SDavid van Moolenbroek p = eol + 1;
558*5d5fbe79SDavid van Moolenbroek eol = strchr(p, '\n');
559*5d5fbe79SDavid van Moolenbroek }
560*5d5fbe79SDavid van Moolenbroek
561*5d5fbe79SDavid van Moolenbroek /* assumes sizeof(buf) <= sizeof(line) */
562*5d5fbe79SDavid van Moolenbroek l = buf + n - p;
563*5d5fbe79SDavid van Moolenbroek if (l > 0) {
564*5d5fbe79SDavid van Moolenbroek memcpy(line, p, n);
565*5d5fbe79SDavid van Moolenbroek linep = line + l;
566*5d5fbe79SDavid van Moolenbroek }
567*5d5fbe79SDavid van Moolenbroek }
568*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
569*5d5fbe79SDavid van Moolenbroek
570*5d5fbe79SDavid van Moolenbroek /*
571*5d5fbe79SDavid van Moolenbroek * ppp_print_string - print a readable representation of a string using
572*5d5fbe79SDavid van Moolenbroek * printer.
573*5d5fbe79SDavid van Moolenbroek */
ppp_print_string(const u_char * p,int len,void (* printer)(void *,const char *,...),void * arg)574*5d5fbe79SDavid van Moolenbroek void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) {
575*5d5fbe79SDavid van Moolenbroek int c;
576*5d5fbe79SDavid van Moolenbroek
577*5d5fbe79SDavid van Moolenbroek printer(arg, "\"");
578*5d5fbe79SDavid van Moolenbroek for (; len > 0; --len) {
579*5d5fbe79SDavid van Moolenbroek c = *p++;
580*5d5fbe79SDavid van Moolenbroek if (' ' <= c && c <= '~') {
581*5d5fbe79SDavid van Moolenbroek if (c == '\\' || c == '"')
582*5d5fbe79SDavid van Moolenbroek printer(arg, "\\");
583*5d5fbe79SDavid van Moolenbroek printer(arg, "%c", c);
584*5d5fbe79SDavid van Moolenbroek } else {
585*5d5fbe79SDavid van Moolenbroek switch (c) {
586*5d5fbe79SDavid van Moolenbroek case '\n':
587*5d5fbe79SDavid van Moolenbroek printer(arg, "\\n");
588*5d5fbe79SDavid van Moolenbroek break;
589*5d5fbe79SDavid van Moolenbroek case '\r':
590*5d5fbe79SDavid van Moolenbroek printer(arg, "\\r");
591*5d5fbe79SDavid van Moolenbroek break;
592*5d5fbe79SDavid van Moolenbroek case '\t':
593*5d5fbe79SDavid van Moolenbroek printer(arg, "\\t");
594*5d5fbe79SDavid van Moolenbroek break;
595*5d5fbe79SDavid van Moolenbroek default:
596*5d5fbe79SDavid van Moolenbroek printer(arg, "\\%.3o", (u8_t)c);
597*5d5fbe79SDavid van Moolenbroek /* no break */
598*5d5fbe79SDavid van Moolenbroek }
599*5d5fbe79SDavid van Moolenbroek }
600*5d5fbe79SDavid van Moolenbroek }
601*5d5fbe79SDavid van Moolenbroek printer(arg, "\"");
602*5d5fbe79SDavid van Moolenbroek }
603*5d5fbe79SDavid van Moolenbroek
604*5d5fbe79SDavid van Moolenbroek /*
605*5d5fbe79SDavid van Moolenbroek * ppp_logit - does the hard work for fatal et al.
606*5d5fbe79SDavid van Moolenbroek */
ppp_logit(int level,const char * fmt,va_list args)607*5d5fbe79SDavid van Moolenbroek static void ppp_logit(int level, const char *fmt, va_list args) {
608*5d5fbe79SDavid van Moolenbroek char buf[1024];
609*5d5fbe79SDavid van Moolenbroek
610*5d5fbe79SDavid van Moolenbroek ppp_vslprintf(buf, sizeof(buf), fmt, args);
611*5d5fbe79SDavid van Moolenbroek ppp_log_write(level, buf);
612*5d5fbe79SDavid van Moolenbroek }
613*5d5fbe79SDavid van Moolenbroek
ppp_log_write(int level,char * buf)614*5d5fbe79SDavid van Moolenbroek static void ppp_log_write(int level, char *buf) {
615*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */
616*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(buf);
617*5d5fbe79SDavid van Moolenbroek PPPDEBUG(level, ("%s\n", buf) );
618*5d5fbe79SDavid van Moolenbroek #if 0
619*5d5fbe79SDavid van Moolenbroek if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) {
620*5d5fbe79SDavid van Moolenbroek int n = strlen(buf);
621*5d5fbe79SDavid van Moolenbroek
622*5d5fbe79SDavid van Moolenbroek if (n > 0 && buf[n-1] == '\n')
623*5d5fbe79SDavid van Moolenbroek --n;
624*5d5fbe79SDavid van Moolenbroek if (write(log_to_fd, buf, n) != n
625*5d5fbe79SDavid van Moolenbroek || write(log_to_fd, "\n", 1) != 1)
626*5d5fbe79SDavid van Moolenbroek log_to_fd = -1;
627*5d5fbe79SDavid van Moolenbroek }
628*5d5fbe79SDavid van Moolenbroek #endif
629*5d5fbe79SDavid van Moolenbroek }
630*5d5fbe79SDavid van Moolenbroek
631*5d5fbe79SDavid van Moolenbroek /*
632*5d5fbe79SDavid van Moolenbroek * ppp_fatal - log an error message and die horribly.
633*5d5fbe79SDavid van Moolenbroek */
ppp_fatal(const char * fmt,...)634*5d5fbe79SDavid van Moolenbroek void ppp_fatal(const char *fmt, ...) {
635*5d5fbe79SDavid van Moolenbroek va_list pvar;
636*5d5fbe79SDavid van Moolenbroek
637*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
638*5d5fbe79SDavid van Moolenbroek ppp_logit(LOG_ERR, fmt, pvar);
639*5d5fbe79SDavid van Moolenbroek va_end(pvar);
640*5d5fbe79SDavid van Moolenbroek
641*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("ppp_fatal", 0); /* as promised */
642*5d5fbe79SDavid van Moolenbroek }
643*5d5fbe79SDavid van Moolenbroek
644*5d5fbe79SDavid van Moolenbroek /*
645*5d5fbe79SDavid van Moolenbroek * ppp_error - log an error message.
646*5d5fbe79SDavid van Moolenbroek */
ppp_error(const char * fmt,...)647*5d5fbe79SDavid van Moolenbroek void ppp_error(const char *fmt, ...) {
648*5d5fbe79SDavid van Moolenbroek va_list pvar;
649*5d5fbe79SDavid van Moolenbroek
650*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
651*5d5fbe79SDavid van Moolenbroek ppp_logit(LOG_ERR, fmt, pvar);
652*5d5fbe79SDavid van Moolenbroek va_end(pvar);
653*5d5fbe79SDavid van Moolenbroek #if 0 /* UNUSED */
654*5d5fbe79SDavid van Moolenbroek ++error_count;
655*5d5fbe79SDavid van Moolenbroek #endif /* UNUSED */
656*5d5fbe79SDavid van Moolenbroek }
657*5d5fbe79SDavid van Moolenbroek
658*5d5fbe79SDavid van Moolenbroek /*
659*5d5fbe79SDavid van Moolenbroek * ppp_warn - log a warning message.
660*5d5fbe79SDavid van Moolenbroek */
ppp_warn(const char * fmt,...)661*5d5fbe79SDavid van Moolenbroek void ppp_warn(const char *fmt, ...) {
662*5d5fbe79SDavid van Moolenbroek va_list pvar;
663*5d5fbe79SDavid van Moolenbroek
664*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
665*5d5fbe79SDavid van Moolenbroek ppp_logit(LOG_WARNING, fmt, pvar);
666*5d5fbe79SDavid van Moolenbroek va_end(pvar);
667*5d5fbe79SDavid van Moolenbroek }
668*5d5fbe79SDavid van Moolenbroek
669*5d5fbe79SDavid van Moolenbroek /*
670*5d5fbe79SDavid van Moolenbroek * ppp_notice - log a notice-level message.
671*5d5fbe79SDavid van Moolenbroek */
ppp_notice(const char * fmt,...)672*5d5fbe79SDavid van Moolenbroek void ppp_notice(const char *fmt, ...) {
673*5d5fbe79SDavid van Moolenbroek va_list pvar;
674*5d5fbe79SDavid van Moolenbroek
675*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
676*5d5fbe79SDavid van Moolenbroek ppp_logit(LOG_NOTICE, fmt, pvar);
677*5d5fbe79SDavid van Moolenbroek va_end(pvar);
678*5d5fbe79SDavid van Moolenbroek }
679*5d5fbe79SDavid van Moolenbroek
680*5d5fbe79SDavid van Moolenbroek /*
681*5d5fbe79SDavid van Moolenbroek * ppp_info - log an informational message.
682*5d5fbe79SDavid van Moolenbroek */
ppp_info(const char * fmt,...)683*5d5fbe79SDavid van Moolenbroek void ppp_info(const char *fmt, ...) {
684*5d5fbe79SDavid van Moolenbroek va_list pvar;
685*5d5fbe79SDavid van Moolenbroek
686*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
687*5d5fbe79SDavid van Moolenbroek ppp_logit(LOG_INFO, fmt, pvar);
688*5d5fbe79SDavid van Moolenbroek va_end(pvar);
689*5d5fbe79SDavid van Moolenbroek }
690*5d5fbe79SDavid van Moolenbroek
691*5d5fbe79SDavid van Moolenbroek /*
692*5d5fbe79SDavid van Moolenbroek * ppp_dbglog - log a debug message.
693*5d5fbe79SDavid van Moolenbroek */
ppp_dbglog(const char * fmt,...)694*5d5fbe79SDavid van Moolenbroek void ppp_dbglog(const char *fmt, ...) {
695*5d5fbe79SDavid van Moolenbroek va_list pvar;
696*5d5fbe79SDavid van Moolenbroek
697*5d5fbe79SDavid van Moolenbroek va_start(pvar, fmt);
698*5d5fbe79SDavid van Moolenbroek ppp_logit(LOG_DEBUG, fmt, pvar);
699*5d5fbe79SDavid van Moolenbroek va_end(pvar);
700*5d5fbe79SDavid van Moolenbroek }
701*5d5fbe79SDavid van Moolenbroek
702*5d5fbe79SDavid van Moolenbroek #if PRINTPKT_SUPPORT
703*5d5fbe79SDavid van Moolenbroek /*
704*5d5fbe79SDavid van Moolenbroek * ppp_dump_packet - print out a packet in readable form if it is interesting.
705*5d5fbe79SDavid van Moolenbroek * Assumes len >= PPP_HDRLEN.
706*5d5fbe79SDavid van Moolenbroek */
ppp_dump_packet(ppp_pcb * pcb,const char * tag,unsigned char * p,int len)707*5d5fbe79SDavid van Moolenbroek void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) {
708*5d5fbe79SDavid van Moolenbroek int proto;
709*5d5fbe79SDavid van Moolenbroek
710*5d5fbe79SDavid van Moolenbroek /*
711*5d5fbe79SDavid van Moolenbroek * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets.
712*5d5fbe79SDavid van Moolenbroek */
713*5d5fbe79SDavid van Moolenbroek proto = (p[0] << 8) + p[1];
714*5d5fbe79SDavid van Moolenbroek if (proto < 0xC000 && (proto & ~0x8000) == proto)
715*5d5fbe79SDavid van Moolenbroek return;
716*5d5fbe79SDavid van Moolenbroek
717*5d5fbe79SDavid van Moolenbroek /*
718*5d5fbe79SDavid van Moolenbroek * don't print valid LCP echo request/reply packets if the link is up.
719*5d5fbe79SDavid van Moolenbroek */
720*5d5fbe79SDavid van Moolenbroek if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) {
721*5d5fbe79SDavid van Moolenbroek unsigned char *lcp = p + 2;
722*5d5fbe79SDavid van Moolenbroek int l = (lcp[2] << 8) + lcp[3];
723*5d5fbe79SDavid van Moolenbroek
724*5d5fbe79SDavid van Moolenbroek if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP)
725*5d5fbe79SDavid van Moolenbroek && l >= HEADERLEN && l <= len - 2)
726*5d5fbe79SDavid van Moolenbroek return;
727*5d5fbe79SDavid van Moolenbroek }
728*5d5fbe79SDavid van Moolenbroek
729*5d5fbe79SDavid van Moolenbroek ppp_dbglog("%s %P", tag, p, len);
730*5d5fbe79SDavid van Moolenbroek }
731*5d5fbe79SDavid van Moolenbroek #endif /* PRINTPKT_SUPPORT */
732*5d5fbe79SDavid van Moolenbroek
733*5d5fbe79SDavid van Moolenbroek #if 0 /* Unused */
734*5d5fbe79SDavid van Moolenbroek
735*5d5fbe79SDavid van Moolenbroek /*
736*5d5fbe79SDavid van Moolenbroek * complete_read - read a full `count' bytes from fd,
737*5d5fbe79SDavid van Moolenbroek * unless end-of-file or an error other than EINTR is encountered.
738*5d5fbe79SDavid van Moolenbroek */
739*5d5fbe79SDavid van Moolenbroek ssize_t
740*5d5fbe79SDavid van Moolenbroek complete_read(int fd, void *buf, size_t count)
741*5d5fbe79SDavid van Moolenbroek {
742*5d5fbe79SDavid van Moolenbroek size_t done;
743*5d5fbe79SDavid van Moolenbroek ssize_t nb;
744*5d5fbe79SDavid van Moolenbroek char *ptr = buf;
745*5d5fbe79SDavid van Moolenbroek
746*5d5fbe79SDavid van Moolenbroek for (done = 0; done < count; ) {
747*5d5fbe79SDavid van Moolenbroek nb = read(fd, ptr, count - done);
748*5d5fbe79SDavid van Moolenbroek if (nb < 0) {
749*5d5fbe79SDavid van Moolenbroek if (errno == EINTR)
750*5d5fbe79SDavid van Moolenbroek continue;
751*5d5fbe79SDavid van Moolenbroek return -1;
752*5d5fbe79SDavid van Moolenbroek }
753*5d5fbe79SDavid van Moolenbroek if (nb == 0)
754*5d5fbe79SDavid van Moolenbroek break;
755*5d5fbe79SDavid van Moolenbroek done += nb;
756*5d5fbe79SDavid van Moolenbroek ptr += nb;
757*5d5fbe79SDavid van Moolenbroek }
758*5d5fbe79SDavid van Moolenbroek return done;
759*5d5fbe79SDavid van Moolenbroek }
760*5d5fbe79SDavid van Moolenbroek
761*5d5fbe79SDavid van Moolenbroek /* Procedures for locking the serial device using a lock file. */
762*5d5fbe79SDavid van Moolenbroek #ifndef LOCK_DIR
763*5d5fbe79SDavid van Moolenbroek #ifdef __linux__
764*5d5fbe79SDavid van Moolenbroek #define LOCK_DIR "/var/lock"
765*5d5fbe79SDavid van Moolenbroek #else
766*5d5fbe79SDavid van Moolenbroek #ifdef SVR4
767*5d5fbe79SDavid van Moolenbroek #define LOCK_DIR "/var/spool/locks"
768*5d5fbe79SDavid van Moolenbroek #else
769*5d5fbe79SDavid van Moolenbroek #define LOCK_DIR "/var/spool/lock"
770*5d5fbe79SDavid van Moolenbroek #endif
771*5d5fbe79SDavid van Moolenbroek #endif
772*5d5fbe79SDavid van Moolenbroek #endif /* LOCK_DIR */
773*5d5fbe79SDavid van Moolenbroek
774*5d5fbe79SDavid van Moolenbroek static char lock_file[MAXPATHLEN];
775*5d5fbe79SDavid van Moolenbroek
776*5d5fbe79SDavid van Moolenbroek /*
777*5d5fbe79SDavid van Moolenbroek * lock - create a lock file for the named device
778*5d5fbe79SDavid van Moolenbroek */
779*5d5fbe79SDavid van Moolenbroek int
780*5d5fbe79SDavid van Moolenbroek lock(dev)
781*5d5fbe79SDavid van Moolenbroek char *dev;
782*5d5fbe79SDavid van Moolenbroek {
783*5d5fbe79SDavid van Moolenbroek #ifdef LOCKLIB
784*5d5fbe79SDavid van Moolenbroek int result;
785*5d5fbe79SDavid van Moolenbroek
786*5d5fbe79SDavid van Moolenbroek result = mklock (dev, (void *) 0);
787*5d5fbe79SDavid van Moolenbroek if (result == 0) {
788*5d5fbe79SDavid van Moolenbroek ppp_strlcpy(lock_file, dev, sizeof(lock_file));
789*5d5fbe79SDavid van Moolenbroek return 0;
790*5d5fbe79SDavid van Moolenbroek }
791*5d5fbe79SDavid van Moolenbroek
792*5d5fbe79SDavid van Moolenbroek if (result > 0)
793*5d5fbe79SDavid van Moolenbroek ppp_notice("Device %s is locked by pid %d", dev, result);
794*5d5fbe79SDavid van Moolenbroek else
795*5d5fbe79SDavid van Moolenbroek ppp_error("Can't create lock file %s", lock_file);
796*5d5fbe79SDavid van Moolenbroek return -1;
797*5d5fbe79SDavid van Moolenbroek
798*5d5fbe79SDavid van Moolenbroek #else /* LOCKLIB */
799*5d5fbe79SDavid van Moolenbroek
800*5d5fbe79SDavid van Moolenbroek char lock_buffer[12];
801*5d5fbe79SDavid van Moolenbroek int fd, pid, n;
802*5d5fbe79SDavid van Moolenbroek
803*5d5fbe79SDavid van Moolenbroek #ifdef SVR4
804*5d5fbe79SDavid van Moolenbroek struct stat sbuf;
805*5d5fbe79SDavid van Moolenbroek
806*5d5fbe79SDavid van Moolenbroek if (stat(dev, &sbuf) < 0) {
807*5d5fbe79SDavid van Moolenbroek ppp_error("Can't get device number for %s: %m", dev);
808*5d5fbe79SDavid van Moolenbroek return -1;
809*5d5fbe79SDavid van Moolenbroek }
810*5d5fbe79SDavid van Moolenbroek if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
811*5d5fbe79SDavid van Moolenbroek ppp_error("Can't lock %s: not a character device", dev);
812*5d5fbe79SDavid van Moolenbroek return -1;
813*5d5fbe79SDavid van Moolenbroek }
814*5d5fbe79SDavid van Moolenbroek ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d",
815*5d5fbe79SDavid van Moolenbroek LOCK_DIR, major(sbuf.st_dev),
816*5d5fbe79SDavid van Moolenbroek major(sbuf.st_rdev), minor(sbuf.st_rdev));
817*5d5fbe79SDavid van Moolenbroek #else
818*5d5fbe79SDavid van Moolenbroek char *p;
819*5d5fbe79SDavid van Moolenbroek char lockdev[MAXPATHLEN];
820*5d5fbe79SDavid van Moolenbroek
821*5d5fbe79SDavid van Moolenbroek if ((p = strstr(dev, "dev/")) != NULL) {
822*5d5fbe79SDavid van Moolenbroek dev = p + 4;
823*5d5fbe79SDavid van Moolenbroek strncpy(lockdev, dev, MAXPATHLEN-1);
824*5d5fbe79SDavid van Moolenbroek lockdev[MAXPATHLEN-1] = 0;
825*5d5fbe79SDavid van Moolenbroek while ((p = strrchr(lockdev, '/')) != NULL) {
826*5d5fbe79SDavid van Moolenbroek *p = '_';
827*5d5fbe79SDavid van Moolenbroek }
828*5d5fbe79SDavid van Moolenbroek dev = lockdev;
829*5d5fbe79SDavid van Moolenbroek } else
830*5d5fbe79SDavid van Moolenbroek if ((p = strrchr(dev, '/')) != NULL)
831*5d5fbe79SDavid van Moolenbroek dev = p + 1;
832*5d5fbe79SDavid van Moolenbroek
833*5d5fbe79SDavid van Moolenbroek ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev);
834*5d5fbe79SDavid van Moolenbroek #endif
835*5d5fbe79SDavid van Moolenbroek
836*5d5fbe79SDavid van Moolenbroek while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
837*5d5fbe79SDavid van Moolenbroek if (errno != EEXIST) {
838*5d5fbe79SDavid van Moolenbroek ppp_error("Can't create lock file %s: %m", lock_file);
839*5d5fbe79SDavid van Moolenbroek break;
840*5d5fbe79SDavid van Moolenbroek }
841*5d5fbe79SDavid van Moolenbroek
842*5d5fbe79SDavid van Moolenbroek /* Read the lock file to find out who has the device locked. */
843*5d5fbe79SDavid van Moolenbroek fd = open(lock_file, O_RDONLY, 0);
844*5d5fbe79SDavid van Moolenbroek if (fd < 0) {
845*5d5fbe79SDavid van Moolenbroek if (errno == ENOENT) /* This is just a timing problem. */
846*5d5fbe79SDavid van Moolenbroek continue;
847*5d5fbe79SDavid van Moolenbroek ppp_error("Can't open existing lock file %s: %m", lock_file);
848*5d5fbe79SDavid van Moolenbroek break;
849*5d5fbe79SDavid van Moolenbroek }
850*5d5fbe79SDavid van Moolenbroek #ifndef LOCK_BINARY
851*5d5fbe79SDavid van Moolenbroek n = read(fd, lock_buffer, 11);
852*5d5fbe79SDavid van Moolenbroek #else
853*5d5fbe79SDavid van Moolenbroek n = read(fd, &pid, sizeof(pid));
854*5d5fbe79SDavid van Moolenbroek #endif /* LOCK_BINARY */
855*5d5fbe79SDavid van Moolenbroek close(fd);
856*5d5fbe79SDavid van Moolenbroek fd = -1;
857*5d5fbe79SDavid van Moolenbroek if (n <= 0) {
858*5d5fbe79SDavid van Moolenbroek ppp_error("Can't read pid from lock file %s", lock_file);
859*5d5fbe79SDavid van Moolenbroek break;
860*5d5fbe79SDavid van Moolenbroek }
861*5d5fbe79SDavid van Moolenbroek
862*5d5fbe79SDavid van Moolenbroek /* See if the process still exists. */
863*5d5fbe79SDavid van Moolenbroek #ifndef LOCK_BINARY
864*5d5fbe79SDavid van Moolenbroek lock_buffer[n] = 0;
865*5d5fbe79SDavid van Moolenbroek pid = atoi(lock_buffer);
866*5d5fbe79SDavid van Moolenbroek #endif /* LOCK_BINARY */
867*5d5fbe79SDavid van Moolenbroek if (pid == getpid())
868*5d5fbe79SDavid van Moolenbroek return 1; /* somebody else locked it for us */
869*5d5fbe79SDavid van Moolenbroek if (pid == 0
870*5d5fbe79SDavid van Moolenbroek || (kill(pid, 0) == -1 && errno == ESRCH)) {
871*5d5fbe79SDavid van Moolenbroek if (unlink (lock_file) == 0) {
872*5d5fbe79SDavid van Moolenbroek ppp_notice("Removed stale lock on %s (pid %d)", dev, pid);
873*5d5fbe79SDavid van Moolenbroek continue;
874*5d5fbe79SDavid van Moolenbroek }
875*5d5fbe79SDavid van Moolenbroek ppp_warn("Couldn't remove stale lock on %s", dev);
876*5d5fbe79SDavid van Moolenbroek } else
877*5d5fbe79SDavid van Moolenbroek ppp_notice("Device %s is locked by pid %d", dev, pid);
878*5d5fbe79SDavid van Moolenbroek break;
879*5d5fbe79SDavid van Moolenbroek }
880*5d5fbe79SDavid van Moolenbroek
881*5d5fbe79SDavid van Moolenbroek if (fd < 0) {
882*5d5fbe79SDavid van Moolenbroek lock_file[0] = 0;
883*5d5fbe79SDavid van Moolenbroek return -1;
884*5d5fbe79SDavid van Moolenbroek }
885*5d5fbe79SDavid van Moolenbroek
886*5d5fbe79SDavid van Moolenbroek pid = getpid();
887*5d5fbe79SDavid van Moolenbroek #ifndef LOCK_BINARY
888*5d5fbe79SDavid van Moolenbroek ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
889*5d5fbe79SDavid van Moolenbroek write (fd, lock_buffer, 11);
890*5d5fbe79SDavid van Moolenbroek #else
891*5d5fbe79SDavid van Moolenbroek write(fd, &pid, sizeof (pid));
892*5d5fbe79SDavid van Moolenbroek #endif
893*5d5fbe79SDavid van Moolenbroek close(fd);
894*5d5fbe79SDavid van Moolenbroek return 0;
895*5d5fbe79SDavid van Moolenbroek
896*5d5fbe79SDavid van Moolenbroek #endif
897*5d5fbe79SDavid van Moolenbroek }
898*5d5fbe79SDavid van Moolenbroek
899*5d5fbe79SDavid van Moolenbroek /*
900*5d5fbe79SDavid van Moolenbroek * relock - called to update our lockfile when we are about to detach,
901*5d5fbe79SDavid van Moolenbroek * thus changing our pid (we fork, the child carries on, and the parent dies).
902*5d5fbe79SDavid van Moolenbroek * Note that this is called by the parent, with pid equal to the pid
903*5d5fbe79SDavid van Moolenbroek * of the child. This avoids a potential race which would exist if
904*5d5fbe79SDavid van Moolenbroek * we had the child rewrite the lockfile (the parent might die first,
905*5d5fbe79SDavid van Moolenbroek * and another process could think the lock was stale if it checked
906*5d5fbe79SDavid van Moolenbroek * between when the parent died and the child rewrote the lockfile).
907*5d5fbe79SDavid van Moolenbroek */
908*5d5fbe79SDavid van Moolenbroek int
909*5d5fbe79SDavid van Moolenbroek relock(pid)
910*5d5fbe79SDavid van Moolenbroek int pid;
911*5d5fbe79SDavid van Moolenbroek {
912*5d5fbe79SDavid van Moolenbroek #ifdef LOCKLIB
913*5d5fbe79SDavid van Moolenbroek /* XXX is there a way to do this? */
914*5d5fbe79SDavid van Moolenbroek return -1;
915*5d5fbe79SDavid van Moolenbroek #else /* LOCKLIB */
916*5d5fbe79SDavid van Moolenbroek
917*5d5fbe79SDavid van Moolenbroek int fd;
918*5d5fbe79SDavid van Moolenbroek char lock_buffer[12];
919*5d5fbe79SDavid van Moolenbroek
920*5d5fbe79SDavid van Moolenbroek if (lock_file[0] == 0)
921*5d5fbe79SDavid van Moolenbroek return -1;
922*5d5fbe79SDavid van Moolenbroek fd = open(lock_file, O_WRONLY, 0);
923*5d5fbe79SDavid van Moolenbroek if (fd < 0) {
924*5d5fbe79SDavid van Moolenbroek ppp_error("Couldn't reopen lock file %s: %m", lock_file);
925*5d5fbe79SDavid van Moolenbroek lock_file[0] = 0;
926*5d5fbe79SDavid van Moolenbroek return -1;
927*5d5fbe79SDavid van Moolenbroek }
928*5d5fbe79SDavid van Moolenbroek
929*5d5fbe79SDavid van Moolenbroek #ifndef LOCK_BINARY
930*5d5fbe79SDavid van Moolenbroek ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
931*5d5fbe79SDavid van Moolenbroek write (fd, lock_buffer, 11);
932*5d5fbe79SDavid van Moolenbroek #else
933*5d5fbe79SDavid van Moolenbroek write(fd, &pid, sizeof(pid));
934*5d5fbe79SDavid van Moolenbroek #endif /* LOCK_BINARY */
935*5d5fbe79SDavid van Moolenbroek close(fd);
936*5d5fbe79SDavid van Moolenbroek return 0;
937*5d5fbe79SDavid van Moolenbroek
938*5d5fbe79SDavid van Moolenbroek #endif /* LOCKLIB */
939*5d5fbe79SDavid van Moolenbroek }
940*5d5fbe79SDavid van Moolenbroek
941*5d5fbe79SDavid van Moolenbroek /*
942*5d5fbe79SDavid van Moolenbroek * unlock - remove our lockfile
943*5d5fbe79SDavid van Moolenbroek */
944*5d5fbe79SDavid van Moolenbroek void
945*5d5fbe79SDavid van Moolenbroek unlock()
946*5d5fbe79SDavid van Moolenbroek {
947*5d5fbe79SDavid van Moolenbroek if (lock_file[0]) {
948*5d5fbe79SDavid van Moolenbroek #ifdef LOCKLIB
949*5d5fbe79SDavid van Moolenbroek (void) rmlock(lock_file, (void *) 0);
950*5d5fbe79SDavid van Moolenbroek #else
951*5d5fbe79SDavid van Moolenbroek unlink(lock_file);
952*5d5fbe79SDavid van Moolenbroek #endif
953*5d5fbe79SDavid van Moolenbroek lock_file[0] = 0;
954*5d5fbe79SDavid van Moolenbroek }
955*5d5fbe79SDavid van Moolenbroek }
956*5d5fbe79SDavid van Moolenbroek
957*5d5fbe79SDavid van Moolenbroek #endif /* Unused */
958*5d5fbe79SDavid van Moolenbroek
959*5d5fbe79SDavid van Moolenbroek #endif /* PPP_SUPPORT */
960