/* * Send a packet and wait for a reply, with exponential backoff. * * The send routine must return the actual number of bytes written, * or -1 on error. * * The receive routine can indicate success by returning the number of * bytes read; it can return 0 to indicate EOF; it can return -1 with a * non-zero errno to indicate failure; finally, it can return -1 with a * zero errno to indicate it isn't done yet. */ ssize_t sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t), void *sbuf, size_t ssize, ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t), void *rbuf, size_t rsize) { ssize_t cc; time_t t, tmo, tlast; long tleft; #ifdef NET_DEBUG if (debug) printf("sendrecv: called\n"); #endif tmo = MINTMO; tlast = 0; tleft = 0; t = getsecs(); for (;;) { if (tleft <= 0) { if (tmo >= MAXTMO) { errno = ETIMEDOUT; return -1; } cc = (*sproc)(d, sbuf, ssize); if (cc != -1 && cc < ssize) panic("sendrecv: short write! (%zd < %zd)", cc, ssize); tleft = tmo; tmo += MINTMO; if (tmo > MAXTMO) tmo = MAXTMO; if (cc == -1) { /* Error on transmit; wait before retrying */ while ((getsecs() - t) < tmo) ; tleft = 0; continue; } tlast = t; } /* Try to get a packet and process it. */ cc = (*rproc)(d, rbuf, rsize, tleft); /* Return on data, EOF or real error. */ if (cc != -1 || errno != 0) return (cc); /* Timed out or didn't get the packet we're waiting for */ t = getsecs(); tleft -= t - tlast; tlast = t; } }
u_int sleep(u_int i) { register time_t t; /* loop for that number of seconds, polling BIOS, so that it may handle interrupts */ for (t = getsecs() + i; getsecs() < t; cnischar()); return 0; }
int le_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout) { satime_t t; int cc; t = getsecs(); do { cc = le_poll(desc, pkt, len); } while (cc == 0 && (getsecs() - t) < timeout); return cc; }
int le_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout) { satime_t t; int cc; t = getsecs(); cc = 0; while (((getsecs() - t) < timeout) && !cc) { cc = le_poll(desc, pkt, len); } return cc; }
static int ofwn_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) { time_t t; int length; #if defined(NETIF_DEBUG) printf("netif_get: pkt=%p, maxlen=%d, timeout=%d\n", pkt, len, timeout); #endif t = getsecs(); do { length = OF_read(netinstance, pkt, len); } while ((length == -2 || length == 0) && (getsecs() - t < timeout)); #if defined(NETIF_DEBUG) printf("netif_get: received length=%d (%x)\n", length, length); #endif if (length < 12) return -1; #if defined(NETIF_VERBOSE_DEBUG) { char *ch = pkt; int i; for(i = 0; i < 96; i += 4) { printf("%02x%02x%02x%02x ", ch[i], ch[i+1], ch[i+2], ch[i+3]); } printf("\n"); } #endif #if defined(NETIF_DEBUG) { struct ether_header *eh = pkt; printf("dst: %s ", ether_sprintf(eh->ether_dhost)); printf("src: %s ", ether_sprintf(eh->ether_shost)); printf("type: 0x%x\n", eh->ether_type & 0xffff); } #endif return length; }
int cfenet_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout) { satime_t t; int cc; t = getsecs(); cc = 0; while (((getsecs() - t) < timeout) && !cc) { cc = cfe_read(booted_dev_fd,pkt,len); if (cc < 0) break; break; } return cc; }
void mii_dealan(struct local *l, unsigned timo) { unsigned val, bound; val = (1U << 13) | (1U << 7) | 0x1f /* advertise all caps */; CSR_WRITE_4(l, P1CR4, val); bound = getsecs() + timo; do { val = CSR_READ_4(l, P1SR); if (val & (1U << 5)) /* link is found up */ break; DELAY(10 * 1000); } while (getsecs() < bound); return; }
time_t time(time_t *tloc) { int secs = getsecs(); if (tloc) *tloc = secs; return secs; }
static int Xtime(void) { time_t tt = getsecs(); if (cmd.argc == 1) printf(ctime(&tt)); return 0; }
/* * Given a pointer into a time zone string, extract a rule in the form * date[/time]. See POSIX section 8 for the format of "date" and "time". * If a valid rule is not found, return NULL. * Otherwise, return a pointer to the first character not part of the rule. */ static const char * getrule(const char *strp, struct rule * rulep) { if (*strp == 'J') { /* * Julian day. */ rulep->r_type = JULIAN_DAY; ++strp; strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); } else if (*strp == 'M') { /* * Month, week, day. */ rulep->r_type = MONTH_NTH_DAY_OF_WEEK; ++strp; strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_week, 1, 5); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); } else if (is_digit(*strp)) { /* * Day of year. */ rulep->r_type = DAY_OF_YEAR; strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); } else return NULL; /* invalid format */ if (strp == NULL) return NULL; if (*strp == '/') { /* * Time specified. */ ++strp; strp = getsecs(strp, &rulep->r_time); } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ return strp; }
time_t time(time_t *tloc) { time_t rv; rv = getsecs(); if (tloc != NULL) *tloc = rv; return (rv); }
/* * Receive a packet, including the ether header. * Return the total length received (or -1 on error). */ ssize_t netif_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timo) { struct romdev *pd; int tick0; ssize_t len; pd = (struct romdev *)desc->io_netif; #ifdef NETIF_DEBUG if (netif_debug) printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", pkt, maxlen, timo); #endif tick0 = getsecs(); do { len = apcall_read(pd->fd, pkt, maxlen); } while ((len == 0) && ((getsecs() - tick0) < timo)); #ifdef NETIF_DEBUG if (netif_debug) printf("netif_get: received len=%d\n", len); #endif if (len < 12) return -1; #ifdef NETIF_DEBUG if (netif_debug) { struct ether_header *eh = pkt; printf("dst: %s ", ether_sprintf(eh->ether_dhost)); printf("src: %s ", ether_sprintf(eh->ether_shost)); printf("type: 0x%x\n", eh->ether_type & 0xFFFF); } #endif return len; }
void mii_dealan(struct local *l, unsigned timo) { unsigned anar, bound; anar = ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA; mii_write(l, l->phy, MII_ANAR, anar); mii_write(l, l->phy, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); l->anlpar = 0; bound = getsecs() + timo; do { l->bmsr = mii_read(l, l->phy, MII_BMSR) | mii_read(l, l->phy, MII_BMSR); /* read twice */ if ((l->bmsr & BMSR_LINK) && (l->bmsr & BMSR_ACOMP)) { l->anlpar = mii_read(l, l->phy, MII_ANLPAR); break; } DELAY(10 * 1000); } while (getsecs() < bound); return; }
/* Fetch required bootp information */ void bootp(int sock) { struct iodesc *d; struct bootp *bp; struct { u_char header[HEADER_SIZE]; struct bootp wbootp; } wbuf; struct { u_char header[HEADER_SIZE]; struct bootp rbootp; } rbuf; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%x\n", (u_int)d); #endif bp = &wbuf.wbootp; bzero(bp, sizeof(*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = HTYPE_ETHERNET; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); bzero(bp->bp_file, sizeof(bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); d->myip = myip; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); (void)sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)); /* Bump xid so next request will be unique. */ ++d->xid; }
static int net_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) { struct netif *nif = desc->io_netif; struct uboot_softc *sc = nif->nif_devdata; time_t t; int err, rlen; #if defined(NETIF_DEBUG) printf("net_get: pkt %p, len %d, timeout %d\n", pkt, len, timeout); #endif t = getsecs(); do { err = ub_dev_recv(sc->sc_handle, sc->sc_rxbuf, len, &rlen); if (err != 0) { printf("net_get: ub_dev_recv() failed, error=%d\n", err); rlen = 0; break; } } while ((rlen == -1 || rlen == 0) && (getsecs() - t < timeout)); #if defined(NETIF_DEBUG) printf("net_get: received len %d (%x)\n", rlen, rlen); #endif if (rlen > 0) { memcpy(pkt, sc->sc_rxbuf, MIN(len, rlen)); if (rlen != len) { #if defined(NETIF_DEBUG) printf("net_get: len %x, rlen %x\n", len, rlen); #endif } return (rlen); } return (-1); }
static int cs_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) { time_t t; int rlen; int i; u_int16_t *p; t = getsecs(); rlen = 0; while (getsecs() - t < timeout && rlen == 0) { if (!(CS_READ_PACKET_PAGE(PKTPG_RX_EVENT) & RX_EVENT_RX_OK)) continue; /* drop status */ CS_READ_2(PORT_RXTX_DATA); /* get frame length */ rlen = CS_READ_2(PORT_RXTX_DATA); if (rlen > len) { CS_WRITE_PACKET_PAGE(PKTPG_RX_CFG, RX_CFG_SKIP); rlen = 0; continue; } p = pkt; for (i = rlen >> 1; i > 0; i--) *p++ = CS_READ_2(PORT_RXTX_DATA); if (rlen & 1) *((u_int8_t *) p + 1) = CS_READ_1(PORT_RXTX_DATA); /* exit while loop */ } return rlen; }
static ssize_t efinet_get(struct iodesc *desc, void **pkt, time_t timeout) { struct netif *nif = desc->io_netif; EFI_SIMPLE_NETWORK *net; EFI_STATUS status; UINTN bufsz; time_t t; char *buf, *ptr; ssize_t ret = -1; net = nif->nif_devdata; if (net == NULL) return (ret); bufsz = net->Mode->MaxPacketSize + ETHER_HDR_LEN + ETHER_CRC_LEN; buf = malloc(bufsz + ETHER_ALIGN); if (buf == NULL) return (ret); ptr = buf + ETHER_ALIGN; t = getsecs(); while ((getsecs() - t) < timeout) { status = net->Receive(net, NULL, &bufsz, ptr, NULL, NULL, NULL); if (status == EFI_SUCCESS) { *pkt = buf; ret = (ssize_t)bufsz; break; } if (status != EFI_NOT_READY) break; } if (ret == -1) free(buf); return (ret); }
static const char *getoffset(register const char *strp, long *const offsetp) { register int neg = 0; if (*strp == '-') { neg = 1; ++strp; } else if (*strp == '+') ++strp; strp = getsecs(strp, offsetp); if (strp == NULL) return NULL; /* illegal time */ if (neg) *offsetp = -*offsetp; return strp; }
/* send request, expect first block (or error) */ int tftp_makereq(struct tftp_handle *h) { struct { u_char header[HEADER_SIZE]; struct tftphdr t; u_char space[FNAME_SIZE + 6]; } wbuf; char *wtail; int l; ssize_t res; struct tftphdr *t; bzero(&wbuf, sizeof(wbuf)); wbuf.t.th_opcode = htons((u_short) RRQ); wtail = wbuf.t.th_stuff; l = strlen(h->path); bcopy(h->path, wtail, l + 1); wtail += l + 1; bcopy("octet", wtail, 6); wtail += 6; t = &h->lastdata.t; /* h->iodesc->myport = htons(--tftpport); */ h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff)); h->iodesc->destport = htons(IPPORT_TFTP); h->iodesc->xid = 1; /* expected block */ res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t, recvtftp, t, sizeof(*t) + RSPACE); if (res == -1) return errno; h->currblock = 1; h->validsize = res; h->islastblock = 0; if (res < SEGSIZE) h->islastblock = 1; /* very short file */ return 0; }
/* Transmit a bootp request */ static ssize_t bootpsend(struct iodesc *d, void *pkt, size_t len) { struct bootp *bp; #ifdef BOOTP_DEBUG if (debug) printf("bootpsend: d=%lx called.\n", (long)d); #endif bp = pkt; bp->bp_secs = htons((u_short)(getsecs() - bot)); #ifdef BOOTP_DEBUG if (debug) printf("bootpsend: calling sendudp\n"); #endif return (sendudp(d, pkt, len)); }
int tgets(char *buf) { int c, i; char *p, *lp = buf; time_t seconds1, seconds2; seconds1 = getsecs(); for (i = 10; i > 0; ) { c = tgetchar() & 0177; if (c) { for (;;) { switch (c) { case '\n': case '\r': *lp = '\0'; putchar('\n'); return (1); case '\b': case '\177': if (lp > buf) { lp--; putchar('\b'); putchar(' '); putchar('\b'); } break; case '#': if (lp > buf) --lp; break; case 'r'&037: putchar('\n'); for (p = buf; p < lp; ++p) putchar(*p); break; case '@': case 'u'&037: case 'w'&037: lp = buf; putchar('\n'); break; default: *lp++ = c; putchar(c); } c = getchar() & 0177; } } if ((seconds2 = getsecs()) != seconds1) { seconds1 = seconds2; i--; } } return (0); }
/* send request, expect first block (or error) */ static int tftp_makereq(struct tftp_handle *h) { struct { u_char header[HEADER_SIZE]; struct tftphdr t; u_char space[FNAME_SIZE + 6]; } __packed __aligned(4) wbuf; char *wtail; int l; ssize_t res; struct tftphdr *t; char *tftp_blksize = NULL; int blksize_l; unsigned short rtype = 0; /* * Allow overriding default TFTP block size by setting * a tftp.blksize environment variable. */ if ((tftp_blksize = getenv("tftp.blksize")) != NULL) { tftp_set_blksize(h, tftp_blksize); } wbuf.t.th_opcode = htons((u_short) RRQ); wtail = wbuf.t.th_stuff; l = strlen(h->path); #ifdef TFTP_PREPEND_PATH if (l > FNAME_SIZE - (sizeof(TFTP_PREPEND_PATH) - 1)) return (ENAMETOOLONG); bcopy(TFTP_PREPEND_PATH, wtail, sizeof(TFTP_PREPEND_PATH) - 1); wtail += sizeof(TFTP_PREPEND_PATH) - 1; #else if (l > FNAME_SIZE) return (ENAMETOOLONG); #endif bcopy(h->path, wtail, l + 1); wtail += l + 1; bcopy("octet", wtail, 6); wtail += 6; bcopy("blksize", wtail, 8); wtail += 8; blksize_l = sprintf(wtail, "%d", h->tftp_blksize); wtail += blksize_l + 1; bcopy("tsize", wtail, 6); wtail += 6; bcopy("0", wtail, 2); wtail += 2; t = &h->lastdata.t; /* h->iodesc->myport = htons(--tftpport); */ h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff)); h->iodesc->destport = htons(IPPORT_TFTP); h->iodesc->xid = 1; /* expected block */ h->currblock = 0; h->islastblock = 0; h->validsize = 0; res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t, &recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype); if (rtype == OACK) return (tftp_getnextblock(h)); /* Server ignored our blksize request, revert to TFTP default. */ h->tftp_blksize = SEGSIZE; switch (rtype) { case DATA: { h->currblock = 1; h->validsize = res; h->islastblock = 0; if (res < h->tftp_blksize) { h->islastblock = 1; /* very short file */ tftp_sendack(h); } return (0); } case ERROR: default: return (errno); } }
/* Fetch required bootp infomation */ void bootp(int sock, int flag) { struct iodesc *d; struct bootp *bp; struct { u_char header[HEADER_SIZE]; struct bootp wbootp; } wbuf; struct { u_char header[HEADER_SIZE]; struct bootp rbootp; } rbuf; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif bp = &wbuf.wbootp; bzero(bp, sizeof(*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); strncpy(bp->bp_file, bootfile, sizeof(bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); #ifdef SUPPORT_DHCP bp->bp_vend[4] = TAG_DHCP_MSGTYPE; bp->bp_vend[5] = 1; bp->bp_vend[6] = DHCPDISCOVER; /* * If we are booting from PXE, we want to send the string * 'PXEClient' to the DHCP server so you have the option of * only responding to PXE aware dhcp requests. */ if (flag & BOOTP_PXE) { bp->bp_vend[7] = TAG_CLASSID; bp->bp_vend[8] = 9; bcopy("PXEClient", &bp->bp_vend[9], 9); bp->bp_vend[18] = TAG_PARAM_REQ; bp->bp_vend[19] = 7; bp->bp_vend[20] = TAG_ROOTPATH; bp->bp_vend[21] = TAG_HOSTNAME; bp->bp_vend[22] = TAG_SWAPSERVER; bp->bp_vend[23] = TAG_GATEWAY; bp->bp_vend[24] = TAG_SUBNET_MASK; bp->bp_vend[25] = TAG_INTF_MTU; bp->bp_vend[26] = TAG_SERVERID; bp->bp_vend[27] = TAG_END; } else bp->bp_vend[7] = TAG_END; #else bp->bp_vend[4] = TAG_END; #endif d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); #ifdef SUPPORT_DHCP expected_dhcpmsgtype = DHCPOFFER; dhcp_ok = 0; #endif if(sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("bootp: no reply\n"); return; } #ifdef SUPPORT_DHCP if(dhcp_ok) { u_int32_t leasetime; bp->bp_vend[6] = DHCPREQUEST; bp->bp_vend[7] = TAG_REQ_ADDR; bp->bp_vend[8] = 4; bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4); bp->bp_vend[13] = TAG_SERVERID; bp->bp_vend[14] = 4; bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4); bp->bp_vend[19] = TAG_LEASETIME; bp->bp_vend[20] = 4; leasetime = htonl(300); bcopy(&leasetime, &bp->bp_vend[21], 4); if (flag & BOOTP_PXE) { bp->bp_vend[25] = TAG_CLASSID; bp->bp_vend[26] = 9; bcopy("PXEClient", &bp->bp_vend[27], 9); bp->bp_vend[36] = TAG_END; } else bp->bp_vend[25] = TAG_END; expected_dhcpmsgtype = DHCPACK; if(sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("DHCPREQUEST failed\n"); return; } } #endif myip = d->myip = rbuf.rbootp.bp_yiaddr; servip = rbuf.rbootp.bp_siaddr; if(rootip.s_addr == INADDR_ANY) rootip = servip; bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile)); bootfile[sizeof(bootfile) - 1] = '\0'; if (!netmask) { if (IN_CLASSA(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSA_NET); else if (IN_CLASSB(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSB_NET); else netmask = htonl(IN_CLASSC_NET); #ifdef BOOTP_DEBUG if (debug) printf("'native netmask' is %s\n", intoa(netmask)); #endif } #ifdef BOOTP_DEBUG if (debug) printf("mask: %s\n", intoa(netmask)); #endif /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("need gateway for root ip\n"); #endif } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); #endif gateip.s_addr = 0; } /* Bump xid so next request will be unique. */ ++d->xid; }
/* Fetch required bootp infomation */ void bootp(int sock) { void *pkt; struct iodesc *d; struct bootp *bp; struct { uchar_t header[HEADER_SIZE]; struct bootp wbootp; } wbuf; struct bootp *rbootp; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif bp = &wbuf.wbootp; bzero(bp, sizeof (*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); strncpy(bp->bp_file, bootfile, sizeof (bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof (vm_rfc1048)); #ifdef SUPPORT_DHCP bp->bp_vend[4] = TAG_DHCP_MSGTYPE; bp->bp_vend[5] = 1; bp->bp_vend[6] = DHCPDISCOVER; bootp_fill_request(&bp->bp_vend[7]); #else bp->bp_vend[4] = TAG_END; #endif d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); #ifdef SUPPORT_DHCP expected_dhcpmsgtype = DHCPOFFER; dhcp_ok = 0; #endif if (sendrecv(d, bootpsend, bp, sizeof (*bp), bootprecv, &pkt, (void **)&rbootp, NULL) == -1) { printf("bootp: no reply\n"); return; } #ifdef SUPPORT_DHCP if (dhcp_ok) { uint32_t leasetime; bp->bp_vend[6] = DHCPREQUEST; bp->bp_vend[7] = TAG_REQ_ADDR; bp->bp_vend[8] = 4; bcopy(&rbootp->bp_yiaddr, &bp->bp_vend[9], 4); bp->bp_vend[13] = TAG_SERVERID; bp->bp_vend[14] = 4; bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4); bp->bp_vend[19] = TAG_LEASETIME; bp->bp_vend[20] = 4; leasetime = htonl(300); bcopy(&leasetime, &bp->bp_vend[21], 4); bootp_fill_request(&bp->bp_vend[25]); expected_dhcpmsgtype = DHCPACK; free(pkt); if (sendrecv(d, bootpsend, bp, sizeof (*bp), bootprecv, &pkt, (void **)&rbootp, NULL) == -1) { printf("DHCPREQUEST failed\n"); return; } } #endif myip = d->myip = rbootp->bp_yiaddr; servip = rbootp->bp_siaddr; if (rootip.s_addr == INADDR_ANY) rootip = servip; bcopy(rbootp->bp_file, bootfile, sizeof (bootfile)); bootfile[sizeof (bootfile) - 1] = '\0'; if (!netmask) { if (IN_CLASSA(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSA_NET); else if (IN_CLASSB(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSB_NET); else netmask = htonl(IN_CLASSC_NET); #ifdef BOOTP_DEBUG if (debug) printf("'native netmask' is %s\n", intoa(netmask)); #endif } #ifdef BOOTP_DEBUG if (debug) printf("mask: %s\n", intoa(netmask)); #endif /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("need gateway for root ip\n"); #endif } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); #endif gateip.s_addr = 0; } /* Bump xid so next request will be unique. */ ++d->xid; free(pkt); }
/* Fetch required bootp information */ void bootp(int sock) { struct iodesc *d; struct bootp *bp; struct { u_char header[UDP_TOTAL_HEADER_SIZE]; struct bootp wbootp; } wbuf; struct { u_char header[UDP_TOTAL_HEADER_SIZE]; struct bootp rbootp; } rbuf; unsigned int index; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif bp = &wbuf.wbootp; (void)memset(bp, 0, sizeof(*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); (void)strncpy((char *)bp->bp_file, bootfile, sizeof(bp->bp_file)); (void)memcpy(bp->bp_vend, vm_rfc1048, sizeof(vm_rfc1048)); index = 4; #ifdef SUPPORT_DHCP bp->bp_vend[index++] = TAG_DHCP_MSGTYPE; bp->bp_vend[index++] = 1; bp->bp_vend[index++] = DHCPDISCOVER; #endif bootp_addvend(&bp->bp_vend[index]); d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); #ifdef SUPPORT_DHCP expected_dhcpmsgtype = DHCPOFFER; dhcp_ok = 0; #endif if (sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("bootp: no reply\n"); return; } #ifdef SUPPORT_DHCP if (dhcp_ok) { u_int32_t leasetime; index = 6; bp->bp_vend[index++] = DHCPREQUEST; bp->bp_vend[index++] = TAG_REQ_ADDR; bp->bp_vend[index++] = 4; (void)memcpy(&bp->bp_vend[9], &rbuf.rbootp.bp_yiaddr, 4); index += 4; bp->bp_vend[index++] = TAG_SERVERID; bp->bp_vend[index++] = 4; (void)memcpy(&bp->bp_vend[index], &dhcp_serverip.s_addr, 4); index += 4; bp->bp_vend[index++] = TAG_LEASETIME; bp->bp_vend[index++] = 4; leasetime = htonl(300); (void)memcpy(&bp->bp_vend[index], &leasetime, 4); index += 4; bootp_addvend(&bp->bp_vend[index]); expected_dhcpmsgtype = DHCPACK; if (sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) == -1) { printf("DHCPREQUEST failed\n"); return; } } #endif myip = d->myip = rbuf.rbootp.bp_yiaddr; servip = rbuf.rbootp.bp_siaddr; if (rootip.s_addr == INADDR_ANY) rootip = servip; (void)memcpy(bootfile, rbuf.rbootp.bp_file, sizeof(bootfile)); bootfile[sizeof(bootfile) - 1] = '\0'; if (IN_CLASSA(myip.s_addr)) nmask = IN_CLASSA_NET; else if (IN_CLASSB(myip.s_addr)) nmask = IN_CLASSB_NET; else nmask = IN_CLASSC_NET; #ifdef BOOTP_DEBUG if (debug) printf("'native netmask' is %s\n", intoa(nmask)); #endif /* Get subnet (or natural net) mask */ netmask = nmask; if (smask) netmask = smask; #ifdef BOOTP_DEBUG if (debug) printf("mask: %s\n", intoa(netmask)); #endif /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("need gateway for root ip\n"); #endif } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); #endif gateip.s_addr = 0; } #ifdef BOOTP_DEBUG if (debug) { printf("client addr: %s\n", inet_ntoa(myip)); if (smask) printf("subnet mask: %s\n", intoa(smask)); if (gateip.s_addr != 0) printf("net gateway: %s\n", inet_ntoa(gateip)); printf("server addr: %s\n", inet_ntoa(rootip)); if (rootpath[0] != '\0') printf("server path: %s\n", rootpath); if (bootfile[0] != '\0') printf("file name: %s\n", bootfile); } #endif /* Bump xid so next request will be unique. */ ++d->xid; }
static int readline(char *buf, size_t n, int to) { #ifdef DEBUG extern int debug; #endif char *p = buf, ch; /* Only do timeout if greater than 0 */ if (to > 0) { u_long i = 0; time_t tt = getsecs() + to; #ifdef DEBUG if (debug > 2) printf ("readline: timeout(%d) at %u\n", to, tt); #endif /* check for timeout expiration less often (for some very constrained archs) */ while (!cnischar()) if (!(i++ % 1000) && (getsecs() >= tt)) break; if (!cnischar()) { strlcpy(buf, "boot", 5); putchar('\n'); return strlen(buf); } } else while (!cnischar()) ; /* User has typed something. Turn off timeouts. */ cmd.timeout = 0; while (1) { switch ((ch = getchar())) { case CTRL('u'): while (p > buf) { putchar('\177'); p--; } continue; case '\n': case '\r': p[1] = *p = '\0'; break; case '\b': case '\177': if (p > buf) { putchar('\177'); p--; } continue; default: if (p - buf < n-1) *p++ = ch; else { putchar('\007'); putchar('\177'); } continue; } break; } return p - buf; }