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); }
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"); } } }