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