/*------------------------------------------------------------------------
 *  tcpwinit - initialize window data for a new connection
 *------------------------------------------------------------------------
 */
int
tcpwinit(struct tcb *ptcb, struct tcb *newptcb, struct ep *pep)
{
	struct	ip	*pip = (struct ip *)pep->ep_data;
	struct	tcp	*ptcp = (struct tcp *)pip->ip_data;
	struct	route	*prt;
	unsigned	mss;
	Bool		local;

	newptcb->tcb_swindow = ptcp->tcp_window;
	newptcb->tcb_lwseq = ptcp->tcp_seq;
	newptcb->tcb_lwack = newptcb->tcb_iss;	/* set in tcpsync()	*/

	prt = (struct route *)rtget(pip->ip_src, RTF_REMOTE);
	local = prt && prt->rt_metric == 0;
	newptcb->tcb_pni = &nif[prt->rt_ifnum];
	rtfree(prt);
	if (local)
		mss = newptcb->tcb_pni->ni_mtu-IPMHLEN-TCPMHLEN;
	else
		mss = 536;	/* RFC 1122 */
	if (ptcb->tcb_smss) {
		newptcb->tcb_smss = min(ptcb->tcb_smss, mss);
		ptcb->tcb_smss = 0;		/* reset server smss	*/
	} else
		newptcb->tcb_smss = mss;
	newptcb->tcb_rmss = mss;		/* receive mss		*/
	newptcb->tcb_cwnd = newptcb->tcb_smss;	/* 1 segment		*/
	newptcb->tcb_ssthresh = 65535;		/* IP max window	*/
	newptcb->tcb_rnext = ptcp->tcp_seq;
	newptcb->tcb_cwin = newptcb->tcb_rnext + newptcb->tcb_rbsize;
}
示例#2
0
/* Supply dst with the contents of the routing tables.
 * If this won't fit in one packet, chop it up into several.
 */
void
supply(struct sockaddr_in *dst,
       struct interface *ifp,		/* output interface */
       enum output_type type,
       int flash,			/* 1=flash update */
       int vers,			/* RIP version */
       int passwd_ok)			/* OK to include cleartext password */
{
	struct rt_entry *rt;
	int def_metric;


	ws.state = 0;
	ws.gen_limit = 1024;

	ws.to = *dst;
	ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr);
	ws.to_std_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_std_mask;

	if (ifp != NULL) {
		ws.to_mask = ifp->int_mask;
		ws.to_net = ifp->int_net;
		if (on_net(ws.to.sin_addr.s_addr, ws.to_net, ws.to_mask))
			ws.state |= WS_ST_TO_ON_NET;

	} else {
		ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0);
		ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
		rt = rtfind(dst->sin_addr.s_addr);
		if (rt)
			ifp = rt->rt_ifp;
	}

	ws.npackets = 0;
	if (flash)
		ws.state |= WS_ST_FLASH;

	if ((ws.ifp = ifp) == NULL) {
		ws.metric = 1;
	} else {
		/* Adjust the advertised metric by the outgoing interface
		 * metric.
		 */
		ws.metric = ifp->int_metric+1;
	}

	ripv12_buf.rip.rip_vers = vers;

	switch (type) {
	case OUT_MULTICAST:
		if (ifp->int_if_flags & IFF_MULTICAST)
			v2buf.type = OUT_MULTICAST;
		else
			v2buf.type = NO_OUT_MULTICAST;
		v12buf.type = OUT_BROADCAST;
		break;

	case OUT_QUERY:
		ws.state |= WS_ST_QUERY;
		/* fall through */
	case OUT_BROADCAST:
	case OUT_UNICAST:
		v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
		v12buf.type = type;
		break;

	case NO_OUT_MULTICAST:
	case NO_OUT_RIPV2:
		break;			/* no output */
	}

	if (vers == RIPv2) {
		/* full RIPv2 only if cannot be heard by RIPv1 listeners */
		if (type != OUT_BROADCAST)
			ws.state |= WS_ST_RIP2_ALL;
		if ((ws.state & WS_ST_QUERY)
		    || !(ws.state & WS_ST_TO_ON_NET)) {
			ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
		} else if (ifp == NULL || !(ifp->int_state & IS_NO_AG)) {
			ws.state |= WS_ST_AG;
			if (type != OUT_BROADCAST
			    && (ifp == NULL
				|| !(ifp->int_state & IS_NO_SUPER_AG)))
				ws.state |= WS_ST_SUPER_AG;
		}
	}

	ws.a = (vers == RIPv2) ? find_auth(ifp) : 0;
	if (!passwd_ok && ws.a != NULL && ws.a->type == RIP_AUTH_PW)
		ws.a = NULL;
	clr_ws_buf(&v12buf,ws.a);
	clr_ws_buf(&v2buf,ws.a);

	/*  Fake a default route if asked and if there is not already
	 * a better, real default route.
	 */
	if (supplier && (def_metric = ifp->int_d_metric) != 0) {
		if (NULL == (rt = rtget(RIP_DEFAULT, 0))
		    || rt->rt_metric+ws.metric >= def_metric) {
			ws.state |= WS_ST_DEFAULT;
			ag_check(0, 0, 0, 0, def_metric, def_metric,
				 0, 0, 0, supply_out);
		} else {
			def_metric = rt->rt_metric+ws.metric;
		}

		/* If both RIPv2 and the poor-man's router discovery
		 * kludge are on, arrange to advertise an extra
		 * default route via RIPv1.
		 */
		if ((ws.state & WS_ST_RIP2_ALL)
		    && (ifp->int_state & IS_PM_RDISC)) {
			ripv12_buf.rip.rip_vers = RIPv1;
			v12buf.n->n_family = RIP_AF_INET;
			v12buf.n->n_dst = htonl(RIP_DEFAULT);
			v12buf.n->n_metric = htonl(def_metric);
			v12buf.n++;
		}
	}

	rn_walktree(rhead, walk_supply, 0);
	ag_flush(0,0,supply_out);

	/* Flush the packet buffers, provided they are not empty and
	 * do not contain only the password.
	 */
	if (v12buf.n != v12buf.base
	    && (v12buf.n > v12buf.base+1
		|| v12buf.base->n_family != RIP_AF_AUTH))
		supply_write(&v12buf);
	if (v2buf.n != v2buf.base
	    && (v2buf.n > v2buf.base+1
		|| v2buf.base->n_family != RIP_AF_AUTH))
		supply_write(&v2buf);

	/* If we sent nothing and this is an answer to a query, send
	 * an empty buffer.
	 */
	if (ws.npackets == 0
	    && (ws.state & WS_ST_QUERY))
		supply_write(&v12buf);
}
示例#3
0
文件: arp.c 项目: darksoul42/bitrig
/*
 * Set an individual arp entry
 */
