kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atm / uni / uniarp_output.c
CommitLineData
984263bc
MD
1/*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
12 *
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD: src/sys/netatm/uni/uniarp_output.c,v 1.3 1999/08/28 00:49:03 peter Exp $
d2438d69 27 * @(#) $DragonFly: src/sys/netproto/atm/uni/uniarp_output.c,v 1.4 2003/08/07 21:54:34 dillon Exp $
984263bc
MD
28 */
29
30/*
31 * ATM Forum UNI Support
32 * ---------------------
33 *
34 * UNI ATMARP support (RFC1577) - Output packet processing
35 *
36 */
37
d2438d69 38#include <netproto/atm/kern_include.h>
984263bc 39
d2438d69
MD
40#include <netproto/atm/ipatm/ipatm_var.h>
41#include <netproto/atm/ipatm/ipatm_serv.h>
1f2de5d4 42#include "uniip_var.h"
984263bc 43
984263bc
MD
44/*
45 * Issue an ATMARP Request PDU
46 *
47 * Arguments:
48 * uip pointer to IP interface
49 * tip pointer to target IP address
50 *
51 * Returns:
52 * 0 PDU was successfully sent
53 * else unable to send PDU
54 *
55 */
56int
57uniarp_arp_req(uip, tip)
58 struct uniip *uip;
59 struct in_addr *tip;
60{
61 KBuffer *m;
62 struct atmarp_hdr *ahp;
63 struct atm_nif *nip;
64 struct ip_nif *inp;
65 struct ipvcc *ivp;
66 struct siginst *sip;
67 char *cp;
68 int len, err;
69
70 inp = uip->uip_ipnif;
71 nip = inp->inf_nif;
72 sip = inp->inf_nif->nif_pif->pif_siginst;
73
74 /*
75 * Figure out how long pdu is going to be
76 */
77 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
78 switch (sip->si_addr.address_format) {
79 case T_ATM_ENDSYS_ADDR:
80 len += sip->si_addr.address_length;
81 break;
82
83 case T_ATM_E164_ADDR:
84 len += sip->si_addr.address_length;
85 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
86 len += sip->si_subaddr.address_length;
87 break;
88 }
89
90 /*
91 * Get a buffer for pdu
92 */
93 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
94 if (m == NULL)
95 return (1);
96
97 /*
98 * Place aligned pdu at end of buffer
99 */
100 KB_TAILALIGN(m, len);
101 KB_DATASTART(m, ahp, struct atmarp_hdr *);
102
103 /*
104 * Setup variable fields pointer
105 */
106 cp = (char *)ahp + sizeof(struct atmarp_hdr);
107
108 /*
109 * Build fields
110 */
111 ahp->ah_hrd = htons(ARP_ATMFORUM);
112 ahp->ah_pro = htons(ETHERTYPE_IP);
113 len = sip->si_addr.address_length;
114 switch (sip->si_addr.address_format) {
115 case T_ATM_ENDSYS_ADDR:
116 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
117
118 /* ah_sha */
119 KM_COPY(sip->si_addr.address, cp, len - 1);
120 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
121 cp += len;
122
123 ahp->ah_sstl = 0;
124 break;
125
126 case T_ATM_E164_ADDR:
127 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
128
129 /* ah_sha */
130 KM_COPY(sip->si_addr.address, cp, len);
131 cp += len;
132
133 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
134 len = sip->si_subaddr.address_length;
135 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
136
137 /* ah_ssa */
138 KM_COPY(sip->si_subaddr.address, cp, len - 1);
139 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
140 cp += len;
141 } else
142 ahp->ah_sstl = 0;
143 break;
144
145 default:
146 ahp->ah_shtl = 0;
147 ahp->ah_sstl = 0;
148 }
149
150 ahp->ah_op = htons(ARP_REQUEST);
151 ahp->ah_spln = sizeof(struct in_addr);
152
153 /* ah_spa */
154 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
155 sizeof(struct in_addr));
156 cp += sizeof(struct in_addr);
157
158 ahp->ah_thtl = 0;
159 ahp->ah_tstl = 0;
160
161 ahp->ah_tpln = sizeof(struct in_addr);
162
163 /* ah_tpa */
164 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
165
166 /*
167 * Finally, send the pdu to the ATMARP server
168 */
169 ivp = uip->uip_arpsvrvcc;
170 if (uniarp_print)
171 uniarp_pdu_print(ivp, m, "send");
172 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
173 if (err) {
174 /*
175 * Didn't make it
176 */
177 KB_FREEALL(m);
178 return (1);
179 }
180
181 return (0);
182}
183
184
185/*
186 * Issue an ATMARP Response PDU
187 *
188 * Arguments:
189 * uip pointer to IP interface
190 * amp pointer to source map entry
191 * tip pointer to target IP address
192 * tatm pointer to target ATM address
193 * tsub pointer to target ATM subaddress
194 * ivp pointer to vcc over which to send pdu
195 *
196 * Returns:
197 * 0 PDU was successfully sent
198 * else unable to send PDU
199 *
200 */
201int
202uniarp_arp_rsp(uip, amp, tip, tatm, tsub, ivp)
203 struct uniip *uip;
204 struct arpmap *amp;
205 struct in_addr *tip;
206 Atm_addr *tatm;
207 Atm_addr *tsub;
208 struct ipvcc *ivp;
209{
210 KBuffer *m;
211 struct atmarp_hdr *ahp;
212 char *cp;
213 int len, err;
214
215 /*
216 * Figure out how long pdu is going to be
217 */
218 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
219 switch (amp->am_dstatm.address_format) {
220 case T_ATM_ENDSYS_ADDR:
221 len += amp->am_dstatm.address_length;
222 break;
223
224 case T_ATM_E164_ADDR:
225 len += amp->am_dstatm.address_length;
226 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR)
227 len += amp->am_dstatmsub.address_length;
228 break;
229 }
230
231 switch (tatm->address_format) {
232 case T_ATM_ENDSYS_ADDR:
233 len += tatm->address_length;
234 break;
235
236 case T_ATM_E164_ADDR:
237 len += tatm->address_length;
238 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
239 len += tsub->address_length;
240 break;
241 }
242
243 /*
244 * Get a buffer for pdu
245 */
246 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
247 if (m == NULL)
248 return (1);
249
250 /*
251 * Place aligned pdu at end of buffer
252 */
253 KB_TAILALIGN(m, len);
254 KB_DATASTART(m, ahp, struct atmarp_hdr *);
255
256 /*
257 * Setup variable fields pointer
258 */
259 cp = (char *)ahp + sizeof(struct atmarp_hdr);
260
261 /*
262 * Build fields
263 */
264 ahp->ah_hrd = htons(ARP_ATMFORUM);
265 ahp->ah_pro = htons(ETHERTYPE_IP);
266 len = amp->am_dstatm.address_length;
267 switch (amp->am_dstatm.address_format) {
268 case T_ATM_ENDSYS_ADDR:
269 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
270
271 /* ah_sha */
272 KM_COPY(amp->am_dstatm.address, cp, len);
273 cp += len;
274
275 ahp->ah_sstl = 0;
276 break;
277
278 case T_ATM_E164_ADDR:
279 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
280
281 /* ah_sha */
282 KM_COPY(amp->am_dstatm.address, cp, len);
283 cp += len;
284
285 if (amp->am_dstatmsub.address_format == T_ATM_ENDSYS_ADDR) {
286 len = amp->am_dstatmsub.address_length;
287 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
288
289 /* ah_ssa */
290 KM_COPY(amp->am_dstatmsub.address, cp, len);
291 cp += len;
292 } else
293 ahp->ah_sstl = 0;
294 break;
295
296 default:
297 ahp->ah_shtl = 0;
298 ahp->ah_sstl = 0;
299 }
300
301 ahp->ah_op = htons(ARP_REPLY);
302 ahp->ah_spln = sizeof(struct in_addr);
303
304 /* ah_spa */
305 KM_COPY((caddr_t)&amp->am_dstip, cp, sizeof(struct in_addr));
306 cp += sizeof(struct in_addr);
307
308 len = tatm->address_length;
309 switch (tatm->address_format) {
310 case T_ATM_ENDSYS_ADDR:
311 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
312
313 /* ah_tha */
314 KM_COPY(tatm->address, cp, len);
315 cp += len;
316
317 ahp->ah_tstl = 0;
318 break;
319
320 case T_ATM_E164_ADDR:
321 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
322
323 /* ah_tha */
324 KM_COPY(tatm->address, cp, len);
325 cp += len;
326
327 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
328 len = tsub->address_length;
329 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
330
331 /* ah_tsa */
332 KM_COPY(tsub->address, cp, len);
333 cp += len;
334 } else
335 ahp->ah_tstl = 0;
336 break;
337
338 default:
339 ahp->ah_thtl = 0;
340 ahp->ah_tstl = 0;
341 }
342
343 ahp->ah_tpln = sizeof(struct in_addr);
344
345 /* ah_tpa */
346 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
347
348 /*
349 * Finally, send the pdu to the vcc peer
350 */
351 if (uniarp_print)
352 uniarp_pdu_print(ivp, m, "send");
353 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
354 if (err) {
355 /*
356 * Didn't make it
357 */
358 KB_FREEALL(m);
359 return (1);
360 }
361
362 return (0);
363}
364
365
366/*
367 * Issue an ATMARP NAK PDU
368 *
369 * Arguments:
370 * uip pointer to IP interface
371 * m pointer to ATMARP_REQ buffer chain
372 * ivp pointer to vcc over which to send pdu
373 *
374 * Returns:
375 * 0 PDU was successfully sent
376 * else unable to send PDU
377 *
378 */
379int
380uniarp_arp_nak(uip, m, ivp)
381 struct uniip *uip;
382 KBuffer *m;
383 struct ipvcc *ivp;
384{
385 struct atmarp_hdr *ahp;
386 int err;
387
388 /*
389 * Get the fixed fields together
390 */
391 if (KB_LEN(m) < sizeof(struct atmarp_hdr)) {
392 KB_PULLUP(m, sizeof(struct atmarp_hdr), m);
393 if (m == NULL)
394 return (1);
395 }
396 KB_DATASTART(m, ahp, struct atmarp_hdr *);
397
398 /*
399 * Set new op-code
400 */
401 ahp->ah_op = htons(ARP_NAK);
402
403 /*
404 * Finally, send the pdu to the vcc peer
405 */
406 if (uniarp_print)
407 uniarp_pdu_print(ivp, m, "send");
408 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
409 if (err) {
410 /*
411 * Didn't make it
412 */
413 KB_FREEALL(m);
414 return (1);
415 }
416
417 return (0);
418}
419
420
421/*
422 * Issue an InATMARP Request PDU
423 *
424 * Arguments:
425 * uip pointer to IP interface
426 * tatm pointer to target ATM address
427 * tsub pointer to target ATM subaddress
428 * ivp pointer to vcc over which to send pdu
429 *
430 * Returns:
431 * 0 PDU was successfully sent
432 * else unable to send PDU
433 *
434 */
435int
436uniarp_inarp_req(uip, tatm, tsub, ivp)
437 struct uniip *uip;
438 Atm_addr *tatm;
439 Atm_addr *tsub;
440 struct ipvcc *ivp;
441{
442 KBuffer *m;
443 struct atmarp_hdr *ahp;
444 struct atm_nif *nip;
445 struct ip_nif *inp;
446 struct siginst *sip;
447 char *cp;
448 int len, err;
449
450 inp = uip->uip_ipnif;
451 nip = inp->inf_nif;
452 sip = inp->inf_nif->nif_pif->pif_siginst;
453
454 /*
455 * Figure out how long pdu is going to be
456 */
457 len = sizeof(struct atmarp_hdr) + sizeof(struct in_addr);
458 switch (sip->si_addr.address_format) {
459 case T_ATM_ENDSYS_ADDR:
460 len += sip->si_addr.address_length;
461 break;
462
463 case T_ATM_E164_ADDR:
464 len += sip->si_addr.address_length;
465 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
466 len += sip->si_subaddr.address_length;
467 break;
468 }
469
470 switch (tatm->address_format) {
471 case T_ATM_ENDSYS_ADDR:
472 len += tatm->address_length;
473 break;
474
475 case T_ATM_E164_ADDR:
476 len += tatm->address_length;
477 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
478 len += tsub->address_length;
479 break;
480 }
481
482 /*
483 * Get a buffer for pdu
484 */
485 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
486 if (m == NULL)
487 return (1);
488
489 /*
490 * Place aligned pdu at end of buffer
491 */
492 KB_TAILALIGN(m, len);
493 KB_DATASTART(m, ahp, struct atmarp_hdr *);
494
495 /*
496 * Setup variable fields pointer
497 */
498 cp = (char *)ahp + sizeof(struct atmarp_hdr);
499
500 /*
501 * Build fields
502 */
503 ahp->ah_hrd = htons(ARP_ATMFORUM);
504 ahp->ah_pro = htons(ETHERTYPE_IP);
505 len = sip->si_addr.address_length;
506 switch (sip->si_addr.address_format) {
507 case T_ATM_ENDSYS_ADDR:
508 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
509
510 /* ah_sha */
511 KM_COPY(sip->si_addr.address, cp, len - 1);
512 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
513 cp += len;
514
515 ahp->ah_sstl = 0;
516 break;
517
518 case T_ATM_E164_ADDR:
519 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
520
521 /* ah_sha */
522 KM_COPY(sip->si_addr.address, cp, len);
523 cp += len;
524
525 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
526 len = sip->si_subaddr.address_length;
527 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
528
529 /* ah_ssa */
530 KM_COPY(sip->si_subaddr.address, cp, len - 1);
531 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
532 cp += len;
533 } else
534 ahp->ah_sstl = 0;
535 break;
536
537 default:
538 ahp->ah_shtl = 0;
539 ahp->ah_sstl = 0;
540 }
541
542 ahp->ah_op = htons(INARP_REQUEST);
543 ahp->ah_spln = sizeof(struct in_addr);
544
545 /* ah_spa */
546 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
547 sizeof(struct in_addr));
548 cp += sizeof(struct in_addr);
549
550 len = tatm->address_length;
551 switch (tatm->address_format) {
552 case T_ATM_ENDSYS_ADDR:
553 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
554
555 /* ah_tha */
556 KM_COPY(tatm->address, cp, len);
557 cp += len;
558
559 ahp->ah_tstl = 0;
560 break;
561
562 case T_ATM_E164_ADDR:
563 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
564
565 /* ah_tha */
566 KM_COPY(tatm->address, cp, len);
567 cp += len;
568
569 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
570 len = tsub->address_length;
571 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
572
573 /* ah_tsa */
574 KM_COPY(tsub->address, cp, len);
575 cp += len;
576 } else
577 ahp->ah_tstl = 0;
578 break;
579
580 default:
581 ahp->ah_thtl = 0;
582 ahp->ah_tstl = 0;
583 }
584
585 ahp->ah_tpln = 0;
586
587 /*
588 * Finally, send the pdu to the vcc peer
589 */
590 if (uniarp_print)
591 uniarp_pdu_print(ivp, m, "send");
592 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
593 if (err) {
594 /*
595 * Didn't make it
596 */
597 KB_FREEALL(m);
598 return (1);
599 }
600
601 return (0);
602}
603
604
605/*
606 * Issue an InATMARP Response PDU
607 *
608 * Arguments:
609 * uip pointer to IP interface
610 * tip pointer to target IP address
611 * tatm pointer to target ATM address
612 * tsub pointer to target ATM subaddress
613 * ivp pointer to vcc over which to send pdu
614 *
615 * Returns:
616 * 0 PDU was successfully sent
617 * else unable to send PDU
618 *
619 */
620int
621uniarp_inarp_rsp(uip, tip, tatm, tsub, ivp)
622 struct uniip *uip;
623 struct in_addr *tip;
624 Atm_addr *tatm;
625 Atm_addr *tsub;
626 struct ipvcc *ivp;
627{
628 KBuffer *m;
629 struct atmarp_hdr *ahp;
630 struct atm_nif *nip;
631 struct ip_nif *inp;
632 struct siginst *sip;
633 char *cp;
634 int len, err;
635
636 inp = uip->uip_ipnif;
637 nip = inp->inf_nif;
638 sip = inp->inf_nif->nif_pif->pif_siginst;
639
640 /*
641 * Figure out how long pdu is going to be
642 */
643 len = sizeof(struct atmarp_hdr) + (2 * sizeof(struct in_addr));
644 switch (sip->si_addr.address_format) {
645 case T_ATM_ENDSYS_ADDR:
646 len += sip->si_addr.address_length;
647 break;
648
649 case T_ATM_E164_ADDR:
650 len += sip->si_addr.address_length;
651 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR)
652 len += sip->si_subaddr.address_length;
653 break;
654 }
655
656 switch (tatm->address_format) {
657 case T_ATM_ENDSYS_ADDR:
658 len += tatm->address_length;
659 break;
660
661 case T_ATM_E164_ADDR:
662 len += tatm->address_length;
663 if (tsub->address_format == T_ATM_ENDSYS_ADDR)
664 len += tsub->address_length;
665 break;
666 }
667
668 /*
669 * Get a buffer for pdu
670 */
671 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
672 if (m == NULL)
673 return (1);
674
675 /*
676 * Place aligned pdu at end of buffer
677 */
678 KB_TAILALIGN(m, len);
679 KB_DATASTART(m, ahp, struct atmarp_hdr *);
680
681 /*
682 * Setup variable fields pointer
683 */
684 cp = (char *)ahp + sizeof(struct atmarp_hdr);
685
686 /*
687 * Build fields
688 */
689 ahp->ah_hrd = htons(ARP_ATMFORUM);
690 ahp->ah_pro = htons(ETHERTYPE_IP);
691 len = sip->si_addr.address_length;
692 switch (sip->si_addr.address_format) {
693 case T_ATM_ENDSYS_ADDR:
694 ahp->ah_shtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
695
696 /* ah_sha */
697 KM_COPY(sip->si_addr.address, cp, len - 1);
698 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
699 cp += len;
700
701 ahp->ah_sstl = 0;
702 break;
703
704 case T_ATM_E164_ADDR:
705 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
706
707 /* ah_sha */
708 KM_COPY(sip->si_addr.address, cp, len);
709 cp += len;
710
711 if (sip->si_subaddr.address_format == T_ATM_ENDSYS_ADDR) {
712 len = sip->si_subaddr.address_length;
713 ahp->ah_sstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
714
715 /* ah_ssa */
716 KM_COPY(sip->si_subaddr.address, cp, len - 1);
717 ((struct atm_addr_nsap *)cp)->aan_sel = nip->nif_sel;
718 cp += len;
719 } else
720 ahp->ah_sstl = 0;
721 break;
722
723 default:
724 ahp->ah_shtl = 0;
725 ahp->ah_sstl = 0;
726 }
727
728 ahp->ah_op = htons(INARP_REPLY);
729 ahp->ah_spln = sizeof(struct in_addr);
730
731 /* ah_spa */
732 KM_COPY((caddr_t)&(IA_SIN(inp->inf_addr)->sin_addr), cp,
733 sizeof(struct in_addr));
734 cp += sizeof(struct in_addr);
735
736 len = tatm->address_length;
737 switch (tatm->address_format) {
738 case T_ATM_ENDSYS_ADDR:
739 ahp->ah_thtl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
740
741 /* ah_tha */
742 KM_COPY(tatm->address, cp, len);
743 cp += len;
744
745 ahp->ah_tstl = 0;
746 break;
747
748 case T_ATM_E164_ADDR:
749 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
750
751 /* ah_tha */
752 KM_COPY(tatm->address, cp, len);
753 cp += len;
754
755 if (tsub->address_format == T_ATM_ENDSYS_ADDR) {
756 len = tsub->address_length;
757 ahp->ah_tstl = ARP_TL_NSAPA | (len & ARP_TL_LMASK);
758
759 /* ah_tsa */
760 KM_COPY(tsub->address, cp, len);
761 cp += len;
762 } else
763 ahp->ah_tstl = 0;
764 break;
765
766 default:
767 ahp->ah_thtl = 0;
768 ahp->ah_tstl = 0;
769 }
770
771 ahp->ah_tpln = sizeof(struct in_addr);
772
773 /* ah_tpa */
774 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
775
776 /*
777 * Finally, send the pdu to the vcc peer
778 */
779 if (uniarp_print)
780 uniarp_pdu_print(ivp, m, "send");
781 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
782 if (err) {
783 /*
784 * Didn't make it
785 */
786 KB_FREEALL(m);
787 return (1);
788 }
789
790 return (0);
791}
792