fetch.9: Minor fixes.
[dragonfly.git] / sys / netproto / atm / uni / uniarp_output.c
blobf11fd85c921f1c97bda4dc8040ea28cfdb3e24cb
1 /*
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
47 * Arguments:
48 * uip pointer to IP interface
49 * tip pointer to target IP address
51 * Returns:
52 * 0 PDU was successfully sent
53 * else unable to send PDU
56 int
57 uniarp_arp_req(struct uniip *uip, struct in_addr *tip)
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;
68 inp = uip->uip_ipnif;
69 nip = inp->inf_nif;
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;
79 break;
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;
89 * Get a buffer for pdu
91 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
92 if (m == NULL)
93 return (1);
96 * Place aligned pdu at end of buffer
98 KB_TAILALIGN(m, len);
99 KB_DATASTART(m, ahp, struct atmarp_hdr *);
102 * Setup variable fields pointer
104 cp = (char *)ahp + sizeof(struct atmarp_hdr);
107 * Build fields
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);
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;
121 ahp->ah_sstl = 0;
122 break;
124 case T_ATM_E164_ADDR:
125 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
127 /* ah_sha */
128 KM_COPY(sip->si_addr.address, cp, len);
129 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);
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;
143 default:
144 ahp->ah_shtl = 0;
145 ahp->ah_sstl = 0;
148 ahp->ah_op = htons(ARP_REQUEST);
149 ahp->ah_spln = sizeof(struct in_addr);
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);
156 ahp->ah_thtl = 0;
157 ahp->ah_tstl = 0;
159 ahp->ah_tpln = sizeof(struct in_addr);
161 /* ah_tpa */
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;
168 if (uniarp_print)
169 uniarp_pdu_print(ivp, m, "send");
170 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
171 if (err) {
173 * Didn't make it
175 KB_FREEALL(m);
176 return (1);
179 return (0);
184 * Issue an ATMARP Response PDU
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
194 * Returns:
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)
203 KBuffer *m;
204 struct atmarp_hdr *ahp;
205 char *cp;
206 int len, err;
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;
215 break;
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;
224 switch (tatm->address_format) {
225 case T_ATM_ENDSYS_ADDR:
226 len += tatm->address_length;
227 break;
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;
237 * Get a buffer for pdu
239 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
240 if (m == NULL)
241 return (1);
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);
255 * Build fields
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);
264 /* ah_sha */
265 KM_COPY(amp->am_dstatm.address, cp, len);
266 cp += len;
268 ahp->ah_sstl = 0;
269 break;
271 case T_ATM_E164_ADDR:
272 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
274 /* ah_sha */
275 KM_COPY(amp->am_dstatm.address, cp, len);
276 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);
282 /* ah_ssa */
283 KM_COPY(amp->am_dstatmsub.address, cp, len);
284 cp += len;
285 } else
286 ahp->ah_sstl = 0;
287 break;
289 default:
290 ahp->ah_shtl = 0;
291 ahp->ah_sstl = 0;
294 ahp->ah_op = htons(ARP_REPLY);
295 ahp->ah_spln = sizeof(struct in_addr);
297 /* ah_spa */
298 KM_COPY((caddr_t)&amp->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);
306 /* ah_tha */
307 KM_COPY(tatm->address, cp, len);
308 cp += len;
310 ahp->ah_tstl = 0;
311 break;
313 case T_ATM_E164_ADDR:
314 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
316 /* ah_tha */
317 KM_COPY(tatm->address, cp, len);
318 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);
324 /* ah_tsa */
325 KM_COPY(tsub->address, cp, len);
326 cp += len;
327 } else
328 ahp->ah_tstl = 0;
329 break;
331 default:
332 ahp->ah_thtl = 0;
333 ahp->ah_tstl = 0;
336 ahp->ah_tpln = sizeof(struct in_addr);
338 /* ah_tpa */
339 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
342 * Finally, send the pdu to the vcc peer
344 if (uniarp_print)
345 uniarp_pdu_print(ivp, m, "send");
346 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
347 if (err) {
349 * Didn't make it
351 KB_FREEALL(m);
352 return (1);
355 return (0);
360 * Issue an ATMARP NAK PDU
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
367 * Returns:
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;
376 int err;
379 * Get the fixed fields together
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);
386 KB_DATASTART(m, ahp, struct atmarp_hdr *);
389 * Set new op-code
391 ahp->ah_op = htons(ARP_NAK);
394 * Finally, send the pdu to the vcc peer
396 if (uniarp_print)
397 uniarp_pdu_print(ivp, m, "send");
398 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
399 if (err) {
401 * Didn't make it
403 KB_FREEALL(m);
404 return (1);
407 return (0);
412 * Issue an InATMARP Request PDU
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
420 * Returns:
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,
427 struct ipvcc *ivp)
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;
437 inp = uip->uip_ipnif;
438 nip = inp->inf_nif;
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;
448 break;
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;
457 switch (tatm->address_format) {
458 case T_ATM_ENDSYS_ADDR:
459 len += tatm->address_length;
460 break;
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;
470 * Get a buffer for pdu
472 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
473 if (m == NULL)
474 return (1);
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);
488 * Build fields
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);
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;
502 ahp->ah_sstl = 0;
503 break;
505 case T_ATM_E164_ADDR:
506 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
508 /* ah_sha */
509 KM_COPY(sip->si_addr.address, cp, len);
510 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);
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;
524 default:
525 ahp->ah_shtl = 0;
526 ahp->ah_sstl = 0;
529 ahp->ah_op = htons(INARP_REQUEST);
530 ahp->ah_spln = sizeof(struct in_addr);
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);
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);
542 /* ah_tha */
543 KM_COPY(tatm->address, cp, len);
544 cp += len;
546 ahp->ah_tstl = 0;
547 break;
549 case T_ATM_E164_ADDR:
550 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
552 /* ah_tha */
553 KM_COPY(tatm->address, cp, len);
554 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);
560 /* ah_tsa */
561 KM_COPY(tsub->address, cp, len);
562 cp += len;
563 } else
564 ahp->ah_tstl = 0;
565 break;
567 default:
568 ahp->ah_thtl = 0;
569 ahp->ah_tstl = 0;
572 ahp->ah_tpln = 0;
575 * Finally, send the pdu to the vcc peer
577 if (uniarp_print)
578 uniarp_pdu_print(ivp, m, "send");
579 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
580 if (err) {
582 * Didn't make it
584 KB_FREEALL(m);
585 return (1);
588 return (0);
593 * Issue an InATMARP Response PDU
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
602 * Returns:
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)
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;
619 inp = uip->uip_ipnif;
620 nip = inp->inf_nif;
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;
630 break;
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;
639 switch (tatm->address_format) {
640 case T_ATM_ENDSYS_ADDR:
641 len += tatm->address_length;
642 break;
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;
652 * Get a buffer for pdu
654 KB_ALLOCPKT(m, len, KB_F_NOWAIT, KB_T_DATA);
655 if (m == NULL)
656 return (1);
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);
670 * Build fields
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);
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;
684 ahp->ah_sstl = 0;
685 break;
687 case T_ATM_E164_ADDR:
688 ahp->ah_shtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
690 /* ah_sha */
691 KM_COPY(sip->si_addr.address, cp, len);
692 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);
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;
706 default:
707 ahp->ah_shtl = 0;
708 ahp->ah_sstl = 0;
711 ahp->ah_op = htons(INARP_REPLY);
712 ahp->ah_spln = sizeof(struct in_addr);
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);
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);
724 /* ah_tha */
725 KM_COPY(tatm->address, cp, len);
726 cp += len;
728 ahp->ah_tstl = 0;
729 break;
731 case T_ATM_E164_ADDR:
732 ahp->ah_thtl = ARP_TL_E164 | (len & ARP_TL_LMASK);
734 /* ah_tha */
735 KM_COPY(tatm->address, cp, len);
736 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);
742 /* ah_tsa */
743 KM_COPY(tsub->address, cp, len);
744 cp += len;
745 } else
746 ahp->ah_tstl = 0;
747 break;
749 default:
750 ahp->ah_thtl = 0;
751 ahp->ah_tstl = 0;
754 ahp->ah_tpln = sizeof(struct in_addr);
756 /* ah_tpa */
757 KM_COPY((caddr_t)tip, cp, sizeof(struct in_addr));
760 * Finally, send the pdu to the vcc peer
762 if (uniarp_print)
763 uniarp_pdu_print(ivp, m, "send");
764 err = atm_cm_cpcs_data(ivp->iv_arpconn, m);
765 if (err) {
767 * Didn't make it
769 KB_FREEALL(m);
770 return (1);
773 return (0);