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