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>