123206Smckusick /* 223206Smckusick * Copyright (c) 1982 Regents of the University of California. 323206Smckusick * All rights reserved. The Berkeley software License Agreement 423206Smckusick * specifies the terms and conditions for redistribution. 523206Smckusick * 6*23980Ssklower * @(#)ns_error.c 6.4 (Berkeley) 07/19/85 723206Smckusick */ 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 61*23980Ssklower /* 62*23980Ssklower * Don't Generate error packets in response to multicasts. 63*23980Ssklower */ 64*23980Ssklower if (oip->idp_dna.x_host.c_host[0] & 1) 65*23980Ssklower goto free; 66*23980Ssklower 6721483Ssklower ns_errstat.ns_es_error++; 6821483Ssklower /* 6921483Ssklower * Make sure that the old IDP packet had 30 bytes of data to return; 7021483Ssklower * if not, don't bother. Also don't EVER error if the old 7121483Ssklower * packet protocol was NS_ERR. 7221483Ssklower */ 7321483Ssklower if (oip->idp_len < sizeof(struct idp)) { 7421483Ssklower ns_errstat.ns_es_oldshort++; 7521483Ssklower goto free; 7621483Ssklower } 7721483Ssklower if (oip->idp_pt == NSPROTO_ERROR) { 7821483Ssklower ns_errstat.ns_es_oldns_err++; 7921483Ssklower goto free; 8021483Ssklower } 8121483Ssklower 8221483Ssklower /* 8321483Ssklower * First, formulate ns_err message 8421483Ssklower */ 8521483Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 8621483Ssklower if (m == NULL) 8721483Ssklower goto free; 8821483Ssklower m->m_len = sizeof(*ep); 8921483Ssklower m->m_off = MMAXOFF - m->m_len; 9021483Ssklower ep = mtod(m, struct ns_epidp *); 9121483Ssklower if ((u_int)type > NS_ERR_TOO_BIG) 9221483Ssklower panic("ns_err_error"); 9321483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 9421483Ssklower ep->ns_ep_errp.ns_err_num = htons(type); 9521483Ssklower ep->ns_ep_errp.ns_err_param = htons(param); 9621483Ssklower bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 9721483Ssklower nip = &ep->ns_ep_idp; 9821483Ssklower nip->idp_len = sizeof(*ep); 9921483Ssklower nip->idp_len = htons((u_short)nip->idp_len); 10021483Ssklower nip->idp_pt = NSPROTO_ERROR; 10121483Ssklower nip->idp_tc = 0; 10221483Ssklower nip->idp_dna = oip->idp_sna; 10321483Ssklower nip->idp_sna = oip->idp_dna; 10421483Ssklower if (idpcksum) { 10521483Ssklower nip->idp_sum = 0; 10621483Ssklower nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 10721483Ssklower } else 10821483Ssklower nip->idp_sum = 0xffff; 10921483Ssklower ns_output(dtom(nip), (struct route *)0, 0); 11021483Ssklower 11121483Ssklower free: 11221483Ssklower m_freem(dtom(oip)); 11321483Ssklower } 11421483Ssklower 11521483Ssklower static struct sockproto ns_errroto = { AF_NS, NSPROTO_ERROR }; 11621483Ssklower static struct sockaddr_ns ns_errsrc = { AF_NS }; 11721483Ssklower static struct sockaddr_ns ns_errdst = { AF_NS }; 11821483Ssklower 11921483Ssklower ns_printhost(p) 12021483Ssklower register struct ns_addr *p; 12121483Ssklower { 12221483Ssklower 12321483Ssklower printf("<net:%x%x,host:%x%x%x,port:%x>", 12421483Ssklower p->x_net.s_net[0], 12521483Ssklower p->x_net.s_net[1], 12621483Ssklower p->x_host.s_host[0], 12721483Ssklower p->x_host.s_host[1], 12821483Ssklower p->x_host.s_host[2], 12921483Ssklower p->x_port); 13021483Ssklower 13121483Ssklower } 13221483Ssklower 13321483Ssklower /* 13421483Ssklower * Process a received NS_ERR message. 13521483Ssklower */ 13621483Ssklower ns_err_input(m) 13721483Ssklower struct mbuf *m; 13821483Ssklower { 13921483Ssklower register struct ns_errp *ep; 14021483Ssklower register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 14121483Ssklower register int i; 14221483Ssklower int type, code, param; 14321483Ssklower extern struct ns_addr if_makeaddr(); 14421483Ssklower 14521483Ssklower /* 14621483Ssklower * Locate ns_err structure in mbuf, and check 14721483Ssklower * that not corrupted and of at least minimum length. 14821483Ssklower */ 14921483Ssklower #ifdef NS_ERRPRINTFS 15021483Ssklower if (ns_errprintfs) { 15121483Ssklower printf("ns_err_input from "); 15221483Ssklower ns_printhost(&epidp->ns_ep_idp.idp_sna); 15321483Ssklower printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 15421483Ssklower } 15521483Ssklower #endif 15621483Ssklower i = sizeof (struct ns_epidp); 15721483Ssklower if ((m->m_off > MMAXOFF || m->m_len < i) && 15821483Ssklower (m = m_pullup(m, i)) == 0) { 15921483Ssklower ns_errstat.ns_es_tooshort++; 16021483Ssklower return; 16121483Ssklower } 16221483Ssklower ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 16321483Ssklower type = ntohs(ep->ns_err_num); 16421483Ssklower param = ntohs(ep->ns_err_param); 165*23980Ssklower ns_errstat.ns_es_inhist[ns_err_x(type)]++; 16621483Ssklower 16721483Ssklower #ifdef NS_ERRPRINTFS 16821483Ssklower /* 16921483Ssklower * Message type specific processing. 17021483Ssklower */ 17121483Ssklower if (ns_errprintfs) 17221483Ssklower printf("ns_err_input, type %d param %d\n", type, param); 17321483Ssklower #endif 17421483Ssklower if (type >= NS_ERR_TOO_BIG) { 17521483Ssklower goto badcode; 17621483Ssklower } 17721483Ssklower ns_errstat.ns_es_outhist[ns_err_x(type)]++; 17821483Ssklower switch (type) { 17921483Ssklower 18021483Ssklower case NS_ERR_UNREACH_HOST: 18121483Ssklower code = PRC_UNREACH_NET; 18221483Ssklower goto deliver; 18321483Ssklower 18421483Ssklower case NS_ERR_TOO_OLD: 18521483Ssklower code = PRC_TIMXCEED_INTRANS; 18621483Ssklower goto deliver; 18721483Ssklower 18821483Ssklower case NS_ERR_TOO_BIG: 18921483Ssklower code = PRC_MSGSIZE; 19021483Ssklower goto deliver; 19121483Ssklower 19221483Ssklower case NS_ERR_FULLUP: 19321483Ssklower code = PRC_QUENCH; 19421483Ssklower goto deliver; 19521483Ssklower 19621483Ssklower case NS_ERR_NOSOCK: 19721483Ssklower code = PRC_UNREACH_PORT; 19821483Ssklower goto deliver; 19921483Ssklower 20021483Ssklower case NS_ERR_UNSPEC_T: 20121483Ssklower case NS_ERR_BADSUM_T: 20221483Ssklower case NS_ERR_BADSUM: 20321483Ssklower case NS_ERR_UNSPEC: 20421483Ssklower code = PRC_PARAMPROB; 20521483Ssklower goto deliver; 20621483Ssklower 20721483Ssklower deliver: 20821483Ssklower /* 20921483Ssklower * Problem with datagram; advise higher level routines. 21021483Ssklower */ 21121483Ssklower #ifdef NS_ERRPRINTFS 21221483Ssklower if (ns_errprintfs) 21321483Ssklower printf("deliver to protocol %d\n", 21421483Ssklower ep->ns_err_idp.idp_pt); 21521483Ssklower #endif 21621483Ssklower switch(ep->ns_err_idp.idp_pt) { 21721483Ssklower case NSPROTO_SPP: 21821483Ssklower spp_ctlinput(code, (caddr_t)ep); 21921483Ssklower break; 22021483Ssklower 22121483Ssklower default: 22221483Ssklower idp_ctlinput(code, (caddr_t)ep); 22321483Ssklower } 22421483Ssklower 22521483Ssklower goto free; 22621483Ssklower 22721483Ssklower default: 22821483Ssklower badcode: 22921483Ssklower ns_errstat.ns_es_badcode++; 23021483Ssklower goto free; 23121483Ssklower 23221483Ssklower } 23321483Ssklower free: 23421483Ssklower m_freem(m); 23521483Ssklower } 23621746Ssklower 23721483Ssklower u_long 23821483Ssklower nstime() 23921483Ssklower { 24021483Ssklower int s = spl6(); 24121483Ssklower u_long t; 24221483Ssklower 24321483Ssklower t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 24421483Ssklower splx(s); 24521483Ssklower return (htonl(t)); 24621483Ssklower } 24721746Ssklower 24821746Ssklower ns_echo(idp) 24921746Ssklower register struct idp *idp; 25021746Ssklower { 25121746Ssklower struct mbuf *m = dtom(idp); 25221746Ssklower register struct echo { 25321746Ssklower struct idp ec_idp; 25421746Ssklower u_short ec_op; /* Operation, 1 = request, 2 = reply */ 25521746Ssklower } *ec = (struct echo *)idp; 25621746Ssklower struct ns_addr temp; 25721746Ssklower 25821746Ssklower if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 25921746Ssklower if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 26021746Ssklower 26121746Ssklower ec->ec_op = htons(2); 26221746Ssklower 26321746Ssklower temp = idp->idp_dna; 26421746Ssklower idp->idp_dna = idp->idp_sna; 26521746Ssklower idp->idp_sna = temp; 26621746Ssklower 26721746Ssklower if (idp->idp_sum != 0xffff) { 26821746Ssklower idp->idp_sum = 0; 26921746Ssklower idp->idp_sum = ns_cksum(m, (((ntohs(idp->idp_len) - 1)|1)+1)); 27021746Ssklower } 27121746Ssklower (void) ns_output(m, 0, NS_FORWARDING); 27221746Ssklower return(0); 27321746Ssklower } 274