]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/ddp.save
xnu-792.24.17.tar.gz
[apple/xnu.git] / bsd / netat / ddp.save
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 */
14 static at_ddp_short_t *ddp_shrink_hdr (mp)
15 register 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 */
44 static gbuf_t *ddp_extend_hdr(mp)
45 register 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
118 From sys_dep.c:
119
120 #ifdef _AIX /* This AIX code (to the end of this file) is no longer supported. */
121
122 int 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
136 int 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
153 int 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
170 int 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
187 int 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
204 int 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
220 int 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
235 void *atalk_kalloc(size) /* AIX version */
236 int size;
237 {
238 return (void *)xmalloc(size, 2, pinned_heap);
239 }
240
241 void atalk_kfree(buf) /* AIX version */
242 void *buf;
243 {
244 xmfree(buf, pinned_heap);
245 }
246
247 int 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
256 int atalk_openref(gref, retfd, proc) /* AIX version */
257 gref_t *gref;
258 int *retfd;
259 void *proc;
260 {
261 extern int _ATrw(), _ATioctl(), _ATselect(), _ATclose(), _ATstat();
262 static 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
283 int 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
300 gbuf_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
317 void gbuf_freeb(m) /* AIX version */
318 gbuf_t *m;
319 {
320 if (m)
321 m_free(m);
322 }
323
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;
329
330 static 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
355 static 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
373 static 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
457 void *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
500 void 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
550 int config_atalk(dev, cmd, uiop) /* AIX only */
551 dev_t dev;
552 int cmd;
553 void *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
579 out:
580 if (nest != LOCK_NEST)
581 unlockl(&kernel_lock);
582 return(err);
583 }
584
585 #endif
586
587 From sys_glue.c:
588
589 #ifdef _AIX /* AIX code, to the end of this file, is no longer supported. */
590
591 int _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
645 l_done:
646 return rc;
647 }
648 #endif /* end AIX section */
649
650 From 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>
661 static struct ns_8022 elap_link; /* The SNAP header description */
662 static struct ns_user elap_user; /* The interface to the demuxer */
663
664 int
665 pat_ifpresent(name) /* AIX */
666 char *name;
667 {
668 return (int)ifunit(name);
669 }
670
671 int
672 pat_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
738 int
739 pat_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
808 void
809 pat_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
833 int
834 pat_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
847 void
848 pat_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 */