1*21746Ssklower /* ns_error.c 6.2 85/06/01 */ 221483Ssklower 321483Ssklower #include "param.h" 421483Ssklower #include "systm.h" 521483Ssklower #include "mbuf.h" 621483Ssklower #include "protosw.h" 721483Ssklower #include "socket.h" 821483Ssklower #include "time.h" 921483Ssklower #include "kernel.h" 1021483Ssklower 1121483Ssklower #include "../net/route.h" 1221483Ssklower 1321483Ssklower #include "ns.h" 1421483Ssklower #include "ns_pcb.h" 1521483Ssklower #include "idp.h" 1621483Ssklower #include "ns_error.h" 1721483Ssklower 1821483Ssklower #ifdef NS_ERRPRINTFS 1921483Ssklower /* 2021483Ssklower * NS_ERR routines: error generation, receive packet processing, and 21*21746Ssklower * routines to turnaround packets back to the originator. 2221483Ssklower */ 2321483Ssklower int ns_errprintfs = 0; 2421483Ssklower #endif 2521483Ssklower 2621483Ssklower /* 2721483Ssklower * Generate an error packet of type error 2821483Ssklower * in response to bad packet. 2921483Ssklower */ 3021483Ssklower 3121483Ssklower ns_error(om, type, param) 3221483Ssklower struct mbuf *om; 3321483Ssklower int type; 3421483Ssklower { 3521483Ssklower register struct ns_epidp *ep; 3621483Ssklower struct mbuf *m; 3721483Ssklower struct idp *nip; 3821483Ssklower register struct idp *oip = mtod(om, struct idp *); 3921483Ssklower extern int idpcksum; 4021483Ssklower 41*21746Ssklower /* 42*21746Ssklower * If this packet was sent to the echo port, 43*21746Ssklower * and nobody was there, just echo it. 44*21746Ssklower * (Yes, this is a wart!) 45*21746Ssklower */ 46*21746Ssklower if (type==NS_ERR_NOSOCK && 47*21746Ssklower oip->idp_dna.x_port==htons(2) && 48*21746Ssklower (type = ns_echo(oip)==0)) 49*21746Ssklower return; 50*21746Ssklower 5121483Ssklower #ifdef NS_ERRPRINTFS 5221483Ssklower if (ns_errprintfs) 5321483Ssklower printf("ns_err_error(%x, %d, %d)\n", oip, type, param); 5421483Ssklower #endif 5521483Ssklower ns_errstat.ns_es_error++; 5621483Ssklower /* 5721483Ssklower * Make sure that the old IDP packet had 30 bytes of data to return; 5821483Ssklower * if not, don't bother. Also don't EVER error if the old 5921483Ssklower * packet protocol was NS_ERR. 6021483Ssklower */ 6121483Ssklower if (oip->idp_len < sizeof(struct idp)) { 6221483Ssklower ns_errstat.ns_es_oldshort++; 6321483Ssklower goto free; 6421483Ssklower } 6521483Ssklower if (oip->idp_pt == NSPROTO_ERROR) { 6621483Ssklower ns_errstat.ns_es_oldns_err++; 6721483Ssklower goto free; 6821483Ssklower } 6921483Ssklower 7021483Ssklower /* 7121483Ssklower * First, formulate ns_err message 7221483Ssklower */ 7321483Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 7421483Ssklower if (m == NULL) 7521483Ssklower goto free; 7621483Ssklower m->m_len = sizeof(*ep); 7721483Ssklower m->m_off = MMAXOFF - m->m_len; 7821483Ssklower ep = mtod(m, struct ns_epidp *); 7921483Ssklower if ((u_int)type > NS_ERR_TOO_BIG) 8021483Ssklower panic("ns_err_error"); 8121483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 8221483Ssklower ep->ns_ep_errp.ns_err_num = htons(type); 8321483Ssklower ep->ns_ep_errp.ns_err_param = htons(param); 8421483Ssklower bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 8521483Ssklower nip = &ep->ns_ep_idp; 8621483Ssklower nip->idp_len = sizeof(*ep); 8721483Ssklower nip->idp_len = htons((u_short)nip->idp_len); 8821483Ssklower nip->idp_pt = NSPROTO_ERROR; 8921483Ssklower nip->idp_tc = 0; 9021483Ssklower nip->idp_dna = oip->idp_sna; 9121483Ssklower nip->idp_sna = oip->idp_dna; 9221483Ssklower if (idpcksum) { 9321483Ssklower nip->idp_sum = 0; 9421483Ssklower nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 9521483Ssklower } else 9621483Ssklower nip->idp_sum = 0xffff; 9721483Ssklower ns_output(dtom(nip), (struct route *)0, 0); 9821483Ssklower 9921483Ssklower free: 10021483Ssklower m_freem(dtom(oip)); 10121483Ssklower } 10221483Ssklower 10321483Ssklower static struct sockproto ns_errroto = { AF_NS, NSPROTO_ERROR }; 10421483Ssklower static struct sockaddr_ns ns_errsrc = { AF_NS }; 10521483Ssklower static struct sockaddr_ns ns_errdst = { AF_NS }; 10621483Ssklower 10721483Ssklower ns_printhost(p) 10821483Ssklower register struct ns_addr *p; 10921483Ssklower { 11021483Ssklower 11121483Ssklower printf("<net:%x%x,host:%x%x%x,port:%x>", 11221483Ssklower p->x_net.s_net[0], 11321483Ssklower p->x_net.s_net[1], 11421483Ssklower p->x_host.s_host[0], 11521483Ssklower p->x_host.s_host[1], 11621483Ssklower p->x_host.s_host[2], 11721483Ssklower p->x_port); 11821483Ssklower 11921483Ssklower } 12021483Ssklower 12121483Ssklower /* 12221483Ssklower * Process a received NS_ERR message. 12321483Ssklower */ 12421483Ssklower ns_err_input(m) 12521483Ssklower struct mbuf *m; 12621483Ssklower { 12721483Ssklower register struct ns_errp *ep; 12821483Ssklower register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 12921483Ssklower register int i; 13021483Ssklower int type, code, param; 13121483Ssklower extern struct ns_addr if_makeaddr(); 13221483Ssklower 13321483Ssklower /* 13421483Ssklower * Locate ns_err structure in mbuf, and check 13521483Ssklower * that not corrupted and of at least minimum length. 13621483Ssklower */ 13721483Ssklower #ifdef NS_ERRPRINTFS 13821483Ssklower if (ns_errprintfs) { 13921483Ssklower printf("ns_err_input from "); 14021483Ssklower ns_printhost(&epidp->ns_ep_idp.idp_sna); 14121483Ssklower printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 14221483Ssklower } 14321483Ssklower #endif 14421483Ssklower i = sizeof (struct ns_epidp); 14521483Ssklower if ((m->m_off > MMAXOFF || m->m_len < i) && 14621483Ssklower (m = m_pullup(m, i)) == 0) { 14721483Ssklower ns_errstat.ns_es_tooshort++; 14821483Ssklower return; 14921483Ssklower } 15021483Ssklower ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 15121483Ssklower type = ntohs(ep->ns_err_num); 15221483Ssklower param = ntohs(ep->ns_err_param); 15321483Ssklower 15421483Ssklower #ifdef NS_ERRPRINTFS 15521483Ssklower /* 15621483Ssklower * Message type specific processing. 15721483Ssklower */ 15821483Ssklower if (ns_errprintfs) 15921483Ssklower printf("ns_err_input, type %d param %d\n", type, param); 16021483Ssklower #endif 16121483Ssklower if (type >= NS_ERR_TOO_BIG) { 16221483Ssklower goto badcode; 16321483Ssklower } 16421483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 16521483Ssklower switch (type) { 16621483Ssklower 16721483Ssklower case NS_ERR_UNREACH_HOST: 16821483Ssklower code = PRC_UNREACH_NET; 16921483Ssklower goto deliver; 17021483Ssklower 17121483Ssklower case NS_ERR_TOO_OLD: 17221483Ssklower code = PRC_TIMXCEED_INTRANS; 17321483Ssklower goto deliver; 17421483Ssklower 17521483Ssklower case NS_ERR_TOO_BIG: 17621483Ssklower code = PRC_MSGSIZE; 17721483Ssklower goto deliver; 17821483Ssklower 17921483Ssklower case NS_ERR_FULLUP: 18021483Ssklower code = PRC_QUENCH; 18121483Ssklower goto deliver; 18221483Ssklower 18321483Ssklower case NS_ERR_NOSOCK: 18421483Ssklower code = PRC_UNREACH_PORT; 18521483Ssklower goto deliver; 18621483Ssklower 18721483Ssklower case NS_ERR_UNSPEC_T: 18821483Ssklower case NS_ERR_BADSUM_T: 18921483Ssklower case NS_ERR_BADSUM: 19021483Ssklower case NS_ERR_UNSPEC: 19121483Ssklower code = PRC_PARAMPROB; 19221483Ssklower goto deliver; 19321483Ssklower 19421483Ssklower deliver: 19521483Ssklower /* 19621483Ssklower * Problem with datagram; advise higher level routines. 19721483Ssklower */ 19821483Ssklower #ifdef NS_ERRPRINTFS 19921483Ssklower if (ns_errprintfs) 20021483Ssklower printf("deliver to protocol %d\n", 20121483Ssklower ep->ns_err_idp.idp_pt); 20221483Ssklower #endif 20321483Ssklower switch(ep->ns_err_idp.idp_pt) { 20421483Ssklower case NSPROTO_SPP: 20521483Ssklower spp_ctlinput(code, (caddr_t)ep); 20621483Ssklower break; 20721483Ssklower 20821483Ssklower default: 20921483Ssklower idp_ctlinput(code, (caddr_t)ep); 21021483Ssklower } 21121483Ssklower 21221483Ssklower goto free; 21321483Ssklower 21421483Ssklower default: 21521483Ssklower badcode: 21621483Ssklower ns_errstat.ns_es_badcode++; 21721483Ssklower goto free; 21821483Ssklower 21921483Ssklower } 22021483Ssklower free: 22121483Ssklower m_freem(m); 22221483Ssklower } 223*21746Ssklower 22421483Ssklower u_long 22521483Ssklower nstime() 22621483Ssklower { 22721483Ssklower int s = spl6(); 22821483Ssklower u_long t; 22921483Ssklower 23021483Ssklower t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 23121483Ssklower splx(s); 23221483Ssklower return (htonl(t)); 23321483Ssklower } 234*21746Ssklower 235*21746Ssklower ns_echo(idp) 236*21746Ssklower register struct idp *idp; 237*21746Ssklower { 238*21746Ssklower struct mbuf *m = dtom(idp); 239*21746Ssklower register struct echo { 240*21746Ssklower struct idp ec_idp; 241*21746Ssklower u_short ec_op; /* Operation, 1 = request, 2 = reply */ 242*21746Ssklower } *ec = (struct echo *)idp; 243*21746Ssklower struct ns_addr temp; 244*21746Ssklower 245*21746Ssklower if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 246*21746Ssklower if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 247*21746Ssklower 248*21746Ssklower ec->ec_op = htons(2); 249*21746Ssklower 250*21746Ssklower temp = idp->idp_dna; 251*21746Ssklower idp->idp_dna = idp->idp_sna; 252*21746Ssklower idp->idp_sna = temp; 253*21746Ssklower 254*21746Ssklower if (idp->idp_sum != 0xffff) { 255*21746Ssklower idp->idp_sum = 0; 256*21746Ssklower idp->idp_sum = ns_cksum(m, (((ntohs(idp->idp_len) - 1)|1)+1)); 257*21746Ssklower } 258*21746Ssklower (void) ns_output(m, 0, NS_FORWARDING); 259*21746Ssklower return(0); 260*21746Ssklower } 261