mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2025-08-04 13:34:38 +08:00

This converts all ppp_*() debug functions to ppp_*(()) macros that ensure the code is left out by the linker if the corresponding debug setting is disabled. Downside is that many lines of code are touched, but since these already differ to upstream PPP sources, I figured that's ok... See bug #55199 Signed-off-by: Simon Goldschmidt <goldsimon@gmx.de>
958 lines
20 KiB
C
958 lines
20 KiB
C
/*
|
|
* utils.c - various utility functions used in pppd.
|
|
*
|
|
* Copyright (c) 1999-2002 Paul Mackerras. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. The name(s) of the authors of this software must not be used to
|
|
* endorse or promote products derived from this software without
|
|
* prior written permission.
|
|
*
|
|
* 3. Redistributions of any form whatsoever must retain the following
|
|
* acknowledgment:
|
|
* "This product includes software developed by Paul Mackerras
|
|
* <paulus@samba.org>".
|
|
*
|
|
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
|
|
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "netif/ppp/ppp_opts.h"
|
|
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
|
|
|
#if 0 /* UNUSED */
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <syslog.h>
|
|
#include <netdb.h>
|
|
#include <time.h>
|
|
#include <utmp.h>
|
|
#include <pwd.h>
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#ifdef SVR4
|
|
#include <sys/mkdev.h>
|
|
#endif
|
|
#endif /* UNUSED */
|
|
|
|
#include "netif/ppp/ppp_impl.h"
|
|
|
|
#include "netif/ppp/fsm.h"
|
|
#include "netif/ppp/lcp.h"
|
|
|
|
#if defined(SUNOS4)
|
|
extern char *strerror();
|
|
#endif
|
|
|
|
static void ppp_logit(int level, const char *fmt, va_list args);
|
|
static void ppp_log_write(int level, char *buf);
|
|
#if PRINTPKT_SUPPORT
|
|
static void ppp_vslp_printer(void *arg, const char *fmt, ...);
|
|
static void ppp_format_packet(const u_char *p, int len,
|
|
void (*printer) (void *, const char *, ...), void *arg);
|
|
|
|
struct buffer_info {
|
|
char *ptr;
|
|
int len;
|
|
};
|
|
#endif /* PRINTPKT_SUPPORT */
|
|
|
|
/*
|
|
* ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
|
|
* always leaves destination null-terminated (for len > 0).
|
|
*/
|
|
size_t ppp_strlcpy(char *dest, const char *src, size_t len) {
|
|
size_t ret = strlen(src);
|
|
|
|
if (len != 0) {
|
|
if (ret < len)
|
|
strcpy(dest, src);
|
|
else {
|
|
strncpy(dest, src, len - 1);
|
|
dest[len-1] = 0;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer,
|
|
* always leaves destination null-terminated (for len > 0).
|
|
*/
|
|
size_t ppp_strlcat(char *dest, const char *src, size_t len) {
|
|
size_t dlen = strlen(dest);
|
|
|
|
return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
|
|
}
|
|
|
|
|
|
/*
|
|
* ppp_slprintf - format a message into a buffer. Like sprintf except we
|
|
* also specify the length of the output buffer, and we handle
|
|
* %m (error message), %v (visible string),
|
|
* %q (quoted string), %t (current time) and %I (IP address) formats.
|
|
* Doesn't do floating-point formats.
|
|
* Returns the number of chars put into buf.
|
|
*/
|
|
int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) {
|
|
va_list args;
|
|
int n;
|
|
|
|
va_start(args, fmt);
|
|
n = ppp_vslprintf(buf, buflen, fmt, args);
|
|
va_end(args);
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
* ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args.
|
|
*/
|
|
#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
|
|
|
|
int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) {
|
|
int c, i, n;
|
|
int width, prec, fillch;
|
|
int base, len, neg, quoted;
|
|
unsigned long val = 0;
|
|
const char *f;
|
|
char *str, *buf0;
|
|
const unsigned char *p;
|
|
char num[32];
|
|
#if 0 /* need port */
|
|
time_t t;
|
|
#endif /* need port */
|
|
u32_t ip;
|
|
static char hexchars[] = "0123456789abcdef";
|
|
#if PRINTPKT_SUPPORT
|
|
struct buffer_info bufinfo;
|
|
#endif /* PRINTPKT_SUPPORT */
|
|
|
|
buf0 = buf;
|
|
--buflen;
|
|
while (buflen > 0) {
|
|
for (f = fmt; *f != '%' && *f != 0; ++f)
|
|
;
|
|
if (f > fmt) {
|
|
len = f - fmt;
|
|
if (len > buflen)
|
|
len = buflen;
|
|
memcpy(buf, fmt, len);
|
|
buf += len;
|
|
buflen -= len;
|
|
fmt = f;
|
|
}
|
|
if (*fmt == 0)
|
|
break;
|
|
c = *++fmt;
|
|
width = 0;
|
|
prec = -1;
|
|
fillch = ' ';
|
|
if (c == '0') {
|
|
fillch = '0';
|
|
c = *++fmt;
|
|
}
|
|
if (c == '*') {
|
|
width = va_arg(args, int);
|
|
c = *++fmt;
|
|
} else {
|
|
while (lwip_isdigit(c)) {
|
|
width = width * 10 + c - '0';
|
|
c = *++fmt;
|
|
}
|
|
}
|
|
if (c == '.') {
|
|
c = *++fmt;
|
|
if (c == '*') {
|
|
prec = va_arg(args, int);
|
|
c = *++fmt;
|
|
} else {
|
|
prec = 0;
|
|
while (lwip_isdigit(c)) {
|
|
prec = prec * 10 + c - '0';
|
|
c = *++fmt;
|
|
}
|
|
}
|
|
}
|
|
str = 0;
|
|
base = 0;
|
|
neg = 0;
|
|
++fmt;
|
|
switch (c) {
|
|
case 'l':
|
|
c = *fmt++;
|
|
switch (c) {
|
|
case 'd':
|
|
val = va_arg(args, long);
|
|
if ((long)val < 0) {
|
|
neg = 1;
|
|
val = (unsigned long)-(long)val;
|
|
}
|
|
base = 10;
|
|
break;
|
|
case 'u':
|
|
val = va_arg(args, unsigned long);
|
|
base = 10;
|
|
break;
|
|
default:
|
|
OUTCHAR('%');
|
|
OUTCHAR('l');
|
|
--fmt; /* so %lz outputs %lz etc. */
|
|
continue;
|
|
}
|
|
break;
|
|
case 'd':
|
|
i = va_arg(args, int);
|
|
if (i < 0) {
|
|
neg = 1;
|
|
val = -i;
|
|
} else
|
|
val = i;
|
|
base = 10;
|
|
break;
|
|
case 'u':
|
|
val = va_arg(args, unsigned int);
|
|
base = 10;
|
|
break;
|
|
case 'o':
|
|
val = va_arg(args, unsigned int);
|
|
base = 8;
|
|
break;
|
|
case 'x':
|
|
case 'X':
|
|
val = va_arg(args, unsigned int);
|
|
base = 16;
|
|
break;
|
|
#if 0 /* unused (and wrong on LLP64 systems) */
|
|
case 'p':
|
|
val = (unsigned long) va_arg(args, void *);
|
|
base = 16;
|
|
neg = 2;
|
|
break;
|
|
#endif /* unused (and wrong on LLP64 systems) */
|
|
case 's':
|
|
str = va_arg(args, char *);
|
|
break;
|
|
case 'c':
|
|
num[0] = va_arg(args, int);
|
|
num[1] = 0;
|
|
str = num;
|
|
break;
|
|
#if 0 /* do we always have strerror() in embedded ? */
|
|
case 'm':
|
|
str = strerror(errno);
|
|
break;
|
|
#endif /* do we always have strerror() in embedded ? */
|
|
case 'I':
|
|
ip = va_arg(args, u32_t);
|
|
ip = lwip_ntohl(ip);
|
|
ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
|
|
(ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
|
|
str = num;
|
|
break;
|
|
#if 0 /* need port */
|
|
case 't':
|
|
time(&t);
|
|
str = ctime(&t);
|
|
str += 4; /* chop off the day name */
|
|
str[15] = 0; /* chop off year and newline */
|
|
break;
|
|
#endif /* need port */
|
|
case 'v': /* "visible" string */
|
|
case 'q': /* quoted string */
|
|
quoted = c == 'q';
|
|
p = va_arg(args, unsigned char *);
|
|
if (p == NULL)
|
|
p = (const unsigned char *)"<NULL>";
|
|
if (fillch == '0' && prec >= 0) {
|
|
n = prec;
|
|
} else {
|
|
n = strlen((const char *)p);
|
|
if (prec >= 0 && n > prec)
|
|
n = prec;
|
|
}
|
|
while (n > 0 && buflen > 0) {
|
|
c = *p++;
|
|
--n;
|
|
if (!quoted && c >= 0x80) {
|
|
OUTCHAR('M');
|
|
OUTCHAR('-');
|
|
c -= 0x80;
|
|
}
|
|
if (quoted && (c == '"' || c == '\\'))
|
|
OUTCHAR('\\');
|
|
if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
|
|
if (quoted) {
|
|
OUTCHAR('\\');
|
|
switch (c) {
|
|
case '\t': OUTCHAR('t'); break;
|
|
case '\n': OUTCHAR('n'); break;
|
|
case '\b': OUTCHAR('b'); break;
|
|
case '\f': OUTCHAR('f'); break;
|
|
default:
|
|
OUTCHAR('x');
|
|
OUTCHAR(hexchars[c >> 4]);
|
|
OUTCHAR(hexchars[c & 0xf]);
|
|
}
|
|
} else {
|
|
if (c == '\t')
|
|
OUTCHAR(c);
|
|
else {
|
|
OUTCHAR('^');
|
|
OUTCHAR(c ^ 0x40);
|
|
}
|
|
}
|
|
} else
|
|
OUTCHAR(c);
|
|
}
|
|
continue;
|
|
#if PRINTPKT_SUPPORT
|
|
case 'P': /* print PPP packet */
|
|
bufinfo.ptr = buf;
|
|
bufinfo.len = buflen + 1;
|
|
p = va_arg(args, unsigned char *);
|
|
n = va_arg(args, int);
|
|
ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo);
|
|
buf = bufinfo.ptr;
|
|
buflen = bufinfo.len - 1;
|
|
continue;
|
|
#endif /* PRINTPKT_SUPPORT */
|
|
case 'B':
|
|
p = va_arg(args, unsigned char *);
|
|
for (n = prec; n > 0; --n) {
|
|
c = *p++;
|
|
if (fillch == ' ')
|
|
OUTCHAR(' ');
|
|
OUTCHAR(hexchars[(c >> 4) & 0xf]);
|
|
OUTCHAR(hexchars[c & 0xf]);
|
|
}
|
|
continue;
|
|
default:
|
|
*buf++ = '%';
|
|
if (c != '%')
|
|
--fmt; /* so %z outputs %z etc. */
|
|
--buflen;
|
|
continue;
|
|
}
|
|
if (base != 0) {
|
|
str = num + sizeof(num);
|
|
*--str = 0;
|
|
while (str > num + neg) {
|
|
*--str = hexchars[val % base];
|
|
val = val / base;
|
|
if (--prec <= 0 && val == 0)
|
|
break;
|
|
}
|
|
switch (neg) {
|
|
case 1:
|
|
*--str = '-';
|
|
break;
|
|
case 2:
|
|
*--str = 'x';
|
|
*--str = '0';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
len = num + sizeof(num) - 1 - str;
|
|
} else {
|
|
len = strlen(str);
|
|
if (prec >= 0 && len > prec)
|
|
len = prec;
|
|
}
|
|
if (width > 0) {
|
|
if (width > buflen)
|
|
width = buflen;
|
|
if ((n = width - len) > 0) {
|
|
buflen -= n;
|
|
for (; n > 0; --n)
|
|
*buf++ = fillch;
|
|
}
|
|
}
|
|
if (len > buflen)
|
|
len = buflen;
|
|
memcpy(buf, str, len);
|
|
buf += len;
|
|
buflen -= len;
|
|
}
|
|
*buf = 0;
|
|
return buf - buf0;
|
|
}
|
|
|
|
#if PRINTPKT_SUPPORT
|
|
/*
|
|
* vslp_printer - used in processing a %P format
|
|
*/
|
|
static void ppp_vslp_printer(void *arg, const char *fmt, ...) {
|
|
int n;
|
|
va_list pvar;
|
|
struct buffer_info *bi;
|
|
|
|
va_start(pvar, fmt);
|
|
bi = (struct buffer_info *) arg;
|
|
n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar);
|
|
va_end(pvar);
|
|
|
|
bi->ptr += n;
|
|
bi->len -= n;
|
|
}
|
|
#endif /* PRINTPKT_SUPPORT */
|
|
|
|
#if 0 /* UNUSED */
|
|
/*
|
|
* log_packet - format a packet and log it.
|
|
*/
|
|
|
|
void
|
|
log_packet(p, len, prefix, level)
|
|
u_char *p;
|
|
int len;
|
|
char *prefix;
|
|
int level;
|
|
{
|
|
init_pr_log(prefix, level);
|
|
ppp_format_packet(p, len, pr_log, &level);
|
|
end_pr_log();
|
|
}
|
|
#endif /* UNUSED */
|
|
|
|
#if PRINTPKT_SUPPORT
|
|
/*
|
|
* ppp_format_packet - make a readable representation of a packet,
|
|
* calling `printer(arg, format, ...)' to output it.
|
|
*/
|
|
static void ppp_format_packet(const u_char *p, int len,
|
|
void (*printer) (void *, const char *, ...), void *arg) {
|
|
int i, n;
|
|
u_short proto;
|
|
const struct protent *protp;
|
|
|
|
if (len >= 2) {
|
|
GETSHORT(proto, p);
|
|
len -= 2;
|
|
for (i = 0; (protp = protocols[i]) != NULL; ++i)
|
|
if (proto == protp->protocol)
|
|
break;
|
|
if (protp != NULL) {
|
|
printer(arg, "[%s", protp->name);
|
|
n = (*protp->printpkt)(p, len, printer, arg);
|
|
printer(arg, "]");
|
|
p += n;
|
|
len -= n;
|
|
} else {
|
|
for (i = 0; (protp = protocols[i]) != NULL; ++i)
|
|
if (proto == (protp->protocol & ~0x8000))
|
|
break;
|
|
if (protp != 0 && protp->data_name != 0) {
|
|
printer(arg, "[%s data]", protp->data_name);
|
|
if (len > 8)
|
|
printer(arg, "%.8B ...", p);
|
|
else
|
|
printer(arg, "%.*B", len, p);
|
|
len = 0;
|
|
} else
|
|
printer(arg, "[proto=0x%x]", proto);
|
|
}
|
|
}
|
|
|
|
if (len > 32)
|
|
printer(arg, "%.32B ...", p);
|
|
else
|
|
printer(arg, "%.*B", len, p);
|
|
}
|
|
#endif /* PRINTPKT_SUPPORT */
|
|
|
|
#if 0 /* UNUSED */
|
|
/*
|
|
* init_pr_log, end_pr_log - initialize and finish use of pr_log.
|
|
*/
|
|
|
|
static char line[256]; /* line to be logged accumulated here */
|
|
static char *linep; /* current pointer within line */
|
|
static int llevel; /* level for logging */
|
|
|
|
void
|
|
init_pr_log(prefix, level)
|
|
const char *prefix;
|
|
int level;
|
|
{
|
|
linep = line;
|
|
if (prefix != NULL) {
|
|
ppp_strlcpy(line, prefix, sizeof(line));
|
|
linep = line + strlen(line);
|
|
}
|
|
llevel = level;
|
|
}
|
|
|
|
void
|
|
end_pr_log()
|
|
{
|
|
if (linep != line) {
|
|
*linep = 0;
|
|
ppp_log_write(llevel, line);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* pr_log - printer routine for outputting to log
|
|
*/
|
|
void
|
|
pr_log (void *arg, const char *fmt, ...)
|
|
{
|
|
int l, n;
|
|
va_list pvar;
|
|
char *p, *eol;
|
|
char buf[256];
|
|
|
|
va_start(pvar, fmt);
|
|
n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar);
|
|
va_end(pvar);
|
|
|
|
p = buf;
|
|
eol = strchr(buf, '\n');
|
|
if (linep != line) {
|
|
l = (eol == NULL)? n: eol - buf;
|
|
if (linep + l < line + sizeof(line)) {
|
|
if (l > 0) {
|
|
memcpy(linep, buf, l);
|
|
linep += l;
|
|
}
|
|
if (eol == NULL)
|
|
return;
|
|
p = eol + 1;
|
|
eol = strchr(p, '\n');
|
|
}
|
|
*linep = 0;
|
|
ppp_log_write(llevel, line);
|
|
linep = line;
|
|
}
|
|
|
|
while (eol != NULL) {
|
|
*eol = 0;
|
|
ppp_log_write(llevel, p);
|
|
p = eol + 1;
|
|
eol = strchr(p, '\n');
|
|
}
|
|
|
|
/* assumes sizeof(buf) <= sizeof(line) */
|
|
l = buf + n - p;
|
|
if (l > 0) {
|
|
memcpy(line, p, n);
|
|
linep = line + l;
|
|
}
|
|
}
|
|
#endif /* UNUSED */
|
|
|
|
/*
|
|
* ppp_print_string - print a readable representation of a string using
|
|
* printer.
|
|
*/
|
|
void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) {
|
|
int c;
|
|
|
|
printer(arg, "\"");
|
|
for (; len > 0; --len) {
|
|
c = *p++;
|
|
if (' ' <= c && c <= '~') {
|
|
if (c == '\\' || c == '"')
|
|
printer(arg, "\\");
|
|
printer(arg, "%c", c);
|
|
} else {
|
|
switch (c) {
|
|
case '\n':
|
|
printer(arg, "\\n");
|
|
break;
|
|
case '\r':
|
|
printer(arg, "\\r");
|
|
break;
|
|
case '\t':
|
|
printer(arg, "\\t");
|
|
break;
|
|
default:
|
|
printer(arg, "\\%.3o", (u8_t)c);
|
|
/* no break */
|
|
}
|
|
}
|
|
}
|
|
printer(arg, "\"");
|
|
}
|
|
|
|
/*
|
|
* ppp_logit - does the hard work for fatal et al.
|
|
*/
|
|
static void ppp_logit(int level, const char *fmt, va_list args) {
|
|
char buf[1024];
|
|
|
|
ppp_vslprintf(buf, sizeof(buf), fmt, args);
|
|
ppp_log_write(level, buf);
|
|
}
|
|
|
|
static void ppp_log_write(int level, char *buf) {
|
|
LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */
|
|
LWIP_UNUSED_ARG(buf);
|
|
PPPDEBUG(level, ("%s\n", buf) );
|
|
#if 0
|
|
if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) {
|
|
int n = strlen(buf);
|
|
|
|
if (n > 0 && buf[n-1] == '\n')
|
|
--n;
|
|
if (write(log_to_fd, buf, n) != n
|
|
|| write(log_to_fd, "\n", 1) != 1)
|
|
log_to_fd = -1;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* ppp_fatal - log an error message and die horribly.
|
|
*/
|
|
void ppp_fatal_impl(const char *fmt, ...) {
|
|
va_list pvar;
|
|
|
|
va_start(pvar, fmt);
|
|
ppp_logit(LOG_ERR, fmt, pvar);
|
|
va_end(pvar);
|
|
|
|
LWIP_ASSERT("ppp_fatal", 0); /* as promised */
|
|
}
|
|
|
|
/*
|
|
* ppp_error - log an error message.
|
|
*/
|
|
void ppp_error_impl(const char *fmt, ...) {
|
|
va_list pvar;
|
|
|
|
va_start(pvar, fmt);
|
|
ppp_logit(LOG_ERR, fmt, pvar);
|
|
va_end(pvar);
|
|
#if 0 /* UNUSED */
|
|
++error_count;
|
|
#endif /* UNUSED */
|
|
}
|
|
|
|
/*
|
|
* ppp_warn - log a warning message.
|
|
*/
|
|
void ppp_warn_impl(const char *fmt, ...) {
|
|
va_list pvar;
|
|
|
|
va_start(pvar, fmt);
|
|
ppp_logit(LOG_WARNING, fmt, pvar);
|
|
va_end(pvar);
|
|
}
|
|
|
|
/*
|
|
* ppp_notice - log a notice-level message.
|
|
*/
|
|
void ppp_notice_impl(const char *fmt, ...) {
|
|
va_list pvar;
|
|
|
|
va_start(pvar, fmt);
|
|
ppp_logit(LOG_NOTICE, fmt, pvar);
|
|
va_end(pvar);
|
|
}
|
|
|
|
/*
|
|
* ppp_info - log an informational message.
|
|
*/
|
|
void ppp_info_impl(const char *fmt, ...) {
|
|
va_list pvar;
|
|
|
|
va_start(pvar, fmt);
|
|
ppp_logit(LOG_INFO, fmt, pvar);
|
|
va_end(pvar);
|
|
}
|
|
|
|
/*
|
|
* ppp_dbglog - log a debug message.
|
|
*/
|
|
void ppp_dbglog_impl(const char *fmt, ...) {
|
|
va_list pvar;
|
|
|
|
va_start(pvar, fmt);
|
|
ppp_logit(LOG_DEBUG, fmt, pvar);
|
|
va_end(pvar);
|
|
}
|
|
|
|
#if PRINTPKT_SUPPORT
|
|
/*
|
|
* ppp_dump_packet - print out a packet in readable form if it is interesting.
|
|
* Assumes len >= PPP_HDRLEN.
|
|
*/
|
|
void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) {
|
|
int proto;
|
|
|
|
/*
|
|
* don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets.
|
|
*/
|
|
proto = (p[0] << 8) + p[1];
|
|
if (proto < 0xC000 && (proto & ~0x8000) == proto)
|
|
return;
|
|
|
|
/*
|
|
* don't print valid LCP echo request/reply packets if the link is up.
|
|
*/
|
|
if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) {
|
|
unsigned char *lcp = p + 2;
|
|
int l = (lcp[2] << 8) + lcp[3];
|
|
|
|
if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP)
|
|
&& l >= HEADERLEN && l <= len - 2)
|
|
return;
|
|
}
|
|
|
|
ppp_dbglog(("%s %P", tag, p, len));
|
|
}
|
|
#endif /* PRINTPKT_SUPPORT */
|
|
|
|
#if 0 /* Unused */
|
|
|
|
/*
|
|
* complete_read - read a full `count' bytes from fd,
|
|
* unless end-of-file or an error other than EINTR is encountered.
|
|
*/
|
|
ssize_t
|
|
complete_read(int fd, void *buf, size_t count)
|
|
{
|
|
size_t done;
|
|
ssize_t nb;
|
|
char *ptr = buf;
|
|
|
|
for (done = 0; done < count; ) {
|
|
nb = read(fd, ptr, count - done);
|
|
if (nb < 0) {
|
|
if (errno == EINTR)
|
|
continue;
|
|
return -1;
|
|
}
|
|
if (nb == 0)
|
|
break;
|
|
done += nb;
|
|
ptr += nb;
|
|
}
|
|
return done;
|
|
}
|
|
|
|
/* Procedures for locking the serial device using a lock file. */
|
|
#ifndef LOCK_DIR
|
|
#ifdef __linux__
|
|
#define LOCK_DIR "/var/lock"
|
|
#else
|
|
#ifdef SVR4
|
|
#define LOCK_DIR "/var/spool/locks"
|
|
#else
|
|
#define LOCK_DIR "/var/spool/lock"
|
|
#endif
|
|
#endif
|
|
#endif /* LOCK_DIR */
|
|
|
|
static char lock_file[MAXPATHLEN];
|
|
|
|
/*
|
|
* lock - create a lock file for the named device
|
|
*/
|
|
int
|
|
lock(dev)
|
|
char *dev;
|
|
{
|
|
#ifdef LOCKLIB
|
|
int result;
|
|
|
|
result = mklock (dev, (void *) 0);
|
|
if (result == 0) {
|
|
ppp_strlcpy(lock_file, dev, sizeof(lock_file));
|
|
return 0;
|
|
}
|
|
|
|
if (result > 0)
|
|
ppp_notice(("Device %s is locked by pid %d", dev, result));
|
|
else
|
|
ppp_error(("Can't create lock file %s", lock_file));
|
|
return -1;
|
|
|
|
#else /* LOCKLIB */
|
|
|
|
char lock_buffer[12];
|
|
int fd, pid, n;
|
|
|
|
#ifdef SVR4
|
|
struct stat sbuf;
|
|
|
|
if (stat(dev, &sbuf) < 0) {
|
|
ppp_error(("Can't get device number for %s: %m", dev));
|
|
return -1;
|
|
}
|
|
if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
|
|
ppp_error(("Can't lock %s: not a character device", dev));
|
|
return -1;
|
|
}
|
|
ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d",
|
|
LOCK_DIR, major(sbuf.st_dev),
|
|
major(sbuf.st_rdev), minor(sbuf.st_rdev));
|
|
#else
|
|
char *p;
|
|
char lockdev[MAXPATHLEN];
|
|
|
|
if ((p = strstr(dev, "dev/")) != NULL) {
|
|
dev = p + 4;
|
|
strncpy(lockdev, dev, MAXPATHLEN-1);
|
|
lockdev[MAXPATHLEN-1] = 0;
|
|
while ((p = strrchr(lockdev, '/')) != NULL) {
|
|
*p = '_';
|
|
}
|
|
dev = lockdev;
|
|
} else
|
|
if ((p = strrchr(dev, '/')) != NULL)
|
|
dev = p + 1;
|
|
|
|
ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev);
|
|
#endif
|
|
|
|
while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
|
|
if (errno != EEXIST) {
|
|
ppp_error(("Can't create lock file %s: %m", lock_file));
|
|
break;
|
|
}
|
|
|
|
/* Read the lock file to find out who has the device locked. */
|
|
fd = open(lock_file, O_RDONLY, 0);
|
|
if (fd < 0) {
|
|
if (errno == ENOENT) /* This is just a timing problem. */
|
|
continue;
|
|
ppp_error(("Can't open existing lock file %s: %m", lock_file));
|
|
break;
|
|
}
|
|
#ifndef LOCK_BINARY
|
|
n = read(fd, lock_buffer, 11);
|
|
#else
|
|
n = read(fd, &pid, sizeof(pid));
|
|
#endif /* LOCK_BINARY */
|
|
close(fd);
|
|
fd = -1;
|
|
if (n <= 0) {
|
|
ppp_error(("Can't read pid from lock file %s", lock_file));
|
|
break;
|
|
}
|
|
|
|
/* See if the process still exists. */
|
|
#ifndef LOCK_BINARY
|
|
lock_buffer[n] = 0;
|
|
pid = atoi(lock_buffer);
|
|
#endif /* LOCK_BINARY */
|
|
if (pid == getpid())
|
|
return 1; /* somebody else locked it for us */
|
|
if (pid == 0
|
|
|| (kill(pid, 0) == -1 && errno == ESRCH)) {
|
|
if (unlink (lock_file) == 0) {
|
|
ppp_notice(("Removed stale lock on %s (pid %d)", dev, pid));
|
|
continue;
|
|
}
|
|
ppp_warn(("Couldn't remove stale lock on %s", dev));
|
|
} else
|
|
ppp_notice(("Device %s is locked by pid %d", dev, pid));
|
|
break;
|
|
}
|
|
|
|
if (fd < 0) {
|
|
lock_file[0] = 0;
|
|
return -1;
|
|
}
|
|
|
|
pid = getpid();
|
|
#ifndef LOCK_BINARY
|
|
ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
|
|
write (fd, lock_buffer, 11);
|
|
#else
|
|
write(fd, &pid, sizeof (pid));
|
|
#endif
|
|
close(fd);
|
|
return 0;
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* relock - called to update our lockfile when we are about to detach,
|
|
* thus changing our pid (we fork, the child carries on, and the parent dies).
|
|
* Note that this is called by the parent, with pid equal to the pid
|
|
* of the child. This avoids a potential race which would exist if
|
|
* we had the child rewrite the lockfile (the parent might die first,
|
|
* and another process could think the lock was stale if it checked
|
|
* between when the parent died and the child rewrote the lockfile).
|
|
*/
|
|
int
|
|
relock(pid)
|
|
int pid;
|
|
{
|
|
#ifdef LOCKLIB
|
|
/* XXX is there a way to do this? */
|
|
return -1;
|
|
#else /* LOCKLIB */
|
|
|
|
int fd;
|
|
char lock_buffer[12];
|
|
|
|
if (lock_file[0] == 0)
|
|
return -1;
|
|
fd = open(lock_file, O_WRONLY, 0);
|
|
if (fd < 0) {
|
|
ppp_error(("Couldn't reopen lock file %s: %m", lock_file));
|
|
lock_file[0] = 0;
|
|
return -1;
|
|
}
|
|
|
|
#ifndef LOCK_BINARY
|
|
ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
|
|
write (fd, lock_buffer, 11);
|
|
#else
|
|
write(fd, &pid, sizeof(pid));
|
|
#endif /* LOCK_BINARY */
|
|
close(fd);
|
|
return 0;
|
|
|
|
#endif /* LOCKLIB */
|
|
}
|
|
|
|
/*
|
|
* unlock - remove our lockfile
|
|
*/
|
|
void
|
|
unlock()
|
|
{
|
|
if (lock_file[0]) {
|
|
#ifdef LOCKLIB
|
|
(void) rmlock(lock_file, (void *) 0);
|
|
#else
|
|
unlink(lock_file);
|
|
#endif
|
|
lock_file[0] = 0;
|
|
}
|
|
}
|
|
|
|
#endif /* Unused */
|
|
|
|
#endif /* PPP_SUPPORT */
|