void addrouteforif(struct interface *ifp) { struct sockaddr_in net; struct sockaddr *dst; int state; struct rt_entry *rt; if (ifp->int_flags & IFF_POINTOPOINT) dst = &ifp->int_dstaddr; else { memset(&net, 0, sizeof (net)); net.sin_family = AF_INET; net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); dst = (struct sockaddr *)&net; } rt = rtfind(dst); if (rt && (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE) return; if (rt) rtdelete(rt); /* * If interface on subnetted network, * install route to network as well. * This is meant for external viewers. */ if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) { struct in_addr subnet; subnet = net.sin_addr; net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); rt = rtfind(dst); if (rt == 0) rtadd(dst, &ifp->int_addr, ifp->int_metric, ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) | RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET)); else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == (RTS_INTERNAL|RTS_SUBNET) && ifp->int_metric < rt->rt_metric) rtchange(rt, &rt->rt_router, ifp->int_metric); net.sin_addr = subnet; } if (ifp->int_transitions++ > 0) syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); state = ifp->int_flags & (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET); if (ifp->int_flags & IFF_POINTOPOINT && (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) & ifp->int_netmask) != ifp->int_net) state &= ~RTS_SUBNET; if (ifp->int_flags & IFF_LOOPBACK) state |= RTS_EXTERNAL; rtadd(dst, &ifp->int_addr, ifp->int_metric, state); if (ifp->int_flags & IFF_POINTOPOINT && foundloopback) add_ptopt_localrt(ifp); }
void add_ptopt_localrt(struct interface *ifp) { struct rt_entry *rt; struct sockaddr *dst; struct sockaddr_in net; int state; state = RTS_INTERFACE | RTS_PASSIVE; /* look for route to logical network */ memset(&net, 0, sizeof (net)); net.sin_family = AF_INET; net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); dst = (struct sockaddr *)&net; rt = rtfind(dst); if (rt && rt->rt_state & RTS_INTERNAL) state |= RTS_SUBNET; dst = &ifp->int_addr; if ((rt = rtfind(dst))!=NULL) { if (rt && rt->rt_state & RTS_INTERFACE) return; rtdelete(rt); } rtadd(dst, &loopaddr, 1, state); }
/*------------------------------------------------------------------------ * hgjoin - handle application request to join a host group *------------------------------------------------------------------------ */ int hgjoin(unsigned ifnum, IPaddr ipa, Bool islocal) { struct hg *phg; int i; if (!IP_CLASSD(ipa)) return SYSERR; /* restrict multicast in multi-homed host to primary interface */ if (ifnum != NI_PRIMARY) return SYSERR; wait(HostGroup.hi_mutex); if (phg = hglookup(ifnum, ipa)) { phg->hg_refs++; signal(HostGroup.hi_mutex); return OK; /* already in it */ } signal(HostGroup.hi_mutex); /* add to host group and routing tables */ if (hgadd(ifnum, ipa, islocal) == SYSERR) return SYSERR; rtadd(ipa, ip_maskall, ipa, 0, NI_LOCAL, RT_INF); /* * advertise membership to multicast router(s); don't advertise * 224.0.0.1 (all multicast hosts) membership. */ if (ipa != ig_allhosts) for (i=0; i < IG_NSEND; ++i) { igmp(IGT_HREPORT, ifnum, ipa); sleep10(IG_DELAY); } return OK; }
/*------------------------------------------------------------------------ * setmask - set the net mask for an interface *------------------------------------------------------------------------ */ int setmask(unsigned ifn, IPaddr mask) { IPaddr defmask; if (nif[ifn].ni_svalid) { /* one set already-- fix things */ rtdel(nif[ifn].ni_subnet, nif[ifn].ni_mask); rtdel(nif[ifn].ni_brc, ip_maskall); rtdel(nif[ifn].ni_subnet, ip_maskall); } nif[ifn].ni_mask = mask; nif[ifn].ni_svalid = TRUE; defmask = netmask(nif[ifn].ni_ip); nif[ifn].ni_subnet = nif[ifn].ni_ip & nif[ifn].ni_mask; if (bsdbrc) nif[ifn].ni_brc = nif[ifn].ni_subnet; else nif[ifn].ni_brc = nif[ifn].ni_subnet | ~nif[ifn].ni_mask; /* set network (not subnet) broadcast */ nif[ifn].ni_nbrc = nif[ifn].ni_ip | ~defmask; /* install routes */ /* net */ rtadd(nif[ifn].ni_subnet, nif[ifn].ni_mask, nif[ifn].ni_ip, 0, ifn, RT_INF); if (bsdbrc) { IPaddr aobrc; /* all 1's broadcast */ aobrc = nif[ifn].ni_subnet | ~nif[ifn].ni_mask; rtadd(aobrc, ip_maskall, nif[ifn].ni_ip, 0, NI_LOCAL, RT_INF); } else /* broadcast (all 1's) */ rtadd(nif[ifn].ni_brc, ip_maskall, nif[ifn].ni_ip, 0, NI_LOCAL, RT_INF); /* broadcast (all 0's) */ rtadd(nif[ifn].ni_subnet, ip_maskall, nif[ifn].ni_ip, 0, NI_LOCAL, RT_INF); return OK; }
/*------------------------------------------------------------------------ * rarpsend - broadcast a RARP packet to obtain my IP address *------------------------------------------------------------------------ */ int rarpsend(int ifn) { STATWORD ps; struct netif *pni = &nif[ifn]; struct ep *pep; int i, mypid, resp; IPaddr junk = 0; /* arg to mkarp; never used */ mypid = getpid(); for (i=0; i<ARP_MAXRETRY; ++i) { pep = mkarp(ifn, EPT_RARP, RA_REQUEST, junk, junk); if ((int)pep == SYSERR) break; disable(ps); rarppid = mypid; restore(ps); recvclr(); write(pni->ni_dev, pep, EP_MINLEN); /* ARP_RESEND is in secs, recvtim uses 1/10's of secs */ resp = recvtim(10*ARP_RESEND<<i); if (resp != TIMEOUT) { /* host route */ rtadd(pni->ni_ip, ip_maskall, pni->ni_ip, 0, NI_LOCAL, RT_INF); /* non-subnetted route */ rtadd(pni->ni_net, ip_maskall, pni->ni_ip, 0, NI_LOCAL, RT_INF); return OK; } } panic("No response to RARP"); return SYSERR; }
void addrouteforif(struct interface *ifp) { struct sockaddr_ipx net; struct sockaddr *dst; struct rt_entry *rt; if (ifp->int_flags & IFF_POINTOPOINT) { int (*match)(); struct interface *ifp2 = ifnet; dst = &ifp->int_dstaddr; /* Search for interfaces with the same net */ ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq); match = afswitch[dst->sa_family].af_netmatch; if (match) for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) { if ((ifp->int_flags & IFF_POINTOPOINT) == 0) continue; if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) { insque(&ifp2->int_sq,&ifp->int_sq); break; } } } else { bzero(&net, sizeof(net)); net.sipx_family = AF_IPX; net.sipx_len = sizeof (net); net.sipx_addr.x_net = satoipx_addr(ifp->int_broadaddr).x_net; dst = (struct sockaddr *)&net; } rt = rtlookup(dst); if (rt) rtdelete(rt); if (tracing) fprintf(stderr, "Adding route to interface %s\n", ifp->int_name); if (ifp->int_transitions++ > 0) syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); rtadd(dst, &ifp->int_addr, ifp->int_metric, 0, ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE)); }
static void addrouteforif(struct interface *ifp) { struct rt_entry *rt; struct in6_addr *dst; if (ifp->int_flags & RIP6_IFF_POINTOPOINT) dst = &ifp->int_dstaddr; else dst = &ifp->int_addr; rt = rtlookup(dst, ifp->int_prefix_length); if (rt != NULL) { if (rt->rt_state & RTS_INTERFACE) return; rtdelete(rt); } rtadd(dst, &ifp->int_addr, ifp->int_prefix_length, ifp->int_metric, 0, _B_TRUE, ifp); }
void gwkludge(void) { struct sockaddr_in dst, gate; FILE *fp; char *type, *dname, *gname, *qual, buf[BUFSIZ]; struct interface *ifp; int metric, n; struct rt_entry route; fp = fopen(_PATH_GATEWAYS, "r"); if (fp == NULL) return; qual = buf; dname = buf + 64; gname = buf + ((BUFSIZ - 64) / 3); type = buf + (((BUFSIZ - 64) * 2) / 3); memset(&dst, 0, sizeof (dst)); memset(&gate, 0, sizeof (gate)); memset(&route, 0, sizeof(route)); /* format: {net | host} XX gateway XX metric DD [passive | external]\n */ #define readentry(fp) \ fscanf((fp), "%s %s gateway %s metric %d %s\n", \ type, dname, gname, &metric, qual) for (;;) { if ((n = readentry(fp)) == EOF) break; /* * Lusertrap. Vendors should ship the line * * CONFIGME CONFIGME gateway CONFIGME metric 1 * */ if (strcmp(type,"CONFIGME")==0) { fprintf(stderr,"Not starting gated. Please configure first.\n"); exit(1); } if (!getnetorhostname(type, dname, &dst)) continue; if (!gethostnameornumber(gname, &gate)) continue; if (metric == 0) /* XXX */ metric = 1; if (strcmp(qual, "passive") == 0) { /* * Passive entries aren't placed in our tables, * only the kernel's, so we don't copy all of the * external routing information within a net. * Internal machines should use the default * route to a suitable gateway (like us). */ route.rt_dst = *(struct sockaddr *) &dst; route.rt_router = *(struct sockaddr *) &gate; route.rt_flags = RTF_UP; if (strcmp(type, "host") == 0) route.rt_flags |= RTF_HOST; if (metric) route.rt_flags |= RTF_GATEWAY; (void) rtioctl(ADD, &route.rt_rt); continue; } if (strcmp(qual, "external") == 0) { /* * Entries marked external are handled * by other means, e.g. EGP, * and are placed in our tables only * to prevent overriding them * with something else. */ rtadd((struct sockaddr *)&dst, (struct sockaddr *)&gate, metric, RTS_EXTERNAL|RTS_PASSIVE); continue; } /* assume no duplicate entries */ externalinterfaces++; ifp = (struct interface *)malloc(sizeof (*ifp)); memset(ifp, 0, sizeof (*ifp)); ifp->int_flags = IFF_REMOTE; /* can't identify broadcast capability */ ifp->int_net = inet_netof_subnet(dst.sin_addr); if (strcmp(type, "host") == 0) { ifp->int_flags |= IFF_POINTOPOINT; ifp->int_dstaddr = *((struct sockaddr *)&dst); } ifp->int_addr = *((struct sockaddr *)&gate); ifp->int_metric = metric; ifp->int_next = ifnet; ifnet = ifp; addrouteforif(ifp); } fclose(fp); }
/*------------------------------------------------------------------------ * netstart - initialize net *------------------------------------------------------------------------ */ int netstart(int userpid) { char str[128]; char *str1 = "sleeping 30 secs to get routes..."; char *str2 = "\ndone.\n"; unsigned long now; int i; if (clkruns == FALSE) panic("net: no clock"); /* initialize ports */ for (i=0 ; i<UPPS ; i++) upqs[i].up_valid = FALSE; udpmutex = screate(1); arpinit(); ipfinit(); /* init the IP frag queue */ /* these need a command to set/clear them. FIX ME!!! */ gateway = 1; IpForwarding = 1; /* == 2 if not a gateway */ IfNumber = Net.nif - 1; /* bsdbrc = 1; */ /* uncomment to use 0's broadcast */ if (gateway) { IPaddr gw; initgate(); gw = dot2ip(DEFRTR); rtadd(RT_DEFAULT, RT_DEFAULT, gw, RTM_INF-1, 1, RT_INF); } else inithost(); rtadd(RT_LOOPBACK, ip_maskall, RT_LOOPBACK, 0, NI_LOCAL, RT_INF); for (i=0; i<Net.nif; ++i) { nif[i].ni_ipinq = newq(NI_INQSZ, QF_NOWAIT); nif[i].ni_hwtype = AR_HARDWARE; /* for ARP */ /* no OTHER's for now */ if (i < 2) nif[i].ni_state = NIS_UP; } /* * wait()'s synchronize to insure initialization is done * before proceeding. */ resume(create(slowtimer, STSTK, STPRI, STNAM, STARGC)); wait(Net.sema); resume(create(ipproc, IPSTK, IPPRI, IPNAM, IPARGC)); wait(Net.sema); resume(create(tcptimer, TMSTK, TMPRI, TMNAM, TMARGC)); wait(Net.sema); resume(create(tcpinp, TCPISTK, TCPIPRI, TCPINAM, TCPIARGC)); wait(Net.sema); resume(create(tcpout, TCPOSTK, TCPOPRI, TCPONAM, TCPOARGC)); wait(Net.sema); if (!gateway) { write(CONSOLE, str1, strlen(str1)); sleep(30); write(CONSOLE, str2, strlen(str2)); } /* get addrs & names */ for (i=0; i<Net.nif; ++i) { IPaddr junk; char junk2[64]; if (i == NI_LOCAL) continue; if (nif[i].ni_state != NIS_UP) continue; junk = getiaddr(i); sprintf(str, "if%d IP %s ha %02x:%02x:%02x:%02x:%02x:%02x ", i, ip2dot(junk2, nif[i].ni_ip), nif[i].ni_hwa.ha_addr[0]&0xff, nif[i].ni_hwa.ha_addr[1]&0xff, nif[i].ni_hwa.ha_addr[2]&0xff, nif[i].ni_hwa.ha_addr[3]&0xff, nif[i].ni_hwa.ha_addr[4]&0xff, nif[i].ni_hwa.ha_addr[5]&0xff); write(CONSOLE, str, strlen(str)); sprintf(str, "br %02x:%02x:%02x:%02x:%02x:%02x\n", nif[i].ni_hwb.ha_addr[0]&0xff, nif[i].ni_hwb.ha_addr[1]&0xff, nif[i].ni_hwb.ha_addr[2]&0xff, nif[i].ni_hwb.ha_addr[3]&0xff, nif[i].ni_hwb.ha_addr[4]&0xff, nif[i].ni_hwb.ha_addr[5]&0xff); write(CONSOLE, str, strlen(str)); icmp(ICT_MASKRQ, 0, nif[i].ni_brc, 0, 0); recvtim(30); /* wait for an answer */ getiname(i, junk2); } getutim(&now); #ifdef MULTICAST hginit(); #endif /* MULTICAST */ #ifdef RIP resume(create(rip, RIPISTK, RIPPRI, RIPNAM, RIPARGC)); #endif /* RIP */ #ifdef OSPF resume(create(ospf, OSPFSTK, OSPFPRI, OSPFNAM, 0)); #endif /* OSPF */ #ifdef SNMP resume(create(snmpd, SNMPSTK, SNMPPRI, SNMPDNAM, 0)); #endif /* SNMP */ rwho(); resume(create(FINGERD, FNGDSTK, FNGDPRI, FNGDNAM, FNGDARGC)); resume(create(ECHOD, ECHOSTK, ECHOPRI, ECHODNAM, 0)); resume(create(udpecho, 1000, 50, "udpecho", 0)); resume(userpid); }