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