示例#1
0
netbuf_t
pppgetbuf(netif_t ifp)
{
    NETBUF_T nb;

    int len = MAX(if_mtu(ifp), PPP_MTU) + PPP_HDRLEN + PPP_FCSLEN;
    nb = NB_ALLOC(len);
    if (nb != NULL)
      {
	NB_SHRINK_TOP(nb, PPP_HDRLEN);
	NB_SHRINK_BOT(nb, PPP_FCSLEN);          /* grown by pppstart() */
      }
    return NB_TO_nb(nb);
}
示例#2
0
int
main(int argc, char *argv[])
{
	char pkt[IP_MAXPACKET];
	ssize_t pktlen, hlen;
	struct ip *pip = (struct ip *)pkt;
	struct sockaddr_in sin;
	socklen_t sinlen;
	int s;
	int mflag;
	u_long mtu;
	u_int16_t maxmss;
	int rtsock;
	int ifindex;
	int pflag;
	u_short port;
	int ch;
	fd_set fdset;

	mflag = pflag = 0;
	port = 0;			/* XXX gcc -Wuninitialized */
	ifindex = 0;
	rtsock = -1;

	while ((ch = getopt(argc, argv, "bi:m:p:v")) != -1)
		switch (ch) {
		case 'b':
			both = 1;
			break;
		case 'i':
			if (!(ifindex = if_mtu(optarg, &mtu))) {
				errx(1, "unknown interface %s", optarg);
				/* NOTREACHED */
			}
			snprintf(pidfilename, sizeof pidfilename,
				 "%stcpmssd.%s.pid", _PATH_VARRUN, optarg);
			break;
		case 'm':
			if ((mtu = atoi(optarg)) < 68) {
				errx(1, "invalid MTU value");
				/* NOTREACHED */
			}
			mflag++;
			break;
		case 'p':
			port = htons(atoi(optarg));
			pflag++;
			break;
		case 'v':
			verbose = 1;
			break;
		case '?':
		default:
			usage();
			/* NOTREACHED */
		}
	argc -= optind;
	argv += optind;

	if (!(!mflag - !ifindex) || !pflag || argc) {
		usage();
		/* NOTREACHED */
	}

	if ((s = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)) == -1) {
		err(1, "can't create divert socket");
		/* NOTREACHED */
	}

	bzero(&sin, sizeof(sin));
	sin.sin_family = PF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = port;

	if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
		err(1, "can't bind divert socket");
		/* NOTREACHED */
	}

	if (ifindex)
		if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) {
			err(1, "can't create routing socket");
			/* NOTREACHED */
		}

	maxmss = MAXMSS(mtu);
	if (verbose)
		fprintf(stderr, "Maximum MSS: %u\n", maxmss);

	if (!verbose)
		if (daemon(0, 0) == -1) {
			err(1, "can't daemonize");
			/* NOTREACHED */
		}

	if (ifindex) {
		FILE *pidfile;

		pidfile = fopen(pidfilename, "w");
		if (pidfile != NULL) {
			fprintf(pidfile, "%d\n", (int)getpid());
			fclose(pidfile);
			if (signal(SIGTERM, sigterm_handler) == SIG_ERR) {
				err(1, "can't install SIGTERM handler");
				/* NOTREACHED */
			}
		}
	}

	while (1) {
		FD_ZERO(&fdset);
		FD_SET(s, &fdset);
		if (rtsock != -1)
			FD_SET(rtsock, &fdset);

		if (select(32, &fdset, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL) == -1) {
			warn("select failed");
			continue;
		}

		if (rtsock != -1 && FD_ISSET(rtsock, &fdset)) {
			struct if_msghdr ifm;

			if ((pktlen = read(rtsock, &ifm, sizeof(ifm))) == -1) {
				warn("read from routing socket failed");
				continue;
			}
			if (ifm.ifm_version != RTM_VERSION) {
				if (verbose)
					warnx("routing message version %d "
					      "not understood", ifm.ifm_version);
				continue;
			}
			if (ifm.ifm_type != RTM_IFINFO ||
			    ifm.ifm_index != ifindex)
				continue;
			if (mtu != ifm.ifm_data.ifi_mtu) {
				mtu = ifm.ifm_data.ifi_mtu;
				maxmss = MAXMSS(mtu);
				if (verbose)
					fprintf(stderr, "Maximum MSS: %u\n", maxmss);
			}
		}

		if (FD_ISSET(s, &fdset)) {
			sinlen = sizeof(sin);

			if ((pktlen = recvfrom(s, pkt, sizeof(pkt), 0,
					       (struct sockaddr *)&sin, &sinlen)) == -1)
				if (errno != EINTR) {
					warn("read from divert socket failed");
					continue;
				}

			hlen = pip->ip_hl << 2;

			/*-
			 * Check for MSS option only for outgoing
			 * TCP packets with zero fragment offset
			 * and correct total and header lengths.
			 */
			if ((both || sin.sin_addr.s_addr == INADDR_ANY) &&
			    pip->ip_p == IPPROTO_TCP &&
			    (ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
			    ntohs(pip->ip_len) == pktlen &&
			    hlen <= pktlen &&
			    pktlen - hlen >= sizeof(struct tcphdr))
				correct_mss((struct tcphdr *)(pkt + hlen),
					    pktlen - hlen, maxmss);

			if (sendto(s, pkt, pktlen, 0,
			    (struct sockaddr *)&sin, sinlen) == -1)
				warn("write to divert socket failed");
		}
	}
}