1*23206Smckusick /* 2*23206Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23206Smckusick * All rights reserved. The Berkeley software License Agreement 4*23206Smckusick * specifies the terms and conditions for redistribution. 5*23206Smckusick * 6*23206Smckusick * @(#)ns_error.c 6.3 (Berkeley) 06/08/85 7*23206Smckusick */ 821483Ssklower 921483Ssklower #include "param.h" 1021483Ssklower #include "systm.h" 1121483Ssklower #include "mbuf.h" 1221483Ssklower #include "protosw.h" 1321483Ssklower #include "socket.h" 1421483Ssklower #include "time.h" 1521483Ssklower #include "kernel.h" 1621483Ssklower 1721483Ssklower #include "../net/route.h" 1821483Ssklower 1921483Ssklower #include "ns.h" 2021483Ssklower #include "ns_pcb.h" 2121483Ssklower #include "idp.h" 2221483Ssklower #include "ns_error.h" 2321483Ssklower 2421483Ssklower #ifdef NS_ERRPRINTFS 2521483Ssklower /* 2621483Ssklower * NS_ERR routines: error generation, receive packet processing, and 2721746Ssklower * routines to turnaround packets back to the originator. 2821483Ssklower */ 2921483Ssklower int ns_errprintfs = 0; 3021483Ssklower #endif 3121483Ssklower 3221483Ssklower /* 3321483Ssklower * Generate an error packet of type error 3421483Ssklower * in response to bad packet. 3521483Ssklower */ 3621483Ssklower 3721483Ssklower ns_error(om, type, param) 3821483Ssklower struct mbuf *om; 3921483Ssklower int type; 4021483Ssklower { 4121483Ssklower register struct ns_epidp *ep; 4221483Ssklower struct mbuf *m; 4321483Ssklower struct idp *nip; 4421483Ssklower register struct idp *oip = mtod(om, struct idp *); 4521483Ssklower extern int idpcksum; 4621483Ssklower 4721746Ssklower /* 4821746Ssklower * If this packet was sent to the echo port, 4921746Ssklower * and nobody was there, just echo it. 5021746Ssklower * (Yes, this is a wart!) 5121746Ssklower */ 5221746Ssklower if (type==NS_ERR_NOSOCK && 5321746Ssklower oip->idp_dna.x_port==htons(2) && 5421746Ssklower (type = ns_echo(oip)==0)) 5521746Ssklower return; 5621746Ssklower 5721483Ssklower #ifdef NS_ERRPRINTFS 5821483Ssklower if (ns_errprintfs) 5921483Ssklower printf("ns_err_error(%x, %d, %d)\n", oip, type, param); 6021483Ssklower #endif 6121483Ssklower ns_errstat.ns_es_error++; 6221483Ssklower /* 6321483Ssklower * Make sure that the old IDP packet had 30 bytes of data to return; 6421483Ssklower * if not, don't bother. Also don't EVER error if the old 6521483Ssklower * packet protocol was NS_ERR. 6621483Ssklower */ 6721483Ssklower if (oip->idp_len < sizeof(struct idp)) { 6821483Ssklower ns_errstat.ns_es_oldshort++; 6921483Ssklower goto free; 7021483Ssklower } 7121483Ssklower if (oip->idp_pt == NSPROTO_ERROR) { 7221483Ssklower ns_errstat.ns_es_oldns_err++; 7321483Ssklower goto free; 7421483Ssklower } 7521483Ssklower 7621483Ssklower /* 7721483Ssklower * First, formulate ns_err message 7821483Ssklower */ 7921483Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 8021483Ssklower if (m == NULL) 8121483Ssklower goto free; 8221483Ssklower m->m_len = sizeof(*ep); 8321483Ssklower m->m_off = MMAXOFF - m->m_len; 8421483Ssklower ep = mtod(m, struct ns_epidp *); 8521483Ssklower if ((u_int)type > NS_ERR_TOO_BIG) 8621483Ssklower panic("ns_err_error"); 8721483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 8821483Ssklower ep->ns_ep_errp.ns_err_num = htons(type); 8921483Ssklower ep->ns_ep_errp.ns_err_param = htons(param); 9021483Ssklower bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 9121483Ssklower nip = &ep->ns_ep_idp; 9221483Ssklower nip->idp_len = sizeof(*ep); 9321483Ssklower nip->idp_len = htons((u_short)nip->idp_len); 9421483Ssklower nip->idp_pt = NSPROTO_ERROR; 9521483Ssklower nip->idp_tc = 0; 9621483Ssklower nip->idp_dna = oip->idp_sna; 9721483Ssklower nip->idp_sna = oip->idp_dna; 9821483Ssklower if (idpcksum) { 9921483Ssklower nip->idp_sum = 0; 10021483Ssklower nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 10121483Ssklower } else 10221483Ssklower nip->idp_sum = 0xffff; 10321483Ssklower ns_output(dtom(nip), (struct route *)0, 0); 10421483Ssklower 10521483Ssklower free: 10621483Ssklower m_freem(dtom(oip)); 10721483Ssklower } 10821483Ssklower 10921483Ssklower static struct sockproto ns_errroto = { AF_NS, NSPROTO_ERROR }; 11021483Ssklower static struct sockaddr_ns ns_errsrc = { AF_NS }; 11121483Ssklower static struct sockaddr_ns ns_errdst = { AF_NS }; 11221483Ssklower 11321483Ssklower ns_printhost(p) 11421483Ssklower register struct ns_addr *p; 11521483Ssklower { 11621483Ssklower 11721483Ssklower printf("<net:%x%x,host:%x%x%x,port:%x>", 11821483Ssklower p->x_net.s_net[0], 11921483Ssklower p->x_net.s_net[1], 12021483Ssklower p->x_host.s_host[0], 12121483Ssklower p->x_host.s_host[1], 12221483Ssklower p->x_host.s_host[2], 12321483Ssklower p->x_port); 12421483Ssklower 12521483Ssklower } 12621483Ssklower 12721483Ssklower /* 12821483Ssklower * Process a received NS_ERR message. 12921483Ssklower */ 13021483Ssklower ns_err_input(m) 13121483Ssklower struct mbuf *m; 13221483Ssklower { 13321483Ssklower register struct ns_errp *ep; 13421483Ssklower register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 13521483Ssklower register int i; 13621483Ssklower int type, code, param; 13721483Ssklower extern struct ns_addr if_makeaddr(); 13821483Ssklower 13921483Ssklower /* 14021483Ssklower * Locate ns_err structure in mbuf, and check 14121483Ssklower * that not corrupted and of at least minimum length. 14221483Ssklower */ 14321483Ssklower #ifdef NS_ERRPRINTFS 14421483Ssklower if (ns_errprintfs) { 14521483Ssklower printf("ns_err_input from "); 14621483Ssklower ns_printhost(&epidp->ns_ep_idp.idp_sna); 14721483Ssklower printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 14821483Ssklower } 14921483Ssklower #endif 15021483Ssklower i = sizeof (struct ns_epidp); 15121483Ssklower if ((m->m_off > MMAXOFF || m->m_len < i) && 15221483Ssklower (m = m_pullup(m, i)) == 0) { 15321483Ssklower ns_errstat.ns_es_tooshort++; 15421483Ssklower return; 15521483Ssklower } 15621483Ssklower ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 15721483Ssklower type = ntohs(ep->ns_err_num); 15821483Ssklower param = ntohs(ep->ns_err_param); 15921483Ssklower 16021483Ssklower #ifdef NS_ERRPRINTFS 16121483Ssklower /* 16221483Ssklower * Message type specific processing. 16321483Ssklower */ 16421483Ssklower if (ns_errprintfs) 16521483Ssklower printf("ns_err_input, type %d param %d\n", type, param); 16621483Ssklower #endif 16721483Ssklower if (type >= NS_ERR_TOO_BIG) { 16821483Ssklower goto badcode; 16921483Ssklower } 17021483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 17121483Ssklower switch (type) { 17221483Ssklower 17321483Ssklower case NS_ERR_UNREACH_HOST: 17421483Ssklower code = PRC_UNREACH_NET; 17521483Ssklower goto deliver; 17621483Ssklower 17721483Ssklower case NS_ERR_TOO_OLD: 17821483Ssklower code = PRC_TIMXCEED_INTRANS; 17921483Ssklower goto deliver; 18021483Ssklower 18121483Ssklower case NS_ERR_TOO_BIG: 18221483Ssklower code = PRC_MSGSIZE; 18321483Ssklower goto deliver; 18421483Ssklower 18521483Ssklower case NS_ERR_FULLUP: 18621483Ssklower code = PRC_QUENCH; 18721483Ssklower goto deliver; 18821483Ssklower 18921483Ssklower case NS_ERR_NOSOCK: 19021483Ssklower code = PRC_UNREACH_PORT; 19121483Ssklower goto deliver; 19221483Ssklower 19321483Ssklower case NS_ERR_UNSPEC_T: 19421483Ssklower case NS_ERR_BADSUM_T: 19521483Ssklower case NS_ERR_BADSUM: 19621483Ssklower case NS_ERR_UNSPEC: 19721483Ssklower code = PRC_PARAMPROB; 19821483Ssklower goto deliver; 19921483Ssklower 20021483Ssklower deliver: 20121483Ssklower /* 20221483Ssklower * Problem with datagram; advise higher level routines. 20321483Ssklower */ 20421483Ssklower #ifdef NS_ERRPRINTFS 20521483Ssklower if (ns_errprintfs) 20621483Ssklower printf("deliver to protocol %d\n", 20721483Ssklower ep->ns_err_idp.idp_pt); 20821483Ssklower #endif 20921483Ssklower switch(ep->ns_err_idp.idp_pt) { 21021483Ssklower case NSPROTO_SPP: 21121483Ssklower spp_ctlinput(code, (caddr_t)ep); 21221483Ssklower break; 21321483Ssklower 21421483Ssklower default: 21521483Ssklower idp_ctlinput(code, (caddr_t)ep); 21621483Ssklower } 21721483Ssklower 21821483Ssklower goto free; 21921483Ssklower 22021483Ssklower default: 22121483Ssklower badcode: 22221483Ssklower ns_errstat.ns_es_badcode++; 22321483Ssklower goto free; 22421483Ssklower 22521483Ssklower } 22621483Ssklower free: 22721483Ssklower m_freem(m); 22821483Ssklower } 22921746Ssklower 23021483Ssklower u_long 23121483Ssklower nstime() 23221483Ssklower { 23321483Ssklower int s = spl6(); 23421483Ssklower u_long t; 23521483Ssklower 23621483Ssklower t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 23721483Ssklower splx(s); 23821483Ssklower return (htonl(t)); 23921483Ssklower } 24021746Ssklower 24121746Ssklower ns_echo(idp) 24221746Ssklower register struct idp *idp; 24321746Ssklower { 24421746Ssklower struct mbuf *m = dtom(idp); 24521746Ssklower register struct echo { 24621746Ssklower struct idp ec_idp; 24721746Ssklower u_short ec_op; /* Operation, 1 = request, 2 = reply */ 24821746Ssklower } *ec = (struct echo *)idp; 24921746Ssklower struct ns_addr temp; 25021746Ssklower 25121746Ssklower if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 25221746Ssklower if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 25321746Ssklower 25421746Ssklower ec->ec_op = htons(2); 25521746Ssklower 25621746Ssklower temp = idp->idp_dna; 25721746Ssklower idp->idp_dna = idp->idp_sna; 25821746Ssklower idp->idp_sna = temp; 25921746Ssklower 26021746Ssklower if (idp->idp_sum != 0xffff) { 26121746Ssklower idp->idp_sum = 0; 26221746Ssklower idp->idp_sum = ns_cksum(m, (((ntohs(idp->idp_len) - 1)|1)+1)); 26321746Ssklower } 26421746Ssklower (void) ns_output(m, 0, NS_FORWARDING); 26521746Ssklower return(0); 26621746Ssklower } 267