1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)ns_error.c 6.3 (Berkeley) 06/08/85 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "mbuf.h" 12 #include "protosw.h" 13 #include "socket.h" 14 #include "time.h" 15 #include "kernel.h" 16 17 #include "../net/route.h" 18 19 #include "ns.h" 20 #include "ns_pcb.h" 21 #include "idp.h" 22 #include "ns_error.h" 23 24 #ifdef NS_ERRPRINTFS 25 /* 26 * NS_ERR routines: error generation, receive packet processing, and 27 * routines to turnaround packets back to the originator. 28 */ 29 int ns_errprintfs = 0; 30 #endif 31 32 /* 33 * Generate an error packet of type error 34 * in response to bad packet. 35 */ 36 37 ns_error(om, type, param) 38 struct mbuf *om; 39 int type; 40 { 41 register struct ns_epidp *ep; 42 struct mbuf *m; 43 struct idp *nip; 44 register struct idp *oip = mtod(om, struct idp *); 45 extern int idpcksum; 46 47 /* 48 * If this packet was sent to the echo port, 49 * and nobody was there, just echo it. 50 * (Yes, this is a wart!) 51 */ 52 if (type==NS_ERR_NOSOCK && 53 oip->idp_dna.x_port==htons(2) && 54 (type = ns_echo(oip)==0)) 55 return; 56 57 #ifdef NS_ERRPRINTFS 58 if (ns_errprintfs) 59 printf("ns_err_error(%x, %d, %d)\n", oip, type, param); 60 #endif 61 ns_errstat.ns_es_error++; 62 /* 63 * Make sure that the old IDP packet had 30 bytes of data to return; 64 * if not, don't bother. Also don't EVER error if the old 65 * packet protocol was NS_ERR. 66 */ 67 if (oip->idp_len < sizeof(struct idp)) { 68 ns_errstat.ns_es_oldshort++; 69 goto free; 70 } 71 if (oip->idp_pt == NSPROTO_ERROR) { 72 ns_errstat.ns_es_oldns_err++; 73 goto free; 74 } 75 76 /* 77 * First, formulate ns_err message 78 */ 79 m = m_get(M_DONTWAIT, MT_HEADER); 80 if (m == NULL) 81 goto free; 82 m->m_len = sizeof(*ep); 83 m->m_off = MMAXOFF - m->m_len; 84 ep = mtod(m, struct ns_epidp *); 85 if ((u_int)type > NS_ERR_TOO_BIG) 86 panic("ns_err_error"); 87 ns_errstat.ns_es_outhist[ns_err_x(type)]++; 88 ep->ns_ep_errp.ns_err_num = htons(type); 89 ep->ns_ep_errp.ns_err_param = htons(param); 90 bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 91 nip = &ep->ns_ep_idp; 92 nip->idp_len = sizeof(*ep); 93 nip->idp_len = htons((u_short)nip->idp_len); 94 nip->idp_pt = NSPROTO_ERROR; 95 nip->idp_tc = 0; 96 nip->idp_dna = oip->idp_sna; 97 nip->idp_sna = oip->idp_dna; 98 if (idpcksum) { 99 nip->idp_sum = 0; 100 nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 101 } else 102 nip->idp_sum = 0xffff; 103 ns_output(dtom(nip), (struct route *)0, 0); 104 105 free: 106 m_freem(dtom(oip)); 107 } 108 109 static struct sockproto ns_errroto = { AF_NS, NSPROTO_ERROR }; 110 static struct sockaddr_ns ns_errsrc = { AF_NS }; 111 static struct sockaddr_ns ns_errdst = { AF_NS }; 112 113 ns_printhost(p) 114 register struct ns_addr *p; 115 { 116 117 printf("<net:%x%x,host:%x%x%x,port:%x>", 118 p->x_net.s_net[0], 119 p->x_net.s_net[1], 120 p->x_host.s_host[0], 121 p->x_host.s_host[1], 122 p->x_host.s_host[2], 123 p->x_port); 124 125 } 126 127 /* 128 * Process a received NS_ERR message. 129 */ 130 ns_err_input(m) 131 struct mbuf *m; 132 { 133 register struct ns_errp *ep; 134 register struct ns_epidp *epidp = mtod(m, struct ns_epidp *); 135 register int i; 136 int type, code, param; 137 extern struct ns_addr if_makeaddr(); 138 139 /* 140 * Locate ns_err structure in mbuf, and check 141 * that not corrupted and of at least minimum length. 142 */ 143 #ifdef NS_ERRPRINTFS 144 if (ns_errprintfs) { 145 printf("ns_err_input from "); 146 ns_printhost(&epidp->ns_ep_idp.idp_sna); 147 printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len)); 148 } 149 #endif 150 i = sizeof (struct ns_epidp); 151 if ((m->m_off > MMAXOFF || m->m_len < i) && 152 (m = m_pullup(m, i)) == 0) { 153 ns_errstat.ns_es_tooshort++; 154 return; 155 } 156 ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp); 157 type = ntohs(ep->ns_err_num); 158 param = ntohs(ep->ns_err_param); 159 160 #ifdef NS_ERRPRINTFS 161 /* 162 * Message type specific processing. 163 */ 164 if (ns_errprintfs) 165 printf("ns_err_input, type %d param %d\n", type, param); 166 #endif 167 if (type >= NS_ERR_TOO_BIG) { 168 goto badcode; 169 } 170 ns_errstat.ns_es_outhist[ns_err_x(type)]++; 171 switch (type) { 172 173 case NS_ERR_UNREACH_HOST: 174 code = PRC_UNREACH_NET; 175 goto deliver; 176 177 case NS_ERR_TOO_OLD: 178 code = PRC_TIMXCEED_INTRANS; 179 goto deliver; 180 181 case NS_ERR_TOO_BIG: 182 code = PRC_MSGSIZE; 183 goto deliver; 184 185 case NS_ERR_FULLUP: 186 code = PRC_QUENCH; 187 goto deliver; 188 189 case NS_ERR_NOSOCK: 190 code = PRC_UNREACH_PORT; 191 goto deliver; 192 193 case NS_ERR_UNSPEC_T: 194 case NS_ERR_BADSUM_T: 195 case NS_ERR_BADSUM: 196 case NS_ERR_UNSPEC: 197 code = PRC_PARAMPROB; 198 goto deliver; 199 200 deliver: 201 /* 202 * Problem with datagram; advise higher level routines. 203 */ 204 #ifdef NS_ERRPRINTFS 205 if (ns_errprintfs) 206 printf("deliver to protocol %d\n", 207 ep->ns_err_idp.idp_pt); 208 #endif 209 switch(ep->ns_err_idp.idp_pt) { 210 case NSPROTO_SPP: 211 spp_ctlinput(code, (caddr_t)ep); 212 break; 213 214 default: 215 idp_ctlinput(code, (caddr_t)ep); 216 } 217 218 goto free; 219 220 default: 221 badcode: 222 ns_errstat.ns_es_badcode++; 223 goto free; 224 225 } 226 free: 227 m_freem(m); 228 } 229 230 u_long 231 nstime() 232 { 233 int s = spl6(); 234 u_long t; 235 236 t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; 237 splx(s); 238 return (htonl(t)); 239 } 240 241 ns_echo(idp) 242 register struct idp *idp; 243 { 244 struct mbuf *m = dtom(idp); 245 register struct echo { 246 struct idp ec_idp; 247 u_short ec_op; /* Operation, 1 = request, 2 = reply */ 248 } *ec = (struct echo *)idp; 249 struct ns_addr temp; 250 251 if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK); 252 if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC); 253 254 ec->ec_op = htons(2); 255 256 temp = idp->idp_dna; 257 idp->idp_dna = idp->idp_sna; 258 idp->idp_sna = temp; 259 260 if (idp->idp_sum != 0xffff) { 261 idp->idp_sum = 0; 262 idp->idp_sum = ns_cksum(m, (((ntohs(idp->idp_len) - 1)|1)+1)); 263 } 264 (void) ns_output(m, 0, NS_FORWARDING); 265 return(0); 266 } 267