../h => (implicitly) ../sys
[unix-history] / usr / src / sys / netiso / tp_inet.c
CommitLineData
2f41dd0f
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22******************************************************************/
23
24/*
25 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26 */
27/*
28 * ARGO TP
29 * $Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $
30 * $Source: /usr/argo/sys/netiso/RCS/tp_inet.c,v $
31 *
32 * Here is where you find the inet-dependent code. We've tried
33 * keep all net-level and (primarily) address-family-dependent stuff
34 * out of the tp source, and everthing here is reached indirectly
35 * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
36 * (see tp_pcb.c).
37 * The routines here are:
38 * in_getsufx: gets transport suffix out of an inpcb structure.
39 * in_putsufx: put transport suffix into an inpcb structure.
40 * in_putnetaddr: put a whole net addr into an inpcb.
41 * in_getnetaddr: get a whole net addr from an inpcb.
42 * in_recycle_suffix: clear suffix for reuse in inpcb
43 * tpip_mtu: figure out what size tpdu to use
44 * tpip_input: take a pkt from ip, strip off its ip header, give to tp
45 * tpip_output_dg: package a pkt for ip given 2 addresses & some data
46 * tpip_output: package a pkt for ip given an inpcb & some data
47 */
48
49#ifndef lint
50static char *rcsid = "$Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $";
51#endif lint
52
53#ifdef INET
54
a50e2bc0 55#include "param.h"
2f41dd0f
KS
56#include "socket.h"
57#include "socketvar.h"
58#include "mbuf.h"
59#include "errno.h"
60#include "time.h"
61#include "../net/if.h"
a50e2bc0
KS
62#include "tp_param.h"
63#include "argo_debug.h"
64#include "tp_stat.h"
65#include "tp_ip.h"
66#include "tp_pcb.h"
67#include "tp_trace.h"
68#include "tp_stat.h"
69#include "tp_tpdu.h"
2f41dd0f
KS
70#include "../netinet/in_var.h"
71
a50e2bc0
KS
72#ifndef ISO
73#include "iso_chksum.c"
74#endif
2f41dd0f
KS
75
76/*
77 * NAME: in_getsufx()
78
79 * CALLED FROM: pr_usrreq() on PRU_BIND,
80 * PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
81 *
82 * FUNCTION, ARGUMENTS, and RETURN VALUE:
83 * Get a transport suffix from an inpcb structure (inp).
84 * The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
85 *
86 * RETURNS: internet port / transport suffix
87 * (CAST TO AN INT)
88 *
89 * SIDE EFFECTS:
90 *
91 * NOTES:
92 */
a50e2bc0 93in_getsufx(inp, lenp, data_out, which)
2f41dd0f 94 struct inpcb *inp;
a50e2bc0
KS
95 u_short *lenp;
96 caddr_t data_out;
2f41dd0f
KS
97 int which;
98{
a50e2bc0 99 *lenp = sizeof(u_short);
2f41dd0f
KS
100 switch (which) {
101 case TP_LOCAL:
a50e2bc0
KS
102 *(u_short *)data_out = inp->inp_lport;
103 return;
2f41dd0f
KS
104
105 case TP_FOREIGN:
a50e2bc0 106 *(u_short *)data_out = inp->inp_fport;
2f41dd0f 107 }
a50e2bc0 108
2f41dd0f
KS
109}
110
111/*
112 * NAME: in_putsufx()
113 *
114 * CALLED FROM: tp_newsocket(); i.e., when a connection
115 * is being established by an incoming CR_TPDU.
116 *
117 * FUNCTION, ARGUMENTS:
118 * Put a transport suffix (found in name) into an inpcb structure (inp).
119 * The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
120 *
121 * RETURNS: Nada
122 *
123 * SIDE EFFECTS:
124 *
125 * NOTES:
126 */
a50e2bc0 127/*ARGSUSED*/
2f41dd0f 128void
a50e2bc0 129in_putsufx(inp, sufxloc, sufxlen, which)
2f41dd0f 130 struct inpcb *inp;
a50e2bc0 131 caddr_t sufxloc;
2f41dd0f
KS
132 int which;
133{
a50e2bc0
KS
134 if (which == TP_FOREIGN) {
135 bcopy(sufxloc, (caddr_t)&inp->inp_fport, sizeof(inp->inp_fport));
2f41dd0f
KS
136 }
137}
138
139/*
140 * NAME: in_recycle_tsuffix()
141 *
142 * CALLED FROM: tp.trans whenever we go into REFWAIT state.
143 *
144 * FUNCTION and ARGUMENT:
145 * Called when a ref is frozen, to allow the suffix to be reused.
146 * (inp) is the net level pcb.
147 *
148 * RETURNS: Nada
149 *
150 * SIDE EFFECTS:
151 *
152 * NOTES: This really shouldn't have to be done in a NET level pcb
153 * but... for the internet world that just the way it is done in BSD...
154 * The alternative is to have the port unusable until the reference
155 * timer goes off.
156 */
157void
158in_recycle_tsuffix(inp)
159 struct inpcb *inp;
160{
161 inp->inp_fport = inp->inp_lport = 0;
162}
163
164/*
165 * NAME: in_putnetaddr()
166 *
167 * CALLED FROM:
168 * tp_newsocket(); i.e., when a connection is being established by an
169 * incoming CR_TPDU.
170 *
171 * FUNCTION and ARGUMENTS:
172 * Copy a whole net addr from a struct sockaddr (name).
173 * into an inpcb (inp).
174 * The argument (which) takes values TP_LOCAL or TP_FOREIGN
175 *
176 * RETURNS: Nada
177 *
178 * SIDE EFFECTS:
179 *
180 * NOTES:
181 */
182void
183in_putnetaddr(inp, name, which)
184 register struct inpcb *inp;
185 struct sockaddr_in *name;
186 int which;
187{
188 switch (which) {
189 case TP_LOCAL:
190 bcopy((caddr_t)&name->sin_addr,
191 (caddr_t)&inp->inp_laddr, sizeof(struct in_addr));
192 /* won't work if the dst address (name) is INADDR_ANY */
193
194 break;
195 case TP_FOREIGN:
196 if( name != (struct sockaddr_in *)0 ) {
197 bcopy((caddr_t)&name->sin_addr,
198 (caddr_t)&inp->inp_faddr, sizeof(struct in_addr));
199 }
200 }
201}
202
203/*
204 * NAME: in_getnetaddr()
205 *
206 * CALLED FROM:
207 * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
208 * FUNCTION and ARGUMENTS:
209 * Copy a whole net addr from an inpcb (inp) into
a50e2bc0 210 * an mbuf (name);
2f41dd0f
KS
211 * The argument (which) takes values TP_LOCAL or TP_FOREIGN.
212 *
213 * RETURNS: Nada
214 *
215 * SIDE EFFECTS:
216 *
217 * NOTES:
218 */
219
220void
221in_getnetaddr( inp, name, which)
a50e2bc0 222 register struct mbuf *name;
2f41dd0f 223 struct inpcb *inp;
2f41dd0f
KS
224 int which;
225{
a50e2bc0
KS
226 register struct sockaddr_in *sin = mtod(name, struct sockaddr_in *);
227 bzero((caddr_t)sin, sizeof(*sin));
2f41dd0f
KS
228 switch (which) {
229 case TP_LOCAL:
a50e2bc0
KS
230 sin->sin_addr = inp->inp_laddr;
231 sin->sin_port = inp->inp_lport;
2f41dd0f 232 break;
2f41dd0f 233 case TP_FOREIGN:
a50e2bc0
KS
234 sin->sin_addr = inp->inp_faddr;
235 sin->sin_port = inp->inp_fport;
2f41dd0f 236 break;
a50e2bc0
KS
237 default:
238 return;
2f41dd0f 239 }
a50e2bc0
KS
240 name->m_len = sin->sin_len = sizeof (*sin);
241 sin->sin_family = AF_INET;
2f41dd0f
KS
242}
243
244/*
245 * NAME: tpip_mtu()
246 *
247 * CALLED FROM:
248 * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
249 *
250 * FUNCTION, ARGUMENTS, and RETURN VALUE:
251 *
252 * Determine the proper maximum transmission unit, i.e., MTU, to use, given
253 * a) the header size for the network protocol and the max transmission
254 * unit on the subnet interface, determined from the information in (inp),
255 * b) the max size negotiated so far (negot)
256 * c) the window size used by the tp connection (found in so),
257 *
258 * The result is put in the integer *size in its integer form and in
259 * *negot in its logarithmic form.
260 *
261 * The rules are:
262 * a) can only negotiate down from the value found in *negot.
263 * b) the MTU must be < the windowsize,
264 * c) If src and dest are on the same net,
265 * we will negotiate the closest size larger than MTU but really USE
266 * the actual device mtu - ll hdr sizes.
267 * otherwise we negotiate the closest size smaller than MTU - ll hdr sizes.
268 *
269 * SIDE EFFECTS:
270 * changes the values addressed by the arguments (size) and (negot)
271 * and
272 * when the peer is not on one of our directly connected subnets, it
273 * looks up a route, leaving the route in the inpcb addressed by (inp)
274 *
275 * NOTES:
276 */
277
278void
279tpip_mtu(so, inp, size, negot)
280 struct socket *so;
281 struct inpcb *inp;
282 int *size;
283 u_char *negot;
284{
285 register struct ifnet *ifp;
286 struct ifnet *tpip_route();
287 struct in_ifaddr *ia;
288 register int i;
289 int windowsize = so->so_rcv.sb_hiwat;
290
291 IFDEBUG(D_CONN)
292 printf("tpip_mtu(0x%x,0x%x,0x%x,0x%x)\n",
293 so, inp, size, negot);
294 printf("tpip_mtu routing to addr 0x%x\n", inp->inp_faddr);
295 ENDDEBUG
296 IFTRACE(D_CONN)
297 tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0);
298 ENDTRACE
299
300 *size = 1 << *negot;
301
302 if( *size > windowsize ) {
303 *size = windowsize;
304 }
305
306 ia = in_iaonnetof(in_netof(inp->inp_faddr));
307 if ( ia == (struct in_ifaddr *)0 ) {
308 ifp = tpip_route(&inp->inp_faddr);
309 if( ifp == (struct ifnet *)0 )
310 return ;
311 } else
312 ifp = ia->ia_ifp;
313
314
315 /****************************************************************
316 * TODO - make this indirect off the socket structure to the
317 * network layer to get headersize
318 * After all, who knows what lies below the IP layer?
319 * Who knows how big the NL header will be?
320 ***************************************************************/
321
322 if( *size > ifp->if_mtu - sizeof(struct ip)) {
323 *size = ifp->if_mtu - sizeof(struct ip);
324 }
325 for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++)
326 ;
327 i--;
328
329 if (in_netof(inp->inp_laddr) != in_netof(inp->inp_faddr)) {
330 i++;
331 } else {
332 *size = 1<<i;
333 }
334 *negot = i;
335
336 IFDEBUG(D_CONN)
337 printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
338 ifp->if_name, *size, *negot);
339 ENDDEBUG
340 IFTRACE(D_CONN)
341 tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n",
342 *size, *negot, 0, 0);
343 ENDTRACE
344
345}
346
347/*
348 * NAME: tpip_output()
349 *
350 * CALLED FROM: tp_emit()
351 *
352 * FUNCTION and ARGUMENTS:
353 * Take a packet(m0) from tp and package it so that ip will accept it.
354 * This means prepending space for the ip header and filling in a few
355 * of the fields.
356 * inp is the inpcb structure; datalen is the length of the data in the
357 * mbuf string m0.
358 * RETURNS:
359 * whatever (E*) is returned form the net layer output routine.
360 *
361 * SIDE EFFECTS:
362 *
363 * NOTES:
364 */
365
366int
367tpip_output(inp, m0, datalen, nochksum)
368 struct inpcb *inp;
369 struct mbuf *m0;
370 int datalen;
371 int nochksum;
372{
373 return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen,
374 &inp->inp_route, nochksum);
375}
376
377/*
378 * NAME: tpip_output_dg()
379 *
380 * CALLED FROM: tp_error_emit()
381 *
382 * FUNCTION and ARGUMENTS:
383 * This is a copy of tpip_output that takes the addresses
384 * instead of a pcb. It's used by the tp_error_emit, when we
385 * don't have an in_pcb with which to call the normal output rtn.
386 *
387 * RETURNS: ENOBUFS or whatever (E*) is
388 * returned form the net layer output routine.
389 *
390 * SIDE EFFECTS:
391 *
392 * NOTES:
393 */
394
a50e2bc0 395/*ARGSUSED*/
2f41dd0f
KS
396int
397tpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
398 struct in_addr *laddr, *faddr;
399 struct mbuf *m0;
400 int datalen;
401 struct route *ro;
402 int nochksum;
403{
404 register struct mbuf *m;
405 register struct ip *ip;
406 int error;
407
408 IFDEBUG(D_EMIT)
409 printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0);
410 ENDDEBUG
411
412
a50e2bc0 413 MGETHDR(m, M_DONTWAIT, TPMT_IPHDR);
2f41dd0f
KS
414 if (m == 0) {
415 error = ENOBUFS;
416 goto bad;
417 }
2f41dd0f 418 m->m_next = m0;
a50e2bc0 419 MH_ALIGN(m, sizeof(struct ip));
2f41dd0f 420 m->m_len = sizeof(struct ip);
2f41dd0f
KS
421
422 ip = mtod(m, struct ip *);
a50e2bc0 423 bzero((caddr_t)ip, sizeof *ip);
2f41dd0f
KS
424
425 ip->ip_p = IPPROTO_TP;
a50e2bc0 426 m->m_pkthdr.len = ip->ip_len = sizeof(struct ip) + datalen;
2f41dd0f
KS
427 ip->ip_ttl = MAXTTL;
428 /* don't know why you need to set ttl;
429 * overlay doesn't even make this available
430 */
431
432 ip->ip_src = *laddr;
433 ip->ip_dst = *faddr;
434
435 IncStat(ts_tpdu_sent);
436 IFDEBUG(D_EMIT)
437 dump_mbuf(m, "tpip_output_dg before ip_output\n");
438 ENDDEBUG
439
440 error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST);
441
442 IFDEBUG(D_EMIT)
443 printf("tpip_output_dg after ip_output\n");
444 ENDDEBUG
445
446 return error;
447
448bad:
449 m_freem(m);
450 IncStat(ts_send_drop);
451 return error;
452}
453
454/*
455 * NAME: tpip_input()
456 *
457 * CALLED FROM:
458 * ip's input routine, indirectly through the protosw.
459 *
460 * FUNCTION and ARGUMENTS:
461 * Take a packet (m) from ip, strip off the ip header and give it to tp
462 *
463 * RETURNS: No return value.
464 *
465 * SIDE EFFECTS:
466 *
467 * NOTES:
468 */
469ProtoHook
a50e2bc0 470tpip_input(m, iplen)
2f41dd0f 471 struct mbuf *m;
a50e2bc0 472 int iplen;
2f41dd0f 473{
2f41dd0f
KS
474 struct sockaddr_in src, dst;
475 register struct ip *ip;
a50e2bc0 476 int s = splnet(), hdrlen;
2f41dd0f
KS
477
478 IncStat(ts_pkt_rcvd);
479
a50e2bc0
KS
480 /*
481 * IP layer has already pulled up the IP header,
482 * but the first byte after the IP header may not be there,
483 * e.g. if you came in via loopback, so you have to do an
484 * m_pullup to before you can even look to see how much you
485 * really need. The good news is that m_pullup will round
486 * up to almost the next mbuf's worth.
487 */
2f41dd0f 488
a50e2bc0
KS
489
490 if((m = m_pullup(m, iplen + 1)) == MNULL)
491 goto discard;
2f41dd0f
KS
492 CHANGE_MTYPE(m, TPMT_DATA);
493
494 /*
a50e2bc0
KS
495 * Now pull up the whole tp header:
496 * Unfortunately, there may be IP options to skip past so we
497 * just fetch it as an unsigned char.
2f41dd0f 498 */
a50e2bc0 499 hdrlen = iplen + 1 + mtod(m, u_char *)[iplen];
2f41dd0f 500
a50e2bc0
KS
501 if( m->m_len < hdrlen ) {
502 if((m = m_pullup(m, hdrlen)) == MNULL){
2f41dd0f
KS
503 IFDEBUG(D_TPINPUT)
504 printf("tp_input, pullup 2!\n");
505 ENDDEBUG
506 goto discard;
507 }
508 }
509 /*
510 * cannot use tp_inputprep() here 'cause you don't
511 * have quite the same situation
512 */
513
514 IFDEBUG(D_TPINPUT)
515 dump_mbuf(m, "after tpip_input both pullups");
516 ENDDEBUG
517 /*
518 * m_pullup may have returned a different mbuf
519 */
a50e2bc0 520 ip = mtod(m, struct ip *);
2f41dd0f
KS
521
522 /*
523 * drop the ip header from the front of the mbuf
524 * this is necessary for the tp checksum
525 */
a50e2bc0
KS
526 m->m_len -= iplen;
527 m->m_data += iplen;
2f41dd0f
KS
528
529 src.sin_addr = *(struct in_addr *)&(ip->ip_src);
530 src.sin_family = AF_INET;
a50e2bc0 531 src.sin_len = sizeof(src);
2f41dd0f
KS
532 dst.sin_addr = *(struct in_addr *)&(ip->ip_dst);
533 dst.sin_family = AF_INET;
a50e2bc0 534 dst.sin_len = sizeof(dst);
2f41dd0f 535
a50e2bc0
KS
536 (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst,
537 0, tpip_output_dg);
2f41dd0f
KS
538 splx(s);
539 return 0;
540
541discard:
542 IFDEBUG(D_TPINPUT)
543 printf("tpip_input DISCARD\n");
544 ENDDEBUG
545 IFTRACE(D_TPINPUT)
546 tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0);
547 ENDTRACE
548 m_freem(m);
549 IncStat(ts_recv_drop);
a50e2bc0 550 splx(s);
2f41dd0f
KS
551 return 0;
552}
553
554
e663c139 555#include "protosw.h"
2f41dd0f
KS
556#include "../netinet/ip_icmp.h"
557
a50e2bc0 558extern void tp_quench();
2f41dd0f
KS
559/*
560 * NAME: tpin_quench()
561 *
562 * CALLED FROM: tpip_ctlinput()
563 *
564 * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench
565 *
566 * RETURNS: Nada
567 *
568 * SIDE EFFECTS:
569 *
570 * NOTES:
571 */
572
573void
574tpin_quench(inp)
575 struct inpcb *inp;
576{
a50e2bc0 577 tp_quench((struct tp_pcb *)inp->inp_socket->so_tpcb, PRC_QUENCH);
2f41dd0f
KS
578}
579
580/*
581 * NAME: tpip_ctlinput()
582 *
583 * CALLED FROM:
584 * The network layer through the protosw table.
585 *
586 * FUNCTION and ARGUMENTS:
587 * When clnp gets an ICMP msg this gets called.
588 * It either returns an error status to the user or
589 * causes all connections on this address to be aborted
590 * by calling the appropriate xx_notify() routine.
591 * (cmd) is the type of ICMP error.
592 * (sa) the address of the sender
593 *
594 * RETURNS: Nothing
595 *
596 * SIDE EFFECTS:
597 *
598 * NOTES:
599 */
600ProtoHook
601tpip_ctlinput(cmd, sin)
602 int cmd;
603 struct sockaddr_in *sin;
604{
605 extern u_char inetctlerrmap[];
606 extern ProtoHook tpin_abort();
607 extern ProtoHook in_rtchange();
608
609 if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK)
610 return 0;
611 if (sin->sin_addr.s_addr == INADDR_ANY)
612 return 0;
613 if (cmd < 0 || cmd > PRC_NCMDS)
614 return 0;
615 switch (cmd) {
616
617 case PRC_QUENCH:
a50e2bc0
KS
618 in_pcbnotify(&tp_inpcb, &sin->sin_addr,
619 0, (int (*)())tp_quench);
2f41dd0f
KS
620 break;
621
622 case PRC_ROUTEDEAD:
623 case PRC_HOSTUNREACH:
624 case PRC_UNREACH_NET:
625 case PRC_IFDOWN:
626 case PRC_HOSTDEAD:
627 in_pcbnotify(&tp_inpcb, &sin->sin_addr,
628 (int)inetctlerrmap[cmd], in_rtchange);
629 break;
630
631 default:
632 /*
633 case PRC_MSGSIZE:
634 case PRC_UNREACH_HOST:
635 case PRC_UNREACH_PROTOCOL:
636 case PRC_UNREACH_PORT:
637 case PRC_UNREACH_NEEDFRAG:
638 case PRC_UNREACH_SRCFAIL:
639 case PRC_REDIRECT_NET:
640 case PRC_REDIRECT_HOST:
641 case PRC_REDIRECT_TOSNET:
642 case PRC_REDIRECT_TOSHOST:
643 case PRC_TIMXCEED_INTRANS:
644 case PRC_TIMXCEED_REASS:
645 case PRC_PARAMPROB:
646 */
a50e2bc0
KS
647 in_pcbnotify(&tp_inpcb, &sin->sin_addr,
648 (int)inetctlerrmap[cmd], tpin_abort);
2f41dd0f
KS
649 }
650 return 0;
651}
652
653/*
654 * NAME: tpin_abort()
655 *
656 * CALLED FROM:
657 * xxx_notify() from tp_ctlinput() when
658 * net level gets some ICMP-equiv. type event.
659 *
660 * FUNCTION and ARGUMENTS:
661 * Cause the connection to be aborted with some sort of error
662 * reason indicating that the network layer caused the abort.
663 * Fakes an ER TPDU so we can go through the driver.
664 *
665 * RETURNS: Nothing
666 *
667 * SIDE EFFECTS:
668 *
669 * NOTES:
670 */
671
672ProtoHook
673tpin_abort(inp)
674 struct inpcb *inp;
675{
676 struct tp_event e;
677
678 e.ev_number = ER_TPDU;
679 e.ATTR(ER_TPDU).e_reason = ENETRESET;
a50e2bc0 680 (void) tp_driver((struct tp_pcb *)inp->inp_ppcb, &e);
2f41dd0f
KS
681 return 0;
682}
683
684#ifdef ARGO_DEBUG
685dump_inaddr(addr)
686 register struct sockaddr_in *addr;
687{
688 printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr);
689}
690#endif ARGO_DEBUG
691
692/*
693 * NAME: tpip_route()
694 *
695 * CALLED FROM: tpip_mtu()
696 *
697 * FUNCTION and ARGUMENTS: given a destination addresss,
698 * find the interface that would be used to send something to this address.
699 *
700 * RETURNS: pointer to an ifnet structure
701 *
702 * SIDE EFFECTS:
703 *
704 * NOTES:
705 */
706struct ifnet *
707tpip_route(dst)
708 struct in_addr *dst;
709{
a50e2bc0
KS
710 struct ifnet *ifp = (struct ifnet *)0;
711 struct sockaddr_in insock;
712 struct sockaddr_in *sin = &insock;
713 struct rtentry *rt;
714 struct ifaddr *ia;
2f41dd0f
KS
715
716 IFDEBUG(D_CONN)
717 printf("tpip_route: dst is x%x\n", *dst);
718 ENDDEBUG
719
a50e2bc0
KS
720 bzero((caddr_t)sin, sizeof (*sin));
721 sin->sin_family = AF_INET;
722 sin->sin_len = sizeof(*sin);
723 sin->sin_addr = *dst;
2f41dd0f 724
a50e2bc0 725 ia = ifa_ifwithdstaddr((struct sockaddr *)sin);
2f41dd0f 726 if (ia == 0)
a50e2bc0 727 ia = ifa_ifwithnet((struct sockaddr *)sin);
2f41dd0f 728 if (ia != 0) {
a50e2bc0 729 ifp = ia->ifa_ifp;
2f41dd0f
KS
730 IFDEBUG(D_CONN)
731 printf("tpip_route: ifp from ia:0x%x\n", ia);
732 ENDDEBUG
733 } else {
a50e2bc0
KS
734 rt = rtalloc1((struct sockaddr *)sin, 0);
735 if (rt != 0) {
736 ifp = rt->rt_ifp;
2f41dd0f 737 IFDEBUG(D_CONN)
a50e2bc0 738 printf("tpip_route: ifp from rentry: 0x%x\n", rt);
2f41dd0f 739 ENDDEBUG
a50e2bc0 740 rtfree(rt);
2f41dd0f
KS
741 }
742 }
743 IFDEBUG(D_CONN)
744 printf("tpip_route: returning 0x%x\n", ifp);
745 if (ifp)
746 printf("tpip_route: if name %s unit 0x%x, mtu 0x%x\n",
747 ifp->if_name, ifp->if_unit, ifp->if_mtu);
748 ENDDEBUG
749 return ifp;
750}
751
752#endif INET