1/* From ddp.c:
2
3	ddp_shrink_hdr()
4	ddp_extend_hdr()
5
6	Saved from xnu/bsd/bsd/netat/ddp.c on 4/14/99.
7*/
8
9#ifdef NOT_USED
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.
13 */
14static	at_ddp_short_t	*ddp_shrink_hdr (mp)
15register gbuf_t	*mp;
16{
17	register at_ddp_t	*ddp;
18	register at_ddp_short_t	*ddp_short;
19	register at_llap_hdr_t	*llap;
20	gbuf_t *newmp;
21
22	if ((newmp = (gbuf_t *)gbuf_copym((gbuf_t *) mp)) == (gbuf_t *)NULL)
23	    return ((at_ddp_short_t *)NULL);
24	gbuf_freem(mp);
25	mp = newmp;
26
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);
31
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);
37}
38
39
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, ... }
43 */
44static	gbuf_t	*ddp_extend_hdr(mp)
45register gbuf_t	*mp;
46{
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];
51	gbuf_t		*m1, *m2;
52
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
59	 * header.
60	 */
61
62	/* Assuming that the llap and ddp short headers are placed next
63	 * to each other in the same buffer
64	 */
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;
67
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.
71	 */
72	if (m1) {
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++;
77			gbuf_freem(m1);
78			return(NULL);
79		}
80	} else
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
84		 * ddp headers
85		 */
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++;
90			return(NULL);
91		} else {
92			gbuf_rinc(m2,AT_WR_OFFSET);
93			gbuf_wset(m2,DDP_X_HDR_SIZE);
94		}
95
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.
99	 */
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);
103
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;
114	return (m2);
115}
116#endif
117
118From sys_dep.c:
119
120#ifdef _AIX  /* This AIX code (to the end of this file) is no longer supported. */
121
122int ATsocket(proto)  /* AIX version */
123	int proto;
124{
125	int err, rc = -1;
126
127	if (sys_ATsocket)
128		rc = (*sys_ATsocket)(proto, &err, 0);
129	else
130		err = ENXIO;
131	if (err)
132		setuerror(err);
133	return rc;
134}
135
136int ATgetmsg(fd, ctlptr, datptr, flags)  /* AIX version */
137	int fd;
138	void *ctlptr;
139	void *datptr;
140	int *flags;
141{
142	int err, rc = -1;
143
144	if (sys_ATgetmsg)
145		rc = (*sys_ATgetmsg)(fd, ctlptr, datptr, flags, &err, 0);
146	else
147		err = ENXIO;
148	if (err)
149		setuerror(err);
150	return rc;
151}
152
153int ATputmsg(fd, ctlptr, datptr, flags)  /* AIX version */
154	int fd;
155	void *ctlptr;
156	void *datptr;
157	int flags;
158{
159	int err, rc = -1;
160
161	if (sys_ATputmsg)
162		rc = (*sys_ATputmsg)(fd, ctlptr, datptr, flags, &err, 0);
163	else
164		err = ENXIO;
165	if (err)
166		setuerror(err);
167	return rc;
168}
169
170int ATPsndreq(fd, buf, len, nowait)   /* AIX version */
171	int fd;
172	unsigned char *buf;
173	int len;
174	int nowait;
175{
176	int err, rc = -1;
177
178	if (sys_ATPsndreq)
179		rc = (*sys_ATPsndreq)(fd, buf, len, nowait, &err, 0);
180	else
181		err = ENXIO;
182	if (err)
183		setuerror(err);
184	return rc;
185}
186
187int ATPsndrsp(fd, respbuff, resplen, datalen)   /* AIX version */
188	int fd;
189	unsigned char *respbuff;
190	int resplen;
191	int datalen;
192{
193	int err, rc = -1;
194
195	if (sys_ATPsndrsp)
196		rc = (*sys_ATPsndrsp)(fd, respbuff, resplen, datalen, &err, 0);
197	else
198		err = ENXIO;
199	if (err)
200		setuerror(err);
201	return rc;
202}
203
204int ATPgetreq(fd, buf, buflen)  /* AIX version */
205	int fd;
206	unsigned char *buf;
207	int buflen;
208{
209	int err, rc = -1;
210
211	if (sys_ATPgetreq)
212		rc = (*sys_ATPgetreq)(fd, buf, buflen, &err, 0);
213	else
214		err = ENXIO;
215	if (err)
216		setuerror(err);
217	return rc;
218}
219
220int ATPgetrsp(fd, bdsp)  /* AIX version */
221	int fd;
222	unsigned char *bdsp;
223{
224	int err, rc = -1;
225
226	if (sys_ATPgetrsp)
227		rc = (*sys_ATPgetrsp)(fd, bdsp, &err, 0);
228	else
229		err = ENXIO;
230	if (err)
231		setuerror(err);
232	return rc;
233}
234
235void *atalk_kalloc(size)   /* AIX version */
236	int size;
237{
238     return (void *)xmalloc(size, 2, pinned_heap);
239}
240
241void atalk_kfree(buf)   /* AIX version */
242	void *buf;
243{
244	xmfree(buf, pinned_heap);
245}
246
247int atalk_closeref(fp, grefp)   /* AIX version */
248	struct file *fp;
249	gref_t **grefp;
250{
251	*grefp = (gref_t *)fp->f_data;
252	fp->f_data = 0;
253	return 0;
254}
255
256int atalk_openref(gref, retfd, proc)  /* AIX version */
257	gref_t *gref;
258	int *retfd;
259	void *proc;
260{
261extern int _ATrw(), _ATioctl(), _ATselect(), _ATclose(), _ATstat();
262static struct fileops fileops = {_ATrw, _ATioctl, _ATselect, _ATclose, _ATstat};
263	int err, fd;
264	struct file *fp;
265	void *crp;
266
267	crp = (void *)crref();
268#ifdef _AIX
269	if ((err = ufdcreate(FREAD|FWRITE,
270			&fileops, 0, DTYPE_OTHER, &fd, crp)) != 0)
271#else
272	if ((err = ufdcreate(FREAD|FWRITE,
273			&fileops, 0, DTYPE_ATALK, &fd, crp)) != 0)
274#endif
275		return err;
276	*retfd = fd;
277	fp = U.U_ufd[fd].fp;
278	fp->f_data = (void *)gref;
279	gref->next = (void *)fp;
280	return 0;
281}
282
283int atalk_getref(fp, fd, grefp, proc)  /* AIX version */
284	struct file *fp;
285	int fd;
286	gref_t **grefp;
287	struct proc *proc;
288{
289	if (fp == 0) {
290		if ((fd < 0) || (fd > U.U_maxofile) || ((fp = U.U_ufd[fd].fp) == 0)) {
291			*grefp = (gref_t *)0;
292			return EBADF;
293		}
294	}
295	if ((*grefp = (gref_t *)fp->f_data) == 0)
296		return EBADF;
297	return 0;
298}
299
300gbuf_t *gbuf_alloc(size, pri)  /* AIX version */
301	int size;
302	int pri;
303{
304	gbuf_t *m;
305
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);
310#endif
311	gbuf_next(m) = 0;
312	gbuf_cont(m) = 0;
313	gbuf_wset(m,0);
314	return m;
315}
316
317void gbuf_freeb(m)  /* AIX version */
318	gbuf_t *m;
319{
320	if (m)
321		m_free(m);
322}
323
324static struct trb *trb_freehead = 0;
325static struct trb *trb_freetail = 0;
326static struct trb *trb_pendhead = 0;
327static int trb_cnt = 0;
328static atlock_t trb_lock;
329
330static void atalk_rem_timeoutcf()  /* AIX version */
331{
332	register int s;
333	register struct trb *trb;
334	register struct trb *tmp_freehead, *tmp_pendhead;
335
336	ATDISABLE(s, trb_lock);
337	tmp_freehead = trb_freehead;
338	trb_freehead = 0;
339	tmp_pendhead = trb_pendhead;
340	trb_pendhead = 0;
341	trb_cnt = 0;
342	ATENABLE(s, trb_lock);
343	while ((trb = tmp_pendhead) != 0) {
344		tmp_pendhead = trb->to_next;
345		while (tstop(trb));
346		tfree(trb);
347	}
348	while ((trb = tmp_freehead) != 0) {
349		tmp_freehead = trb->to_next;
350		tfree(trb);
351	}
352	dPrintf(D_M_ATP,D_L_ERROR, "atalk: timer stopped!\n",0,0,0,0,0);
353}
354
355static void atalk_timeoutcf(cnt)  /* AIX version */
356	int cnt;
357{
358	register int i;
359	register struct trb *trb;
360
361	if (trb_freehead == 0) {
362		for (i=0; i < cnt-1; i++) {
363			trb = (struct trb *)talloc();
364			trb->to_next = trb_freehead;
365			trb_freehead = trb;
366			if (!i) trb_freetail = trb;
367			trb_cnt++;
368		}
369	}
370	ATLOCKINIT(trb_lock);
371}
372
373static void atalk_clock(trb)  /* AIX version */
374	register struct trb *trb;
375{
376	register int s;
377	register struct trb *next;
378	void (*tof)();
379	void *arg;
380
381	ATDISABLE(s, trb_lock);
382	if (trb_pendhead && trb->func) {
383		/*
384		 * remove the timeout from the pending queue
385		 */
386		if (trb_pendhead == trb)
387			trb_pendhead = trb->to_next;
388		else {
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;
392					trb->func = 0;
393					break;
394				}
395			}
396			if (trb->func) {
397				dPrintf(D_M_ATP,D_L_WARNING,
398					"atalk_clock: %d,%x,%x\n", trb_cnt,trb,trb_pendhead,0,0);
399				/*
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!
404				 */
405				for (next=trb_freehead; next; next=next->to_next) {
406					if (next == trb)
407					{
408						ATENABLE(s, trb_lock);
409						return;
410					}
411				}
412				/*
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.
416				 */
417				trb->to_next = 0;
418				if (trb_freehead)
419					trb_freetail->to_next = trb;
420				else
421					trb_freehead = trb;
422				trb_freetail = trb;
423				trb_cnt++;
424				ATENABLE(s, trb_lock);
425				return;
426			}
427		}
428
429		/*
430		 * process the timeout
431		 */
432		trb->func = 0;
433		trb->to_next = 0;
434		tof = trb->tof;
435		trb->tof = 0;
436		arg = (void *)trb->func_data;
437		trb->func_data = 999;
438		if (trb_freehead)
439			trb_freetail->to_next = trb;
440		else
441			trb_freehead = trb;
442		trb_freetail = trb;
443		trb_cnt++;
444		ATENABLE(s, trb_lock);
445		if (tof) {
446			dPrintf(D_M_ATP,D_L_VERBOSE, "atalk_clock: func=%x, arg=%x, %d\n",
447				tof,arg,trb_cnt,0,0);
448			(*tof)(arg);
449		} else {
450			dPrintf(D_M_ATP,D_L_ERROR, "atalk_clock: func=%x, arg=%x, %d\n",
451				tof,arg,trb_cnt,0,0);
452		}
453	} else
454		ATENABLE(s, trb_lock);
455}
456
457void *atalk_timeout(func, arg, ticks)  /* AIX version */
458	void (*func)();
459	void *arg;
460	int ticks;
461{
462	register int s;
463	register struct trb *trb;
464
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);
467	/*
468	 * set up the timeout request
469	 */
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);
475		return 0;
476	}
477	trb_freehead = trb->to_next;
478	trb->to_next = trb_pendhead;
479	trb_pendhead = trb;
480	trb_cnt--;
481	trb->timeout.it_value.tv_sec  =  ticks / HZ;
482	trb->timeout.it_value.tv_nsec = (ticks % HZ) * (NS_PER_SEC / HZ);
483	trb->knext     = 0;
484	trb->kprev     = 0;
485	trb->flags     = 0;
486	trb->tof       = func;
487	trb->func      = (void (*)())atalk_clock;
488	trb->func_data = (ulong)arg;
489	trb->ipri      = PL_IMP;
490	trb->id        = -1;
491
492	/*
493	 * start the timeout
494	 */
495	ATENABLE(s, trb_lock);
496	tstart(trb);
497	return (void *)trb;
498}
499
500void atalk_untimeout(func, arg, trb)  /* AIX version */
501	void (*func)();
502	void *arg;
503	register struct trb *trb;
504{
505	register int s;
506	register struct trb *next;
507
508	dPrintf(D_M_ATP,D_L_VERBOSE,
509		"atalk_untimeout: func=%x,arg=%x, %d\n", func,arg,trb_cnt,0,0);
510
511	ATDISABLE(s, trb_lock);
512	if (trb == 0) {
513		for (trb=trb_pendhead; trb; trb=trb->to_next) {
514			if ((func == trb->tof) && (arg == (void *)trb->func_data))
515				break;
516		}
517	}
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))
522			{
523			trb->tof = 0;
524			ATENABLE(s, trb_lock);
525			return;
526			}
527		trb->func = 0;
528		while (tstop(trb));
529		if (trb_pendhead == trb)
530			trb_pendhead = trb->to_next;
531		else {
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);
537					return;
538				}
539			}
540			next->to_next = trb->to_next;
541		}
542		trb->to_next = 0;
543		trb_freetail->to_next = trb;
544		trb_freetail = trb;
545		trb_cnt++;
546	}
547	ATENABLE(s, trb_lock);
548}
549
550int config_atalk(dev, cmd, uiop)  /* AIX only */
551dev_t dev;
552int cmd;
553void *uiop;
554{
555	static int loaded = 0;
556	int err, nest;
557
558	err = 0;
559	nest = lockl(&kernel_lock, LOCK_SHORT);
560
561	if (cmd == CFG_INIT) {
562		if (loaded)
563			goto out;
564		vm_protect(0, 4096, 3);
565		atalk_timeoutcf(256);
566		atalk_load();
567		loaded = 1;
568
569	} else if (cmd == CFG_TERM) {
570		if (!loaded)
571			goto out;
572		atalk_rem_timeoutcf();
573		atalk_unload();
574		loaded = 0;
575
576	} else
577		err =  EINVAL;
578
579out:
580	if (nest != LOCK_NEST)
581		unlockl(&kernel_lock);
582	return(err);
583}
584
585#endif
586
587From sys_glue.c:
588
589#ifdef _AIX  /* AIX code, to the end of this file, is no longer supported. */
590
591int _ATselect(fp, corl, reqevents, retevents, notify) /* AIX version */
592	void *fp;
593	int corl;
594	unsigned short reqevents;
595	unsigned short *retevents;
596	void (*notify)();
597{
598	int s, err, rc = 0;
599	gref_t *gref;
600	unsigned short sevents = 0;
601
602	if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
603		return err;
604
605	ATDISABLE(s, gref->lock);
606	if (reqevents & POLLIN) {
607		if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
608			sevents |= POLLIN;
609	}
610
611	if (reqevents & POLLOUT) {
612		if (gref->writeable) {
613			if ((*gref->writeable)(gref))
614				sevents |= POLLOUT;
615		} else
616			sevents |= POLLOUT;
617	}
618
619	if ((sevents == 0) && ((reqevents & POLLSYNC) == 0)) {
620		if (rc = selreg(corl, 99, gref, reqevents, notify)) {
621			ATENABLE(s, gref->lock);
622			goto l_done;
623		}
624
625          if (reqevents & POLLIN) {
626			if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
627				sevents |= POLLIN;
628			else
629				gref->sevents |= POLLIN;
630          }
631
632          if (reqevents & POLLOUT) {
633			if (gref->writeable) {
634				if ((*gref->writeable)(gref))
635					sevents |= POLLOUT;
636				else
637					gref->sevents |= POLLOUT;
638			} else
639				sevents |= POLLOUT;
640          }
641     }
642	ATENABLE(s, gref->lock);
643     *retevents = sevents;
644
645l_done:
646	return rc;
647}
648#endif  /* end AIX section */
649
650From drv_dep.c:
651
652
653
654
655#ifdef _AIX
656/* AIX section to end of file (not supported) */
657
658/* from beginning of file ... */
659#include <sys/cdli.h>
660#include <sys/ndd.h>
661static struct ns_8022 elap_link;     /* The SNAP header description */
662static struct ns_user elap_user;     /* The interface to the demuxer */
663
664int
665pat_ifpresent(name) /* AIX */
666	char *name;
667{
668	return (int)ifunit(name);
669}
670
671int
672pat_output(pat_id, mlist, dst_addr, type) /* AIX */
673	int	pat_id;
674	gbuf_t *mlist;
675	unsigned char *dst_addr;
676	int 	type;
677{
678	int len;
679	pat_unit_t *patp;
680	gbuf_t *m, *m_prev, *new_mlist, *m_temp;
681	struct ndd *nddp;
682	short size;
683	enet_header_t *enet_header;
684	llc_header_t *llc_header;
685
686	patp = (pat_unit_t *)&pat_units[pat_id];
687	if (patp->state != PAT_ONLINE) {
688		gbuf_freel(mlist);
689		return ENOTREADY;
690	}
691
692	if (patp->xtype == IFTYPE_NULLTALK) {
693		gbuf_freel(mlist);
694		return 0;
695	}
696
697	nddp = (void *)patp->nddp;
698	new_mlist = 0;
699
700  for (m = mlist; m; m = mlist) {
701	mlist = gbuf_next(m);
702	gbuf_next(m) = 0;
703
704	gbuf_prepend(m,ENET_LLC_SIZE);
705	if (m == 0) {
706		if (mlist)
707			gbuf_freel(mlist);
708		if (new_mlist)
709			gbuf_freel(new_mlist);
710		return 0;
711	}
712
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;
720
721	m->m_pkthdr.len = size;
722	m->m_pkthdr.rcvif = 0;
723
724	if (new_mlist)
725		gbuf_next(m_prev) = m;
726	else
727		new_mlist = m;
728	m_prev = m;
729	pktsOut++;
730  }
731
732	if (new_mlist)
733		(*nddp->ndd_output)(nddp, new_mlist);
734
735	return 0;
736}
737
738int
739pat_online (ifName, ifType)  /* AIX */
740	char	*ifName;
741	char	*ifType;
742{
743	void pat_input();
744	int pat_id;
745	pat_unit_t *patp;
746	struct ndd *nddp;
747	char ns_name[8];
748
749	if ((pat_id = pat_ID(ifName)) == -1)
750		return (-1);
751	patp = &pat_units[pat_id];
752
753	if (patp->xtype == IFTYPE_ETHERTALK) {
754		ns_name[0] = ifName[0];
755		ns_name[1] = 'n';
756		strcpy(&ns_name[2], &ifName[1]);
757	} else if (patp->xtype == IFTYPE_NULLTALK) {
758		patp->xaddrlen = 6;
759		bzero(patp->xaddr, patp->xaddrlen);
760		if (ifType)
761			*ifType = patp->xtype;
762		patp->nddp = (void *)0;
763		patp->state  = PAT_ONLINE;
764		at_statep->flags |= AT_ST_IF_CHANGED;
765		return (pat_id);
766	} else
767		return -1;
768
769	if (ns_alloc(ns_name, &nddp))
770		return -1;
771
772	bzero(&elap_user, sizeof(elap_user));
773	elap_user.isr = pat_input;
774	elap_user.pkt_format = NS_HANDLE_HEADERS|NS_INCLUDE_MAC;
775
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))
782		return -1;
783
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));
792		return -1;
793	}
794
795	patp->xaddrlen = nddp->ndd_addrlen;
796	bcopy(nddp->ndd_physaddr, patp->xaddr, patp->xaddrlen);
797
798	if (ifType)
799		*ifType = patp->xtype;
800
801	patp->nddp = (void *)nddp;
802	patp->state  = PAT_ONLINE;
803	at_statep->flags |= AT_ST_IF_CHANGED;
804
805	return (pat_id);
806}
807
808void
809pat_offline(pat_id)  /* AIX */
810	int pat_id;
811{
812	pat_unit_t *patp = &pat_units[pat_id];
813
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));
826		ns_free(patp->nddp);
827	  }
828		at_statep->flags |= AT_ST_IF_CHANGED;
829		bzero(patp, sizeof(pat_unit_t));
830	}
831}
832
833int
834pat_mcast(pat_id, control, data) /* AIX */
835	int pat_id;
836	int control;
837	unsigned char *data;
838{
839	struct ndd *nddp;
840
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);
845}
846
847void
848pat_input(nddp, m, unused)  /* AIX */
849	struct ndd *nddp;
850	gbuf_t *m;
851	void *unused;
852{
853	extern int ddprunning_flag;
854	llc_header_t *llc_header;
855	int pat_id;
856	pat_unit_t *patp;
857	char src[6];
858	enet_header_t *enet_header = (enet_header_t *)gbuf_rptr(m);
859
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))
863			break;
864	}
865	if (pat_id == xpatcnt) {
866		gbuf_freem(m);
867		return;
868	}
869
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)) {
875			gbuf_freem(m);
876			return;
877		}
878		llc_header = (llc_header_t *)(enet_header+1);
879  	}
880
881	gbuf_rinc(m,(ENET_LLC_SIZE));
882	(void)fetch_and_add((atomic_p)&ddprunning_flag, 1);
883	pktsIn++;
884	if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_aarp)) {
885		patp->aarp_func(gbuf_rptr(m), patp->context);
886		gbuf_freem(m);
887	} else if (LLC_PROTO_EQUAL(llc_header->protocol,snap_proto_ddp)) {
888		/* if we're a router take all pkts */
889		if (!ROUTING_MODE) {
890			if (patp->addr_check(gbuf_rptr(m), patp->context)
891					== AARP_ERR_NOT_OURS) {
892				gbuf_freem(m);
893				(void)fetch_and_add((atomic_p)&ddprunning_flag, -1);
894				return;
895			}
896		}
897		gbuf_set_type(m, MSG_DATA);
898		elap_input(m, patp->context, src);
899	} else
900		gbuf_freem(m);
901	(void)fetch_and_add((atomic_p)&ddprunning_flag, -1);
902}
903#endif  /* AIX */
904