Annotation of embedaddon/mpd/src/util.c, revision 1.1.1.3
1.1 misho 1:
2: /*
3: * util.c
4: *
5: * Written by Archie Cobbs <archie@freebsd.org>
6: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
7: * See ``COPYRIGHT.whistle''
8: */
9:
10: #include "ppp.h"
11: #include "util.h"
12: #include <termios.h>
1.1.1.2 misho 13: #include <paths.h>
1.1 misho 14:
1.1.1.2 misho 15: #include <libutil.h>
1.1 misho 16: #include <netdb.h>
17: #include <tcpd.h>
18: #include <sys/wait.h>
19: #include <sys/sysctl.h>
20: #include <net/route.h>
21: #include <netinet/if_ether.h>
1.1.1.3 ! misho 22: #include <net/ethernet.h>
! 23: #include <osreldate.h>
1.1 misho 24:
25: /*
26: * DEFINITIONS
27: */
28:
29: #define MAX_FILENAME 1000
30: #define MAX_LINE_ARGS 50
31: #define BIG_LINE_SIZE 1000
32: #define MAX_OPEN_DELAY 2
33: #define MAX_LOCK_ATTEMPTS 30
34:
35: /*
36: * INTERNAL VARIABLES
37: */
38:
1.1.1.2 misho 39: #ifndef USE_NG_PRED1
1.1 misho 40: static const u_int16_t Crc16Table[256] = {
41: /* 00 */ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
42: /* 08 */ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
43: /* 10 */ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
44: /* 18 */ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
45: /* 20 */ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
46: /* 28 */ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
47: /* 30 */ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
48: /* 38 */ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
49: /* 40 */ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
50: /* 48 */ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
51: /* 50 */ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
52: /* 58 */ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
53: /* 60 */ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
54: /* 68 */ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
55: /* 70 */ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
56: /* 78 */ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
57: /* 80 */ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
58: /* 88 */ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
59: /* 90 */ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
60: /* 98 */ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
61: /* a0 */ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
62: /* a8 */ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
63: /* b0 */ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
64: /* b8 */ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
65: /* c0 */ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
66: /* c8 */ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
67: /* d0 */ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
68: /* d8 */ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
69: /* e0 */ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
70: /* e8 */ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
71: /* f0 */ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
72: /* f8 */ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
73: };
1.1.1.2 misho 74: #endif
1.1 misho 75:
76: static FILE *lockFp = NULL;
77:
78: /*
79: * INTERNAL FUNCTIONS
80: */
81:
82: static void Escape(char *line);
83: static char *ReadLine(FILE *fp, int *lineNum, char *result, int resultsize);
84:
85: static char HexVal(char c);
86:
87: static void IndexConfFile(FILE *fp, struct configfile **cf);
88:
89: struct configfiles *ConfigFilesIndex=NULL;
90:
91: #undef isspace
92: #define isspace(c) (((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\r')?1:0)
93:
94: /*
95: * LengthenArray()
96: */
97:
98: void
99: LengthenArray(void *array, size_t esize, int *alenp, const char *type)
100: {
101: void **const arrayp = (void **)array;
102: void *newa;
103:
104: newa = Malloc(type, (*alenp + 1) * esize);
105: if (*arrayp != NULL) {
106: memcpy(newa, *arrayp, *alenp * esize);
107: Freee(*arrayp);
108: }
109: *arrayp = newa;
110: (*alenp)++;
111: }
112:
113: /*
114: * ExecCmd()
115: */
116:
117: int
118: ExecCmd(int log, const char *label, const char *fmt, ...)
119: {
120: int rtn;
121: char cmd[BIG_LINE_SIZE];
122: char cmdn[BIG_LINE_SIZE];
123: va_list ap;
124:
125: va_start(ap, fmt);
126: vsnprintf(cmd, sizeof(cmd), fmt, ap);
127: va_end(ap);
128: strcpy(cmdn, cmd);
129:
130: /* Log command on the console */
131:
132: Log(log, ("[%s] system: %s", label, cmd));
133:
134: /* Hide any stdout output of command */
135:
1.1.1.2 misho 136: snprintf(cmdn + strlen(cmdn), sizeof(cmdn) - strlen(cmdn), " >%s 2>&1", _PATH_DEVNULL);
1.1 misho 137:
138: /* Do command */
139:
140: if ((rtn = system(cmdn)))
141: Log(log|LG_ERR, ("[%s] system: command \"%s\" returned %d", label, cmd, rtn));
142:
143: /* Return command's return value */
144:
145: return(rtn);
146: }
147:
148: /*
149: * ExecCmdNosh()
150: */
151:
152: int
153: ExecCmdNosh(int log, const char *label, const char *fmt, ...)
154: {
155: int rtn;
156: char cmd[BIG_LINE_SIZE];
157: char *cmdp = &(cmd[0]);
158: char *argv[256];
159: char **arg;
160: va_list ap;
161:
162: pid_t pid, savedpid;
163: int pstat;
164: struct sigaction ign, intact, quitact;
165: sigset_t newsigblock, oldsigblock;
166:
167: va_start(ap, fmt);
168: vsnprintf(cmd, sizeof(cmd), fmt, ap);
169: va_end(ap);
170:
171: /* Log command on the console */
172: Log(log, ("[%s] exec: %s", label, cmd));
173:
174: /* Parce args */
175: for (arg = &argv[0]; (*arg = strsep(&cmdp, " \t")) != NULL;) {
176: if (**arg != '\0') {
177: if (++arg >= &argv[255])
178: break;
179: }
180: }
181: *arg = NULL;
182:
183: /* Do command */
184:
185: /*
186: * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save
187: * existing signal dispositions.
188: */
189: ign.sa_handler = SIG_IGN;
190: (void)sigemptyset(&ign.sa_mask);
191: ign.sa_flags = 0;
192: (void)sigaction(SIGINT, &ign, &intact);
193: (void)sigaction(SIGQUIT, &ign, &quitact);
194: (void)sigemptyset(&newsigblock);
195: (void)sigaddset(&newsigblock, SIGCHLD);
196: (void)sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
197: switch(pid = fork()) {
198: case -1: /* error */
199: break;
200: case 0: /* child */
201: /*
202: * Restore original signal dispositions and exec the command.
203: */
204: (void)sigaction(SIGINT, &intact, NULL);
205: (void)sigaction(SIGQUIT, &quitact, NULL);
206: (void)sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
207: close(1);
1.1.1.2 misho 208: open(_PATH_DEVNULL, O_WRONLY);
1.1 misho 209: close(2);
1.1.1.2 misho 210: open(_PATH_DEVNULL, O_WRONLY);
1.1 misho 211: execv(argv[0], argv);
212: exit(127);
213: default: /* parent */
214: savedpid = pid;
215: do {
216: pid = wait4(savedpid, &pstat, 0, (struct rusage *)0);
217: } while (pid == -1 && errno == EINTR);
218: break;
219: }
220: (void)sigaction(SIGINT, &intact, NULL);
221: (void)sigaction(SIGQUIT, &quitact, NULL);
222: (void)sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
223:
224: rtn = (pid == -1 ? -1 : pstat);
225:
226: if (rtn)
227: Log(log|LG_ERR, ("[%s] system: command \"%s\" returned %d", label, cmd, rtn));
228:
229: /* Return command's return value */
230: return(rtn);
231: }
232:
233: /*
234: * ParseLine()
235: *
236: * Parse arguments, respecting double quotes and backslash escapes.
237: * Returns number of arguments, at most "max_args". This destroys
238: * the original line. The arguments returned are Malloc()'d strings
239: * which must be freed by the caller using FreeArgs().
240: */
241:
242: int
243: ParseLine(char *line, char *av[], int max_args, int copy)
244: {
245: int ac;
246: char *s, *arg;
247:
248: /* Get args one at a time */
249:
250: for (ac = 0; ac < max_args; ac++)
251: {
252:
253: /* Skip white space */
254:
255: while (*line && isspace(*line))
256: line++;
257:
258: /* Done? */
259:
260: if (*line == 0)
261: break;
262:
263: /* Get normal or quoted arg */
264:
265: if (*line == '"')
266: {
267:
268: /* Stop only upon matching quote or NUL */
269:
270: for (arg = ++line; *line; line++)
271: if (*line == '"')
272: {
273: *line++ = 0;
274: break;
275: }
276: else if (*line == '\\' && line[1] != 0)
277: {
278: strcpy(line, line + 1);
279: Escape(line);
280: }
281: }
282: else
283: {
284:
285: /* NUL terminate this argument at first white space */
286:
287: for (arg = line; *line && !isspace(*line); line++);
288: if (*line)
289: *line++ = 0;
290:
291: /* Convert characters */
292:
293: for (s = arg; *s; s++)
294: if (*s == '\\')
295: {
296: strcpy(s, s + 1);
297: Escape(s);
298: }
299: }
300:
301: /* Make a copy of this arg */
302:
303: if (copy) {
304: strcpy(av[ac] = Malloc(MB_CMD, strlen(arg) + 1), arg);
305: }
306: else
307: av[ac] = arg;
308: }
309:
310: #if 0
311: {
312: int k;
313:
314: printf("ParseLine: %d args:\n", ac);
315: for (k = 0; k < ac; k++)
316: printf(" [%2d] \"%s\"\n", k, av[k]);
317: }
318: #endif
319:
320: return(ac);
321: }
322:
323: /*
324: * FreeArgs()
325: */
326:
327: void
328: FreeArgs(int ac, char *av[])
329: {
330: while (ac > 0)
331: Freee(av[--ac]);
332: }
333:
334: /*
335: * Escape()
336: *
337: * Give a string, interpret the beginning characters as an escape
338: * code and return with that code converted.
339: */
340:
341: static void
342: Escape(char *line)
343: {
344: int x, k;
345: char *s = line;
346:
347: switch (*line)
348: {
349: case 't': *s = '\t'; return;
350: case 'n': *s = '\n'; return;
351: case 'r': *s = '\r'; return;
352: case 's': *s = ' '; return;
353: case '"': *s = '"'; return;
354: case '0': case '1': case '2': case '3':
355: case '4': case '5': case '6': case '7':
356: for (x = k = 0; k < 3 && *s >= '0' && *s <= '7'; s++)
357: x = (x << 3) + (*s - '0');
358: *--s = x;
359: break;
360: case 'x':
361: for (s++, x = k = 0; k < 2 && isxdigit(*s); s++)
362: x = (x << 4) + (isdigit(*s) ? (*s - '0') : (tolower(*s) - 'a' + 10));
363: *--s = x;
364: break;
365: default:
366: return;
367: }
368: strcpy(line, s);
369: }
370:
371: /*
372: * ReadFile()
373: *
374: * Read the commands specified for the target in the specified
375: * file, which can be found in the PATH_CONF_DIR directory.
376: * Returns negative if the file or target was not found.
377: */
378:
379: int
380: ReadFile(const char *filename, const char *target,
381: int (*func)(Context ctx, int ac, char *av[], const char *file, int line), Context ctx)
382: {
383: FILE *fp;
384: int ac;
385: char *av[MAX_LINE_ARGS];
386: char *line;
387: char buf[BIG_LINE_SIZE];
388: struct configfile *cf;
389: int lineNum;
390:
391: /* Open file */
392:
393: if ((fp = OpenConfFile(filename, &cf)) == NULL)
1.1.1.3 ! misho 394: return(-2);
1.1 misho 395:
396: /* Find label */
397:
398: if (SeekToLabel(fp, target, &lineNum, cf) < 0) {
399: fclose(fp);
400: return(-1);
401: }
402:
403: /* Execute command list */
404:
405: while ((line = ReadFullLine(fp, &lineNum, buf, sizeof(buf))) != NULL)
406: {
407: if (!isspace(*line))
408: {
409: break;
410: }
411: ac = ParseLine(line, av, sizeof(av) / sizeof(*av), 0);
412: (*func)(ctx, ac, av, filename, lineNum);
413: }
414:
415: /* Done */
416:
417: fclose(fp);
418: return(0);
419: }
420:
421: /*
422: * IndexConfFile()
423: *
424: * Scan config file for labels
425: */
426:
427: static void
428: IndexConfFile(FILE *fp, struct configfile **cf)
429: {
430: char *s, *line;
431: char buf[BIG_LINE_SIZE];
432: struct configfile **tmp;
433: int lineNum;
434:
435: /* Start at beginning */
436:
437: rewind(fp);
438: lineNum = 0;
439:
440: tmp=cf;
441:
442: /* Find label */
443:
444: while ((line = ReadFullLine(fp, &lineNum, buf, sizeof(buf))) != NULL)
445: {
446: if (isspace(*line))
447: continue;
448: if ((s = strtok(line, " \t\f:"))) {
449: (*tmp)=Malloc(MB_CMDL, sizeof(struct configfile));
450: (*tmp)->label=strcpy(Malloc(MB_CMDL, strlen(s)+1),s);
451: (*tmp)->linenum=lineNum;
452: (*tmp)->seek=ftello(fp);
453: tmp=&((*tmp)->next);
454: }
455: }
456: }
457:
458: /*
459: * SeekToLabel()
460: *
461: * Find a label in file and position file pointer just after it
462: */
463:
464: int
465: SeekToLabel(FILE *fp, const char *label, int *lineNum, struct configfile *cf)
466: {
467: char *s, *line;
468: char buf[BIG_LINE_SIZE];
469: struct configfile *tmp;
470:
471: if (cf) { /* Trying to use index */
472: tmp=cf;
473: while (tmp && strcmp(tmp->label,label)) {
474: tmp=tmp->next;
475: }
476: if (tmp) {
477: fseeko(fp,tmp->seek, SEEK_SET);
478: if (lineNum)
479: *lineNum=tmp->linenum;
480: return(0);
481: }
482: } else { /* There are no index */
483:
484: /* Start at beginning */
485: rewind(fp);
486: if (lineNum)
487: *lineNum = 0;
488:
489: /* Find label */
490:
491: while ((line = ReadFullLine(fp, lineNum, buf, sizeof(buf))) != NULL)
492: {
493: if (isspace(*line))
494: continue;
495: if ((s = strtok(line, " \t\f:")) && !strcmp(s, label))
496: return(0);
497: }
498: }
499:
500: /* Not found */
501: Log(LG_ERR, ("Label '%s' not found", label));
502: return(-1);
503: }
504:
505: /*
506: * OpenConfFile()
507: *
508: * Open a configuration file
509: */
510:
511: FILE *
512: OpenConfFile(const char *name, struct configfile **cf)
513: {
514: char pathname[MAX_FILENAME];
515: FILE *fp;
516: struct configfiles **tmp;
517:
518: /* Build full pathname */
519: if (name[0] == '/')
520: snprintf(pathname, sizeof(pathname), "%s", name);
521: else
522: snprintf(pathname, sizeof(pathname), "%s/%s", gConfDirectory, name);
523:
524: /* Open file */
525:
526: if ((fp = fopen(pathname, "r")) == NULL)
527: {
528: Perror("%s: Can't open file '%s'", __FUNCTION__, pathname);
529: return(NULL);
530: }
531: (void) fcntl(fileno(fp), F_SETFD, 1);
532:
533: if (cf) {
534: tmp=&ConfigFilesIndex;
535: while ((*tmp) && strcmp((*tmp)->filename,name)) {
536: tmp=&((*tmp)->next);
537: }
538: if (!(*tmp)) {
539: (*tmp) = Malloc(MB_CMD, sizeof(struct configfiles));
540: (*tmp)->filename = strcpy(Malloc(MB_CMD, strlen(name)+1),name);
541: (*tmp)->sections = NULL;
542: (*tmp)->next = NULL;
543: IndexConfFile(fp, &((*tmp)->sections));
544: }
545: *cf=(*tmp)->sections;
546: }
547:
548: return(fp);
549: }
550:
551: /*
552: * ReadFullLine()
553: *
554: * Read a full line, respecting backslash continuations.
555: * Returns pointer to Malloc'd storage, which must be Freee'd
556: */
557:
558: char *
559: ReadFullLine(FILE *fp, int *lineNum, char *result, int resultsize)
560: {
561: int len, linelen, resultlinesize, continuation;
562: char line[BIG_LINE_SIZE];
563: char real_line[BIG_LINE_SIZE];
564: char *resultline;
565:
566: if (result!=NULL && resultsize>0) {
567: resultline=result;
568: resultlinesize=resultsize;
569: } else {
570: resultline=line;
571: resultlinesize=sizeof(line);
572: }
573:
574: resultline[0] = 0;
575: linelen = 0;
576: continuation = TRUE;
577:
578: while ( continuation )
579: {
580:
581: /* Get next real line */
582:
583: if (ReadLine(fp, lineNum, real_line, sizeof(real_line)) == NULL) {
584: if (*resultline)
585: break;
586: else
587: return(NULL);
588: }
589:
590: /* Strip trailing white space, detect backslash */
591:
592: for (len = strlen(real_line);
593: len > 0 && isspace(real_line[len - 1]);
594: len--) {};
595: real_line[len] = 0;
596:
597: if ((continuation = (len && real_line[len - 1] == '\\')))
598: real_line[len - 1] = ' ';
599:
600: /* Append real line to what we've got so far */
601:
602: strlcpy(resultline + linelen, real_line, resultlinesize - linelen);
603: linelen += len;
604: if (linelen > sizeof(line) - 1)
605: linelen = sizeof(line) - 1;
606: }
607:
608: /* Report any overflow */
609:
610: if (linelen >= sizeof(line) - 1)
611: Log(LG_ERR, ("warning: line too long, truncated"));
612:
613: /* Copy line and return */
614:
615: if (result!=NULL && resultsize>0)
616: return resultline;
617: else
618: return strcpy(Malloc(MB_CMD, linelen + 1), resultline);
619: }
620:
621: /*
622: * ReadLine()
623: *
624: * Read a line, skipping blank lines & comments. A comment
625: * is a line whose first non-white-space character is a hash.
626: */
627:
628: static char *
629: ReadLine(FILE *fp, int *lineNum, char *result, int resultsize)
630: {
631: int empty;
632: char *s;
633: int ch;
634:
635: if ((!result) || (resultsize <= 0))
636: return (NULL);
637:
638: /* Get first non-empty, non-commented line */
639: empty = TRUE;
640: while ( empty ) {
641:
642: /* Read next line from file */
643: if ((fgets(result, resultsize, fp)) == NULL)
644: return(NULL);
645: if (lineNum)
646: (*lineNum)++;
647:
648: /* Truncate long lines */
649: if (strlen(result) > (resultsize - 2)) {
650: Log(LG_ERR, ("warning: line too long, truncated"));
651: while ((ch = getc(fp)) != EOF && ch != '\n');
652: }
653:
654: /* Ignore comments */
655: s = result + strspn(result, " \t");
656: if (*s == '#') {
657: *s = 0;
658: } else {
659: /* Is this line empty? */
660: for ( ; *s; s++) {
661: if (!isspace(*s)) {
662: empty = FALSE;
663: break;
664: }
665: }
666: }
667: }
668:
669: return(result);
670: }
671:
1.1.1.2 misho 672: #ifdef PHYSTYPE_MODEM
1.1 misho 673: /*
674: * OpenSerialDevice()
675: *
676: * Open and configure a serial device. Call ExclusiveCloseDevice()
677: * to close a file descriptor returned by this function.
678: */
679:
680: int
681: OpenSerialDevice(const char *label, const char *path, int baudrate)
682: {
683: struct termios attr;
684: int fd;
685:
686: /* Open & lock serial port */
687:
688: if ((fd = ExclusiveOpenDevice(label, path)) < 0)
689: return(-1);
690:
691: /* Set non-blocking I/O */
692:
693: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
694: {
695: Perror("[%s] can't set \"%s\" to non-blocking", label, path);
696: goto failed;
697: }
698:
699: /* Set serial port raw mode, baud rate, hardware flow control, etc. */
700:
701: if (tcgetattr(fd, &attr) < 0)
702: {
703: Perror("[%s] can't tcgetattr \"%s\"", label, path);
704: goto failed;
705: }
706:
707: cfmakeraw(&attr);
708:
709: attr.c_cflag &= ~(CSIZE|PARENB|PARODD);
710: attr.c_cflag |= (CS8|CREAD|CLOCAL|HUPCL|CCTS_OFLOW|CRTS_IFLOW);
711: attr.c_iflag &= ~(IXANY|IMAXBEL|ISTRIP|IXON|IXOFF|BRKINT|ICRNL|INLCR);
712: attr.c_iflag |= (IGNBRK|IGNPAR);
713: attr.c_oflag &= ~OPOST;
714: attr.c_lflag = 0;
715:
716: cfsetspeed(&attr, (speed_t) baudrate);
717:
718: if (tcsetattr(fd, TCSANOW, &attr) < 0)
719: {
720: Perror("[%s] can't tcsetattr \"%s\"", label, path);
721: failed:
722: ExclusiveCloseDevice(label, fd, path);
723: return(-1);
724: }
725:
726: /* OK */
727:
728: return(fd);
729: }
730:
731: /*
732: * ExclusiveOpenDevice()
733: */
734:
735: int
736: ExclusiveOpenDevice(const char *label, const char *pathname)
737: {
738: int fd, locked = FALSE;
739: const char *ttyname = NULL;
740: time_t startTime;
741:
742: /* Lock device UUCP style, if it resides in /dev */
743:
1.1.1.2 misho 744: if (!strncmp(pathname, _PATH_DEV, 5))
1.1 misho 745: {
1.1.1.2 misho 746: int res;
1.1 misho 747: ttyname = pathname + 5;
1.1.1.2 misho 748: if ((res = uu_lock(ttyname)) != UU_LOCK_OK) {
749: Log(LG_ERR, ("[%s] uu_lock(%s): %s", label, ttyname, uu_lockerr(res)));
1.1 misho 750: return(-1);
751: }
752: locked = TRUE;
753: }
754:
755: /* Open it, but give up after so many interruptions */
756:
757: for (startTime = time(NULL);
758: (fd = open(pathname, O_RDWR, 0)) < 0
759: && time(NULL) < startTime + MAX_OPEN_DELAY; )
760: if (errno != EINTR)
761: {
762: Perror("[%s] can't open %s", label, pathname);
763: if (locked)
1.1.1.2 misho 764: uu_unlock(ttyname);
1.1 misho 765: return(-1);
766: }
767:
768: /* Did we succeed? */
769:
770: if (fd < 0)
771: {
772: Log(LG_ERR, ("[%s] can't open %s after %d secs",
773: label, pathname, MAX_OPEN_DELAY));
774: if (locked)
1.1.1.2 misho 775: uu_unlock(ttyname);
1.1 misho 776: return(-1);
777: }
778: (void) fcntl(fd, F_SETFD, 1);
779:
780: /* Done */
781:
782: return(fd);
783: }
784:
785: /*
786: * ExclusiveCloseDevice()
787: */
788:
789: void
790: ExclusiveCloseDevice(const char *label, int fd, const char *pathname)
791: {
792: int rtn = -1;
793: const char *ttyname;
794: time_t startTime;
795:
796: /* Close file(s) */
797:
798: for (startTime = time(NULL);
799: time(NULL) < startTime + MAX_OPEN_DELAY && (rtn = close(fd)) < 0; )
800: if (errno != EINTR)
801: {
802: Perror("[%s] can't close %s", label, pathname);
803: break;
804: }
805:
806: /* Did we succeed? */
807:
808: if ((rtn < 0) && (errno == EINTR))
809: {
810: Log(LG_ERR, ("[%s] can't close %s after %d secs",
811: label, pathname, MAX_OPEN_DELAY));
812: DoExit(EX_ERRDEAD);
813: }
814:
815: /* Remove lock */
816:
1.1.1.2 misho 817: if (!strncmp(pathname, _PATH_DEV, 5))
1.1 misho 818: {
819: ttyname = pathname + 5;
1.1.1.2 misho 820: if (uu_unlock(ttyname) < 0)
1.1 misho 821: Perror("[%s] can't unlock %s", label, ttyname);
822: }
823: }
1.1.1.2 misho 824: #endif /* PHYSTYPE_MODEM */
1.1 misho 825:
826:
827: /*
828: * GenerateMagic()
829: *
830: * Generate random number which will be used as magic number.
831: * This could be made a little more "random"...
832: */
833:
834: u_long
835: GenerateMagic(void)
836: {
837: time_t now;
838: struct timeval tval;
839:
840: time(&now);
841: gettimeofday(&tval, NULL);
842: now += (tval.tv_sec ^ tval.tv_usec) + getppid();
843: now *= gPid;
844: return(now);
845: }
846:
847: /*
848: * PIDCheck()
849: *
850: * See if process is already running and deal with PID file.
851: */
852:
853: int
854: PIDCheck(const char *filename, int killem)
855: {
1.1.1.3 ! misho 856: int n_tries;
! 857: struct pidfh *pfh = NULL;
1.1 misho 858:
859: /* Sanity */
860:
861: assert(!lockFp);
862:
863: /* Atomically open and lock file */
864:
1.1.1.3 ! misho 865: for (n_tries = 0; n_tries < MAX_LOCK_ATTEMPTS; n_tries++)
1.1 misho 866: {
1.1.1.3 ! misho 867: pid_t old_pid;
1.1 misho 868:
1.1.1.3 ! misho 869: pfh = pidfile_open(filename, 0644, &old_pid);
! 870: if (pfh == NULL) {
! 871: if (errno == EEXIST) {
! 872: if (!killem) {
! 873: Log(LG_ERR, ("already running as process %d", old_pid));
! 874: return(-1);
! 875: }
! 876: if (kill(old_pid, SIGTERM) < 0)
! 877: switch (errno) {
! 878: case ESRCH:
! 879: Log(LG_ERR, ("process %d no longer exists", old_pid));
! 880: break;
! 881: default:
! 882: Perror("%s: kill(%d)", __FUNCTION__, old_pid);
! 883: return(-1);
! 884: }
! 885: /* Wait and try again */
! 886: Log(LG_ERR, ("waiting for process %d to die...", old_pid));
! 887: sleep(1);
! 888: } else {
! 889: Perror("cannot open pid file");
! 890: return(-1);
! 891: }
! 892: } else {
! 893: pidfile_write(pfh);
! 894: break;
1.1 misho 895: }
896: }
897: if (n_tries == MAX_LOCK_ATTEMPTS)
898: {
899: Log(LG_ERR, ("can't lock %s after %d attempts", filename, n_tries));
900: return(-1);
901: }
902: return(0);
903: }
904:
905: /*
906: * GetInetSocket()
907: *
908: * Get a TCP socket and bind it to an address. Set SO_REUSEADDR on the socket.
909: */
910:
911: int
912: GetInetSocket(int type, struct u_addr *addr, in_port_t port, int block, char *ebuf, size_t len)
913: {
914: int sock;
915: static int one = 1;
916: struct sockaddr_storage sa;
917:
918: u_addrtosockaddr(addr,port,&sa);
919:
920: /* Get and bind non-blocking socket */
921:
922: if ((sock = socket(sa.ss_family, type, type == SOCK_STREAM ? IPPROTO_TCP : 0)) < 0)
923: {
924: snprintf(ebuf, len, "socket: %s", strerror(errno));
925: return(-1);
926: }
927: (void) fcntl(sock, F_SETFD, 1);
928: if (!block)
929: {
930: if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
931: {
932: snprintf(ebuf, len, "can't set socket non-blocking: %s", strerror(errno));
933: close(sock);
934: return(-1);
935: }
936: }
937: if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
938: {
939: snprintf(ebuf, len, "setsockopt: %s", strerror(errno));
940: close(sock);
941: return(-1);
942: }
943:
944: if (bind(sock, (struct sockaddr *) &sa, sa.ss_len) < 0)
945: {
946: snprintf(ebuf, len, "bind: %s", strerror(errno));
947: close(sock);
948: return(-1);
949: }
950:
951: return(sock);
952: }
953:
954:
955: /*
956: * TcpGetListenPort()
957: *
958: * Get port for incoming telnet connections
959: */
960:
961: int
962: TcpGetListenPort(struct u_addr *addr, in_port_t port, int block)
963: {
964: char ebuf[100];
965: int sock;
966: int saverrno;
967:
968: /* Get socket */
969:
970: if ((sock = GetInetSocket(SOCK_STREAM, addr, port, block, ebuf, sizeof(ebuf))) < 0)
971: {
972: saverrno = errno;
973: Log(LG_ERR, ("%s", ebuf));
974: errno = saverrno;
975: return(-1);
976: }
977:
978: /* Make socket available for connections */
979:
1.1.1.3 ! misho 980: if (listen(sock, -1) < 0)
1.1 misho 981: {
982: Perror("%s: listen", __FUNCTION__);
983: (void) close(sock);
984: return(-1);
985: }
986:
987: /* Done */
988:
989: return(sock);
990: }
991:
992:
993: /*
994: * TcpAcceptConnection()
995: *
996: * Accept next connection on port
997: */
998:
999: int
1000: TcpAcceptConnection(int sock, struct sockaddr_storage *addr, int block)
1001: {
1002: int new_sock;
1003: socklen_t size=sizeof(struct sockaddr_storage);
1004:
1005: /* Accept incoming connection */
1006:
1007: memset(addr, 0, sizeof(*addr));
1008: if ((new_sock = accept(sock, (struct sockaddr *) addr, &size)) < 0) {
1009: Perror("%s: accept", __FUNCTION__);
1010: return(-1);
1011: }
1012:
1013: #ifdef USE_WRAP
1014: if (Enabled(&gGlobalConf.options, GLOBAL_CONF_TCPWRAPPER)) {
1015: struct request_info req;
1016: request_init(&req, RQ_DAEMON, "mpd", RQ_FILE, new_sock, NULL);
1017: fromhost(&req);
1018: if (!hosts_access(&req)) {
1019: Log(LG_ERR, ("refused connection (tcp-wrapper) from %s",
1020: eval_client(&req)));
1021: close(new_sock);
1022: return(-1);
1023: }
1024: }
1025: #endif
1026:
1027: if (!block)
1028: {
1029: (void) fcntl(new_sock, F_SETFD, 1);
1030: if (fcntl(new_sock, F_SETFL, O_NONBLOCK) < 0) {
1031: Perror("%s: fcntl", __FUNCTION__);
1032: return(-1);
1033: }
1034: }
1035:
1036: /* Done */
1037:
1038: return(new_sock);
1039: }
1040:
1041:
1042: /*
1043: * ShowMesg()
1044: */
1045:
1046: void
1047: ShowMesg(int log, const char *pref, const char *buf, int len)
1048: {
1049: char *s, mesg[256];
1050:
1051: if (len > 0)
1052: {
1053: if (len > sizeof(mesg) - 1)
1054: len = sizeof(mesg) - 1;
1055: memcpy(mesg, buf, len);
1056: mesg[len] = 0;
1057: for (s = strtok(mesg, "\r\n"); s; s = strtok(NULL, "\r\n"))
1058: Log(log, ("[%s] MESG: %s", pref, s));
1059: }
1060: }
1061:
1062: /*
1063: * Bin2Hex()
1064: */
1065:
1066: char *
1067: Bin2Hex(const unsigned char *bin, size_t len)
1068: {
1069: static char hexconvtab[] = "0123456789abcdef";
1070: size_t i, j;
1071: char *buf;
1072:
1.1.1.2 misho 1073: if (len > 0) {
1074: buf = Malloc(MB_UTIL, len * 2 + 1);
1075: for (i = j = 0; i < len; i++) {
1076: buf[j++] = hexconvtab[bin[i] >> 4];
1077: buf[j++] = hexconvtab[bin[i] & 15];
1078: }
1079: buf[j] = 0;
1080: } else {
1081: buf = Malloc(MB_UTIL, 3);
1082: buf[0] = '0';
1083: buf[1] = '0';
1084: buf[2] = 0;
1.1 misho 1085: }
1086: return buf;
1087: }
1088:
1089: /*
1090: * Hex2Bin()
1091: */
1092:
1093: u_char *
1094: Hex2Bin(char *hexstr)
1095: {
1096: int i;
1097: u_char *binval;
1098:
1099: binval = Malloc(MB_UTIL, strlen(hexstr) / 2);
1100:
1101: for (i = 0; i < strlen(hexstr) / 2; i++) {
1102: binval[i] = 16 * HexVal(hexstr[2*i]) + HexVal(hexstr[2*i+1]);
1103: }
1104:
1105: return binval;
1106: }
1107:
1108: static char
1109: HexVal(char c)
1110: {
1111: if (c >= '0' && c <= '9') {
1112: return (c - '0');
1113: } else if (c >= 'a' && c <= 'z') {
1114: return (c - 'a' + 10);
1115: } else if (c >= 'A' && c <= 'Z') {
1116: return (c - 'A' + 10);
1117: } else {
1118: return (-1);
1119: }
1120: }
1121:
1.1.1.2 misho 1122: #ifndef USE_NG_PRED1
1.1 misho 1123: /*
1124: * Crc16()
1125: *
1126: * Compute the 16 bit frame check value, per RFC 1171 Appendix B,
1127: * on an array of bytes.
1128: */
1129:
1130: u_short
1131: Crc16(u_short crc, u_char *cp, int len)
1132: {
1133: while (len--)
1134: crc = (crc >> 8) ^ Crc16Table[(crc ^ *cp++) & 0xff];
1135: return(crc);
1136: }
1.1.1.2 misho 1137: #endif
1.1 misho 1138:
1139: /*
1140: * GetAnyIpAddress()
1141: *
1142: * Get any non-loopback IP address owned by this machine
1143: * Prefer addresses from non-point-to-point interfaces.
1144: */
1145:
1146: int
1147: GetAnyIpAddress(struct u_addr *ipaddr, const char *ifname)
1148: {
1149: int s, p2p = 0;
1150: struct in_addr ipa = { 0 };
1151: static struct in_addr nipa = { 0 };
1152: static int have_nipa = 0;
1153: struct ifreq *ifr, *ifend;
1154: struct ifreq ifreq;
1155: struct ifconf ifc;
1156: unsigned int buffsize = IFCONF_BUFFSIZE;
1157:
1158: /* use cached IP to reduce number of syscalls */
1159: if (ifname == NULL && have_nipa) {
1160: in_addrtou_addr(&nipa, ipaddr);
1161: return(0);
1162: }
1163:
1164: /* Get socket */
1165: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
1166: Perror("%s: Socket creation error", __FUNCTION__);
1167: return(-1);
1168: }
1169:
1170: /* Try simple call for the first IP on interface */
1171: if (ifname != NULL) {
1172: strlcpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name));
1173: if (ioctl(s, SIOCGIFADDR, &ifreq) < 0) {
1174: if (errno != ENXIO)
1175: Perror("%s: ioctl(SIOCGIFADDR)", __FUNCTION__);
1176: close(s);
1177: return(-1);
1178: }
1179: ipa = ((struct sockaddr_in *)&ifreq.ifr_ifru.ifru_addr)->sin_addr;
1180: if ((ntohl(ipa.s_addr)>>24) == 127)
1181: ipa.s_addr = 0; /* We don't like 127.0.0.1 */
1182: }
1183:
1184: /* If simple is not enouth try complex call */
1185: if (ipa.s_addr == 0) {
1186: struct ifreq *ifs;
1187: while (1) {
1188: ifc.ifc_len = buffsize;
1189: ifc.ifc_req = ifs = Malloc(MB_UTIL, ifc.ifc_len);
1190: if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
1191: Freee(ifs);
1192: if (errno != ENXIO)
1193: Perror("%s: ioctl(SIOCGIFCONF)", __FUNCTION__);
1194: close(s);
1195: return(-1);
1196: }
1197:
1198: /* if used size is too close to allocated size retry with a larger buffer */
1199: if (ifc.ifc_len + 128 < buffsize)
1200: break;
1201:
1202: Freee(ifs);
1203: if (buffsize >= IFCONF_BUFFMAXSIZE) {
1204: Log(LG_ERR, ("%s: Max buffer size reached", __FUNCTION__));
1205: close(s);
1206: return(-1);
1207: }
1208: buffsize *= 2;
1209: }
1210:
1211: for (ifend = (struct ifreq *)(void *)(ifc.ifc_buf + ifc.ifc_len),
1212: ifr = ifc.ifc_req;
1213: ifr < ifend;
1214: ifr = (struct ifreq *)(void *)((char *) &ifr->ifr_addr
1215: + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
1216: if (ifr->ifr_addr.sa_family == AF_INET) {
1217:
1218: if (ifname!=NULL && strcmp(ifname,ifr->ifr_name))
1219: continue;
1220:
1221: /* Check that the interface is up; prefer non-p2p and non-loopback */
1222: strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1223: if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0)
1224: continue;
1225: if ((ifreq.ifr_flags & IFF_UP) != IFF_UP)
1226: continue;
1227: if ((ifreq.ifr_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) && ipa.s_addr)
1228: continue;
1229: if ((ntohl(((struct sockaddr_in *)(void *)&ifr->ifr_addr)->sin_addr.s_addr)>>24)==127)
1230: continue;
1231:
1232: /* Save IP address and interface name */
1233: ipa = ((struct sockaddr_in *)(void *)&ifr->ifr_addr)->sin_addr;
1234: p2p = (ifreq.ifr_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0;
1235:
1236: if (!p2p) break;
1237: }
1238: }
1239: Freee(ifs);
1240: }
1241: close(s);
1242:
1243: /* Found? */
1244: if (ipa.s_addr == 0)
1245: return(-1);
1246: if (ifname == NULL) {
1247: nipa = ipa;
1248: have_nipa = 1;
1249: }
1250: in_addrtou_addr(&ipa, ipaddr);
1251: return(0);
1252: }
1253:
1254: /*
1255: * GetEther()
1256: *
1257: * Get the hardware address of an interface on the the same subnet as addr.
1258: * If addr == NULL, finds the address of any local ethernet interface.
1259: */
1260:
1261: int
1262: GetEther(struct u_addr *addr, struct sockaddr_dl *hwaddr)
1263: {
1264: int s;
1265: struct ifreq *ifr, *bifr, *ifend, *ifp;
1266: u_int32_t ina, mask, bmask;
1267: struct ifreq ifreq;
1268: struct ifconf ifc;
1269: struct ifreq *ifs;
1270: unsigned int buffsize = IFCONF_BUFFSIZE;
1271:
1272: static struct sockaddr_dl nhwaddr;
1273: static int have_nhwaddr = 0;
1274:
1275: /* cache value to reduce number of syscalls */
1276: if (addr == NULL && have_nhwaddr) {
1277: memcpy(hwaddr, &nhwaddr,
1278: sizeof(*hwaddr));
1279: return(0);
1280: }
1281:
1282: /* Get interface list */
1283: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
1284: Perror("%s: Socket creation error", __FUNCTION__);
1285: return(-1);
1286: }
1287:
1288: while (1) {
1289: ifc.ifc_len = buffsize;
1290: ifc.ifc_req = ifs = Malloc(MB_UTIL, ifc.ifc_len);
1291: if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
1292: Freee(ifs);
1293: Perror("%s: ioctl(SIOCGIFCONF)", __FUNCTION__);
1294: close(s);
1295: return(-1);
1296: }
1297:
1298: /* if used size is too close to allocated size retry with a larger buffer */
1299: if (ifc.ifc_len + 128 < buffsize)
1300: break;
1301:
1302: Freee(ifs);
1303: if (buffsize >= IFCONF_BUFFMAXSIZE) {
1304: Log(LG_ERR, ("%s: Max buffer size reached", __FUNCTION__));
1305: close(s);
1306: return(-1);
1307: }
1308: buffsize *= 2;
1309: }
1310:
1311: /*
1312: * Scan through looking for an interface with an IP
1313: * address on same subnet as `addr'.
1314: */
1315: bifr = NULL;
1316: bmask = 0;
1317: for (ifend = (struct ifreq *)(void *)(ifc.ifc_buf + ifc.ifc_len),
1318: ifr = ifc.ifc_req;
1319: ifr < ifend;
1320: ifr = (struct ifreq *)(void *)((char *) &ifr->ifr_addr
1321: + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
1322: if (ifr->ifr_addr.sa_family == AF_INET) {
1323:
1324: /* Save IP address and interface name */
1325: ina = ((struct sockaddr_in *)(void *)&ifr->ifr_addr)->sin_addr.s_addr;
1326: strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1327: ifreq.ifr_addr = ifr->ifr_addr;
1328:
1329: /* Check that the interface is up, and not point-to-point or loopback */
1.1.1.2 misho 1330: if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) {
1331: Log(LG_IFACE2, ("ioctl(SIOCGIFFLAGS, %s): %d", ifr->ifr_name, errno));
1.1 misho 1332: continue;
1.1.1.2 misho 1333: }
1.1 misho 1334: if ((ifreq.ifr_flags &
1335: (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1336: != (IFF_UP|IFF_BROADCAST))
1337: continue;
1338:
1339: if (addr) {
1340: /* Get its netmask and check that it's on the right subnet */
1341: if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0)
1342: continue;
1343: mask = ((struct sockaddr_in *)(void *)&ifreq.ifr_addr)->sin_addr.s_addr;
1344: if ((addr->u.ip4.s_addr & mask) != (ina & mask))
1345: continue;
1346: /* Is this the best match? */
1347: if (mask >= bmask) {
1348: bmask = mask;
1349: bifr = ifr;
1350: }
1351: continue;
1352: }
1353:
1354: /* OK */
1355: bifr = ifr;
1356: break;
1357: }
1358: }
1359: close(s);
1360:
1361: /* Found? */
1362: if (bifr == NULL) {
1363: Freee(ifs);
1364: return(-1);
1365: }
1366:
1367: /* Now scan again looking for a link-level address for this interface */
1368: for (ifp = bifr, ifr = ifc.ifc_req; ifr < ifend; ) {
1369: if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
1370: && ifr->ifr_addr.sa_family == AF_LINK) {
1371: if (addr == NULL) {
1372: memcpy(&nhwaddr, (struct sockaddr_dl *)(void *)&ifr->ifr_addr,
1373: sizeof(*hwaddr));
1374: have_nhwaddr = 1;
1375: }
1376: memcpy(hwaddr, (struct sockaddr_dl *)(void *)&ifr->ifr_addr,
1377: sizeof(*hwaddr));
1378: Freee(ifs);
1379: return(0);
1380: }
1381: ifr = (struct ifreq *)(void *)((char *)&ifr->ifr_addr
1382: + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)));
1383: }
1384:
1385: /* Not found! */
1386: Freee(ifs);
1387: return(-1);
1388: }
1389:
1390: int
1391: GetPeerEther(struct u_addr *addr, struct sockaddr_dl *hwaddr)
1392: {
1393: int mib[6];
1394: size_t needed;
1395: char *lim, *buf, *next;
1396: struct rt_msghdr *rtm;
1397: struct sockaddr_inarp *sin2;
1398: struct sockaddr_dl *sdl;
1399: int st, found_entry = 0;
1400:
1401: mib[0] = CTL_NET;
1402: mib[1] = PF_ROUTE;
1403: mib[2] = 0;
1404: mib[3] = addr->family;
1405: mib[4] = NET_RT_FLAGS;
1406: #ifdef RTF_LLINFO
1407: mib[5] = RTF_LLINFO;
1408: #else
1409: mib[5] = 0;
1410: #endif
1411: if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
1.1.1.2 misho 1412: Perror("route-sysctl-estimate");
1.1 misho 1413: return (0);
1414: }
1415: if (needed == 0) /* empty table */
1416: return 0;
1417: buf = NULL;
1418: for (;;) {
1419: if (buf)
1420: Freee(buf);
1421: buf = Malloc(MB_UTIL, needed);
1422: st = sysctl(mib, 6, buf, &needed, NULL, 0);
1423: if (st == 0 || errno != ENOMEM)
1424: break;
1425: needed += needed / 8;
1426: }
1427: if (st == -1) {
1428: Log(LG_ERR, ("actual retrieval of routing table"));
1429: Freee(buf);
1430: return (0);
1431: }
1432: lim = buf + needed;
1433: for (next = buf; next < lim; next += rtm->rtm_msglen) {
1434: rtm = (struct rt_msghdr *)next;
1435: sin2 = (struct sockaddr_inarp *)(rtm + 1);
1436: if (addr->u.ip4.s_addr == sin2->sin_addr.s_addr) {
1437: sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
1438: memcpy(hwaddr, sdl, sdl->sdl_len);
1439: found_entry = 1;
1440: break;
1441: }
1442: }
1443: Freee(buf);
1444: return (found_entry);
1445: }
1446:
1447: /*
1448: * Decode ASCII message
1449: */
1450: void
1451: ppp_util_ascify(char *buf, size_t bsiz, const char *data, size_t len)
1452: {
1453: char *bp;
1454: int i;
1455:
1456: for (bp = buf, i = 0; i < len; i++) {
1457: const char ch = (char)data[i];
1458:
1459: if (bsiz < 3)
1460: break;
1461: switch (ch) {
1462: case '\t':
1463: *bp++ = '\\';
1464: *bp++ = 't';
1465: bsiz -= 2;
1466: break;
1467: case '\n':
1468: *bp++ = '\\';
1469: *bp++ = 'n';
1470: bsiz -= 2;
1471: break;
1472: case '\r':
1473: *bp++ = '\\';
1474: *bp++ = 'r';
1475: bsiz -= 2;
1476: break;
1477: default:
1478: if (isprint(ch & 0x7f)) {
1479: *bp++ = ch;
1480: bsiz--;
1481: } else {
1482: *bp++ = '^';
1483: *bp++ = '@' + (ch & 0x1f);
1484: bsiz -= 2;
1485: }
1486: break;
1487: }
1488: }
1489: *bp = '\0';
1490: }
1491:
1.1.1.3 ! misho 1492: #ifndef HAVE_NTOA_R
! 1493: /*
! 1494: * Convert a binary representation of an ethernet address to an ASCII string.
! 1495: */
! 1496: char *
! 1497: ether_ntoa_r(const struct ether_addr *n, char *a)
! 1498: {
! 1499: int i;
! 1500:
! 1501: i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0],
! 1502: n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]);
! 1503: if (i < 17)
! 1504: return (NULL);
! 1505: return (a);
! 1506: }
! 1507: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>