/*------------------------------------------------------------------------ * lsr_xmit - transmit pending Link State Request packets *------------------------------------------------------------------------ */ int lsr_xmit(struct ospf_if *pif, struct ospf_nb *pnb) { struct ep *pephead, *pep; struct ip *pip; struct ospf *po; int len; pephead = (struct ep *)headq(pnb->nb_lsrl); if (pephead == 0) return OK; pep = (struct ep *)getbuf(Net.netpool); if ((int)pep == SYSERR) return SYSERR; /* make a copy */ pip = (struct ip *)pephead->ep_data; po = (struct ospf *)pip->ip_data; len = EP_HLEN + IPMHLEN + po->ospf_len; memcpy(pep, pephead, len); pip = (struct ip *)pep->ep_data; po = (struct ospf *)pip->ip_data; po->ospf_authtype = hs2net(pif->if_area->ar_authtype); memset(po->ospf_auth, 0, AUTHLEN); len = po->ospf_len; po->ospf_len = hs2net(po->ospf_len); pep->ep_order &= ~EPO_OSPF; po->ospf_cksum = 0; po->ospf_cksum = cksum((WORD *)po, len); memcpy(po->ospf_auth, pif->if_area->ar_auth, AUTHLEN); pip->ip_src = ip_anyaddr; ipsend(pnb->nb_ipa, pep, len, IPT_OSPF, IPP_INCTL, IP_TTL); pnb->nb_tlsr = pif->if_rintv; return OK; }
/*------------------------------------------------------------------------ * mkarp - allocate and fill in an ARP or RARP packet *------------------------------------------------------------------------ */ static struct ep * mkarp(int ifn, short type, short op, IPaddr spa, IPaddr tpa) { register struct arp *parp; struct ep *pep; pep = (struct ep *) getbuf(Net.netpool); if ((int)pep == SYSERR) return (struct ep *)SYSERR; memcpy(pep->ep_dst, nif[ifn].ni_hwb.ha_addr, EP_ALEN); pep->ep_order = ~0; pep->ep_type = type; parp = (struct arp *)pep->ep_data; parp->ar_hwtype = hs2net(AR_HARDWARE); parp->ar_prtype = hs2net(EPT_IP); parp->ar_hwlen = EP_ALEN; parp->ar_prlen = IP_ALEN; parp->ar_op = hs2net(op); memcpy(SHA(parp), nif[ifn].ni_hwa.ha_addr, EP_ALEN); memcpy(SPA(parp), &spa, IP_ALEN); memcpy(THA(parp), nif[ifn].ni_hwa.ha_addr, EP_ALEN); memcpy(TPA(parp), &tpa, IP_ALEN); return pep; }
/*------------------------------------------------------------------------ * iph2net - convert an IP packet header from host to net byte order *------------------------------------------------------------------------ */ struct ip * iph2net(struct ip *pip) { /* NOTE: does not include IP options */ pip->ip_len = hs2net(pip->ip_len); pip->ip_id = hs2net(pip->ip_id); pip->ip_fragoff = hs2net(pip->ip_fragoff); return pip; }
/*------------------------------------------------------------------------- * mon_bootp_request - *------------------------------------------------------------------------- */ int mon_bootp_request(int secs) { struct bootp_msg bppacket; struct ep *pep; struct ip *pip; struct udp *pup; pep = (struct ep *)getbuf(mon_bufpool); if (pep == 0) { #ifdef PRINTERR kprintf("bootp_request: !! no buffer\n"); #endif return SYSERR; } pip = (struct ip *)pep->ep_data; pup = (struct udp *)pip->ip_data; make_bootp_packet(&bppacket, secs); /* set the BOOTP data */ blkcopy(pup->u_data, &bppacket, BOOTP_SIZE); /* now set the UDP header info */ pup->u_src = hs2net(BOOTP_CPORT); pup->u_dst = hs2net(BOOTP_SPORT); pup->u_len = hs2net(U_HLEN + BOOTP_SIZE); pup->u_cksum = 0; /* now set the IP header info */ pip->ip_proto = IPT_UDP; pip->ip_verlen = (IP_VERSION<<4) | IP_MINHLEN; pip->ip_tos = 0; pip->ip_len = hs2net(IPMHLEN + U_HLEN + BOOTP_SIZE); pip->ip_id = 0; pip->ip_fragoff = 0; pip->ip_ttl = IP_TTL; pip->ip_src = 0; pip->ip_dst = mon_ip_maskall; pip->ip_cksum = 0; pip->ip_cksum = mon_cksum(pip, IPMHLEN); /* now set the ethernet info */ blkcopy(pep->ep_eh.eh_dst, EP_BRC, EP_ALEN); pep->ep_eh.eh_type = EPT_IP; return((mon_nif[0].ni_write)(pep, EP_HLEN+U_HLEN+IPMHLEN+BOOTP_SIZE)); }
/*------------------------------------------------------------------------ * ue_write - write a single packet to an SMC Ultra Ethernet *------------------------------------------------------------------------ */ int ue_write(struct devsw *pdev, unsigned char *pep0, unsigned len) { struct ep *pep = (struct ep *)pep0; struct utdev *pud; pud = (struct utdev *)pdev->dvioblk; if (len > EP_MAXLEN) { nif[pud->ud_ifnum].ni_odiscard++; freebuf(pep); return SYSERR; } /* subtract the local header */ len -= (int)&pep->ep_eh - (int)pep; if (len < EP_MINLEN) len = EP_MINLEN; memcpy(pep->ep_src, pud->ud_paddr, EP_ALEN); pep->ep_len = len; pep->ep_type = hs2net(pep->ep_type); pep->ep_order &= ~EPO_NET; if (enq(pud->ud_outq, pep, 0) < 0) { nif[pud->ud_ifnum].ni_odiscard++; freebuf(pep); ue_wstrt(pud); return SYSERR; } ue_wstrt(pud); return OK; }
/** * Send a UDP packet across the network to a certain destination * @param udpptr Pointer to UDP control block * @param datalen Length of data to be sent * @param buf Data to be sent * @return OK if packet is sent properly, otherwise SYSERR */ syscall udpSend(struct udp *udpptr, ushort datalen, void *buf) { struct packet *pkt; struct udpPkt *udppkt = NULL; int result; pkt = netGetbuf(); if (SYSERR == (int)pkt) { return SYSERR; } /* Set the length of the packet and set the curr pointer back that * length */ pkt->len = UDP_HDR_LEN + datalen; /* Round the datalength to maintain word alignment */ pkt->curr -= (3 + (ulong)(pkt->len)) & ~0x03; /* Set UDP header fields and fill the packet with the data */ udppkt = (struct udpPkt *)(pkt->curr); udppkt->srcPort = hs2net(udpptr->localpt); udppkt->dstPort = hs2net(udpptr->remotept); udppkt->len = hs2net(pkt->len); udppkt->chksum = 0; /* Zero out the data buffer so empty space is padded with zeroes */ bzero(udppkt->data, datalen); memcpy(udppkt->data, buf, datalen); /* Calculate UDP checksum (which happens to be the same as TCP's) */ udppkt->chksum = udpChksum(pkt, UDP_HDR_LEN + datalen, &(udpptr->localip), &(udpptr->remoteip)); /* Send the UDP packet through IP */ result = ipv4Send(pkt, &(udpptr->localip), &(udpptr->remoteip), IPv4_PROTO_UDP); if (SYSERR == netFreebuf(pkt)) { return SYSERR; } return result; }
void udpdump(struct udp *pudp, int dlen, int order) { int u_sport, u_dport, u_udplen, u_ucksum; if (order & EPO_UDP) { u_sport = pudp->u_sport; u_dport = pudp->u_dport; u_udplen = pudp->u_udplen; u_ucksum = pudp->u_ucksum; } else { u_sport = hs2net(pudp->u_sport); u_dport = hs2net(pudp->u_dport); u_udplen = hs2net(pudp->u_udplen); u_ucksum = hs2net(pudp->u_ucksum); } kprintf("UDP:\tsrc %5u dst %5u len %d cksum %04x\n", u_sport, u_dport, u_udplen, u_ucksum); hexdump((uint8_t *)pudp+UHLEN, dlen - UHLEN); }
/** * 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; }
//------------------------------------------------------------------------ // udpsend - send one UDP datagram to a given (foreign) IP address //------------------------------------------------------------------------ int udpsend(IPaddr faddr, int fport, int lport, struct epacket *packet, int datalen) { struct udp *udpptr; struct ip *ipptr; // Fill in UDP header; pass to ipsend to fill in IP header ipptr = (struct ip *)packet->ep_data; ipptr->i_proto = IPRO_UDP; udpptr = (struct udp *)ipptr->i_data; udpptr->u_sport = hs2net(lport); udpptr->u_dport = hs2net(fport); udpptr->u_udplen = hs2net(UHLEN + datalen); if (isodd(datalen)) udpptr->u_data[datalen] = (char)0; udpptr->u_ucksum = 0; return ipsend(faddr, packet, UHLEN + datalen); }
static struct packet *makePkt(ushort localpt, ushort remotept, struct netaddr *localip, struct netaddr *remoteip, ushort datalen, void *buf) { struct packet *pkt; struct udpPkt *udppkt = NULL; pkt = netGetbuf(); if (SYSERR == (int)pkt) { return (struct packet *)SYSERR; } /* Set the length of the packet and set the curr pointer back that * length */ pkt->len = UDP_HDR_LEN + datalen; /* Round the datalength to maintain word alignment */ pkt->curr -= (3 + (ulong)(pkt->len)) & ~0x03; /* Set UDP header fields and fill the packet with the data */ udppkt = (struct udpPkt *)(pkt->curr); udppkt->srcPort = hs2net(localpt); udppkt->dstPort = hs2net(remotept); udppkt->len = hs2net(pkt->len); udppkt->chksum = 0; /* Zero out the data buffer so empty space is padded with zeroes */ bzero(udppkt->data, datalen); memcpy(udppkt->data, buf, datalen); udppkt->chksum = udpChksum(pkt, UDP_HDR_LEN + datalen, localip, remoteip); return pkt; }
/*------------------------------------------------------------------------- * 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); }
/** * Send a TFTP RRQ (Read Request) packet over a UDP connection to the TFTP * server. This instructs the TFTP server to begin sending the contents of the * specified file. Not intended to be used outside of the TFTP code. * * @param udpdev * Device descriptor for the open UDP device. * @param filename * Name of the file to request. * * @return * OK if packet sent successfully; SYSERR otherwise. */ syscall tftpSendRRQ(int udpdev, const char *filename) { char *p; uint filenamelen; uint pktlen; struct tftpPkt pkt; /* Do sanity check on filename. */ filenamelen = strnlen(filename, 256); if (0 == filenamelen || 256 == filenamelen) { TFTP_TRACE("Filename is invalid."); return SYSERR; } TFTP_TRACE("RRQ \"%s\" (mode: octet)", filename); /* Set TFTP opcode to RRQ (Read Request). */ pkt.opcode = hs2net(TFTP_OPCODE_RRQ); /* Set up filename and mode. */ p = pkt.RRQ.filename_and_mode; memcpy(p, filename, filenamelen + 1); p += filenamelen + 1; memcpy(p, "octet", 6); p += 6; /* Write the resulting packet to the UDP device. */ pktlen = p - (char*)&pkt; if (pktlen != write(udpdev, &pkt, pktlen)) { TFTP_TRACE("Error sending RRQ"); return SYSERR; } return OK; }
/*------------------------------------------------------------------------ * ip2name - return DNS name for a host given its IP address *------------------------------------------------------------------------ */ char * ip2name(IPaddr ip, char *nam) { char tmpstr[20]; /* temporary string buffer */ char *buf; /* buffer to hold domain query */ int dg, i; register char *p; register struct dn_mesg *dnptr; dnptr = (struct dn_mesg *) (buf = (char *) getmem(DN_MLEN)); *nam = NULLCH; dnptr->dn_id = 0; dnptr->dn_opparm = hs2net(DN_RD); dnptr->dn_qcount = hs2net(1); dnptr->dn_acount = dnptr->dn_ncount = dnptr->dn_dcount = 0; p = dnptr->dn_qaaa; /* Fill in question with ip[3].ip[2].ip[1].ip[0].in-addr.arpa */ for (i=3 ; i >= 0 ; i--) { sprintf(tmpstr, "%u", ((char *)&ip)[i] & LOWBYTE); dn_cat(p, tmpstr); } dn_cat(p, "in-addr"); dn_cat(p, "arpa"); *p++ = NULLCH; /* terminate name */ /* Add query type and query class fields to name */ ( (struct dn_qsuf *)p )->dn_type = hs2net(DN_QTPR); ( (struct dn_qsuf *)p )->dn_clas = hs2net(DN_QCIN); p += sizeof(struct dn_qsuf); /* Send query */ dg = open(UDP, NSERVER, ANYLPORT); control(dg, DG_SETMODE, DG_DMODE | DG_TMODE); if (write (dg, buf, p - buf) == SYSERR) panic("ip2name write(%d) failed\n", dg); i = read(dg, buf, DN_MLEN); if (i == SYSERR) panic("ip2name read(%d) failed\n", dg); if (i == TIMEOUT) { close(dg); return ip2dot(nam, ip); } close(dg); if (net2hs(dnptr->dn_opparm) & DN_RESP || net2hs(dnptr->dn_acount) <= 0) { freemem(buf, DN_MLEN); return ip2dot(nam, ip); } /* In answer, skip name and remainder of resource record header */ while (*p != NULLCH) if (*p & DN_CMPRS) /* compressed section of name */ *++p = NULLCH; else p += *p + 1; p += DN_RLEN + 1; /* Copy name to user */ *nam = NULLCH; while (*p != NULLCH) { if (*p & DN_CMPRS) p = buf + (net2hs(*(int *)p) & DN_CPTR); else { strncat(nam, p+1, *p); strcat(nam, "."); p += *p + 1; } } if (strlen(nam)) /* remove trailing dot */ nam[strlen(nam) - 1] = NULLCH; else ip2dot(nam, ip); freemem(buf, DN_MLEN); return nam; }
/** * 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; }
static int ethloopn_test(bool verbose, int dev) { bool passed = TRUE; bool subpass; uint memsize; int i, value, len; struct etherGram *inpkt; struct etherGram *outpkt; char *payload; char str[80]; int devminor; struct ethloop *pelp; struct netaddr addr; device *pdev; pdev = (device *)&devtab[dev]; devminor = pdev->minor; pelp = &elooptab[devminor]; sprintf(str, "%s Open", pdev->name); testPrint(verbose, str); failif((SYSERR == open(dev)), ""); /* Allocate temporary buffers. */ memsize = sizeof(struct etherGram) + MAX_PAYLOAD - 1; inpkt = memget(memsize); outpkt = memget(memsize); payload = &(outpkt->payload[0]); control(dev, NET_GET_HWADDR, (int)&addr, NULL); memcpy(outpkt->dst, addr.addr, addr.len); memcpy(outpkt->src, addr.addr, addr.len); outpkt->type_len = hs2net(ETH_TYPE_ARP); /* generate payload content */ for (i = 0; i < MAX_PAYLOAD; i++) { /* Cycle through 0x20 to 0x7d (range of 0x5e) */ value = (i % 0x5e) + 0x20; payload[i] = value; } /* oversized packet (paylod 1502 bytes + 14 byte header) */ sprintf(str, "%s 1516 byte packet", pelp->dev->name); testPrint(verbose, str); len = write(dev, outpkt, 1516); failif((SYSERR != len), ""); /* max packet (payload 1500 bytes + 14 byte header) */ sprintf(str, "%s 1514 byte packet (write)", pelp->dev->name); testPrint(verbose, str); len = write(dev, outpkt, 1514); failif((len != 1514), ""); sprintf(str, "%s 1514 byte packet (read)", pelp->dev->name); testPrint(verbose, str); bzero(inpkt, memsize); len = read(dev, inpkt, 1514); failif((len != 1514) || (0 != memcmp(outpkt, inpkt, 1514)), ""); /* 'normal' packet (payload 686 bytes + 14 byte header) */ sprintf(str, "%s 700 byte packet (write)", pelp->dev->name); testPrint(verbose, str); len = write(dev, outpkt, 700); failif((len != 700), ""); sprintf(str, "%s 700 byte packet (read)", pelp->dev->name); testPrint(verbose, str); bzero(inpkt, memsize); len = read(dev, inpkt, 700); failif((len != 700) || (0 != memcmp(outpkt, inpkt, 700)), ""); /* small packet (payload 16 bytes + 14 byte header) */ sprintf(str, "%s 30 byte packet (write)", pelp->dev->name); testPrint(verbose, str); len = write(dev, outpkt, 30); failif((len != 30), ""); sprintf(str, "%s 30 byte packet (read)", pelp->dev->name); testPrint(verbose, str); bzero(inpkt, memsize); len = read(dev, inpkt, 30); failif((len != 30) || (0 != memcmp(outpkt, inpkt, 30)), ""); /* micro packet (12 bytes) */ sprintf(str, "%s 12 byte packet", pelp->dev->name); testPrint(verbose, str); len = write(dev, outpkt, 12); failif((SYSERR != len), ""); /* send 512 random sized packets */ sprintf(str, "%s 512 random-sized packets", pelp->dev->name); testPrint(verbose, str); subpass = TRUE; for (i = 0; i < 512; i++) { len = 32 + (rand() % 1200); value = write(dev, outpkt, len); if (value != len) { subpass = FALSE; } bzero(inpkt, memsize); value = read(dev, inpkt, len); if ((value != len) || (0 != memcmp(outpkt, inpkt, len))) { subpass = FALSE; } } failif((TRUE != subpass), ""); /* hold packet (payload 686 bytes + 14 byte header) */ control(dev, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); sprintf(str, "%s 700 byte packet (write hold)", pelp->dev->name); testPrint(verbose, str); len = write(dev, outpkt, 700); failif((len != 700), ""); sprintf(str, "%s 700 byte packet (read hold)", pelp->dev->name); testPrint(verbose, str); bzero(inpkt, memsize); len = control(dev, ELOOP_CTRL_GETHOLD, (int)inpkt, 700); failif((0 != memcmp(outpkt, inpkt, 700)), ""); /* drop packet (payload 686 bytes + 14 byte header) */ control(dev, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_DROPNXT, NULL); sprintf(str, "%s 700 byte packet (write drop)", pelp->dev->name); testPrint(verbose, str); len = write(dev, outpkt, 700); failif((len != 700), ""); sprintf(str, "%s 700 byte packet (write)", pelp->dev->name); testPrint(verbose, str); outpkt->dst[0] += 1; len = write(dev, outpkt, 700); failif((len != 700), ""); sprintf(str, "%s 700 byte packet (read)", pelp->dev->name); testPrint(verbose, str); bzero(inpkt, memsize); len = read(dev, inpkt, 700); failif((len != 700) || (0 != memcmp(outpkt, inpkt, 700)), ""); /* Free temporary buffers. */ memfree(outpkt, memsize); memfree(inpkt, memsize); sprintf(str, "%s Close", pdev->name); testPrint(verbose, str); failif((SYSERR == close(dev)), ""); return passed; }
/** * Fragments packet into maximum transmission unit sized chunks. * @param pkt the packet to fragment * @return OK */ syscall ipv4SendFrag(struct packet *pkt, struct netaddr *nxthop) { uint ihl; uchar *data; uint dRem = 0; // The amount of data remaining to be fragmented ushort froff; ushort lastFlag; ushort dLen; // Incoming packet structures struct ipv4Pkt *ip; // Outgoing packet structures struct ipv4Pkt *outip; struct packet *outpkt; IPv4_TRACE("Declaration"); if (NULL == pkt) { return SYSERR; } // Setup incoming packet structures ip = (struct ipv4Pkt *)pkt->curr; if (net2hs(ip->len) <= pkt->nif->mtu) { IPv4_TRACE("NetSend"); if (netaddrequal(&pkt->nif->ipbrc, nxthop)) { IPv4_TRACE("Subnet Broadcast"); return netSend(pkt, &NETADDR_GLOBAL_ETH_BRC, nxthop, ETHER_TYPE_IPv4); } return netSend(pkt, NULL, nxthop, ETHER_TYPE_IPv4); } // Verify header does not have DF if (net2hs(ip->flags_froff) & IPv4_FLAG_DF) { IPv4_TRACE("net2hs of froff"); /* Send ICMP message */ icmpDestUnreach(pkt, ICMP_FOFF_DFSET); return SYSERR; } ihl = (ip->ver_ihl & IPv4_IHL) * 4; data = ((uchar *)ip) + ihl; dRem = net2hs(ip->len) - ihl; froff = net2hs(ip->flags_froff) & IPv4_FROFF; lastFlag = net2hs(ip->flags_froff) & IPv4_FLAGS; // Length of data in this packet will be MTU - header length, // rounded down to nearest multiple of 8 bytes. dLen = (pkt->nif->mtu - ihl) & ~0x7; pkt->len = ihl + dLen; ip->len = hs2net(pkt->len); // Set more fragments flag ip->flags_froff = IPv4_FLAG_MF & froff; ip->flags_froff = hs2net(ip->flags_froff); ip->chksum = 0; ip->chksum = netChksum((uchar *)ip, ihl); netSend(pkt, NULL, nxthop, ETHER_TYPE_IPv4); dRem -= dLen; data += dLen; froff += (dLen / 8); // Get memory from stack for outgoing fragment outpkt = netGetbuf(); if (SYSERR == (int)outpkt) { IPv4_TRACE("allocating outpkt"); return SYSERR; } // Set up outgoing packet pointers and variables outpkt->curr -= pkt->nif->mtu; outip = (struct ipv4Pkt *)outpkt->curr; outpkt->nif = pkt->nif; memcpy(outip, ip, IPv4_HDR_LEN); // While packet must be fragmented while (dRem > 0) { if (((dRem + 7) & ~0x7) > pkt->nif->mtu + IPv4_HDR_LEN) { dLen = (pkt->nif->mtu - IPv4_HDR_LEN) & ~0x7; } else { dLen = dRem; } // Copy data segment memcpy(outip->opts, data, dLen); // Set more fragments flag if (dLen == dRem) { outip->flags_froff = lastFlag & froff; } else { outip->flags_froff = IPv4_FLAG_MF & froff; } outip->flags_froff = hs2net(outip->flags_froff); // Update fields outip->len = hs2net(IPv4_HDR_LEN + dLen); outip->chksum = 0; outip->chksum = netChksum((uchar *)outip, IPv4_HDR_LEN); // Update outgoing packet length outpkt->len = net2hs(outip->len); // Send fragment netSend(outpkt, NULL, nxthop, ETHER_TYPE_IPv4); dRem -= dLen; data += dLen; froff += (dLen / 8); } IPv4_TRACE("freeing outpkt"); netFreebuf(outpkt); return OK; }
/** * Tests ARP. * @return OK when testing is complete */ thread test_arp(bool verbose) { bool passed = TRUE; int i = 0; struct netaddr ip; struct netaddr mask; struct netaddr praddr; struct netaddr hwaddr; struct netaddr addrbuf; struct pcap_file_header pcap; struct pcap_pkthdr phdr; struct packet *pkt; struct netif *netptr; struct ethloop *pelp; uchar *data; uchar *request; struct arpPkt *arp; struct arpEntry *entry; uchar buf[ELOOP_BUFSIZE]; int nproc; int nout; int wait; tid_typ tids[ARP_NTHRWAIT]; tid_typ tid; irqmask im; enable(); ip.type = NETADDR_IPv4; ip.len = IPv4_ADDR_LEN; ip.addr[0] = 192; ip.addr[1] = 168; ip.addr[2] = 1; ip.addr[3] = 6; mask.type = NETADDR_IPv4; mask.len = IPv4_ADDR_LEN; mask.addr[0] = 255; mask.addr[1] = 255; mask.addr[2] = 255; mask.addr[3] = 0; /* Initialize loopback ethernet and network interface */ testPrint(verbose, "Test case initialization"); data = (uchar *)(&_binary_data_testarp_pcap_start); memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); if (SYSERR == open(ELOOP)) { failif(TRUE, ""); } else { failif((SYSERR == netUp(ELOOP, &ip, &mask, NULL)), ""); } if (!passed) { testFail(TRUE, ""); return OK; } /* Setup pointers to underlying structures */ #if NNETIF for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (ELOOP == netiftab[i].dev)) { break; } } #endif netptr = &netiftab[i]; pelp = &elooptab[devtab[ELOOP].minor]; pkt = netGetbuf(); if ((int)pkt != SYSERR) { pkt->nif = netptr; } praddr.type = NETADDR_IPv4; praddr.len = IPv4_ADDR_LEN; praddr.addr[0] = 192; praddr.addr[1] = 168; praddr.addr[2] = 1; praddr.addr[3] = 3; hwaddr.type = NETADDR_ETHERNET; hwaddr.len = ETH_ADDR_LEN; hwaddr.addr[0] = 0xAA; hwaddr.addr[1] = 0xBB; hwaddr.addr[2] = 0xCC; hwaddr.addr[3] = 0xDD; hwaddr.addr[4] = 0xEE; hwaddr.addr[5] = 0xFF; /* Test arpPkt structure */ testPrint(verbose, "Header structure (Request)"); /* Get 1st packet */ memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } pkt = netGetbuf(); pkt->len += ARP_CONST_HDR_LEN + (2 * IPv4_ADDR_LEN) + (2 * ETH_ADDR_LEN); pkt->curr -= pkt->len; arp = (struct arpPkt *)pkt->curr; arp->hwtype = hs2net(ARP_HWTYPE_ETHERNET); arp->prtype = hs2net(ARP_PRTYPE_IPv4); arp->hwalen = ETH_ADDR_LEN; arp->pralen = IPv4_ADDR_LEN; arp->op = hs2net(ARP_OP_RQST); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); /* Test arpPkt structure */ testPrint(verbose, "Header structure (Reply)"); /* Get 2nd packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } arp->op = hs2net(ARP_OP_REPLY); memcpy(&arp->addrs[ARP_ADDR_DHA(arp)], &arp->addrs[ARP_ADDR_SHA(arp)], arp->hwalen); arp->addrs[ARP_ADDR_DHA(arp) + ETH_ADDR_LEN - 1] = 0xCC; memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); /* Test arpAlloc, free entry exists */ testPrint(verbose, "Allocate free entry"); /* Make first entry used */ arptab[0].state = ARP_USED; arptab[0].expires = clktime + ARP_TTL_UNRESOLVED; entry = arpAlloc(); failif(((NULL == entry) || (entry == &arptab[0]) || (0 == (entry->state & ARP_USED))), ""); /* Test arpAlloc, free entry exists */ testPrint(verbose, "Allocate used entry"); arptab[1].state = ARP_USED; arptab[1].expires = clktime + 1; /* Make all entries (except the first 2) have ARP_TTL_RESOLVED */ for (i = 2; i < ARP_NENTRY; i++) { arptab[i].state = ARP_USED; arptab[i].expires = clktime + ARP_TTL_RESOLVED; } entry = arpAlloc(); failif(((NULL == entry) || (entry != &arptab[1]) || (0 == (entry->state & ARP_USED))), ""); /* Test arpNotify */ testPrint(verbose, "Notify waiting threads (bad params)"); failif((SYSERR != arpNotify(NULL, TIMEOUT)), ""); /* Test arpNotify */ testPrint(verbose, "Notify waiting threads"); entry = &arptab[0]; entry->state = ARP_UNRESOLVED; for (i = 0; i < ARP_NTHRWAIT; i++) { tid = create((void *)notifyTest, INITSTK, INITPRIO, "notifyTest", 0); tids[i] = tid; entry->waiting[i] = tid; entry->count++; ready(tid, RESCHED_NO); } recvclr(); arpNotify(entry, ARP_MSG_RESOLVED); nout = FALSE; nproc = 0; tid = recvtime(100); while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) { for (i = 0; i < ARP_NTHRWAIT; i++) { if (tid == tids[i]) { tids[i] = NULL; } } nproc++; tid = recvtime(100); } for (i = 0; i < ARP_NTHRWAIT; i++) { if (tids[i] != NULL) { kill(tids[i]); nout = TRUE; } } failif(nout || (entry->count != 0), ""); /* Test arpFree */ testPrint(verbose, "Free entry (bad params)"); failif((SYSERR != arpFree(NULL)), ""); /* Test arpFree */ testPrint(verbose, "Free resolved entry"); entry = &arptab[0]; entry->state = ARP_RESOLVED; entry->expires = clktime; failif(((SYSERR == arpFree(entry)) || (entry->expires != 0)), ""); /* Test arpFree */ testPrint(verbose, "Free unresolved entry"); entry = &arptab[0]; entry->state = ARP_UNRESOLVED; for (i = 0; i < ARP_NTHRWAIT; i++) { tid = create((void *)freeTest, INITSTK, INITPRIO, "freeTest", 0); tids[i] = tid; entry->waiting[i] = tid; entry->count++; ready(tid, RESCHED_NO); } recvclr(); if (SYSERR == arpFree(entry)) { failif(TRUE, "Returned SYSERR"); } else { nout = FALSE; nproc = 0; tid = recvtime(100); while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) { for (i = 0; i < ARP_NTHRWAIT; i++) { if (tid == tids[i]) { tids[i] = NULL; } } nproc++; tid = recvtime(100); } for (i = 0; i < ARP_NTHRWAIT; i++) { if (tids[i] != NULL) { kill(tids[i]); nout = TRUE; } } failif(nout || (entry->count != 0), ""); } /* Test arpGetEntry */ testPrint(verbose, "Get entry"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } nout = 4; if (ARP_NENTRY < nout) { nout = ARP_NENTRY; } for (i = 1; i < nout; i++) { entry = &arptab[i]; entry->state = ARP_RESOLVED; entry->nif = netptr; praddr.addr[3] = i + 1; hwaddr.addr[5] = ((i + 0xA) << 4) + (i + 0xA); netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_RESOLVED; } for (i = 1; i < nout; i++) { praddr.addr[3] = i + 1; entry = arpGetEntry(&praddr); if (entry != &arptab[i]) { break; } } failif((i != nout), ""); /* Test arpGetEntry with timeout */ testPrint(verbose, "Get entry (timeout entries)"); arptab[i].expires = clktime - 1; praddr.addr[3] = 2; entry = arpGetEntry(&praddr); if (entry != &arptab[1]) { failif(TRUE, "Incorrect entry"); } else { failif((arptab[0].state != ARP_FREE), "Did not free expired entry"); } for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } /* Test receive reply for non-existing ARP table entry */ testPrint(verbose, "Receive ARP reply, new entry"); /* Get 3rd packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 3; hwaddr.addr[5] = 0xCC; nout = pelp->nout; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(10); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry and ensure reply was not sent */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if (ARP_RESOLVED == arptab[i].state) { entry = &arptab[i]; break; } } if (NULL == entry) { failif(TRUE, "No entry inserted"); } else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) || (entry->nif != netptr) || (entry->count != 0)) { failif(TRUE, "Entry incorrect"); } else if (pelp->nout > (nout + 1)) { failif(TRUE, "Reply sent to reply"); } else { failif(FALSE, ""); } } /* Test receive request for non-existing ARP table entry */ testPrint(verbose, "Receive ARP request, new entry"); /* Get 4th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 1; hwaddr.addr[5] = 0xAA; nout = pelp->nout; nproc = netptr->nproc; im = disable(); write(ELOOP, data, phdr.caplen); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); restore(im); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry and ensure reply was not sent */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } if (NULL == entry) { failif(TRUE, "No entry inserted"); } else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) || (entry->nif != netptr) || (entry->count != 0)) { failif(TRUE, "Entry incorrect"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); /* Get 5th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } failif((memcmp(data, buf, phdr.caplen) != 0), "Invalid reply"); } } /* Test receive request for non-supported hardware type */ testPrint(verbose, "Receive ARP request, bad HW type"); /* Get 6th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test receive reply for non-supported protocol type */ testPrint(verbose, "Receive ARP reply, bad protocol type"); /* Get 7th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test receive reply for existing resolved ARP table entry */ testPrint(verbose, "Receive ARP reply, resolved entry"); /* Get 8th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 3; hwaddr.addr[5] = 0x0C; nout = pelp->nout; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((FALSE == netaddrequal(&hwaddr, &entry->hwaddr)), "Entry incorrect"); } /* Test receive request not for me */ testPrint(verbose, "Receive ARP request, not mine"); /* Get 9th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 4; hwaddr.addr[5] = 0xDD; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test arpSendRequest */ testPrint(verbose, "Send ARP request (bad params)"); failif((SYSERR != arpSendRqst(NULL)), ""); /* Test arpSendRequest */ testPrint(verbose, "Send ARP request"); /* Get 10th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } entry = &arptab[0]; entry->state = ARP_UNRESOLVED; entry->nif = netptr; praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == arpSendRqst(entry)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); failif((memcmp(buf, data, phdr.caplen) != 0), ""); } /* Test arpLookup */ testPrint(verbose, "Lookup address (bad params)"); failif((SYSERR != arpLookup(NULL, NULL, NULL)), ""); /* Test arpLookup */ testPrint(verbose, "Lookup existing resolved address"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } entry = &arptab[0]; entry->state = ARP_RESOLVED; entry->nif = netptr; praddr.addr[3] = 1; hwaddr.addr[5] = 0xAA; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup existing unresolved address"); entry = &arptab[1]; entry->state = ARP_UNRESOLVED; entry->nif = netptr; praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); request = data; wait = phdr.caplen; /* Get 11th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, request, wait, data, phdr.caplen), RESCHED_NO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { kill(tid); failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup max threads wait for resolve"); entry->state = ARP_UNRESOLVED; entry->count = ARP_NTHRWAIT; failif((arpLookup(netptr, &praddr, &addrbuf) != SYSERR), ""); /* Test arpLookup */ testPrint(verbose, "Lookup non-existing unresolved addr"); praddr.addr[3] = 3; hwaddr.addr[5] = 0xCC; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); request = data; wait = phdr.caplen; /* Get 12th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } request = data; wait = phdr.caplen; /* Get 13th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, request, wait, data, phdr.caplen), RESCHED_NO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { kill(tid); failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup timeout"); praddr.addr[3] = 4; hwaddr.addr[5] = 0xDD; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_DROPALL, NULL); failif((SYSERR != arpLookup(netptr, &praddr, &addrbuf)), ""); /* Stop loopback ethernet and network interface */ testPrint(verbose, "Test case cleanup"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } failif(((SYSERR == netFreebuf(pkt)) || (SYSERR == netDown(ELOOP)) || (SYSERR == close(ELOOP))), ""); if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/*------------------------------------------------------------------------ * gname - use the DNS to look up the name *------------------------------------------------------------------------ */ static IPaddr gname(char *nam) { IPaddr ip; char tmpstr[64]; /* temporary string buffer */ char *buf; /* buffer to hold domain query */ int dg, i; register char *p, *p2, *p3; register struct dn_mesg *dnptr; dnptr = (struct dn_mesg *) (buf = (char *) getmem(DN_MLEN)); dnptr->dn_id = 0; dnptr->dn_opparm = hs2net(DN_RD); dnptr->dn_qcount = hs2net(1); dnptr->dn_acount = dnptr->dn_ncount = dnptr->dn_dcount = 0; p = dnptr->dn_qaaa; strcpy(tmpstr, nam); p2 = tmpstr; while (p3=index(p2, '.')) { *p3 = '\0'; dn_cat(p, p2); p2 = p3+1; } dn_cat(p, p2); *p++ = NULLCH; /* terminate name */ /* Add query type and query class fields to name */ ( (struct dn_qsuf *)p )->dn_type = hs2net(DN_QTHA); ( (struct dn_qsuf *)p )->dn_clas = hs2net(DN_QCIN); p += sizeof(struct dn_qsuf); /* send query */ dg = open(UDP, NSERVER, ANYLPORT); control(dg, DG_SETMODE, DG_DMODE | DG_TMODE); write (dg, buf, p - buf); if ( (i = read(dg, buf, DN_MLEN)) == SYSERR || i == TIMEOUT) { close(dg); freemem(buf, DN_MLEN); return (IPaddr)SYSERR; } close(dg); if (net2hs(dnptr->dn_opparm) & DN_RESP || net2hs(dnptr->dn_acount) <= 0) { freemem(buf, DN_MLEN); return (IPaddr)SYSERR; } /* In answer, skip name and remainder of resource record header */ while (*p != NULLCH) if (*p & DN_CMPRS) /* compressed section of name */ *++p = NULLCH; else p += *p + 1; p += DN_RLEN + 1; /* Copy IP to user */ for (i=0; i < IP_ALEN; ++i) ((char *)&ip)[i] = *p++; freemem(buf, DN_MLEN); return ip; }
/** * Sends an ARP request for an ARP table entry over a network interface. * @param entry ARP table entry * @return OK if packet was sent, otherwise SYSERR */ syscall arpSendRqst(struct arpEntry *entry) { struct netif *netptr = NULL; struct packet *pkt = NULL; struct arpPkt *arp = NULL; int result; /* Error check pointers */ if (NULL == entry) { return SYSERR; } ARP_TRACE("Sending ARP request"); /* Setup pointer to network interface */ netptr = entry->nif; /* Obtain a buffer for the packet */ pkt = netGetbuf(); if (SYSERR == (int)pkt) { ARP_TRACE("Failed to acquire packet buffer"); return SYSERR; } /* Place ARP header at end of packet buffer */ pkt->nif = netptr; pkt->len = ARP_CONST_HDR_LEN + netptr->hwaddr.len * 2 + netptr->ip.len * 2; pkt->curr -= pkt->len; arp = (struct arpPkt *)pkt->curr; /* Fill in ARP header */ arp->hwtype = hs2net(netptr->hwaddr.type); arp->prtype = hs2net(netptr->ip.type); arp->hwalen = netptr->hwaddr.len; arp->pralen = netptr->ip.len; arp->op = hs2net(ARP_OP_RQST); ARP_TRACE("Filled in types, lens, and op"); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], entry->praddr.addr, arp->pralen); ARP_TRACE("Filled in addrs"); /* Send packet */ result = netSend(pkt, &netptr->hwbrc, NULL, ETHER_TYPE_ARP); ARP_TRACE("Sent packet"); /* Free buffer for the packet */ if (SYSERR == netFreebuf(pkt)) { ARP_TRACE("Failed to free packet buffer"); return SYSERR; } /* Return result of netSend */ return result; }
/* returns 0 upon success; -1 upon error */ int sntp_request_time(PFBYTE ip_sntp_server, int *socket_no, PNTP_TIME_FORMAT current_timestamp, int version, int mode, dword *ticks_when_sent, PEBSTIME res_ebs_tod) { NTP_PKT ntp_request; struct sockaddr_in sin; int len; /* Allocate a socket */ if ( (*socket_no = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { DEBUG_ERROR("sntp_request_time: socket failed", EBS_INT1, xn_getlasterror(), 0); return(-1); } /* Bind my ip address port NTP port */ sin.sin_family = AF_INET; #if !CFG_UNIX_COMPLIANT_SOCK_STRUCTS sin.sin_addr = INADDR_ANY; #else sin.sin_addr.s_addr = INADDR_ANY; #endif sin.sin_port = hs2net(NTP_PORT); if (bind(*socket_no, (PSOCKADDR)&sin, sizeof(sin)) < 0) { DEBUG_ERROR("sntp_request_time: bind failed", EBS_INT1, xn_getlasterror(), 0); closesocket(*socket_no); return(-1); } /* Connect to remote NTP server */ tc_mv4((PFBYTE)&sin.sin_addr, ip_sntp_server, IP_ALEN); if (connect(*socket_no, (PSOCKADDR)&sin, sizeof(sin)) < 0) { DEBUG_ERROR("sntp_request_time: connect failed", EBS_INT1, xn_getlasterror(), 0); closesocket(*socket_no); return(-1); } /* format request */ tc_memset((PFBYTE)&ntp_request, 0, sizeof(NTP_PKT)); ntp_request.li_vn_mode = (byte)mode; ntp_request.li_vn_mode |= version; ntp_request.poll = 6; /* get current time of day from ostime.c */ convert_ebs_time_to_time(res_ebs_tod, current_timestamp); *ticks_when_sent = ks_get_ticks(); #if (DEBUG_DELAY_TICKS) DEBUG_ERROR("ticks_when_sent set to : ", DINT1, *ticks_when_sent, 0); #endif /* send request */ if ((len=send(*socket_no, (PFCHAR)&ntp_request, sizeof(NTP_PKT), 0)) < sizeof(NTP_PKT)) { if (len < 0) { DEBUG_ERROR("sntp_request_time: send failed", EBS_INT1, xn_getlasterror(), 0); closesocket(*socket_no); return(-1); } else { DEBUG_ERROR("sntp_request_time: sent less bytes: exp, act:", EBS_INT2, sizeof(NTP_PKT), len); } } return(0); }