1: /*
   2:  * Copyright (c) 1984, 1985, 1986 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_input.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "param.h"
  10: #include "systm.h"
  11: #include "mbuf.h"
  12: #include "domain.h"
  13: #include "protosw.h"
  14: #include "socket.h"
  15: #include "socketvar.h"
  16: #include "errno.h"
  17: #include "time.h"
  18: #include "kernel.h"
  19: 
  20: #include "../net/if.h"
  21: #include "../net/route.h"
  22: #include "../net/raw_cb.h"
  23: 
  24: #include "ns.h"
  25: #include "ns_if.h"
  26: #include "ns_pcb.h"
  27: #include "idp.h"
  28: #include "idp_var.h"
  29: #include "ns_error.h"
  30: 
  31: /*
  32:  * NS initialization.
  33:  */
  34: union ns_host   ns_thishost;
  35: union ns_host   ns_zerohost;
  36: union ns_host   ns_broadhost;
  37: union ns_net    ns_zeronet;
  38: union ns_net    ns_broadnet;
  39: 
  40: static u_short allones[] = {-1, -1, -1};
  41: 
  42: struct nspcb nspcb;
  43: struct nspcb nsrawpcb;
  44: 
  45: struct ifqueue  nsintrq;
  46: int nsqmaxlen = IFQ_MAXLEN;
  47: 
  48: int idpcksum = 1;
  49: long    ns_pexseq;
  50: 
  51: ns_init()
  52: {
  53:     extern struct timeval time;
  54: 
  55:     ns_broadhost = * (union ns_host *) allones;
  56:     ns_broadnet = * (union ns_net *) allones;
  57:     nspcb.nsp_next = nspcb.nsp_prev = &nspcb;
  58:     nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb;
  59:     nsintrq.ifq_maxlen = nsqmaxlen;
  60:     ns_pexseq = time.tv_usec;
  61: }
  62: 
  63: /*
  64:  * Idp input routine.  Pass to next level.
  65:  */
  66: int nsintr_getpck = 0;
  67: int nsintr_swtch = 0;
  68: nsintr()
  69: {
  70:     register struct idp *idp;
  71:     register struct mbuf *m;
  72:     register struct nspcb *nsp;
  73:     struct ifnet *ifp;
  74:     struct mbuf *m0;
  75:     register int i;
  76:     int len, s, error;
  77:     char oddpacketp;
  78: 
  79: next:
  80:     /*
  81: 	 * Get next datagram off input queue and get IDP header
  82: 	 * in first mbuf.
  83: 	 */
  84:     s = splimp();
  85:     IF_DEQUEUEIF(&nsintrq, m, ifp);
  86:     splx(s);
  87:     nsintr_getpck++;
  88:     if (m == 0)
  89:         return;
  90:     if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct idp)) &&
  91:         (m = m_pullup(m, sizeof (struct idp))) == 0) {
  92:         idpstat.idps_toosmall++;
  93:         goto next;
  94:     }
  95: 
  96:     /*
  97: 	 * Give any raw listeners a crack at the packet
  98: 	 */
  99:     for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
 100:         struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
 101:         if (m1) idp_input(m1, nsp, ifp);
 102:     }
 103: 
 104:     idp = mtod(m, struct idp *);
 105:     len = ntohs(idp->idp_len);
 106:     if (oddpacketp = len & 1) {
 107:         len++;      /* If this packet is of odd length,
 108: 				   preserve garbage byte for checksum */
 109:     }
 110: 
 111:     /*
 112: 	 * Check that the amount of data in the buffers
 113: 	 * is as at least much as the IDP header would have us expect.
 114: 	 * Trim mbufs if longer than we expect.
 115: 	 * Drop packet if shorter than we expect.
 116: 	 */
 117:     i = -len;
 118:     m0 = m;
 119:     for (;;) {
 120:         i += m->m_len;
 121:         if (m->m_next == 0)
 122:             break;
 123:         m = m->m_next;
 124:     }
 125:     if (i != 0) {
 126:         if (i < 0) {
 127:             idpstat.idps_tooshort++;
 128:             m = m0;
 129:             goto bad;
 130:         }
 131:         if (i <= m->m_len)
 132:             m->m_len -= i;
 133:         else
 134:             m_adj(m0, -i);
 135:     }
 136:     m = m0;
 137:     if (idpcksum && ((i = idp->idp_sum)!=0xffff)) {
 138:         idp->idp_sum = 0;
 139:         if (i != (idp->idp_sum = ns_cksum(m,len))) {
 140:             idpstat.idps_badsum++;
 141:             idp->idp_sum = i;
 142:             if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host))
 143:                 error = NS_ERR_BADSUM;
 144:             else
 145:                 error = NS_ERR_BADSUM_T;
 146:             ns_error(m, error, 0);
 147:             goto next;
 148:         }
 149:     }
 150:     /*
 151: 	 * Is this a directed broadcast?
 152: 	 */
 153:     if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) {
 154:         if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) &&
 155:             (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) &&
 156:             (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) &&
 157:             (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) {
 158:             /*
 159: 			 * Look to see if I need to eat this packet.
 160: 			 * Algorithm is to forward all young packets
 161: 			 * and prematurely age any packets which will
 162: 			 * by physically broadcasted.
 163: 			 * Any very old packets eaten without forwarding
 164: 			 * would die anyway.
 165: 			 *
 166: 			 * Suggestion of Bill Nesheim, Cornell U.
 167: 			 */
 168:             if (idp->idp_tc < NS_MAXHOPS) {
 169:                 idp_forward(idp);
 170:                 goto next;
 171:             }
 172:         }
 173:     /*
 174: 	 * Is this our packet? If not, forward.
 175: 	 */
 176:     } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) {
 177:         idp_forward(idp);
 178:         goto next;
 179:     }
 180:     /*
 181: 	 * Locate pcb for datagram.
 182: 	 */
 183:     nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD);
 184:     /*
 185: 	 * Switch out to protocol's input routine.
 186: 	 */
 187:     nsintr_swtch++;
 188:     if (nsp) {
 189:         if (oddpacketp) {
 190:             m_adj(m0, -1);
 191:         }
 192:         if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0)
 193:             switch (idp->idp_pt) {
 194: 
 195:                 case NSPROTO_SPP:
 196:                     spp_input(m, nsp, ifp);
 197:                     goto next;
 198: 
 199:                 case NSPROTO_ERROR:
 200:                     ns_err_input(m);
 201:                     goto next;
 202:             }
 203:         idp_input(m, nsp, ifp);
 204:     } else {
 205:         ns_error(m, NS_ERR_NOSOCK, 0);
 206:     }
 207:     goto next;
 208: 
 209: bad:
 210:     m_freem(m);
 211:     goto next;
 212: }
 213: 
 214: u_char nsctlerrmap[PRC_NCMDS] = {
 215:     ECONNABORTED,   ECONNABORTED,   0,      0,
 216:     0,      0,      EHOSTDOWN,  EHOSTUNREACH,
 217:     ENETUNREACH,    EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
 218:     EMSGSIZE,   0,      0,      0,
 219:     0,      0,      0,      0
 220: };
 221: 
 222: idp_donosocks = 1;
 223: 
 224: idp_ctlinput(cmd, arg)
 225:     int cmd;
 226:     caddr_t arg;
 227: {
 228:     struct ns_addr *ns;
 229:     struct nspcb *nsp;
 230:     struct ns_errp *errp;
 231:     int idp_abort();
 232:     extern struct nspcb *idp_drop();
 233:     int type;
 234: 
 235:     if (cmd < 0 || cmd > PRC_NCMDS)
 236:         return;
 237:     if (nsctlerrmap[cmd] == 0)
 238:         return;     /* XXX */
 239:     type = NS_ERR_UNREACH_HOST;
 240:     switch (cmd) {
 241:         struct sockaddr_ns *sns;
 242: 
 243:     case PRC_IFDOWN:
 244:     case PRC_HOSTDEAD:
 245:     case PRC_HOSTUNREACH:
 246:         sns = (struct sockaddr_ns *)arg;
 247:         if (sns->sns_family != AF_INET)
 248:             return;
 249:         ns = &sns->sns_addr;
 250:         break;
 251: 
 252:     default:
 253:         errp = (struct ns_errp *)arg;
 254:         ns = &errp->ns_err_idp.idp_dna;
 255:         type = errp->ns_err_num;
 256:         type = ntohs((u_short)type);
 257:     }
 258:     switch (type) {
 259: 
 260:     case NS_ERR_UNREACH_HOST:
 261:         ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0);
 262:         break;
 263: 
 264:     case NS_ERR_NOSOCK:
 265:         nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port,
 266:             NS_WILDCARD);
 267:         if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr))
 268:             (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
 269:     }
 270: }
 271: 
 272: int idpprintfs = 0;
 273: int idpforwarding = 1;
 274: /*
 275:  * Forward a packet.  If some error occurs return the sender
 276:  * an error packet.  Note we can't always generate a meaningful
 277:  * error message because the NS errors don't have a large enough repetoire
 278:  * of codes and types.
 279:  */
 280: struct route idp_droute;
 281: struct route idp_sroute;
 282: 
 283: idp_forward(idp)
 284:     register struct idp *idp;
 285: {
 286:     register int error, type, code;
 287:     struct mbuf *mcopy = NULL;
 288:     int agedelta = 1;
 289:     int flags = NS_FORWARDING;
 290:     int ok_there = 0;
 291:     int ok_back = 0;
 292: 
 293:     if (idpprintfs) {
 294:         printf("forward: src ");
 295:         ns_printhost(&idp->idp_sna);
 296:         printf(", dst ");
 297:         ns_printhost(&idp->idp_dna);
 298:         printf("hop count %d\n", idp->idp_tc);
 299:     }
 300:     if (idpforwarding == 0) {
 301:         /* can't tell difference between net and host */
 302:         type = NS_ERR_UNREACH_HOST, code = 0;
 303:         goto senderror;
 304:     }
 305:     idp->idp_tc++;
 306:     if (idp->idp_tc > NS_MAXHOPS) {
 307:         type = NS_ERR_TOO_OLD, code = 0;
 308:         goto senderror;
 309:     }
 310:     /*
 311: 	 * Save at most 42 bytes of the packet in case
 312: 	 * we need to generate an NS error message to the src.
 313: 	 */
 314:     mcopy = m_copy(dtom(idp), 0, imin((int)ntohs(idp->idp_len), 42));
 315: 
 316:     if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
 317:         type = NS_ERR_UNREACH_HOST, code = 0;
 318:         goto senderror;
 319:     }
 320:     /*
 321: 	 * Here we think about  forwarding  broadcast packets,
 322: 	 * so we try to insure that it doesn't go back out
 323: 	 * on the interface it came in on.  Also, if we
 324: 	 * are going to physically broadcast this, let us
 325: 	 * age the packet so we can eat it safely the second time around.
 326: 	 */
 327:     if (idp->idp_dna.x_host.c_host[0] & 0x1) {
 328:         struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
 329:         struct ifnet *ifp;
 330:         if (ia) {
 331:             /* I'm gonna hafta eat this packet */
 332:             agedelta += NS_MAXHOPS - idp->idp_tc;
 333:             idp->idp_tc = NS_MAXHOPS;
 334:         }
 335:         if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) {
 336:             /* error = ENETUNREACH; He'll never get it! */
 337:             m_freem(dtom(idp));
 338:             goto cleanup;
 339:         }
 340:         if (idp_droute.ro_rt &&
 341:             (ifp=idp_droute.ro_rt->rt_ifp) &&
 342:             idp_sroute.ro_rt &&
 343:             (ifp!=idp_sroute.ro_rt->rt_ifp)) {
 344:             flags |= NS_ALLOWBROADCAST;
 345:         } else {
 346:             type = NS_ERR_UNREACH_HOST, code = 0;
 347:             goto senderror;
 348:         }
 349:     }
 350:     /* need to adjust checksum */
 351:     if (idp->idp_sum!=0xffff) {
 352:         union bytes {
 353:             u_char c[4];
 354:             u_short s[2];
 355:             long l;
 356:         } x;
 357:         register int shift;
 358:         x.l = 0; x.c[0] = agedelta;
 359:         shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf;
 360:         x.l = idp->idp_sum + (x.l << shift);
 361:         x.l = x.s[0] + x.s[1];
 362:         x.l = x.s[0] + x.s[1];
 363:         if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l;
 364:     }
 365:     if ((error = ns_output(dtom(idp), &idp_droute, flags)) &&
 366:         (mcopy!=NULL)) {
 367:         idp = mtod(mcopy, struct idp *);
 368:         type = NS_ERR_UNSPEC_T, code = 0;
 369:         switch (error) {
 370: 
 371:         case ENETUNREACH:
 372:         case EHOSTDOWN:
 373:         case EHOSTUNREACH:
 374:         case ENETDOWN:
 375:         case EPERM:
 376:             type = NS_ERR_UNREACH_HOST;
 377:             break;
 378: 
 379:         case EMSGSIZE:
 380:             type = NS_ERR_TOO_BIG;
 381:             code = 576; /* too hard to figure out mtu here */
 382:             break;
 383: 
 384:         case ENOBUFS:
 385:             type = NS_ERR_UNSPEC_T;
 386:             break;
 387:         }
 388:         mcopy = NULL;
 389:     senderror:
 390:         ns_error(dtom(idp), type, code);
 391:     }
 392: cleanup:
 393:     if (ok_there)
 394:         idp_undo_route(&idp_droute);
 395:     if (ok_back)
 396:         idp_undo_route(&idp_sroute);
 397:     if (mcopy != NULL)
 398:         m_freem(mcopy);
 399: }
 400: 
 401: idp_do_route(src, ro)
 402: struct ns_addr *src;
 403: struct route *ro;
 404: {
 405: 
 406:     struct sockaddr_ns *dst;
 407: 
 408:     bzero((caddr_t)ro, sizeof (*ro));
 409:     dst = (struct sockaddr_ns *)&ro->ro_dst;
 410: 
 411:     dst->sns_family = AF_NS;
 412:     dst->sns_addr = *src;
 413:     dst->sns_addr.x_port = 0;
 414:     rtalloc(ro);
 415:     if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) {
 416:         return (0);
 417:     }
 418:     ro->ro_rt->rt_use++;
 419:     return (1);
 420: }
 421: 
 422: idp_undo_route(ro)
 423: register struct route *ro;
 424: {
 425:     if (ro->ro_rt) {RTFREE(ro->ro_rt);}
 426: }
 427: static union ns_net
 428: ns_zeronet;
 429: 
 430: ns_watch_output(m, ifp)
 431: struct mbuf *m;
 432: struct ifnet *ifp;
 433: {
 434:     register struct nspcb *nsp;
 435:     register struct ifaddr *ia;
 436:     /*
 437: 	 * Give any raw listeners a crack at the packet
 438: 	 */
 439:     for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
 440:         struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
 441:         if (m0) {
 442:             struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
 443: 
 444:             if(m1 == NULL)
 445:                 m_freem(m0);
 446:             else {
 447:                 register struct idp *idp;
 448: 
 449:                 m1->m_off = MMINOFF;
 450:                 m1->m_len = sizeof (*idp);
 451:                 m1->m_next = m0;
 452:                 idp = mtod(m1, struct idp *);
 453:                 idp->idp_sna.x_net = ns_zeronet;
 454:                 idp->idp_sna.x_host = ns_thishost;
 455:                 if (ifp && (ifp->if_flags & IFF_POINTOPOINT))
 456:                     for(ia = ifp->if_addrlist; ia;
 457:                             ia = ia->ifa_next) {
 458:                     if (ia->ifa_addr.sa_family==AF_NS) {
 459:                         idp->idp_sna =
 460:                         satons_addr(ia->ifa_dstaddr);
 461:                         break;
 462:                     }
 463:                     }
 464:                 idp->idp_len = 0xffff;
 465:                 idp_input(m1, nsp, ifp);
 466:             }
 467:         }
 468:     }
 469: }

