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