File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / util.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>