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

Defined functions

idp_ctlinput defined in line 231; never used
idp_do_route defined in line 408; used 2 times
idp_forward defined in line 290; used 2 times
idp_undo_route defined in line 429; used 2 times
ns_init defined in line 58; never used
ns_watch_output defined in line 437; never used
nsintr defined in line 75; never used

Defined variables

allones defined in line 47; used 2 times
idp_droute defined in line 287; used 5 times
idp_sroute defined in line 288; used 4 times
idpcksum defined in line 55; used 1 times
idpforwarding defined in line 280; used 1 times
idpprintfs defined in line 279; used 1 times
ns_broadhost defined in line 43; used 2 times
ns_broadnet defined in line 45; used 2 times
ns_pexseq defined in line 56; used 1 times
  • in line 67
ns_thishost defined in line 41; used 3 times
ns_zerohost defined in line 42; never used
ns_zeronet defined in line 435; used 3 times
nsctlerrmap defined in line 221; used 3 times
nsintr_getpck defined in line 73; used 1 times
  • in line 94
nsintr_swtch defined in line 74; used 1 times
nsintrq defined in line 52; used 2 times
nspcb defined in line 49; used 3 times
  • in line 64(3)
nsqmaxlen defined in line 53; used 1 times
  • in line 66
nsrawpcb defined in line 50; used 7 times

Defined union's

bytes defined in line 359; never used
Last modified: 1988-04-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4411
Valid CSS Valid XHTML 1.0 Strict