6 Saved from xnu/bsd/bsd/netat/ddp.c on 4/14/99.
10 /* This routine shrinks the ddp header from long to short,
11 * It also prepends ALAP header and fills up some of the
12 * fields as appropriate.
14 static at_ddp_short_t *ddp_shrink_hdr (mp)
17 register at_ddp_t *ddp;
18 register at_ddp_short_t *ddp_short;
19 register at_llap_hdr_t *llap;
22 if ((newmp = (gbuf_t *)gbuf_copym((gbuf_t *) mp)) == (gbuf_t *)NULL)
23 return ((at_ddp_short_t *)NULL);
27 ddp = (at_ddp_t *)gbuf_rptr(mp);
28 gbuf_rinc(mp,((DDP_X_HDR_SIZE - DDP_HDR_SIZE) - LLAP_HDR_SIZE));
29 llap = (at_llap_hdr_t *)gbuf_rptr(mp);
30 ddp_short = (at_ddp_short_t *)(gbuf_rptr(mp) + LLAP_HDR_SIZE);
32 llap->destination = ddp->dst_node;
33 llap->type = LLAP_TYPE_DDP;
34 ddp_short->length = ddp->length - (DDP_X_HDR_SIZE - DDP_HDR_SIZE);
35 ddp_short->unused = 0;
36 return ((at_ddp_short_t *)mp);
40 /* mp points to message of the form {llap, short ddp, ...}.
41 * Get rid of llap, extend ddp header to make it of the form
42 * {extended ddp, ... }
44 static gbuf_t *ddp_extend_hdr(mp)
47 register at_llap_hdr_t *llap;
48 register at_ddp_short_t *ddp_short;
49 register at_ddp_t *ddp;
50 char buf[DDP_HDR_SIZE + LLAP_HDR_SIZE];
53 /* We need to remove the llap header from the packet and extend the
54 * short DDP header in to a long one. 5 bytes of additional space
55 * is required in effect, but we can not afford to put these 5 bytes
56 * in a separate buffer, since the ddp buffer would end up being
57 * fragmented into two pieces, which is a no-no. So, we first get
58 * rid of the llap and ddp short headers and then add the extended
62 /* Assuming that the llap and ddp short headers are placed next
63 * to each other in the same buffer
65 bcopy(gbuf_rptr(mp), buf, LLAP_HDR_SIZE + DDP_HDR_SIZE);
66 m1 = ddp_adjmsg(mp, LLAP_HDR_SIZE+DDP_HDR_SIZE) ? mp : 0;
68 /* If the message did not contain any ddp data bytes, then m would
69 * be NULL at this point... and we can't just grow a NULL message,
70 * we need to ALLOC a new one.
73 if ((m2 = (gbuf_t *)ddp_growmsg(m1, -DDP_X_HDR_SIZE)) == NULL) {
74 dPrintf(D_M_DDP, D_L_WARNING,
75 ("Dropping packet - no bufs to extend hdr"));
76 at_ddp_stats.rcv_dropped_nobuf++;
81 /* Original message mp has already been freed by ddp_adjmsg if we
82 * managed to arrive here... this case occurs only when the
83 * message mp did not contain any ddp data bytes, only lap and
86 if ((m2 = gbuf_alloc(AT_WR_OFFSET+DDP_X_HDR_SIZE, PRI_MED)) == NULL) {
87 dPrintf(D_M_DDP,D_L_WARNING,
88 ("Packet (no data) dropped - no bufs to extend hdr"));
89 at_ddp_stats.rcv_dropped_nobuf++;
92 gbuf_rinc(m2,AT_WR_OFFSET);
93 gbuf_wset(m2,DDP_X_HDR_SIZE);
96 /* By the time we arrive here, m2 points to message of the form
97 * {Extended DDP, ... }
98 * mp and m1 are either non-existent or irrelevant.
100 ddp = (at_ddp_t *)gbuf_rptr(m2);
101 llap = (at_llap_hdr_t *)buf;
102 ddp_short = (at_ddp_short_t *)(buf + LLAP_HDR_SIZE);
104 ddp->unused = ddp->hopcount = 0;
105 ddp->length = ddp_short->length + DDP_X_HDR_SIZE - DDP_HDR_SIZE;
106 UAS_ASSIGN(ddp->checksum, 0);
107 NET_NET(ddp->dst_net, ifID_home->ifThisNode.atalk_net);
108 NET_NET(ddp->src_net, ifID_home->ifThisNode.atalk_net);
109 ddp->src_node = llap->source;
110 ddp->dst_node = llap->destination;
111 ddp->dst_socket = ddp_short->dst_socket;
112 ddp->src_socket = ddp_short->src_socket;
113 ddp->type = ddp_short->type;
120 #ifdef _AIX /* This AIX code (to the end of this file) is no longer supported. */
122 int ATsocket(proto) /* AIX version */
128 rc = (*sys_ATsocket)(proto, &err, 0);
136 int ATgetmsg(fd, ctlptr, datptr, flags) /* AIX version */
145 rc = (*sys_ATgetmsg)(fd, ctlptr, datptr, flags, &err, 0);
153 int ATputmsg(fd, ctlptr, datptr, flags) /* AIX version */
162 rc = (*sys_ATputmsg)(fd, ctlptr, datptr, flags, &err, 0);
170 int ATPsndreq(fd, buf, len, nowait) /* AIX version */
179 rc = (*sys_ATPsndreq)(fd, buf, len, nowait, &err, 0);
187 int ATPsndrsp(fd, respbuff, resplen, datalen) /* AIX version */
189 unsigned char *respbuff;
196 rc = (*sys_ATPsndrsp)(fd, respbuff, resplen, datalen, &err, 0);
204 int ATPgetreq(fd, buf, buflen) /* AIX version */
212 rc = (*sys_ATPgetreq)(fd, buf, buflen, &err, 0);
220 int ATPgetrsp(fd, bdsp) /* AIX version */
227 rc = (*sys_ATPgetrsp)(fd, bdsp, &err, 0);
235 void *atalk_kalloc(size) /* AIX version */
238 return (void *)xmalloc(size, 2, pinned_heap);
241 void atalk_kfree(buf) /* AIX version */
244 xmfree(buf, pinned_heap);
247 int atalk_closeref(fp, grefp) /* AIX version */
251 *grefp = (gref_t *)fp->f_data;
256 int atalk_openref(gref, retfd, proc) /* AIX version */
261 extern int _ATrw(), _ATioctl(), _ATselect(), _ATclose(), _ATstat();
262 static struct fileops fileops = {_ATrw, _ATioctl, _ATselect, _ATclose, _ATstat};
267 crp = (void *)crref();
269 if ((err = ufdcreate(FREAD|FWRITE,
270 &fileops, 0, DTYPE_OTHER, &fd, crp)) != 0)
272 if ((err = ufdcreate(FREAD|FWRITE,
273 &fileops, 0, DTYPE_ATALK, &fd, crp)) != 0)
278 fp->f_data = (void *)gref;
279 gref->next = (void *)fp;
283 int atalk_getref(fp, fd, grefp, proc) /* AIX version */
290 if ((fd < 0) || (fd > U.U_maxofile) || ((fp = U.U_ufd[fd].fp) == 0)) {
291 *grefp = (gref_t *)0;
295 if ((*grefp = (gref_t *)fp->f_data) == 0)
300 gbuf_t *gbuf_alloc(size, pri) /* AIX version */
306 m = (size > MHLEN) ? (gbuf_t *)m_getclustm(M_DONTWAIT, MSG_DATA, size)
307 : (gbuf_t *)m_gethdr(M_DONTWAIT, MSG_DATA);
308 #ifdef APPLETALK_DEBUG
309 kprintf("gbuf_alloc: for size = %d m=%x\n", size, m);
317 void gbuf_freeb(m) /* AIX version */
324 static struct trb *trb_freehead = 0;
325 static struct trb *trb_freetail = 0;
326 static struct trb *trb_pendhead = 0;
327 static int trb_cnt = 0;
328 static atlock_t trb_lock;
330 static void atalk_rem_timeoutcf() /* AIX version */
333 register struct trb *trb;
334 register struct trb *tmp_freehead, *tmp_pendhead;
336 ATDISABLE(s, trb_lock);
337 tmp_freehead = trb_freehead;
339 tmp_pendhead = trb_pendhead;
342 ATENABLE(s, trb_lock);
343 while ((trb = tmp_pendhead) != 0) {
344 tmp_pendhead = trb->to_next;
348 while ((trb = tmp_freehead) != 0) {
349 tmp_freehead = trb->to_next;
352 dPrintf(D_M_ATP,D_L_ERROR, "atalk: timer stopped!\n",0,0,0,0,0);
355 static void atalk_timeoutcf(cnt) /* AIX version */
359 register struct trb *trb;
361 if (trb_freehead == 0) {
362 for (i=0; i < cnt-1; i++) {
363 trb = (struct trb *)talloc();
364 trb->to_next = trb_freehead;
366 if (!i) trb_freetail = trb;
370 ATLOCKINIT(trb_lock);
373 static void atalk_clock(trb) /* AIX version */
374 register struct trb *trb;
377 register struct trb *next;
381 ATDISABLE(s, trb_lock);
382 if (trb_pendhead && trb->func) {
384 * remove the timeout from the pending queue
386 if (trb_pendhead == trb)
387 trb_pendhead = trb->to_next;
389 for (next=trb_pendhead; next->to_next; next=next->to_next) {
390 if (next->to_next == trb) {
391 next->to_next = trb->to_next;
397 dPrintf(D_M_ATP,D_L_WARNING,
398 "atalk_clock: %d,%x,%x\n", trb_cnt,trb,trb_pendhead,0,0);
400 * we have not found the trb in the pending list - something
401 * has gone wrong here. maybe the trb has been returned to
402 * the free list; in which case, we should simply ignore
403 * this timeout event!
405 for (next=trb_freehead; next; next=next->to_next) {
408 ATENABLE(s, trb_lock);
413 * the trb is not in the free list either - something has
414 * really gone wacky here! all we can do now is put the
415 * trb back into the free list and hope that it will be ok.
419 trb_freetail->to_next = trb;
424 ATENABLE(s, trb_lock);
430 * process the timeout
436 arg = (void *)trb->func_data;
437 trb->func_data = 999;
439 trb_freetail->to_next = trb;
444 ATENABLE(s, trb_lock);
446 dPrintf(D_M_ATP,D_L_VERBOSE, "atalk_clock: func=%x, arg=%x, %d\n",
447 tof,arg,trb_cnt,0,0);
450 dPrintf(D_M_ATP,D_L_ERROR, "atalk_clock: func=%x, arg=%x, %d\n",
451 tof,arg,trb_cnt,0,0);
454 ATENABLE(s, trb_lock);
457 void *atalk_timeout(func, arg, ticks) /* AIX version */
463 register struct trb *trb;
465 dPrintf(D_M_ATP,D_L_VERBOSE,
466 "atalk_timeout: func=%x,arg=%x,time=%d, %d,%x\n", func,arg,ticks,trb_cnt,trb_pendhead);
468 * set up the timeout request
470 ATDISABLE(s, trb_lock);
471 if ((trb = trb_freehead) == 0) {
472 ATENABLE(s, trb_lock);
473 dPrintf(D_M_ATP,D_L_WARNING,
474 "atalk_timeout: NO TRB! time=%d, %d\n", ticks,trb_cnt,0,0,0);
477 trb_freehead = trb->to_next;
478 trb->to_next = trb_pendhead;
481 trb->timeout.it_value.tv_sec = ticks / HZ;
482 trb->timeout.it_value.tv_nsec = (ticks % HZ) * (NS_PER_SEC / HZ);
487 trb->func = (void (*)())atalk_clock;
488 trb->func_data = (ulong)arg;
495 ATENABLE(s, trb_lock);
500 void atalk_untimeout(func, arg, trb) /* AIX version */
503 register struct trb *trb;
506 register struct trb *next;
508 dPrintf(D_M_ATP,D_L_VERBOSE,
509 "atalk_untimeout: func=%x,arg=%x, %d\n", func,arg,trb_cnt,0,0);
511 ATDISABLE(s, trb_lock);
513 for (trb=trb_pendhead; trb; trb=trb->to_next) {
514 if ((func == trb->tof) && (arg == (void *)trb->func_data))
518 if (trb && (trb->func == (void (*)())atalk_clock)
519 && (func == trb->tof) && (arg == (void *)trb->func_data)) {
520 trb->func_data = 999;
521 if (!(trb->flags & T_PENDING))
524 ATENABLE(s, trb_lock);
529 if (trb_pendhead == trb)
530 trb_pendhead = trb->to_next;
532 for (next=trb_pendhead; next->to_next != trb; next=next->to_next) {
533 if (next->to_next == 0) {
534 ATENABLE(s, trb_lock);
535 dPrintf(D_M_ATP,D_L_WARNING,
536 "atalk_untimeout: UNKNOWN TRB %x...\n",trb,0,0,0,0);
540 next->to_next = trb->to_next;
543 trb_freetail->to_next = trb;
547 ATENABLE(s, trb_lock);
550 int config_atalk(dev, cmd, uiop) /* AIX only */
555 static int loaded = 0;
559 nest = lockl(&kernel_lock, LOCK_SHORT);
561 if (cmd == CFG_INIT) {
564 vm_protect(0, 4096, 3);
565 atalk_timeoutcf(256);
569 } else if (cmd == CFG_TERM) {
572 atalk_rem_timeoutcf();
580 if (nest != LOCK_NEST)
581 unlockl(&kernel_lock);
589 #ifdef _AIX /* AIX code, to the end of this file, is no longer supported. */
591 int _ATselect(fp, corl, reqevents, retevents, notify) /* AIX version */
594 unsigned short reqevents;
595 unsigned short *retevents;
600 unsigned short sevents = 0;
602 if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
605 ATDISABLE(s, gref->lock);
606 if (reqevents & POLLIN) {
607 if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
611 if (reqevents & POLLOUT) {
612 if (gref->writeable) {
613 if ((*gref->writeable)(gref))
619 if ((sevents == 0) && ((reqevents & POLLSYNC) == 0)) {
620 if (rc = selreg(corl, 99, gref, reqevents, notify)) {
621 ATENABLE(s, gref->lock);
625 if (reqevents & POLLIN) {
626 if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
629 gref->sevents |= POLLIN;
632 if (reqevents & POLLOUT) {
633 if (gref->writeable) {
634 if ((*gref->writeable)(gref))
637 gref->sevents |= POLLOUT;
642 ATENABLE(s, gref->lock);
643 *retevents = sevents;
648 #endif /* end AIX section */
656 /* AIX section to end of file (not supported) */
658 /* from beginning of file ... */
659 #include <sys/cdli.h>
661 static struct ns_8022 elap_link; /* The SNAP header description */
662 static struct ns_user elap_user; /* The interface to the demuxer */
665 pat_ifpresent(name) /* AIX */
668 return (int)ifunit(name);
672 pat_output(pat_id, mlist, dst_addr, type) /* AIX */
675 unsigned char *dst_addr;
680 gbuf_t *m, *m_prev, *new_mlist, *m_temp;
683 enet_header_t *enet_header;
684 llc_header_t *llc_header;
686 patp = (pat_unit_t *)&pat_units[pat_id];
687 if (patp->state != PAT_ONLINE) {
692 if (patp->xtype == IFTYPE_NULLTALK) {
697 nddp = (void *)patp->nddp;
700 for (m = mlist; m; m = mlist) {
701 mlist = gbuf_next(m);
704 gbuf_prepend(m,ENET_LLC_SIZE);
709 gbuf_freel(new_mlist);
713 enet_header = (enet_header_t *)gbuf_rptr(m);
714 bcopy(dst_addr, enet_header->dst, sizeof(enet_header->dst));
715 bcopy(patp->xaddr, enet_header->src, sizeof(enet_header->src));
716 size = gbuf_msgsize(m);
717 enet_header->len = size - sizeof(enet_header_t);
718 llc_header = (llc_header_t *)(gbuf_rptr(m)+sizeof(enet_header_t));
719 *llc_header = (type == AARP_AT_TYPE) ? snap_hdr_aarp : snap_hdr_at;
721 m->m_pkthdr.len = size;
722 m->m_pkthdr.rcvif = 0;
725 gbuf_next(m_prev) = m;
733 (*nddp->ndd_output)(nddp, new_mlist);
739 pat_online (ifName, ifType) /* AIX */
749 if ((pat_id = pat_ID(ifName)) == -1)
751 patp = &pat_units[pat_id];
753 if (patp->xtype == IFTYPE_ETHERTALK) {
754 ns_name[0] = ifName[0];
756 strcpy(&ns_name[2], &ifName[1]);
757 } else if (patp->xtype == IFTYPE_NULLTALK) {
759 bzero(patp->xaddr, patp->xaddrlen);
761 *ifType = patp->xtype;
762 patp->nddp = (void *)0;
763 patp->state = PAT_ONLINE;
764 at_statep->flags |= AT_ST_IF_CHANGED;
769 if (ns_alloc(ns_name, &nddp))
772 bzero(&elap_user, sizeof(elap_user));
773 elap_user.isr = pat_input;
774 elap_user.pkt_format = NS_HANDLE_HEADERS|NS_INCLUDE_MAC;
776 elap_link.filtertype = NS_8022_LLC_DSAP_SNAP;
777 elap_link.orgcode[0] = 0;
778 elap_link.orgcode[2] = 0;
779 elap_link.dsap = DSAP_SNAP;
780 elap_link.ethertype = 0x80f3; /* AARP SNAP code */
781 if (ns_add_filter(nddp, &elap_link, sizeof(elap_link), &elap_user))
784 elap_link.orgcode[0] = 0x08;
785 elap_link.orgcode[2] = 0x07;
786 elap_link.ethertype = 0x809b; /* DDP SNAP code */
787 if (ns_add_filter(nddp, &elap_link, sizeof(elap_link), &elap_user)) {
788 elap_link.orgcode[0] = 0;
789 elap_link.orgcode[2] = 0;
790 elap_link.ethertype = 0x80f3; /* AARP SNAP code */
791 (void)ns_del_filter(nddp, &elap_link, sizeof(elap_link));
795 patp->xaddrlen = nddp->ndd_addrlen;
796 bcopy(nddp->ndd_physaddr, patp->xaddr, patp->xaddrlen);
799 *ifType = patp->xtype;
801 patp->nddp = (void *)nddp;
802 patp->state = PAT_ONLINE;
803 at_statep->flags |= AT_ST_IF_CHANGED;
809 pat_offline(pat_id) /* AIX */
812 pat_unit_t *patp = &pat_units[pat_id];
814 if (patp->state == PAT_ONLINE) {
815 if (patp->xtype != IFTYPE_NULLTALK) {
816 elap_link.filtertype = NS_8022_LLC_DSAP_SNAP;
817 elap_link.orgcode[0] = 0;
818 elap_link.orgcode[2] = 0;
819 elap_link.dsap = DSAP_SNAP;
820 elap_link.ethertype = 0x80f3; /* AARP SNAP code */
821 (void)ns_del_filter(patp->nddp, &elap_link, sizeof(elap_link));
822 elap_link.orgcode[0] = 0x08;
823 elap_link.orgcode[2] = 0x07;
824 elap_link.ethertype = 0x809b; /* DDP SNAP code */
825 (void)ns_del_filter(patp->nddp, &elap_link, sizeof(elap_link));
828 at_statep->flags |= AT_ST_IF_CHANGED;
829 bzero(patp, sizeof(pat_unit_t));
834 pat_mcast(pat_id, control, data) /* AIX */
841 nddp = (struct ndd *)pat_units[pat_id].nddp;
842 return (*nddp->ndd_ctl)(nddp, (control == PAT_REG_MCAST) ?
843 NDD_ENABLE_ADDRESS : NDD_DISABLE_ADDRESS,
844 data, nddp->ndd_addrlen);
848 pat_input(nddp, m, unused) /* AIX */
853 extern int ddprunning_flag;
854 llc_header_t *llc_header;
858 enet_header_t *enet_header = (enet_header_t *)gbuf_rptr(m);
860 for (pat_id=0, patp = &pat_units[pat_id];
861 pat_id < xpatcnt; pat_id++, patp++) {
862 if ((patp->state == PAT_ONLINE) && (patp->nddp == nddp))
865 if (pat_id == xpatcnt) {
870 /* Ignore multicast packets from local station */
871 if (patp->xtype == IFTYPE_ETHERTALK) {
872 bcopy((char *)enet_header->src, src, sizeof(src));
873 if ((enet_header->dst[0] & 1) &&
874 (bcmp(src, patp->xaddr, sizeof(src)) == 0)) {
878 llc_header = (llc_header_t *)(enet_header+1);
881 gbuf_rinc(m,(ENET_LLC_SIZE));
882 (void)fetch_and_add((atomic_p)&ddprunning_flag, 1);
884 if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_aarp)) {
885 patp->aarp_func(gbuf_rptr(m), patp->context);
887 } else if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_ddp)) {
888 /* if we're a router take all pkts */
890 if (patp->addr_check(gbuf_rptr(m), patp->context)
891 == AARP_ERR_NOT_OURS) {
893 (void)fetch_and_add((atomic_p)&ddprunning_flag, -1);
897 gbuf_set_type(m, MSG_DATA);
898 elap_input(m, patp->context, src);
901 (void)fetch_and_add((atomic_p)&ddprunning_flag, -1);