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