blob: d1ccf74ebb5063e3427d9dec2165358728fe4c9e [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * utils.c - various utility functions used in pppd.
3 *
4 * Copyright (c) 1999 The Australian National University.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the Australian National University. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#define RCSID "$Id: utils.c,v 1.1 2008-08-04 06:11:52 winfred Exp $"
21
22#include <stdio.h>
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <time.h>
28#include <signal.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <syslog.h>
32#include <netdb.h>
33#include <utmp.h>
34#include <pwd.h>
35#include <sys/param.h>
36#include <sys/types.h>
37#include <sys/wait.h>
38#include <sys/time.h>
39#include <sys/resource.h>
40#include <sys/stat.h>
41#include <sys/socket.h>
42#include <net/ethernet.h>
43#include <netinet/in.h>
44#ifdef SVR4
45#include <sys/mkdev.h>
46#endif
47
48#include "pppd.h"
49
50#include <sys/sysinfo.h>
51
52static const char rcsid[] = RCSID;
53
54#if defined(SUNOS4)
55extern char *strerror();
56#endif
57
58static void vslp_printer __P((void *, char *, ...));
59static void format_packet __P((u_char *, int, void (*) (void *, char *, ...),
60 void *));
61
62struct buffer_info {
63 char *ptr;
64 int len;
65};
66
67/*
68 * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
69 * always leaves destination null-terminated (for len > 0).
70 */
71size_t
72strlcpy(dest, src, len)
73 char *dest;
74 const char *src;
75 size_t len;
76{
77 size_t ret = strlen(src);
78
79 if (len != 0) {
80 if (ret < len)
81 strcpy(dest, src);
82 else {
83 strncpy(dest, src, len - 1);
84 dest[len-1] = 0;
85 }
86 }
87 return ret;
88}
89
90/*
91 * strlcat - like strcat/strncat, doesn't overflow destination buffer,
92 * always leaves destination null-terminated (for len > 0).
93 */
94size_t
95strlcat(dest, src, len)
96 char *dest;
97 const char *src;
98 size_t len;
99{
100 size_t dlen = strlen(dest);
101
102 return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
103}
104
105
106/*
107 * slprintf - format a message into a buffer. Like sprintf except we
108 * also specify the length of the output buffer, and we handle
109 * %r (recursive format), %m (error message), %v (visible string),
110 * %q (quoted string), %t (current time) and %I (IP address) formats.
111 * Doesn't do floating-point formats.
112 * Returns the number of chars put into buf.
113 */
114int
115slprintf __V((char *buf, int buflen, char *fmt, ...))
116{
117 va_list args;
118 int n;
119
120#if defined(__STDC__)
121 va_start(args, fmt);
122#else
123 char *buf;
124 int buflen;
125 char *fmt;
126 va_start(args);
127 buf = va_arg(args, char *);
128 buflen = va_arg(args, int);
129 fmt = va_arg(args, char *);
130#endif
131 n = vslprintf(buf, buflen, fmt, args);
132 va_end(args);
133 return n;
134}
135
136/*
137 * vslprintf - like slprintf, takes a va_list instead of a list of args.
138 */
139#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
140
141int
142vslprintf(buf, buflen, fmt, args)
143 char *buf;
144 int buflen;
145 char *fmt;
146 va_list args;
147{
148 int c, i, n;
149 int width, prec, fillch;
150 int base, len, neg, quoted;
151 unsigned long val = 0;
152 char *str, *f, *buf0;
153 unsigned char *p;
154 char num[32];
155 time_t t;
156 u_int32_t ip;
157 static char hexchars[] = "0123456789abcdef";
158 struct buffer_info bufinfo;
159
160 buf0 = buf;
161 --buflen;
162 while (buflen > 0) {
163 for (f = fmt; *f != '%' && *f != 0; ++f)
164 ;
165 if (f > fmt) {
166 len = f - fmt;
167 if (len > buflen)
168 len = buflen;
169 memcpy(buf, fmt, len);
170 buf += len;
171 buflen -= len;
172 fmt = f;
173 }
174 if (*fmt == 0)
175 break;
176 c = *++fmt;
177 width = 0;
178 prec = -1;
179 fillch = ' ';
180 if (c == '0') {
181 fillch = '0';
182 c = *++fmt;
183 }
184 if (c == '*') {
185 width = va_arg(args, int);
186 c = *++fmt;
187 } else {
188 while (isdigit(c)) {
189 width = width * 10 + c - '0';
190 c = *++fmt;
191 }
192 }
193 if (c == '.') {
194 c = *++fmt;
195 if (c == '*') {
196 prec = va_arg(args, int);
197 c = *++fmt;
198 } else {
199 prec = 0;
200 while (isdigit(c)) {
201 prec = prec * 10 + c - '0';
202 c = *++fmt;
203 }
204 }
205 }
206 str = 0;
207 base = 0;
208 neg = 0;
209 ++fmt;
210 switch (c) {
211 case 'd':
212 i = va_arg(args, int);
213 if (i < 0) {
214 neg = 1;
215 val = -i;
216 } else
217 val = i;
218 base = 10;
219 break;
220 case 'u':
221 val = va_arg(args, unsigned int);
222 base = 10;
223 break;
224 case 'o':
225 val = va_arg(args, unsigned int);
226 base = 8;
227 break;
228 case 'x':
229 case 'X':
230 val = va_arg(args, unsigned int);
231 base = 16;
232 break;
233 case 'p':
234 val = (unsigned long) va_arg(args, void *);
235 base = 16;
236 neg = 2;
237 break;
238 case 's':
239 str = va_arg(args, char *);
240 break;
241 case 'c':
242 num[0] = va_arg(args, int);
243 num[1] = 0;
244 str = num;
245 break;
246 case 'm':
247 str = strerror(errno);
248 break;
249 case 'I':
250 ip = va_arg(args, u_int32_t);
251 ip = ntohl(ip);
252 slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
253 (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
254 str = num;
255 break;
256 case 'E':
257 p = va_arg (args, unsigned char *);
258 for (n = ETH_ALEN; n > 0; --n) {
259 c = *p++;
260 OUTCHAR (hexchars[(c >> 4) & 0xf]);
261 OUTCHAR (hexchars[c & 0xf]);
262 if (n > 1)
263 OUTCHAR (':');
264 }
265 continue;
266 case 'r':
267 f = va_arg(args, char *);
268
269 n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list));
270 buf += n;
271 buflen -= n;
272 continue;
273 case 't':
274 time(&t);
275 str = ctime(&t);
276 str += 4; /* chop off the day name */
277 str[15] = 0; /* chop off year and newline */
278 break;
279 case 'v': /* "visible" string */
280 case 'q': /* quoted string */
281 quoted = c == 'q';
282 p = va_arg(args, unsigned char *);
283 if (fillch == '0' && prec >= 0) {
284 n = prec;
285 } else {
286 n = strlen((char *)p);
287 if (prec >= 0 && n > prec)
288 n = prec;
289 }
290 while (n > 0 && buflen > 0) {
291 c = *p++;
292 --n;
293 if (!quoted && c >= 0x80) {
294 OUTCHAR('M');
295 OUTCHAR('-');
296 c -= 0x80;
297 }
298 if (quoted && (c == '"' || c == '\\'))
299 OUTCHAR('\\');
300 if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
301 if (quoted) {
302 OUTCHAR('\\');
303 switch (c) {
304 case '\t': OUTCHAR('t'); break;
305 case '\n': OUTCHAR('n'); break;
306 case '\b': OUTCHAR('b'); break;
307 case '\f': OUTCHAR('f'); break;
308 default:
309 OUTCHAR('x');
310 OUTCHAR(hexchars[c >> 4]);
311 OUTCHAR(hexchars[c & 0xf]);
312 }
313 } else {
314 if (c == '\t')
315 OUTCHAR(c);
316 else {
317 OUTCHAR('^');
318 OUTCHAR(c ^ 0x40);
319 }
320 }
321 } else
322 OUTCHAR(c);
323 }
324 continue;
325 case 'P': /* print PPP packet */
326 bufinfo.ptr = buf;
327 bufinfo.len = buflen + 1;
328 p = va_arg(args, unsigned char *);
329 n = va_arg(args, int);
330 format_packet(p, n, vslp_printer, &bufinfo);
331 buf = bufinfo.ptr;
332 buflen = bufinfo.len - 1;
333 continue;
334 case 'B':
335 p = va_arg(args, unsigned char *);
336 for (n = prec; n > 0; --n) {
337 c = *p++;
338 if (fillch == ' ')
339 OUTCHAR(' ');
340 OUTCHAR(hexchars[(c >> 4) & 0xf]);
341 OUTCHAR(hexchars[c & 0xf]);
342 }
343 continue;
344 default:
345 *buf++ = '%';
346 if (c != '%')
347 --fmt; /* so %z outputs %z etc. */
348 --buflen;
349 continue;
350 }
351 if (base != 0) {
352 str = num + sizeof(num);
353 *--str = 0;
354 while (str > num + neg) {
355 *--str = hexchars[val % base];
356 val = val / base;
357 if (--prec <= 0 && val == 0)
358 break;
359 }
360 switch (neg) {
361 case 1:
362 *--str = '-';
363 break;
364 case 2:
365 *--str = 'x';
366 *--str = '0';
367 break;
368 }
369 len = num + sizeof(num) - 1 - str;
370 } else {
371 len = strlen(str);
372 if (prec >= 0 && len > prec)
373 len = prec;
374 }
375 if (width > 0) {
376 if (width > buflen)
377 width = buflen;
378 if ((n = width - len) > 0) {
379 buflen -= n;
380 for (; n > 0; --n)
381 *buf++ = fillch;
382 }
383 }
384 if (len > buflen)
385 len = buflen;
386 memcpy(buf, str, len);
387 buf += len;
388 buflen -= len;
389 }
390 *buf = 0;
391 return buf - buf0;
392}
393
394/*
395 * vslp_printer - used in processing a %P format
396 */
397static void
398vslp_printer __V((void *arg, char *fmt, ...))
399{
400 int n;
401 va_list pvar;
402 struct buffer_info *bi;
403
404#if defined(__STDC__)
405 va_start(pvar, fmt);
406#else
407 void *arg;
408 char *fmt;
409 va_start(pvar);
410 arg = va_arg(pvar, void *);
411 fmt = va_arg(pvar, char *);
412#endif
413
414 bi = (struct buffer_info *) arg;
415 n = vslprintf(bi->ptr, bi->len, fmt, pvar);
416 va_end(pvar);
417
418 bi->ptr += n;
419 bi->len -= n;
420}
421
422#ifdef unused
423/*
424 * log_packet - format a packet and log it.
425 */
426
427void
428log_packet(p, len, prefix, level)
429 u_char *p;
430 int len;
431 char *prefix;
432 int level;
433{
434 init_pr_log(prefix, level);
435 format_packet(p, len, pr_log, &level);
436 end_pr_log();
437}
438#endif /* unused */
439
440/*
441 * format_packet - make a readable representation of a packet,
442 * calling `printer(arg, format, ...)' to output it.
443 */
444static void
445format_packet(p, len, printer, arg)
446 u_char *p;
447 int len;
448 void (*printer) __P((void *, char *, ...));
449 void *arg;
450{
451 int i, n;
452 u_short proto;
453 struct protent *protp;
454
455 if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
456 p += 2;
457 GETSHORT(proto, p);
458 len -= PPP_HDRLEN;
459 for (i = 0; (protp = protocols[i]) != NULL; ++i)
460 if (proto == protp->protocol)
461 break;
462 if (protp != NULL) {
463 printer(arg, "[%s", protp->name);
464 n = (*protp->printpkt)(p, len, printer, arg);
465 printer(arg, "]");
466 p += n;
467 len -= n;
468 } else {
469 for (i = 0; (protp = protocols[i]) != NULL; ++i)
470 if (proto == (protp->protocol & ~0x8000))
471 break;
472 if (protp != 0 && protp->data_name != 0) {
473 printer(arg, "[%s data]", protp->data_name);
474 if (len > 8)
475 printer(arg, "%.8B ...", p);
476 else
477 printer(arg, "%.*B", len, p);
478 len = 0;
479 } else
480 printer(arg, "[proto=0x%x]", proto);
481 }
482 }
483
484 if (len > 32)
485 printer(arg, "%.32B ...", p);
486 else
487 printer(arg, "%.*B", len, p);
488}
489
490#ifdef DEBUG
491
492static void logit __P((int, char *, va_list));
493static void log_write __P((int, char *));
494
495/*
496 * init_pr_log, end_pr_log - initialize and finish use of pr_log.
497 */
498
499static char line[256]; /* line to be logged accumulated here */
500static char *linep; /* current pointer within line */
501static int llevel; /* level for logging */
502
503void
504init_pr_log(prefix, level)
505 char *prefix;
506 int level;
507{
508 linep = line;
509 if (prefix != NULL) {
510 strlcpy(line, prefix, sizeof(line));
511 linep = line + strlen(line);
512 }
513 llevel = level;
514}
515
516void
517end_pr_log()
518{
519 if (linep != line) {
520 *linep = 0;
521 log_write(llevel, line);
522 }
523}
524
525/*
526 * pr_log - printer routine for outputting to syslog
527 */
528void
529pr_log __V((void *arg, char *fmt, ...))
530{
531 int l, n;
532 va_list pvar;
533 char *p, *eol;
534 char buf[256];
535
536#if defined(__STDC__)
537 va_start(pvar, fmt);
538#else
539 void *arg;
540 char *fmt;
541 va_start(pvar);
542 arg = va_arg(pvar, void *);
543 fmt = va_arg(pvar, char *);
544#endif
545
546 n = vslprintf(buf, sizeof(buf), fmt, pvar);
547 va_end(pvar);
548
549 p = buf;
550 eol = strchr(buf, '\n');
551 if (linep != line) {
552 l = (eol == NULL)? n: eol - buf;
553 if (linep + l < line + sizeof(line)) {
554 if (l > 0) {
555 memcpy(linep, buf, l);
556 linep += l;
557 }
558 if (eol == NULL)
559 return;
560 p = eol + 1;
561 eol = strchr(p, '\n');
562 }
563 *linep = 0;
564 log_write(llevel, line);
565 linep = line;
566 }
567
568 while (eol != NULL) {
569 *eol = 0;
570 log_write(llevel, p);
571 p = eol + 1;
572 eol = strchr(p, '\n');
573 }
574
575 /* assumes sizeof(buf) <= sizeof(line) */
576 l = buf + n - p;
577 if (l > 0) {
578 memcpy(line, p, n);
579 linep = line + l;
580 }
581}
582
583/*
584 * print_string - print a readable representation of a string using
585 * printer.
586 */
587void
588print_string(p, len, printer, arg)
589 char *p;
590 int len;
591 void (*printer) __P((void *, char *, ...));
592 void *arg;
593{
594 int c;
595
596 printer(arg, "\"");
597 for (; len > 0; --len) {
598 c = *p++;
599 if (' ' <= c && c <= '~') {
600 if (c == '\\' || c == '"')
601 printer(arg, "\\");
602 printer(arg, "%c", c);
603 } else {
604 switch (c) {
605 case '\n':
606 printer(arg, "\\n");
607 break;
608 case '\r':
609 printer(arg, "\\r");
610 break;
611 case '\t':
612 printer(arg, "\\t");
613 break;
614 default:
615 printer(arg, "\\%.3o", c);
616 }
617 }
618 }
619 printer(arg, "\"");
620}
621
622/*
623 * logit - does the hard work for fatal et al.
624 */
625static void
626logit(level, fmt, args)
627 int level;
628 char *fmt;
629 va_list args;
630{
631 int n;
632 char buf[1024];
633
634 n = vslprintf(buf, sizeof(buf), fmt, args);
635 log_write(level, buf);
636}
637
638static void
639log_write(level, buf)
640 int level;
641 char *buf;
642{
643 syslog(level, "%s", buf);
644 if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) {
645 int n = strlen(buf);
646
647 if (n > 0 && buf[n-1] == '\n')
648 --n;
649 if (write(log_to_fd, buf, n) != n
650 || write(log_to_fd, "\n", 1) != 1)
651 log_to_fd = -1;
652 }
653}
654
655/*
656 * fatal - log an error message and die horribly.
657 */
658void
659fatal __V((char *fmt, ...))
660{
661 va_list pvar;
662
663#if defined(__STDC__)
664 va_start(pvar, fmt);
665#else
666 char *fmt;
667 va_start(pvar);
668 fmt = va_arg(pvar, char *);
669#endif
670
671 logit(LOG_ERR, fmt, pvar);
672 va_end(pvar);
673
674 die(1); /* as promised */
675}
676
677/*
678 * error - log an error message.
679 */
680void
681error __V((char *fmt, ...))
682{
683 va_list pvar;
684
685#if defined(__STDC__)
686 va_start(pvar, fmt);
687#else
688 char *fmt;
689 va_start(pvar);
690 fmt = va_arg(pvar, char *);
691#endif
692
693 logit(LOG_ERR, fmt, pvar);
694 va_end(pvar);
695}
696
697/*
698 * warn - log a warning message.
699 */
700void
701warn __V((char *fmt, ...))
702{
703 va_list pvar;
704
705#if defined(__STDC__)
706 va_start(pvar, fmt);
707#else
708 char *fmt;
709 va_start(pvar);
710 fmt = va_arg(pvar, char *);
711#endif
712
713 logit(LOG_WARNING, fmt, pvar);
714 va_end(pvar);
715}
716
717/*
718 * notice - log a notice-level message.
719 */
720void
721notice __V((char *fmt, ...))
722{
723 va_list pvar;
724
725#if defined(__STDC__)
726 va_start(pvar, fmt);
727#else
728 char *fmt;
729 va_start(pvar);
730 fmt = va_arg(pvar, char *);
731#endif
732
733 logit(LOG_NOTICE, fmt, pvar);
734 va_end(pvar);
735}
736
737/*
738 * info - log an informational message.
739 */
740void
741info __V((char *fmt, ...))
742{
743 va_list pvar;
744
745#if defined(__STDC__)
746 va_start(pvar, fmt);
747#else
748 char *fmt;
749 va_start(pvar);
750 fmt = va_arg(pvar, char *);
751#endif
752
753 logit(LOG_INFO, fmt, pvar);
754 va_end(pvar);
755}
756
757/*
758 * dbglog - log a debug message.
759 */
760void
761dbglog __V((char *fmt, ...))
762{
763 va_list pvar;
764
765#if defined(__STDC__)
766 va_start(pvar, fmt);
767#else
768 char *fmt;
769 va_start(pvar);
770 fmt = va_arg(pvar, char *);
771#endif
772
773 logit(LOG_DEBUG, fmt, pvar);
774 va_end(pvar);
775}
776
777#endif /* DEBUG */
778
779//==================================================
780#include <fcntl.h>
781#define GOT_IP 0x01
782#define RELEASE_IP 0x02
783#define GET_IP_ERROR 0x03
784#define RELEASE_WAN_CONTROL 0x04
785#define SET_LED(val) \
786{ \
787 int filep; \
788 if ((filep = open("/dev/extio", O_RDWR,0))) \
789 { \
790 ioctl(filep, val, 0); \
791 close(filep); \
792 } \
793}
794//==================================================
795
796int
797log_to_file(char *buf) // add by honor
798{
799 FILE *fp;
800
801 if ((fp = fopen("/tmp/ppp/log", "w"))) {
802 fprintf(fp, "%s", buf);
803 fclose(fp);
804 SET_LED(GET_IP_ERROR)
805 return 1;
806 }
807 return 0;
808}
809
810int
811my_gettimeofday(struct timeval *timenow, struct timezone *tz)
812{
813 struct sysinfo info;
814
815 sysinfo(&info);
816
817 timenow->tv_sec = info.uptime;
818 timenow->tv_usec = 0;
819
820 return 0;
821}
822