/*------------------------------------------------------------------------- * mon_bootp_parse - *------------------------------------------------------------------------- */ int mon_bootp_parse(struct bootp_msg *p) { unsigned long cookie; cookie = *(unsigned long *)p->vend; if (net2hl(cookie) != RFC1084) { #ifdef PRINTERR kprintf("Incorrect RFC 1084 magic cookie in BOOTP reply.\n"); #endif return SYSERR; } /* grab my IP addr */ mon_eth_pni->ni_ip = p->yiaddr; /* boot server IP */ mon_tftp_server = p->siaddr; /* boot file name */ strcpy(mon_boot_fname, p->file); #ifdef DEBUG kprintf("my IP addr is %x.\n", net2hl(mon_eth_pni->ni_ip)); kprintf("Boot file: %s, server: %x.\n", mon_boot_fname, net2hl(mon_tftp_server)); #endif return(OK); }
/*------------------------------------------------------------------------ * getutim -- obtain time in seconds past Jan 1, 1970, ut (gmt) *------------------------------------------------------------------------ */ SYSCALL getutim(unsigned long *timvar) { int dev; int len; int ret; u_long now; u_long utnow; char *msg = "No time server response\n"; wait(clmutex); ret = OK; if (clktime < SECPERHR) { /* assume small numbers invalid */ if ((dev=open(UDP, TSERVER, ANYLPORT)) == SYSERR || control(dev,DG_SETMODE,DG_TMODE|DG_DMODE) == SYSERR) { panic(msg); ret = SYSERR; } write(dev, msg, 2); /* send junk packet to prompt */ if (read(dev,&utnow,4) != 4) { ret = SYSERR; } else clktime = net2xt( net2hl(utnow) ); close(dev); } *timvar = clktime; signal(clmutex); return(ret); }
/*------------------------------------------------------------------------ * tcpsmss - set sender MSS from option in incoming segment *------------------------------------------------------------------------ */ int tcpsmss(struct tcb *ptcb, struct tcp *ptcp, u_char *popt) { unsigned mss, len; len = *++popt; ++popt; /* skip length field */ if ((ptcp->tcp_code & TCPF_SYN) == 0) return len; switch (len-2) { /* subtract kind & len */ case sizeof(char): mss = *popt; break; case sizeof(short): mss = net2hs(*(unsigned short *)popt); break; case sizeof(long): mss = net2hl(*(unsigned long *)popt); break; default: mss = ptcb->tcb_smss; break; } mss -= TCPMHLEN; /* save just the data buffer size */ if (ptcb->tcb_smss) ptcb->tcb_smss = min(mss, ptcb->tcb_smss); else ptcb->tcb_smss = mss; return len; }
/** * Return elapsed trip time in microseconds. */ static ulong echoTripTime(struct packet *pkt) { struct icmpPkt *icmp = NULL; struct icmpEcho *echo = NULL; ulong elapsed = 0, cycPerTick = 0; icmp = (struct icmpPkt *)pkt->curr; echo = (struct icmpEcho *)icmp->data; cycPerTick = platform.clkfreq / CLKTICKS_PER_SEC; elapsed = (echo->arrivcyc - net2hl(echo->timecyc)) % cycPerTick; elapsed += (echo->arrivtic - net2hl(echo->timetic)) * cycPerTick; elapsed += (echo->arrivsec - net2hl(echo->timesec)) * platform.clkfreq; elapsed = elapsed / (platform.clkfreq / 1000000); return elapsed; }
/*------------------------------------------------------------------------ * rwhoind - rwho daemon to record info from incoming rwho packets *------------------------------------------------------------------------ */ PROCESS rwhoind(void) { STATWORD ps; int dev; int len; int i; u_long now; struct rwhopac *rpacptr; struct rwent *rwptr; if ( (dev=open(UDP, ANYFPORT, (void *)UP_RWHO)) == SYSERR || control(dev, DG_SETMODE, DG_DMODE) == SYSERR) panic("rwho_in: cannot open rwho port"); while (TRUE) { if ( (len = read(dev,Rwho.rbuf,RWMAXP)) == SYSERR ) continue; rpacptr = (struct rwhopac *) Rwho.rbuf; rpacptr->rw_host[RMACLEN-1] = '\00'; for (i=0 ; i<Rwho.rwnent ; i++) { rwptr = &Rwho.rwcache[i]; if (strncmp(rpacptr->rw_host, rwptr->rwmach, RMACLEN) == 0) break; } if (i >= Rwho.rwnent) { disable(ps); if (Rwho.rwnent >= RWCSIZ) { restore(ps); continue; } rwptr = &Rwho.rwcache[Rwho.rwnent++]; strncpy(rwptr->rwmach, rpacptr->rw_host, RMACLEN); restore(ps); } rwptr->rwboot = net2hl(rpacptr->rw_btim); gettime(&now); rwptr->rwlast = now; rwptr->rwslast = net2hl(rpacptr->rw_sndtim); for (i=0 ; i<RWNLOAD ; i++) rwptr->rwload[i] = net2hl(rpacptr->rw_load[i]); rwptr->rwusers = (len-RWMINP)/sizeof(struct rw_who); } }
/** * 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; }
/*------------------------------------------------------------------------ * lsr_add - add a link state summary to a link state request packet *------------------------------------------------------------------------ */ struct ep * lsr_add(struct ospf_if *pif, struct ospf_lss *plss, struct ep *pep) { struct ip *pip; struct ospf *po; struct ospf_lsr *plsr; if (pep == 0) { pep = ospflsrtmpl(pif); if (pep == 0) return 0; } pip = (struct ip *)pep->ep_data; po = (struct ospf *)pip->ip_data; plsr = (struct ospf_lsr *)((char *)po + po->ospf_len); plsr->lsr_type = net2hl((unsigned long)plss->lss_type); plsr->lsr_lsid = plss->lss_lsid; plsr->lsr_rid = plss->lss_rid; po->ospf_len += LSRLEN; return pep; }
/** * The comments for dhcpRecvReply() apply, but for do_dhcpRecvReply() there is * no timeout and it is executed in a separate thread; furthermore, since this * thread can be killed at any time, it must use the memory passed in the @p pkt * parameter rather than allocating its own memory. */ static thread do_dhcpRecvReply(int descrp, struct dhcpData *data, struct packet *pkt) { const struct etherPkt *epkt; const struct ipv4Pkt *ipv4; const struct udpPkt *udp; const struct dhcpPkt *dhcp; const uchar *opts; uint maxlen; int found_msg; int retval; const uchar *gatewayptr; const uchar *maskptr; const uchar *opts_end; uint serverIpv4Addr; int mtu; int linkhdrlen; mtu = control(descrp, NET_GET_MTU, 0, 0); linkhdrlen = control(descrp, NET_GET_LINKHDRLEN, 0, 0); if (SYSERR == mtu || SYSERR == linkhdrlen) { return SYSERR; } maxlen = linkhdrlen + mtu; /* Receive packets until we find a response we're waiting for. */ next_packet: do { /* Receive next packet from the network device. */ int len = read(descrp, pkt->data, maxlen); if (len == SYSERR || len <= 0) { data->recvStatus = SYSERR; return SYSERR; } pkt->len = len; DHCP_TRACE("Received packet (len=%u).", pkt->len); /* Make sure packet is at least the minimum length of a DHCP packet. */ if (pkt->len < (ETH_HDR_LEN + IPv4_HDR_LEN + UDP_HDR_LEN + DHCP_HDR_LEN)) { DHCP_TRACE("Too short to be a DHCP packet."); goto next_packet; } /* Set up header pointers */ epkt = (const struct etherPkt *)pkt->data; ipv4 = (const struct ipv4Pkt *)epkt->data; udp = (const struct udpPkt *)ipv4->opts; dhcp = (const struct dhcpPkt *)udp->data; /* DHCP packets must be type IPv4, protocol UDP, UDP dest port DHCPC, * and UDP source port DHCPS. * * Also check the DHCP header: Is it actually a reply to this client? * */ if ((ETHER_TYPE_IPv4 != net2hs(epkt->type)) || (IPv4_PROTO_UDP != ipv4->proto) || (UDP_PORT_DHCPC != net2hs(udp->dstPort)) || (UDP_PORT_DHCPS != net2hs(udp->srcPort)) || (DHCP_OP_REPLY != dhcp->op) || (data->cxid != net2hl(dhcp->xid))) { DHCP_TRACE("Not a DHCP reply to this client."); goto next_packet; } DHCP_TRACE("Received DHCP reply."); #if DHCP_DROP_PACKET_PERCENT != 0 /* Stress testing. */ if (rand() % 100 < DHCP_DROP_PACKET_PERCENT) { DHCP_TRACE("WARNING: Ignoring valid DHCP packet for test purposes."); goto next_packet; } #endif /* We got a valid DHCP reply. Now parse the DHCP options. This needs * to be done carefully to avoid overrunning the packet buffer if the * options data is invalid. */ opts = dhcp->opts; maskptr = NULL; gatewayptr = NULL; serverIpv4Addr = 0; opts_end = opts + (pkt->len - (ETH_HDR_LEN + IPv4_HDR_LEN + UDP_HDR_LEN + DHCP_HDR_LEN)); found_msg = -1; for (;;) { uchar opt, len; /* Get the next option type. */ if (opts >= opts_end) { DHCP_TRACE("Invalid DHCP options."); goto next_packet; } opt = *opts++; /* Break on DHCP_OPT_END (marks end of DHCP options). */ if (DHCP_OPT_END == opt) { DHCP_TRACE("Reached DHCP_OPT_END."); break; } /* Get length of the data for this option. */ if (opts >= opts_end) { DHCP_TRACE("Invalid DHCP options."); goto next_packet; } len = *opts++; if (opts + len >= opts_end) { DHCP_TRACE("Invalid DHCP options."); goto next_packet; } /* Process the specific DHCP option. Ignore unrecognized options. * */ switch (opt) { case DHCP_OPT_MSGTYPE: DHCP_TRACE("DHCP_OPT_MSGTYPE: %d", *opts); if (len >= 1) { if ((DHCPC_STATE_SELECTING == data->state && *opts == DHCPOFFER) || (DHCPC_STATE_REQUESTING == data->state && (DHCPACK == *opts || DHCPNAK == *opts))) { found_msg = *opts; } } break; case DHCP_OPT_SUBNET: if (len >= IPv4_ADDR_LEN) { maskptr = opts; } break; case DHCP_OPT_GATEWAY: if (len >= IPv4_ADDR_LEN) { gatewayptr = opts; } break; case DHCP_OPT_SERVER: if (len >= IPv4_ADDR_LEN) { /* Server Identifier option. */ serverIpv4Addr = ((uint)opts[0] << 24) | ((uint)opts[1] << 16) | ((uint)opts[2] << 8) | ((uint)opts[3] << 0); } break; } /* Advance by the length of the option's data. */ opts += len; } } while (found_msg < 0); /* We received a reply of at least the right type as one we were looking * for. */ /* Don't consider a DHCPACK reply to be valid unless it provided a subnet * mask. */ if (DHCPACK == found_msg && NULL == maskptr) { DHCP_TRACE("Ignoring DHCPACK (no subnet mask provided)."); goto next_packet; } /* Note: The server's IP address is supposed to be specified in the Server * Identifier option, *not* in the siaddr (Server IP Address) field. This * is because, somewhat unintuitively, siaddr is used for the address of the * next server in the bootstrap process, which may not be the same as the * DHCP server. But if the Server Identifier option wasn't present, use * siaddr anyway. */ if (0 == serverIpv4Addr) { serverIpv4Addr = net2hl(dhcp->siaddr); if (0 == serverIpv4Addr) { DHCP_TRACE("Server IP address empty."); goto next_packet; } } if (DHCPOFFER == found_msg) { /* DHCPOFFER: Remember offer and server addresses. */ data->serverIpv4Addr = serverIpv4Addr; data->offeredIpv4Addr = net2hl(dhcp->yiaddr); memcpy(data->serverHwAddr, epkt->src, ETH_ADDR_LEN); retval = OK; } else { /* Received DHCPACK or DHCPNAK. Ensure it's from the same server to * which we sent the DHCPREQUEST; if not, ignore the packet. */ if (serverIpv4Addr != data->serverIpv4Addr) { DHCP_TRACE("Reply from wrong server."); goto next_packet; } if (DHCPNAK == found_msg) { /* DHCPNAK: Return error to make client try DHCPDISCOVER again */ retval = SYSERR; } else { /* DHCPACK: Set network interface addresses */ data->ip.type = NETADDR_IPv4; data->ip.len = IPv4_ADDR_LEN; /* yiaddr in a DHCPACK should be the same as the yiaddr stored from * the DHCPOFFER, but using the value in DHCPACK is preferable since * it's the value the server thinks it assigned. */ memcpy(data->ip.addr, &dhcp->yiaddr, IPv4_ADDR_LEN); data->clientIpv4Addr = net2hl(dhcp->yiaddr); data->mask.type = NETADDR_IPv4; data->mask.len = IPv4_ADDR_LEN; memcpy(data->mask.addr, maskptr, IPv4_ADDR_LEN); if (NULL != gatewayptr) { data->gateway.type = NETADDR_IPv4; data->gateway.len = IPv4_ADDR_LEN; memcpy(data->gateway.addr, gatewayptr, IPv4_ADDR_LEN); } /* If provided in the DHCPACK, set the address of next server and * the boot file (e.g. for TFTP). */ if (0 != dhcp->siaddr) { data->next_server.type = NETADDR_IPv4; data->next_server.len = IPv4_ADDR_LEN; memcpy(data->next_server.addr, &dhcp->siaddr, IPv4_ADDR_LEN); } if ('\0' != dhcp->file[0]) { memcpy(data->bootfile, dhcp->file, sizeof(data->bootfile) - 1); } #ifdef ENABLE_DHCP_TRACE { char str_addr[24]; netaddrsprintf(str_addr, &data->ip); DHCP_TRACE("Set ip=%s", str_addr); netaddrsprintf(str_addr, &data->mask); DHCP_TRACE("Set mask=%s", str_addr); if (NULL != gatewayptr) { netaddrsprintf(str_addr, &data->gateway); DHCP_TRACE("Set gateway=%s", str_addr); } else { DHCP_TRACE("No gateway."); } netaddrsprintf(str_addr, &data->next_server); DHCP_TRACE("TFTP server=%s", str_addr); DHCP_TRACE("Bootfile=%s", data->bootfile); } #endif retval = OK; } } data->recvStatus = retval; return retval; }
/** * @ingroup snoop * * Print contents of an TCP packet * @param tcp TCP packet * @return OK if print successful, SYSERR if error occurs */ int snoopPrintTcp(struct tcpPkt *tcp, char verbose) { char descrp[40]; char output[40]; /* Error check pointer */ if (NULL == tcp) { return SYSERR; } if (verbose >= SNOOP_VERBOSE_ONE) { printf(" ----- TCP Header -----\n", ""); /* Source Port */ if (verbose >= SNOOP_VERBOSE_TWO) { snoopPrintTcpPort(net2hs(tcp->srcpt), descrp); } else { sprintf(descrp, ""); } sprintf(output, "%d %s", net2hs(tcp->srcpt), descrp); printf(" Src Port: %-25s ", output); /* Destination Port */ if (verbose >= SNOOP_VERBOSE_TWO) { snoopPrintTcpPort(net2hs(tcp->dstpt), descrp); } else { sprintf(descrp, ""); } sprintf(output, "%d %s", net2hs(tcp->dstpt), descrp); printf("Dst Port: %-25s\n", output); /* Sequence number */ printf(" Seq Num: %-14u ", net2hl(tcp->seqnum)); /* Acknowledgement number */ printf("Ack Num: %-14u ", net2hl(tcp->acknum)); /* Control flags */ printf("Ctrl: "); if (tcp->control & TCP_CTRL_URG) { printf("U "); } if (tcp->control & TCP_CTRL_ACK) { printf("A "); } if (tcp->control & TCP_CTRL_PSH) { printf("P "); } if (tcp->control & TCP_CTRL_RST) { printf("R "); } if (tcp->control & TCP_CTRL_SYN) { printf("S "); } if (tcp->control & TCP_CTRL_FIN) { printf("F "); } printf("\n"); if (verbose >= SNOOP_VERBOSE_TWO) { sprintf(output, "%d bytes", offset2octets(tcp->offset)); printf(" Offset: %-15s ", output); sprintf(output, "%d bytes", net2hs(tcp->window)); printf("Window: %-15s ", output); printf("Chksum: 0x%04X\n", net2hs(tcp->chksum)); } } return OK; }
/* ******************************************************************** */ int sntp_process_result(int socket_no, PNTP_TIME_FORMAT current_timestamp, int version, dword ticks_when_sent, PEBSTIME res_ebs_tod) { int n_received; NTP_PKT ntp_response; NTP_TIME_FORMAT temp_time1; NTP_TIME_FORMAT temp_time2; NTP_TIME_FORMAT t1; NTP_TIME_FORMAT t2; NTP_TIME_FORMAT t3; NTP_TIME_FORMAT t4; NTP_TIME_FORMAT local_offset; NTP_TIME_FORMAT delay_time; /* round trip delay */ #if (DELAY_TICKS) dword delay_ticks; dword curr_ticks; #endif RTIP_BOOLEAN gmt_neg; #if (DELAY_TICKS) curr_ticks = ks_get_ticks(); if (CHECK_GREATER(curr_ticks, ticks_when_sent)) delay_ticks = curr_ticks - ticks_when_sent; else delay_ticks = (int)( (long)((long)curr_ticks - (long)ticks_when_sent) ); #if (DEBUG_DELAY_TICKS) DEBUG_ERROR("ks_get_ticks, ticks_when_sent: ", DINT2, curr_ticks, ticks_when_sent); #endif #endif /* Get a packet */ n_received = recv(socket_no, (PFCHAR)&ntp_response, sizeof(ntp_response), 0); if (n_received < 0) { DEBUG_ERROR("sntp_process_result: recv failed", EBS_INT1, xn_getlasterror(), 0); } closesocket(socket_no); /* verify response - mode */ if ( ((ntp_response.li_vn_mode & NTP_MODE_MASK) != NTP_SYM_PASSIVE) && ((ntp_response.li_vn_mode & NTP_MODE_MASK) != NTP_RESPONSE) ) { DEBUG_ERROR("sntp_process_result: response invalid: exp, act", EBS_INT2, NTP_SYM_PASSIVE, ntp_response.li_vn_mode & NTP_MODE_MASK); return(-1); } /* verify response - stratum */ if ( (ntp_response.stratum < 1) || (ntp_response.stratum > 14) ) { DEBUG_ERROR("sntp_process_result: stratum invalid: ", EBS_INT1, ntp_response.stratum, 0); return(-1); } /* verify response - version */ if ( (ntp_response.li_vn_mode & NTP_VERSION_MASK) != version ) { DEBUG_ERROR("sntp_process_result: response invalid - version : exp, act", EBS_INT2, version, ntp_response.li_vn_mode & NTP_VERSION_MASK); return(-1); } ntp_response.rcv_timestamp.seconds = net2hl(ntp_response.rcv_timestamp.seconds); ntp_response.ref_timestamp.seconds = net2hl(ntp_response.ref_timestamp.seconds); ntp_response.transmit_timestamp.seconds = net2hl(ntp_response.transmit_timestamp.seconds); /* seconds since Jan 1, 1970 */ /* DEBUG_ERROR("TIME SECONDS: seconds: ", DINT2, */ /* ntp_response.rcv_timestamp.seconds, */ /* ntp_response.rcv_timestamp.frac_sec); */ #if (DISPLAY_RCV_TIME) DEBUG_ERROR("\n***** RCV TIME *****", NOVAR, 0, 0); display_sntp_time(ntp_response.rcv_timestamp.seconds); #endif #if (DISPLAY_INT_TIMES) /* DEBUG_ERROR("***** REF TIME *****", NOVAR, 0, 0); */ /* display_sntp_time(ntp_response.ref_timestamp.seconds); */ /* DEBUG_ERROR("***** TRANSMIT TIME *****", NOVAR, 0, 0); */ /* display_sntp_time(ntp_response.transmit_timestamp.seconds); */ #endif #if (DELAY_TICKS) t4.seconds = delay_ticks / ks_ticks_p_sec(); t4.frac_sec = 0; /* tbd */ DEBUG_ERROR("delay_ticks, t4.sec", DINT2, delay_ticks, t4.seconds); #endif /* set the following */ /* t2 = time request received by server */ /* t3 = time reply sent by server */ /* t4 = time reply received by client */ STRUCT_COPY(t1, *current_timestamp); STRUCT_COPY(t2, ntp_response.rcv_timestamp); STRUCT_COPY(t3, ntp_response.transmit_timestamp); #if (!DELAY_TICKS) STRUCT_COPY(t4, *current_timestamp); #endif /* set time response took to arrive from time sent */ /* delay_time = (t4-t1) - (t2-t3) */ time_sub(&temp_time1, &t4, &t1); time_sub(&temp_time2, &t2, &t3); time_sub(&delay_time, &temp_time1, &temp_time2); /* calculate local time offset */ /* local clock offset */ time_sub(&temp_time1, &t2, &t1); time_sub(&temp_time2, &t3, &t4); time_add(&local_offset, &temp_time1, &temp_time2); time_div_2(&local_offset); #if (DISPLAY_DELAY_OFFSET) display_total_time("\nDELAY TIME: ", delay_time.seconds); display_total_time("OFFSET TIME: ", local_offset.seconds); #endif gmt_neg = FALSE; #if (!ADD_OFFSET) if (CFG_GMT_DIFF < 0) { gmt_neg = TRUE; /* convert hours to seconds, hence multiply by 3600; */ /* make it positive and it will be subtracted below */ local_offset.seconds = -(CFG_GMT_DIFF * SEC_PER_HOUR); } else { /* CFG_GMT_DIFF is positive so seconds is always positive */ local_offset.seconds = (dword)(CFG_GMT_DIFF * SEC_PER_HOUR); } #endif local_offset.frac_sec = 0; /* update time with delay */ time_add(&temp_time1, &t3, &delay_time); /* save current time for next request */ STRUCT_COPY(*current_timestamp, temp_time1); /* update time with time zone */ if (gmt_neg) time_sub(&temp_time2, &temp_time1, &local_offset); else time_add(&temp_time2, &temp_time1, &local_offset); /* display_total_time("BEFORE CONVERSION TO ebs_tod ", temp_time2.seconds); */ /* display_total_time("FINAL TIME ", temp_time2.seconds); */ /* convert time returned by SNTP server to RTIP internal format */ convert_time_to_ebs_time(temp_time2.seconds, res_ebs_tod); return(0); }