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