Ejemplo n.º 1
0
static ssize_t
ether_Write(struct physical *p, const void *v, size_t n)
{
  struct etherdevice *dev = device2ether(p->handler);

  return NgSendData(p->fd, dev->hook, v, n) == -1 ? -1 : (ssize_t)n;
}
Ejemplo n.º 2
0
static ssize_t
ng_Write(struct physical *p, const void *v, size_t n)
{
    struct ngdevice *dev = device2ng(p->handler);

    switch (p->dl->state) {
    case DATALINK_DIAL:
    case DATALINK_LOGIN:
        return ng_MessageOut(dev, v) ? (ssize_t)n : -1;
    }
    return NgSendData(p->fd, dev->hook, v, n) == -1 ? -1 : (ssize_t)n;
}
Ejemplo n.º 3
0
static void
Spawn(const char *prog, const char *acname, const char *provider,
      const char *exec, struct ngm_connect ngc, int cs, int ds, void *request,
      int sz, int debug)
{
  char msgbuf[sizeof(struct ng_mesg) + sizeof(struct ngpppoe_sts)];
  struct ng_mesg *rep = (struct ng_mesg *)msgbuf;
  struct ngpppoe_sts *sts = (struct ngpppoe_sts *)(msgbuf + sizeof *rep);
  struct ngpppoe_init_data *data;
  char env[18], unknown[14], sessionid[5], *path;
  unsigned char *macaddr;
  const char *msg;
  int ret, slen;

  switch ((ret = fork())) {
    case -1:
      syslog(LOG_ERR, "fork: %m");
      break;

    case 0:
      switch (fork()) {
        case 0:
          break;
        case -1:
          _exit(errno);
        default:
          _exit(0);
      }
      close(cs);
      close(ds);

      /* Create a new socket node */
      if (debug)
        syslog(LOG_INFO, "Creating a new socket node");

      if (NgMkSockNode(NULL, &cs, &ds) == -1) {
        syslog(LOG_ERR, "Cannot create netgraph socket node: %m");
        _exit(EX_CANTCREAT);
      }

      /* Connect the PPPoE node to our new socket node.  */
      snprintf(ngc.ourhook, sizeof ngc.ourhook, "exec-%ld", (long)getpid());
      memcpy(ngc.peerhook, ngc.ourhook, sizeof ngc.peerhook);

      if (debug)
        syslog(LOG_INFO, "Sending CONNECT from .:%s -> %s.%s",
               ngc.ourhook, ngc.path, ngc.peerhook);
      if (NgSendMsg(cs, ".:", NGM_GENERIC_COOKIE,
                    NGM_CONNECT, &ngc, sizeof ngc) < 0) {
        syslog(LOG_ERR, "Cannot CONNECT PPPoE and socket nodes: %m");
        _exit(EX_OSERR);
      }

      /*
       * If we tell the socket node not to LINGER, it will go away when
       * the last hook is removed.
       */
      if (debug)
        syslog(LOG_INFO, "Sending NGM_SOCK_CMD_NOLINGER to socket");
      if (NgSendMsg(cs, ".:", NGM_SOCKET_COOKIE,
                    NGM_SOCK_CMD_NOLINGER, NULL, 0) < 0) {
        syslog(LOG_ERR, "Cannot send NGM_SOCK_CMD_NOLINGER: %m");
        _exit(EX_OSERR);
      }

      /* Put the PPPoE node into OFFER mode */
      slen = strlen(acname);
      data = (struct ngpppoe_init_data *)alloca(sizeof *data + slen);
      snprintf(data->hook, sizeof data->hook, "%s", ngc.ourhook);
      memcpy(data->data, acname, slen);
      data->data_len = slen;

      path = (char *)alloca(strlen(ngc.ourhook) + 3);
      strcpy(path, ".:");
      strcpy(path + 2, ngc.ourhook);

      syslog(LOG_INFO, "Offering to %s as access concentrator %s",
             path, acname);
      if (NgSendMsg(cs, path, NGM_PPPOE_COOKIE, NGM_PPPOE_OFFER,
                    data, sizeof *data + slen) == -1) {
        syslog(LOG_INFO, "%s: Cannot OFFER on netgraph node: %m", path);
        _exit(EX_OSERR);
      }
      /* If we have a provider code, set it */
      if (provider) {
        slen = strlen(provider);
        data = (struct ngpppoe_init_data *)alloca(sizeof *data + slen);
        snprintf(data->hook, sizeof data->hook, "%s", ngc.ourhook);
        memcpy(data->data, provider, slen);
        data->data_len = slen;

        syslog(LOG_INFO, "adding to %s as offered service %s",
             path, acname);
        if (NgSendMsg(cs, path, NGM_PPPOE_COOKIE, NGM_PPPOE_SERVICE,
                    data, sizeof *data + slen) == -1) {
          syslog(LOG_INFO, "%s: Cannot add service on netgraph node: %m", path);
          _exit(EX_OSERR);
        }
      }

      /* Put the peer's MAC address in the environment */
      if (sz >= sizeof(struct ether_header)) {
        macaddr = ((struct ether_header *)request)->ether_shost;
        snprintf(env, sizeof(env), "%x:%x:%x:%x:%x:%x",
                 macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4],
                 macaddr[5]);
        if (setenv(HISMACADDR, env, 1) != 0)
          syslog(LOG_INFO, "setenv: cannot set %s: %m", HISMACADDR);
      }

      /* And send our request data to the waiting node */
      if (debug)
        syslog(LOG_INFO, "Sending original request to %s (%d bytes)", path, sz);
      if (NgSendData(ds, ngc.ourhook, request, sz) == -1) {
        syslog(LOG_ERR, "Cannot send original request to %s: %m", path);
        _exit(EX_OSERR);
      }

      /* Then wait for a success indication */

      if (debug)
        syslog(LOG_INFO, "Waiting for a SUCCESS reply %s", path);

      do {
        if ((ret = NgRecvMsg(cs, rep, sizeof msgbuf, NULL)) < 0) {
          syslog(LOG_ERR, "%s: Cannot receive a message: %m", path);
          _exit(EX_OSERR);
        }

        if (ret == 0) {
          /* The socket has been closed */
          syslog(LOG_INFO, "%s: Client timed out", path);
          _exit(EX_TEMPFAIL);
        }

        if (rep->header.version != NG_VERSION) {
          syslog(LOG_ERR, "%ld: Unexpected netgraph version, expected %ld",
                 (long)rep->header.version, (long)NG_VERSION);
          _exit(EX_PROTOCOL);
        }

        if (rep->header.typecookie != NGM_PPPOE_COOKIE) {
          syslog(LOG_INFO, "%ld: Unexpected netgraph cookie, expected %ld",
                 (long)rep->header.typecookie, (long)NGM_PPPOE_COOKIE);
          continue;
        }

        switch (rep->header.cmd) {
          case NGM_PPPOE_SET_FLAG:	msg = "SET_FLAG";	break;
          case NGM_PPPOE_CONNECT:	msg = "CONNECT";	break;
          case NGM_PPPOE_LISTEN:	msg = "LISTEN";		break;
          case NGM_PPPOE_OFFER:		msg = "OFFER";		break;
          case NGM_PPPOE_SUCCESS:	msg = "SUCCESS";	break;
          case NGM_PPPOE_FAIL:		msg = "FAIL";		break;
          case NGM_PPPOE_CLOSE:		msg = "CLOSE";		break;
          case NGM_PPPOE_GET_STATUS:	msg = "GET_STATUS";	break;
          case NGM_PPPOE_ACNAME:
            msg = "ACNAME";
            if (setenv("ACNAME", sts->hook, 1) != 0)
              syslog(LOG_WARNING, "setenv: cannot set ACNAME=%s: %m",
                     sts->hook);
            break;
          case NGM_PPPOE_SESSIONID:
            msg = "SESSIONID";
            snprintf(sessionid, sizeof sessionid, "%04x", *(u_int16_t *)sts);
            if (setenv("SESSIONID", sessionid, 1) != 0)
              syslog(LOG_WARNING, "setenv: cannot set SESSIONID=%s: %m",
                     sessionid);
            break;
          default:
            snprintf(unknown, sizeof unknown, "<%d>", (int)rep->header.cmd);
            msg = unknown;
            break;
        }

        switch (rep->header.cmd) {
          case NGM_PPPOE_FAIL:
          case NGM_PPPOE_CLOSE:
            syslog(LOG_ERR, "Received NGM_PPPOE_%s (hook \"%s\")",
                   msg, sts->hook);
            _exit(0);
        }

        syslog(LOG_INFO, "Received NGM_PPPOE_%s (hook \"%s\")", msg, sts->hook);
      } while (rep->header.cmd != NGM_PPPOE_SUCCESS);

      dup2(ds, STDIN_FILENO);
      dup2(ds, STDOUT_FILENO);
      close(ds);
      close(cs);

      setsid();
      syslog(LOG_INFO, "Executing: %s", exec);
      execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", exec, (char *)NULL);
      syslog(LOG_ERR, "execlp failed: %m");
      _exit(EX_OSFILE);

    default:
      wait(&ret);
      errno = ret;
      if (errno)
        syslog(LOG_ERR, "Second fork failed: %m");
      break;
  }
}
Ejemplo n.º 4
0
/*
 * main()
 */
