/*------------------------------------------------------------------------ * netnum - compute the network portion of a given IP address *------------------------------------------------------------------------ */ IPaddr netnum(IPaddr ipa) { IPaddr mask = ~0; if (IP_CLASSA(ipa)) mask = hl2net(0xff000000); if (IP_CLASSB(ipa)) mask = hl2net(0xffff0000); if (IP_CLASSC(ipa)) mask = hl2net(0xffffff00); return ipa & mask; }
/*------------------------------------------------------------------------ * dd_queue - generate Data Description packets *------------------------------------------------------------------------ */ void dd_queue(struct ospf_if *pif, struct ospf_nb *pnb) { struct ep *pep; struct ip *pip; struct ospf *po; struct ospf_dd *pdd; pep = ospfddtmpl(pif); if (pep == 0) return; pip = (struct ip *)pep->ep_data; po = (struct ospf *)pip->ip_data; pdd = (struct ospf_dd *)po->ospf_data; if (pnb->nb_state == NBS_EXSTART) { pdd->dd_control = DDC_INIT | DDC_MORE | DDC_MSTR; pdd->dd_seq = hl2net(pnb->nb_seq); if (enq(pnb->nb_dsl, pep, 0) < 0) freebuf(pep); dd_xmit(pif, pnb); pnb->nb_trexmt = pif->if_rintv; return; } /* else we're in EXCHANGE state */ lss_build(pif, pnb, pep); dd_xmit(pif, pnb); if (pnb->nb_master) pnb->nb_trexmt = pif->if_rintv; }
/*------------------------------------------------------------------------ * netmask - set the default mask for the given net *------------------------------------------------------------------------ */ IPaddr netmask(IPaddr net) { IPaddr netpart; int i; if (net == 0) return net; /* check for net match (for subnets) */ netpart = netnum(net); for (i=0; i<Net.nif; ++i) if (nif[i].ni_svalid && nif[i].ni_ivalid && nif[i].ni_net == netpart) return nif[i].ni_mask; if (IP_CLASSA(net)) return hl2net(0xff000000); if (IP_CLASSB(net)) return hl2net(0xffff0000); if (IP_CLASSC(net)) return hl2net(0xffffff00); return ~0; }
/** * Send an ICMP Echo (Ping) Request. * @param dst destination address * @param id ping stream identifier * @param seq sequence number * @return OK if packet was sent, otherwise SYSERR */ syscall icmpEchoRequest(struct netaddr *dst, ushort id, ushort seq) { struct packet *pkt = NULL; struct icmpEcho *echo = NULL; int result = OK; irqmask im; ICMP_TRACE("echo request(%d, %d)", id, seq); pkt = netGetbuf(); if (SYSERR == (int)pkt) { ICMP_TRACE("Failed to acquire packet buffer"); return SYSERR; } pkt->len = sizeof(struct icmpEcho); pkt->curr -= pkt->len; echo = (struct icmpEcho *)pkt->curr; echo->id = hs2net(id); echo->seq = hs2net(seq); /* Our optional data payload includes room for the departure */ /* and arrival timestamps, in seconds, milliseconds, and */ /* clock cycles. */ im = disable(); echo->timecyc = hl2net(clkcount()); echo->timetic = hl2net(clkticks); echo->timesec = hl2net(clktime); restore(im); echo->arrivcyc = 0; echo->arrivtic = 0; echo->arrivsec = 0; ICMP_TRACE("Sending Echo Request id = %d, seq = %d, time = %d.%d", net2hs(echo->id), net2hs(echo->seq), net2hl(echo->timesec), net2hl(echo->timetic)); result = icmpSend(pkt, ICMP_ECHO, 0, sizeof(struct icmpEcho), dst); netFreebuf(pkt); return result; }
/*------------------------------------------------------------------------- * make_bootp_packet - *------------------------------------------------------------------------- */ static int make_bootp_packet(struct bootp_msg *bptr, int secs) { bzero(bptr, BOOTP_SIZE); bptr->op = BOOTREQUEST; bptr->htype = AR_HARDWARE; bptr->hlen = EP_ALEN; bptr->xid = 47; /* just a random number that's nonzero */ bptr->secs = hs2net(secs); blkcopy(bptr->chaddr, (char *)&(mon_eth[0].ed_paddr), EP_ALEN); *(int *)bptr->vend = hl2net(RFC1084); bptr->vend[5] = 0xff; #ifdef DEBUG kprintf("Using ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", bptr->chaddr[0], bptr->chaddr[1], bptr->chaddr[2], bptr->chaddr[3], bptr->chaddr[4], bptr->chaddr[5]); #endif return(OK); }
/*------------------------------------------------------------------------ * rwhod - Periodically clean cache and (optionally) send rwho packets *------------------------------------------------------------------------ */ PROCESS rwhod(void) { STATWORD ps; char *p; int i, j; struct rwent *rwptr; struct rwent *myptr; struct rwhopac *rpacptr; struct rw_who *rwwptr; struct ep *pep; u_long now; int len; /* Initialize rwho information */ Rwho.rwnent = 1; Rwho.rwsend = TRUE; getutim(&Rwho.rwbtime); myptr = &Rwho.rwcache[0]; myptr->rwboot = myptr->rwlast = myptr->rwslast = Rwho.rwbtime; for (i=0 ; i<3 ; i++) myptr->rwload[i] = 0L; myptr->rwusers = 1; for( ; TRUE ; sleep(RWDELAY) ) { if (getname(myptr->rwmach) == SYSERR) continue; if (p = index(myptr->rwmach, '.')) *p = '\0'; getutim(&now); myptr->rwlast = myptr->rwslast = now; disable(ps); for (i=0 ; i<Rwho.rwnent ; i++) { rwptr = &Rwho.rwcache[i]; if (now - rwptr->rwlast > RWMAXDT) { Rwho.rwnent--; for (j=i-- ; j<Rwho.rwnent ; j++) Rwho.rwcache[j] = Rwho.rwcache[j+1]; } } restore(ps); if (!Rwho.rwsend) continue; pep = (struct ep *)getbuf(Net.netpool); rpacptr = (struct rwhopac *) ((struct udp *) (((struct ip *)pep->ep_data)->ip_data))->u_data; rpacptr->rw_vers = RWVERSION; rpacptr->rw_type= RWSTATUS; rpacptr->rw_sndtim = hl2net(now); rpacptr->rw_rtim = 0L; getname(rpacptr->rw_host); if (p = index(rpacptr->rw_host, '.')) *p = '\0'; for (j=0 ; j<RWNLOAD ; j++) rpacptr->rw_load[j] = 0L; rpacptr->rw_btim = hl2net(Rwho.rwbtime); len = RWMINP; if ( marked(Shl.shmark) && Shl.shused ) { rwwptr = &rpacptr->rw_rww[0]; strcpy (rwwptr->rw_tty, "Console"); strncpy(rwwptr->rw_nam, Shl.shuser, RWNLEN); rwwptr->rw_ton = hl2net(Shl.shlogon); rwwptr->rw_idle = hl2net(now - Shl.shlast); len += sizeof(struct rw_who); } for (i=0; i<(Net.nif-1); ++i) { struct ep *pep2; if (i == NI_LOCAL) continue; if (nif[i].ni_state != NIS_UP) continue; pep2 = (struct ep *)getbuf(Net.netpool); if (pep2 == (struct ep *)SYSERR) break; memcpy(pep2, pep, EP_HLEN+IP_ALEN+len); udpsend(nif[i].ni_brc, UP_RWHO, UP_RWHO, pep2, len, 1); } udpsend(nif[i].ni_brc, UP_RWHO, UP_RWHO, pep, len, 1); } }
//------------------------------------------------------------------------ // rwhod - Periodically clean cache and (optionally) send rwho packets //------------------------------------------------------------------------ PROCESS rwhod(void) { int i, j; struct rwent *rwptr; struct rwent *myptr; struct rwhopac *rpacptr; struct rw_who *rwwptr; struct epacket *packet; IPaddr mynet; long now; int len; int ps; // Initialize rwho information Rwho.rwnent = 1; Rwho.rwsend = TRUE; getutime(&Rwho.rwbtime); myptr = &Rwho.rwcache[0]; getname(myptr->rwmach, RMACLEN); myptr->rwboot = myptr->rwlast = myptr->rwslast = Rwho.rwbtime; for (i = 0; i < 3; i++) myptr->rwload[i] = 0L; myptr->rwusers = 1; getnet(mynet); for (; TRUE; sleep(RWDELAY)) { getutime(&now); myptr->rwlast = myptr->rwslast = now; ps = disable(); for (i = 0; i < Rwho.rwnent; i++) { rwptr = &Rwho.rwcache[i]; if (now - rwptr->rwlast > RWMAXDT) { Rwho.rwnent--; for (j = i--; j < Rwho.rwnent; j++) Rwho.rwcache[j] = Rwho.rwcache[j + 1]; } } restore(ps); if (!Rwho.rwsend) continue; packet = (struct epacket *)getbuf(Net.netpool); rpacptr = (struct rwhopac *) ((struct udp *) (((struct ip *)packet->ep_data)->i_data))->u_data; rpacptr->rw_vers = RWVERSION; rpacptr->rw_type = RWSTATUS; rpacptr->rw_sndtim = hl2net(now); rpacptr->rw_rtim = 0L; getname(rpacptr->rw_host, sizeof(rpacptr->rw_host)); for (j = 0; j < RWNLOAD; j++) rpacptr->rw_load[j] = 0L; rpacptr->rw_btim = hl2net(Rwho.rwbtime); len = RWMINP; if (marked(Shl.shmark) && Shl.shused) { rwwptr = &rpacptr->rw_rww[0]; strlcpy(rwwptr->rw_tty, "Console", RWNLEN); strncpy(rwwptr->rw_nam, Shl.shuser, RWNLEN); rwwptr->rw_ton = hl2net(Shl.shlogon); rwwptr->rw_idle = hl2net(now - Shl.shlast); len += sizeof(struct rw_who); } udpsend(mynet, URWHO, URWHO, packet, len); } }
/** * Sends a reset in response to an incorrect TCP packet * @param pkt incoming packet which requires a reset response * @param src source IP address of the packet * @param dst destination IP address of the packet */ int tcpSendRst(struct packet *pkt, struct netaddr *src, struct netaddr *dst) { struct packet *out; struct tcpPkt *tcp; struct tcpPkt *outtcp; ushort datalen; int result; ushort tcplen; /* Setup packet pointers */ tcp = (struct tcpPkt *)pkt->curr; tcplen = pkt->len - (pkt->curr - pkt->linkhdr); /* Verify not sending a reset in response to a reset */ if (tcp->control & TCP_CTRL_RST) { return OK; } /* Get space to construct packet */ out = netGetbuf(); if (SYSERR == (int)out) { return SYSERR; } out->curr -= TCP_HDR_LEN; out->len += TCP_HDR_LEN; /* Set TCP header fields */ outtcp = (struct tcpPkt *)out->curr; outtcp->srcpt = tcp->dstpt; outtcp->dstpt = tcp->srcpt; outtcp->offset = octets2offset(TCP_HDR_LEN); outtcp->control = TCP_CTRL_RST; if (tcp->control & TCP_CTRL_ACK) { outtcp->seqnum = tcp->acknum; } else { outtcp->seqnum = 0; outtcp->control |= TCP_CTRL_ACK; } datalen = tcplen - offset2octets(tcp->offset); if (tcp->control & TCP_CTRL_SYN) { datalen++; } if (tcp->control & TCP_CTRL_FIN) { datalen++; } outtcp->acknum = tcp->seqnum + datalen; /* Convert TCP header fields to net order */ outtcp->srcpt = hs2net(outtcp->srcpt); outtcp->dstpt = hs2net(outtcp->dstpt); outtcp->seqnum = hl2net(outtcp->seqnum); outtcp->acknum = hl2net(outtcp->acknum); outtcp->window = hs2net(outtcp->window); outtcp->urgent = hs2net(outtcp->urgent); /* Calculate TCP checksum */ outtcp->chksum = tcpChksum(out, TCP_HDR_LEN, src, dst); /* Send TCP packet */ result = ipv4Send(out, src, dst, IPv4_PROTO_TCP); if (SYSERR == netFreebuf(out)) { return SYSERR; } return result; }