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