int
main(int ac, char *av[])
{
	struct ngm_connect ngc;
	const char *path = NULL;
	const char *hook = DEFAULT_HOOKNAME;
	int     csock, dsock;
	int     asciiFlag = 0;
	int     loopFlag = 0;
	int	noInput = 0;
	int	execFlag = 0;
	int	ch;

	if ((msgs = sl_init()) == NULL)
		err(EX_OSERR, NULL);

	/* Parse flags */
	while ((ch = getopt(ac, av, "aedlm:nsS")) != -1) {
		switch (ch) {
		case 'a':
			asciiFlag = 1;
			break;
		case 'd':
			NgSetDebug(NgSetDebug(-1) + 1);
			break;
		case 'e':
			execFlag = 1;
			break;
		case 'l':
			loopFlag = 1;
			break;
		case 'n':
			noInput = 1;
			break;
		case 'm':
			if (sl_add(msgs, optarg) == -1)
				err(EX_OSERR, NULL);
			break;
		case 's':
			outfd = STDIN_FILENO;
			break;
		case 'S':
			infd = STDOUT_FILENO;
			break;
		case '?':
		default:
			Usage();
		}
	}
	ac -= optind;
	av += optind;

	if (execFlag) {
		if (asciiFlag || loopFlag) {
			fprintf(stderr, "conflicting options\n");
			Usage();
		}
		if (ac < 3)
			Usage();
		path = av[0];
		hook = av[1];
		av += 2;
		ac -= 2;
	} else {
		/* Get params */
		switch (ac) {
		case 2:
			hook = av[1];
			/* FALLTHROUGH */
		case 1:
			path = av[0];
			break;
		default:
			Usage();
		}
	}

	/* Get sockets */
	if (NgMkSockNode(NULL, &csock, &dsock) < 0)
		errx(EX_OSERR, "can't get sockets");

	/* Connect socket node to specified node */
	snprintf(ngc.path, sizeof(ngc.path), "%s", path);
	snprintf(ngc.ourhook, sizeof(ngc.ourhook), NG_SOCK_HOOK_NAME);
	snprintf(ngc.peerhook, sizeof(ngc.peerhook), "%s", hook);

	if (NgSendMsg(csock, ".",
	    NGM_GENERIC_COOKIE, NGM_CONNECT, &ngc, sizeof(ngc)) < 0)
		errx(EX_OSERR, "can't connect to node");

	if (execFlag) {
		/* move dsock to fd 0 and 1 */
		(void)close(0);
		(void)close(1);
		if (!noInput)
			(void)dup2(dsock, 0);
		(void)dup2(dsock, 1);

		send_msgs(csock, path);

		/* try executing the program */
		(void)execv(av[0], av);
		err(EX_OSERR, "%s", av[0]);

	} else
		send_msgs(csock, path);

	/* Close standard input if not reading from it */
	if (noInput)
		fclose(stdin);

	/* Relay data */
	while (1) {
		fd_set  rfds;

		/* Setup bits */
		FD_ZERO(&rfds);
		if (!noInput)
			FD_SET(infd, &rfds);
		FD_SET(dsock, &rfds);

		/* Wait for something to happen */
		if (select(FD_SETSIZE, &rfds, NULL, NULL, NULL) < 0)
			err(EX_OSERR, "select");

		/* Check data from socket */
		if (FD_ISSET(dsock, &rfds)) {
			char    buf[BUF_SIZE];
			int     rl, wl;

			/* Read packet from socket */
			if ((rl = NgRecvData(dsock,
			    buf, sizeof(buf), NULL)) < 0)
				err(EX_OSERR, "read(hook)");
			if (rl == 0)
				errx(EX_OSERR, "read EOF from hook?!");

			/* Write packet to stdout */
			if (asciiFlag)
				WriteAscii((u_char *) buf, rl);
			else if ((wl = write(outfd, buf, rl)) != rl) {
				if (wl < 0) {
					err(EX_OSERR, "write(stdout)");
				} else {
					errx(EX_OSERR,
					    "stdout: read %d, wrote %d",
					    rl, wl);
				}
			}
			/* Loopback */
			if (loopFlag) {
				if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0)
					err(EX_OSERR, "write(hook)");
			}
		}

		/* Check data from stdin */
		if (FD_ISSET(infd, &rfds)) {
			char    buf[BUF_SIZE];
			int     rl;

			/* Read packet from stdin */
			if ((rl = read(infd, buf, sizeof(buf))) < 0)
				err(EX_OSERR, "read(stdin)");
			if (rl == 0)
				errx(EX_OSERR, "EOF(stdin)");

			/* Write packet to socket */
			if (NgSendData(dsock, NG_SOCK_HOOK_NAME, buf, rl) < 0)
				err(EX_OSERR, "write(hook)");
		}
	}
}