/*------------------------------------------------------------------------ * 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; }
static int processRequest(int sd) { char buf[1024]; int len; if ((len = readHeader(sd, buf)) < 0) return len; if (len == 0) { logWarn("File not found, sending zero response\n", len); ipsend(sd, &idDefault, CERT_HEADER_LEN); return 0; } logNorm("Received header. Receiving data of length = %d\n", len); certHeader_t *req = (certHeader_t *) buf; if ((len = recvBytes(sd, &req->data, len)) <= 0) return len; char *filename = &req->data[0]; filename[len] = 0; char *fileBuf; logNorm("Reading certificate file '%s'\n", filename); if ((len = readFile(filename, &fileBuf)) < 0) return len; int rspLen = CERT_HEADER_LEN + len; certHeader_t *rsp = (certHeader_t *) malloc(rspLen); if (rsp == NULL) dieError("%s.malloc\n", __func__); memcpy(&rsp->id, idDefault, 4); rsp->length = htonl(len); memcpy(&rsp->data, fileBuf, len); hexdump(&rsp->data, 16, 16); logNorm("Sending certificate of size %d bytes\n", len); len = ipsend(sd, rsp, rspLen); free(fileBuf); free(rsp); return len; }
/*------------------------------------------------------------------------ * icmp - send an ICMP message *------------------------------------------------------------------------ */ int icmp(u_short type, u_short code, IPaddr dst, void *pa1, void *pa2) { struct ep *pep; struct ip *pip; struct icmp *pic; Bool isresp, iserr; int datalen; IcmpOutMsgs++; pep = icsetbuf(type, pa1, &isresp, &iserr); if (pep == 0) { IcmpOutErrors++; return SYSERR; } pip = (struct ip *)pep->ep_data; pic = (struct icmp *) pip->ip_data; datalen = IC_HLEN; /* we fill in the source here, so routing won't break it */ if (isresp) { if (iserr) { if (!icerrok(pep)) { freebuf(pep); return OK; } memcpy(pic->ic_data, pip, IP_HLEN(pip)+8); datalen += IP_HLEN(pip)+8; } icsetsrc(pip); } else pip->ip_src = ip_anyaddr; pip->ip_dst = dst; pic->ic_type = (char) type; pic->ic_code = (char) code; if (!isresp) { if (type == ICT_ECHORQ) pic->ic_seq = (int) pa1; else pic->ic_seq = 0; pic->ic_id = getpid(); } datalen += icsetdata(type, pip, pa2); pic->ic_cksum = 0; pic->ic_cksum = cksum((WORD *)pic, datalen); ipsend(dst, pep, datalen, IPT_ICMP, IPP_INCTL, IP_TTL); return OK; }
static int client() { int sd = ipConnectPeer(arg.host, arg.port, 3); int filenameLen = strlen(arg.url); int reqLen = CERT_HEADER_LEN + filenameLen; certHeader_t *req = (certHeader_t *) malloc(reqLen); if (req == NULL) dieError("%s.malloc\n", __func__); req->id[0] = 'C'; req->id[1] = 'R'; req->id[2] = 'T'; req->id[3] = '0'; req->length = htonl(filenameLen); memcpy(&req->data[0], arg.url, filenameLen); logNorm("Requesting certificate '%s' (data len = %d)\n", arg.url, filenameLen); int len = ipsend(sd, req, reqLen); free(req); if (len < 0) return len; // Read the response char buf[1024]; if ((len = readHeader(sd, buf)) < 0) return len; if (len == 0) { logError("Received error response (certificate not found?)\n"); return -2; } void *certBuf = malloc(len); if (certBuf == NULL) dieError("%s.malloc\n", __func__); // Read the certificate int res; logNorm("Reading certificate of %d bytes\n", len); if ((res = recvBytes(sd, certBuf, len)) < 0) return res; hexdump(certBuf, 16, 16); close(sd); return 0; }
/*------------------------------------------------------------------------ * tcpreset - generate a reset in response to a bad packet *------------------------------------------------------------------------ */ int tcpreset(struct ep *pepin) { struct ep *pepout; struct ip *pipin = (struct ip *)pepin->ep_data, *pipout; struct tcp *ptcpin = (struct tcp *)pipin->ip_data, *ptcpout; int datalen; if (ptcpin->tcp_code & TCPF_RST) return OK; /* no RESETs on RESETs */ pepout = (struct ep *)getbuf(Net.netpool); if ((int)pepout == SYSERR) return SYSERR; pipout = (struct ip *)pepout->ep_data; pipout->ip_src = pipin->ip_dst; pipout->ip_dst = pipin->ip_src; ptcpout = (struct tcp *)pipout->ip_data; ptcpout->tcp_sport = ptcpin->tcp_dport; ptcpout->tcp_dport = ptcpin->tcp_sport; if (ptcpin->tcp_code & TCPF_ACK) { ptcpout->tcp_seq = ptcpin->tcp_ack; ptcpout->tcp_code = TCPF_RST; } else { ptcpout->tcp_seq = 0; ptcpout->tcp_code = TCPF_RST|TCPF_ACK; } datalen = pipin->ip_len - IP_HLEN(pipin) - TCP_HLEN(ptcpin); if (ptcpin->tcp_code & TCPF_SYN) datalen++; if (ptcpin->tcp_code & TCPF_FIN) datalen++; ptcpout->tcp_ack = ptcpin->tcp_seq + datalen; ptcpout->tcp_offset = TCPHOFFSET; ptcpout->tcp_window = ptcpout->tcp_urgptr = 0; tcph2net(ptcpout); ptcpout->tcp_cksum = 0; ptcpout->tcp_cksum = tcpcksum(pepout, TCPMHLEN); TcpOutSegs++; TcpOutRsts++; return ipsend(pipin->ip_src, pepout, TCPMHLEN, IPT_TCP, IPP_NORMAL, IP_TTL); }
//------------------------------------------------------------------------ // 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); }
//------------------------------------------------------------------------ // netout - start network by finding address and forward IP packets //------------------------------------------------------------------------ PROCESS netout(int userpid, int icmpp) { struct epacket *packet; struct ip *ipptr; long tim; int len; char name[MNAMELEN]; IPaddr addr; getaddr(addr); gettime(&tim); getname(name, MNAMELEN); resume(userpid); while (TRUE) { packet = (struct epacket *)preceive(icmpp); ipptr = (struct ip *)packet->ep_data; memmove(addr, ipptr->i_dest, IPLEN); len = net2hs(ipptr->i_paclen) - IPHLEN; ipsend(addr, packet, len); } }
/*------------------------------------------------------------------------ * tcpackit - generate an ACK for a received TCP packet *------------------------------------------------------------------------ */ int tcpackit(struct tcb *ptcb, struct ep *pepin) { struct ep *pepout; struct ip *pipin = (struct ip *)pepin->ep_data, *pipout; struct tcp *ptcpin = (struct tcp *)pipin->ip_data, *ptcpout; if (ptcpin->tcp_code & TCPF_RST) return OK; if (pipin->ip_len <= IP_HLEN(pipin) + TCP_HLEN(ptcpin) && !(ptcpin->tcp_code & (TCPF_SYN|TCPF_FIN))) return OK; /* duplicate ACK */ pepout = (struct ep *)getbuf(Net.netpool); if ((int)pepout == SYSERR) return SYSERR; pepout->ep_order = ~0; pipout = (struct ip *)pepout->ep_data; pipout->ip_src = pipin->ip_dst; pipout->ip_dst = pipin->ip_src; ptcpout = (struct tcp *)pipout->ip_data; ptcpout->tcp_sport = ptcpin->tcp_dport; ptcpout->tcp_dport = ptcpin->tcp_sport; ptcpout->tcp_seq = ptcb->tcb_snext; ptcpout->tcp_ack = ptcb->tcb_rnext; ptcpout->tcp_code = TCPF_ACK; ptcpout->tcp_offset = TCPHOFFSET; ptcpout->tcp_window = tcprwindow(ptcb); ptcpout->tcp_urgptr = 0; ptcpout->tcp_cksum = 0; tcph2net(ptcpout); pepout->ep_order &= ~EPO_TCP; ptcpout->tcp_cksum = tcpcksum(pepout, TCPMHLEN); TcpOutSegs++; return ipsend(pipin->ip_src, pepout, TCPMHLEN, IPT_TCP, IPP_NORMAL, IP_TTL); }
/*------------------------------------------------------------------------ * icmp_in - handle ICMP packet coming in from the network *------------------------------------------------------------------------ */ int icmp_in(struct netif *pni, struct ep *pep) { struct ip *pip; struct icmp *pic; int i, len; pip = (struct ip *)pep->ep_data; pic = (struct icmp *) pip->ip_data; len = pip->ip_len - IP_HLEN(pip); if (cksum((WORD *)pic, len)) { IcmpInErrors++; freebuf(pep); return SYSERR; } IcmpInMsgs++; switch(pic->ic_type) { case ICT_ECHORQ: IcmpInEchos++; return icmp(ICT_ECHORP, 0, pip->ip_src, pep, 0); case ICT_MASKRQ: IcmpInAddrMasks++; if (!gateway) { freebuf(pep); return OK; } pic->ic_type = (char) ICT_MASKRP; *(IPaddr *)pic->ic_data = netmask(pip->ip_dst); break; case ICT_MASKRP: IcmpInAddrMaskReps++; for (i=0; i<Net.nif; ++i) if (nif[i].ni_ip == pip->ip_dst) break; if (i != Net.nif) { setmask(i, *(IPaddr *)pic->ic_data); send(pic->ic_id, ICT_MASKRP); } freebuf(pep); return OK; case ICT_ECHORP: IcmpInEchoReps++; if (send(pic->ic_id, (int)pep) != OK) freebuf(pep); return OK; case ICT_REDIRECT: IcmpInRedirects++; icredirect(pep); return OK; case ICT_DESTUR: IcmpInDestUnreachs++; freebuf(pep); return OK; case ICT_SRCQ: IcmpInSrcQuenchs++; freebuf(pep); return OK; case ICT_TIMEX: IcmpInTimeExcds++; freebuf(pep); return OK; case ICT_PARAMP: IcmpInParmProbs++; freebuf(pep); return OK; case ICT_TIMERQ: IcmpInTimestamps++; freebuf(pep); return OK; case ICT_TIMERP: IcmpInTimestampReps++; freebuf(pep); return OK; default: IcmpInErrors++; freebuf(pep); return OK; } icsetsrc(pip); len = pip->ip_len - IP_HLEN(pip); pic->ic_cksum = 0; pic->ic_cksum = cksum((WORD *)pic, len); IcmpOutMsgs++; ipsend(pip->ip_dst, pep, len, IPT_ICMP, IPP_INCTL, IP_TTL); return OK; }