int
set(int argc, char *argv[])
{
	struct sockaddr_inarp *sin;
	struct sockaddr_dl *sdl;
	struct rt_msghdr *rtm;
	char *eaddr = argv[1], *host = argv[0];
	struct ether_addr *ea;

	sin = &sin_m;
	rtm = &(m_rtmsg.m_rtm);

	getsocket();
	argc -= 2;
	argv += 2;
	sdl_m = blank_sdl;		/* struct copy */
	sin_m = blank_sin;		/* struct copy */
	if (getinetaddr(host, &sin->sin_addr) == -1)
		return (1);
	ea = ether_aton(eaddr);
	if (ea == NULL)
		errx(1, "invalid ethernet address: %s", eaddr);
	memcpy(LLADDR(&sdl_m), ea, sizeof(*ea));
	sdl_m.sdl_alen = 6;
	expire_time = 0;
	doing_proxy = flags = export_only = 0;
	while (argc-- > 0) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timeval now;

			gettimeofday(&now, 0);
			expire_time = now.tv_sec + 20 * 60;
			if (flags & RTF_PERMANENT_ARP) {
				/* temp or permanent, not both */
				usage();
				return (0);
			}
		} else if (strncmp(argv[0], "pub", 3) == 0) {
			flags |= RTF_ANNOUNCE;
			doing_proxy = SIN_PROXY;
		} else if (strncmp(argv[0], "permanent", 9) == 0) {
			flags |= RTF_PERMANENT_ARP;
			if (expire_time != 0) {
				/* temp or permanent, not both */
				usage();
				return (0);
			}
		}

		argv++;
	}

tryagain:
	if (rtget(&sin, &sdl)) {
		warn("%s", host);
		return (1);
	}

	if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
		if (sdl->sdl_family == AF_LINK &&
		    (rtm->rtm_flags & RTF_LLINFO) &&
		    !(rtm->rtm_flags & RTF_GATEWAY))
			switch (sdl->sdl_type) {
			case IFT_ETHER:
			case IFT_FDDI:
			case IFT_ISO88023:
			case IFT_ISO88024:
			case IFT_ISO88025:
			case IFT_CARP:
				goto overwrite;
			}

		if (doing_proxy == 0) {
			printf("set: can only proxy for %s\n", host);
			return (1);
		}
		if (sin_m.sin_other & SIN_PROXY) {
			printf("set: proxy entry exists for non 802 device\n");
			return (1);
		}
		sin_m.sin_other = SIN_PROXY;
		export_only = 1;
		goto tryagain;
	}

overwrite:
	if (sdl->sdl_family != AF_LINK) {
		printf("cannot intuit interface index and type for %s\n", host);
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return (rtmsg(RTM_ADD));
}