/*------------------------------------------------------------------------ * 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; }
/* 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); }
/* * 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)); }