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.4 (Berkeley) 07/19/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 /* 62 * Don't Generate error packets in response to multicasts. 63 */ 64 if (oip->idp_dna.x_host.c_host[0] & 1) 65 goto free; 66 67 ns_errstat.ns_es_error++; 68 /* 69 * Make sure that the old IDP packet had 30 bytes of data to return; 70 * if not, don't bother. Also don't EVER error if the old 71 * packet protocol was NS_ERR. 72 */ 73 if (oip->idp_len < sizeof(struct idp)) { 74 ns_errstat.ns_es_oldshort++; 75 goto free; 76 } 77 if (oip->idp_pt == NSPROTO_ERROR) { 78 ns_errstat.ns_es_oldns_err++; 79 goto free; 80 } 81 82 /* 83 * First, formulate ns_err message 84 */ 85 m = m_get(M_DONTWAIT, MT_HEADER); 86 if (m == NULL) 87 goto free; 88 m->m_len = sizeof(*ep); 89 m->m_off = MMAXOFF - m->m_len; 90 ep = mtod(m, struct ns_epidp *); 91 if ((u_int)type > NS_ERR_TOO_BIG) 92 panic("ns_err_error"); 93 ns_errstat.ns_es_outhist[ns_err_x(type)]++; 94 ep->ns_ep_errp.ns_err_num = htons(type); 95 ep->ns_ep_errp.ns_err_param = htons(param); 96 bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42); 97 nip = &ep->ns_ep_idp; 98 nip->idp_len = sizeof(*ep); 99 nip->idp_len = htons((u_short)nip->idp_len); 100 nip->idp_pt = NSPROTO_ERROR; 101 nip->idp_tc = 0; 102 nip->idp_dna = oip->idp_sna; 103 nip->idp_sna = oip->idp_dna; 104 if (idpcksum) { 105 nip->idp_sum = 0; 106 nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep)); 107 } else 108 nip->idp_sum = 0xffff; 109 ns_output(dtom(nip), (struct route *)0, 0); 110 111 free: 112 m_freem(dtom(oip)); 113 } 114 115 static struct sockproto ns_errroto = { AF_NS, NSPROTO_ERROR }; 116 static struct sockaddr_ns ns_errsrc = { AF_NS }; 117 static struct sockaddr_ns ns_errdst = { AF_NS }; 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