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