3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
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 $
31 * ATM Forum UNI Support
32 * ---------------------
34 * UNI ATMARP support (RFC1577) - Output packet processing
38 #include <netproto/atm/kern_include.h>
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/ipatm/ipatm_serv.h>
42 #include "uniip_var.h"
45 * Issue an ATMARP Request PDU
48 * uip pointer to IP interface
49 * tip pointer to target IP address
52 * 0 PDU was successfully sent
53 * else unable to send PDU
57 uniarp_arp_req(struct uniip
*uip
, struct in_addr
*tip
)
60 struct atmarp_hdr
*ahp
;
70 sip
= inp
->inf_nif
->nif_pif
->pif_siginst
;
73 * Figure out how long pdu is going to be
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
;
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
;
89 * Get a buffer for pdu
91 KB_ALLOCPKT(m
, len
, KB_F_NOWAIT
, KB_T_DATA
);
96 * Place aligned pdu at end of buffer
99 KB_DATASTART(m
, ahp
, struct atmarp_hdr
*);
102 * Setup variable fields pointer
104 cp
= (char *)ahp
+ sizeof(struct atmarp_hdr
);
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
);
117 KM_COPY(sip
->si_addr
.address
, cp
, len
- 1);
118 ((struct atm_addr_nsap
*)cp
)->aan_sel
= nip
->nif_sel
;
124 case T_ATM_E164_ADDR
:
125 ahp
->ah_shtl
= ARP_TL_E164
| (len
& ARP_TL_LMASK
);
128 KM_COPY(sip
->si_addr
.address
, cp
, len
);
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
);
136 KM_COPY(sip
->si_subaddr
.address
, cp
, len
- 1);
137 ((struct atm_addr_nsap
*)cp
)->aan_sel
= nip
->nif_sel
;
148 ahp
->ah_op
= htons(ARP_REQUEST
);
149 ahp
->ah_spln
= sizeof(struct in_addr
);
152 KM_COPY((caddr_t
)&(IA_SIN(inp
->inf_addr
)->sin_addr
), cp
,
153 sizeof(struct in_addr
));
154 cp
+= sizeof(struct in_addr
);
159 ahp
->ah_tpln
= sizeof(struct in_addr
);
162 KM_COPY((caddr_t
)tip
, cp
, sizeof(struct in_addr
));
165 * Finally, send the pdu to the ATMARP server
167 ivp
= uip
->uip_arpsvrvcc
;
169 uniarp_pdu_print(ivp
, m
, "send");
170 err
= atm_cm_cpcs_data(ivp
->iv_arpconn
, m
);
184 * Issue an ATMARP Response PDU
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
195 * 0 PDU was successfully sent
196 * else unable to send PDU
200 uniarp_arp_rsp(struct uniip
*uip
, struct arpmap
*amp
, struct in_addr
*tip
,
201 Atm_addr
*tatm
, Atm_addr
*tsub
, struct ipvcc
*ivp
)
204 struct atmarp_hdr
*ahp
;
209 * Figure out how long pdu is going to be
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
;
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
;
224 switch (tatm
->address_format
) {
225 case T_ATM_ENDSYS_ADDR
:
226 len
+= tatm
->address_length
;
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
;
237 * Get a buffer for pdu
239 KB_ALLOCPKT(m
, len
, KB_F_NOWAIT
, KB_T_DATA
);
244 * Place aligned pdu at end of buffer
246 KB_TAILALIGN(m
, len
);
247 KB_DATASTART(m
, ahp
, struct atmarp_hdr
*);
250 * Setup variable fields pointer
252 cp
= (char *)ahp
+ sizeof(struct atmarp_hdr
);
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
);
265 KM_COPY(amp
->am_dstatm
.address
, cp
, len
);
271 case T_ATM_E164_ADDR
:
272 ahp
->ah_shtl
= ARP_TL_E164
| (len
& ARP_TL_LMASK
);
275 KM_COPY(amp
->am_dstatm
.address
, cp
, len
);
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
);
283 KM_COPY(amp
->am_dstatmsub
.address
, cp
, len
);
294 ahp
->ah_op
= htons(ARP_REPLY
);
295 ahp
->ah_spln
= sizeof(struct in_addr
);
298 KM_COPY((caddr_t
)&
->am_dstip
, cp
, sizeof(struct in_addr
));
299 cp
+= sizeof(struct in_addr
);
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
);
307 KM_COPY(tatm
->address
, cp
, len
);
313 case T_ATM_E164_ADDR
:
314 ahp
->ah_thtl
= ARP_TL_E164
| (len
& ARP_TL_LMASK
);
317 KM_COPY(tatm
->address
, cp
, len
);
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
);
325 KM_COPY(tsub
->address
, cp
, len
);
336 ahp
->ah_tpln
= sizeof(struct in_addr
);
339 KM_COPY((caddr_t
)tip
, cp
, sizeof(struct in_addr
));
342 * Finally, send the pdu to the vcc peer
345 uniarp_pdu_print(ivp
, m
, "send");
346 err
= atm_cm_cpcs_data(ivp
->iv_arpconn
, m
);
360 * Issue an ATMARP NAK PDU
363 * uip pointer to IP interface
364 * m pointer to ATMARP_REQ buffer chain
365 * ivp pointer to vcc over which to send pdu
368 * 0 PDU was successfully sent
369 * else unable to send PDU
373 uniarp_arp_nak(struct uniip
*uip
, KBuffer
*m
, struct ipvcc
*ivp
)
375 struct atmarp_hdr
*ahp
;
379 * Get the fixed fields together
381 if (KB_LEN(m
) < sizeof(struct atmarp_hdr
)) {
382 KB_PULLUP(m
, sizeof(struct atmarp_hdr
), m
);
386 KB_DATASTART(m
, ahp
, struct atmarp_hdr
*);
391 ahp
->ah_op
= htons(ARP_NAK
);
394 * Finally, send the pdu to the vcc peer
397 uniarp_pdu_print(ivp
, m
, "send");
398 err
= atm_cm_cpcs_data(ivp
->iv_arpconn
, m
);
412 * Issue an InATMARP Request PDU
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
421 * 0 PDU was successfully sent
422 * else unable to send PDU
426 uniarp_inarp_req(struct uniip
*uip
, Atm_addr
*tatm
, Atm_addr
*tsub
,
430 struct atmarp_hdr
*ahp
;
437 inp
= uip
->uip_ipnif
;
439 sip
= inp
->inf_nif
->nif_pif
->pif_siginst
;
442 * Figure out how long pdu is going to be
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
;
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
;
457 switch (tatm
->address_format
) {
458 case T_ATM_ENDSYS_ADDR
:
459 len
+= tatm
->address_length
;
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
;
470 * Get a buffer for pdu
472 KB_ALLOCPKT(m
, len
, KB_F_NOWAIT
, KB_T_DATA
);
477 * Place aligned pdu at end of buffer
479 KB_TAILALIGN(m
, len
);
480 KB_DATASTART(m
, ahp
, struct atmarp_hdr
*);
483 * Setup variable fields pointer
485 cp
= (char *)ahp
+ sizeof(struct atmarp_hdr
);
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
);
498 KM_COPY(sip
->si_addr
.address
, cp
, len
- 1);
499 ((struct atm_addr_nsap
*)cp
)->aan_sel
= nip
->nif_sel
;
505 case T_ATM_E164_ADDR
:
506 ahp
->ah_shtl
= ARP_TL_E164
| (len
& ARP_TL_LMASK
);
509 KM_COPY(sip
->si_addr
.address
, cp
, len
);
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
);
517 KM_COPY(sip
->si_subaddr
.address
, cp
, len
- 1);
518 ((struct atm_addr_nsap
*)cp
)->aan_sel
= nip
->nif_sel
;
529 ahp
->ah_op
= htons(INARP_REQUEST
);
530 ahp
->ah_spln
= sizeof(struct in_addr
);
533 KM_COPY((caddr_t
)&(IA_SIN(inp
->inf_addr
)->sin_addr
), cp
,
534 sizeof(struct in_addr
));
535 cp
+= sizeof(struct in_addr
);
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
);
543 KM_COPY(tatm
->address
, cp
, len
);
549 case T_ATM_E164_ADDR
:
550 ahp
->ah_thtl
= ARP_TL_E164
| (len
& ARP_TL_LMASK
);
553 KM_COPY(tatm
->address
, cp
, len
);
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
);
561 KM_COPY(tsub
->address
, cp
, len
);
575 * Finally, send the pdu to the vcc peer
578 uniarp_pdu_print(ivp
, m
, "send");
579 err
= atm_cm_cpcs_data(ivp
->iv_arpconn
, m
);
593 * Issue an InATMARP Response PDU
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
603 * 0 PDU was successfully sent
604 * else unable to send PDU
608 uniarp_inarp_rsp(struct uniip
*uip
, struct in_addr
*tip
, Atm_addr
*tatm
,
609 Atm_addr
*tsub
, struct ipvcc
*ivp
)
612 struct atmarp_hdr
*ahp
;
619 inp
= uip
->uip_ipnif
;
621 sip
= inp
->inf_nif
->nif_pif
->pif_siginst
;
624 * Figure out how long pdu is going to be
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
;
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
;
639 switch (tatm
->address_format
) {
640 case T_ATM_ENDSYS_ADDR
:
641 len
+= tatm
->address_length
;
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
;
652 * Get a buffer for pdu
654 KB_ALLOCPKT(m
, len
, KB_F_NOWAIT
, KB_T_DATA
);
659 * Place aligned pdu at end of buffer
661 KB_TAILALIGN(m
, len
);
662 KB_DATASTART(m
, ahp
, struct atmarp_hdr
*);
665 * Setup variable fields pointer
667 cp
= (char *)ahp
+ sizeof(struct atmarp_hdr
);
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
);
680 KM_COPY(sip
->si_addr
.address
, cp
, len
- 1);
681 ((struct atm_addr_nsap
*)cp
)->aan_sel
= nip
->nif_sel
;
687 case T_ATM_E164_ADDR
:
688 ahp
->ah_shtl
= ARP_TL_E164
| (len
& ARP_TL_LMASK
);
691 KM_COPY(sip
->si_addr
.address
, cp
, len
);
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
);
699 KM_COPY(sip
->si_subaddr
.address
, cp
, len
- 1);
700 ((struct atm_addr_nsap
*)cp
)->aan_sel
= nip
->nif_sel
;
711 ahp
->ah_op
= htons(INARP_REPLY
);
712 ahp
->ah_spln
= sizeof(struct in_addr
);
715 KM_COPY((caddr_t
)&(IA_SIN(inp
->inf_addr
)->sin_addr
), cp
,
716 sizeof(struct in_addr
));
717 cp
+= sizeof(struct in_addr
);
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
);
725 KM_COPY(tatm
->address
, cp
, len
);
731 case T_ATM_E164_ADDR
:
732 ahp
->ah_thtl
= ARP_TL_E164
| (len
& ARP_TL_LMASK
);
735 KM_COPY(tatm
->address
, cp
, len
);
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
);
743 KM_COPY(tsub
->address
, cp
, len
);
754 ahp
->ah_tpln
= sizeof(struct in_addr
);
757 KM_COPY((caddr_t
)tip
, cp
, sizeof(struct in_addr
));
760 * Finally, send the pdu to the vcc peer
763 uniarp_pdu_print(ivp
, m
, "send");
764 err
= atm_cm_cpcs_data(ivp
->iv_arpconn
, m
);