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