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