Defined functions

idp_ctlinput defined in line 224; used 4 times
idp_do_route defined in line 401; used 2 times
idp_forward defined in line 283; used 2 times
idp_undo_route defined in line 422; used 2 times
ns_init defined in line 51; used 2 times
ns_watch_output defined in line 430; used 2 times
nsintr defined in line 68; used 2 times

Defined variables

allones defined in line 40; used 2 times
idp_droute defined in line 280; used 5 times
idp_sroute defined in line 281; used 4 times
idpcksum defined in line 48; used 1 times
idpforwarding defined in line 273; used 1 times
idpprintfs defined in line 272; used 1 times
ns_broadhost defined in line 36; used 2 times
ns_broadnet defined in line 38; used 2 times
ns_pexseq defined in line 49; used 1 times
  • in line 60
ns_thishost defined in line 34; used 3 times
ns_zerohost defined in line 35; never used
ns_zeronet defined in line 428; used 3 times
nsctlerrmap defined in line 214; used 3 times
nsintr_getpck defined in line 66; used 1 times
  • in line 87
nsintr_swtch defined in line 67; used 1 times
nsintrq defined in line 45; used 2 times
nspcb defined in line 42; used 3 times
  • in line 57(3)
nsqmaxlen defined in line 46; used 1 times
  • in line 59
nsrawpcb defined in line 43; used 7 times

Defined union's

bytes defined in line 352; never used
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2000
Valid CSS Valid XHTML 1.0 Strict