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