|
|
1.1 root 1: /* tcp.c - MIB realization of the TCP group */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/snmp/RCS/tcp.c,v 7.7 90/07/09 14:49:43 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/snmp/RCS/tcp.c,v 7.7 90/07/09 14:49:43 mrose Exp $
9: *
10: * Contributed by NYSERNet Inc. This work was partially supported by the
11: * U.S. Defense Advanced Research Projects Agency and the Rome Air Development
12: * Center of the U.S. Air Force Systems Command under contract number
13: * F30602-88-C-0016.
14: *
15: *
16: * $Log: tcp.c,v $
17: * Revision 7.7 90/07/09 14:49:43 mrose
18: * sync
19: *
20: * Revision 7.6 90/06/05 20:47:27 mrose
21: * touch-up
22: *
23: * Revision 7.5 90/04/23 00:08:16 mrose
24: * touch-up
25: *
26: * Revision 7.4 90/04/18 08:52:06 mrose
27: * oid_normalize
28: *
29: * Revision 7.3 90/02/27 18:50:07 mrose
30: * unix stuff
31: *
32: * Revision 7.2 90/01/27 08:22:09 mrose
33: * touch-up
34: *
35: * Revision 7.1 89/12/11 10:40:40 mrose
36: * touch-up
37: *
38: * Revision 7.0 89/11/23 22:23:35 mrose
39: * Release 6.0
40: *
41: */
42:
43: /*
44: * NOTICE
45: *
46: * Acquisition, use, and distribution of this module and related
47: * materials are subject to the restrictions of a license agreement.
48: * Consult the Preface in the User's Manual for the full terms of
49: * this agreement.
50: *
51: */
52:
53:
54: #include <stdio.h>
55: #include "mib.h"
56: #ifdef BSD43_Tahoe
57: #include <machine/endian.h>
58: #endif
59:
60: #include "internet.h"
61: #ifdef BSD44
62: #include <machine/machparam.h>
63: #endif
64: #include <sys/protosw.h>
65: #include <sys/socketvar.h>
66: #include <net/route.h>
67: #include <netinet/in_systm.h>
68: #ifdef BSD44
69: #include <netinet/ip.h>
70: #endif
71: #include <netinet/in_pcb.h>
72: #include <netinet/tcp.h>
73: #include <netinet/tcp_fsm.h>
74: #include <netinet/tcp_timer.h>
75: #include <netinet/tcp_var.h>
76:
77: /* */
78:
79: #define RTOA_OTHER 1 /* tcpRtoAlgorithm */
80: #define RTOA_VANJ 4 /* .. */
81:
82: #define MXCN_NONE (-1) /* tcpMaxConn */
83:
84:
85: static struct tcpstat tcpstat;
86:
87: static int tcpConnections;
88:
89: /* */
90:
91: #define tcpRtoAlgorithm 0
92: #define tcpRtoMin 1
93: #define tcpRtoMax 2
94: #define tcpMaxConn 3
95: #define tcpActiveOpens 4
96: #define tcpPassiveOpens 5
97: #define tcpAttemptFails 6
98: #define tcpEstabResets 7
99: #define tcpCurrEstab 8
100: #define tcpInSegs 9
101: #define tcpOutSegs 10
102: #define tcpRetransSegs 11
103: #ifndef SUNOS4
104: #define tcpInErrs 12
105: #else
106: #undef tcpInErrs 12
107: #endif
108: #undef tcpOutRsts 13 /* NOT IMPLEMENTED */
109:
110:
111: static int o_tcp (oi, v, offset)
112: OI oi;
113: register struct type_SNMP_VarBind *v;
114: int offset;
115: {
116: int ifvar;
117: register struct tcpstat *tcps = &tcpstat;
118: register OID oid = oi -> oi_name;
119: register OT ot = oi -> oi_type;
120: static int lastq = -1;
121:
122: ifvar = (int) ot -> ot_info;
123: switch (offset) {
124: case type_SNMP_PDUs_get__request:
125: if (oid -> oid_nelem != ot -> ot_name -> oid_nelem + 1
126: || oid -> oid_elements[oid -> oid_nelem - 1] != 0)
127: return int_SNMP_error__status_noSuchName;
128: break;
129:
130: case type_SNMP_PDUs_get__next__request:
131: if (oid -> oid_nelem == ot -> ot_name -> oid_nelem) {
132: OID new;
133:
134: if ((new = oid_extend (oid, 1)) == NULLOID)
135: return int_SNMP_error__status_genErr;
136: new -> oid_elements[new -> oid_nelem - 1] = 0;
137:
138: if (v -> name)
139: free_SNMP_ObjectName (v -> name);
140: v -> name = new;
141: }
142: else
143: return NOTOK;
144: break;
145:
146: default:
147: return int_SNMP_error__status_genErr;
148: }
149:
150: switch (ifvar) {
151: case tcpCurrEstab:
152: if (get_connections () == NOTOK)
153: return int_SNMP_error__status_genErr;
154: break;
155:
156: default:
157: if (quantum != lastq) {
158: lastq = quantum;
159:
160: if (getkmem (nl + N_TCPSTAT, (caddr_t) tcps, sizeof *tcps)
161: == NOTOK)
162: return int_SNMP_error__status_genErr;
163: }
164: break;
165: }
166:
167: switch (ifvar) {
168: case tcpRtoAlgorithm:
169: #ifdef TCPTV_REXMTMAX
170: return o_integer (oi, v, RTOA_VANJ);
171: #else
172: return o_integer (oi, v, RTOA_OTHER);
173: #endif
174:
175: case tcpRtoMin:
176: return o_integer (oi, v, TCPTV_MIN * 100); /* milliseconds */
177:
178: #ifdef TCPTV_REXMTMAX
179: case tcpRtoMax:
180: return o_integer (oi, v, TCPTV_REXMTMAX * 100); /* .. */
181: #endif
182:
183: case tcpMaxConn:
184: return o_integer (oi, v, MXCN_NONE);
185:
186: #ifdef TCPTV_REXMTMAX
187: case tcpActiveOpens:
188: return o_integer (oi, v, tcps -> tcps_connattempt);
189:
190: case tcpPassiveOpens:
191: return o_integer (oi, v, tcps -> tcps_accepts);
192:
193: case tcpAttemptFails:
194: return o_integer (oi, v, tcps -> tcps_conndrops);
195:
196: case tcpEstabResets:
197: return o_integer (oi, v, tcps -> tcps_drops);
198: #endif
199:
200: case tcpCurrEstab:
201: return o_integer (oi, v, tcpConnections);
202:
203: #ifdef TCPTV_REXMTMAX
204: case tcpInSegs:
205: return o_integer (oi, v, tcps -> tcps_rcvtotal);
206:
207: case tcpOutSegs:
208: return o_integer (oi, v, tcps -> tcps_sndtotal
209: - tcps -> tcps_sndrexmitpack);
210:
211: case tcpRetransSegs:
212: return o_integer (oi, v, tcps -> tcps_sndrexmitpack);
213: #endif
214:
215: #ifdef tcpInErrs
216: case tcpInErrs:
217: #ifndef BSD44
218: return o_integer (oi, v, tcps -> tcps_badsegs);
219: #else
220: return o_integer (oi, v, tcps -> tcps_rcvbadsum
221: + tcps -> tcps_rcvbadoff
222: + tcps -> tcps_rcvshort);
223: #endif
224: #endif
225:
226: default:
227: return int_SNMP_error__status_noSuchName;
228: }
229: }
230:
231: /* */
232:
233: static int tcp_states[TCP_NSTATES];
234:
235:
236: struct tcptab {
237: #define TT_SIZE 10 /* object instance */
238: unsigned int tt_instance[TT_SIZE];
239:
240: struct inpcb tt_pcb; /* protocol control block */
241:
242: struct socket tt_socb; /* socket info */
243:
244: struct tcpcb tt_tcpb; /* TCP info */
245:
246: struct tcptab *tt_next;
247: };
248:
249: static struct tcptab *tts = NULL;
250:
251:
252: struct tcptab *get_tcpent ();
253:
254: /* */
255:
256: #define tcpConnState 0
257: #define tcpConnLocalAddress 1
258: #define tcpConnLocalPort 2
259: #define tcpConnRemAddress 3
260: #define tcpConnRemPort 4
261: #define unixTcpConnSendQ 5
262: #define unixTcpConnRecvQ 6
263:
264:
265: static int o_tcp_conn (oi, v, offset)
266: OI oi;
267: register struct type_SNMP_VarBind *v;
268: int offset;
269: {
270: int ifvar;
271: register int i;
272: register unsigned int *ip,
273: *jp;
274: register struct tcptab *tt;
275: struct sockaddr_in netaddr;
276: register OID oid = oi -> oi_name;
277: OID new;
278: register OT ot = oi -> oi_type;
279:
280: if (get_connections () == NOTOK)
281: return int_SNMP_error__status_genErr;
282:
283: ifvar = (int) ot -> ot_info;
284: switch (offset) {
285: case type_SNMP_PDUs_get__request:
286: if (oid -> oid_nelem != ot -> ot_name -> oid_nelem + TT_SIZE)
287: return int_SNMP_error__status_noSuchName;
288: if ((tt = get_tcpent (oid -> oid_elements + oid -> oid_nelem
289: - TT_SIZE, 0)) == NULL)
290: return int_SNMP_error__status_noSuchName;
291: break;
292:
293: case type_SNMP_PDUs_get__next__request:
294: if ((i = oid -> oid_nelem - ot -> ot_name -> oid_nelem) != 0
295: && i < TT_SIZE) {
296: for (jp = (ip = oid -> oid_elements + ot -> ot_name -> oid_nelem - 1) + i;
297: jp > ip;
298: jp--)
299: if (*jp != 0)
300: break;
301: if (jp == ip)
302: oid -> oid_nelem = ot -> ot_name -> oid_nelem;
303: else {
304: if ((new = oid_normalize (oid, TT_SIZE - i, 65536))
305: == NULLOID)
306: return int_SNMP_error__status_genErr;
307: if (v -> name)
308: free_SNMP_ObjectName (v -> name);
309: v -> name = oid = new;
310: }
311: }
312:
313: if (oid -> oid_nelem == ot -> ot_name -> oid_nelem) {
314: if ((tt = tts) == NULL)
315: return NOTOK;
316:
317: if ((new = oid_extend (oid, TT_SIZE)) == NULLOID)
318: return int_SNMP_error__status_genErr;
319: ip = new -> oid_elements + new -> oid_nelem - TT_SIZE;
320: jp = tt -> tt_instance;
321: for (i = TT_SIZE; i > 0; i--)
322: *ip++ = *jp++;
323:
324: if (v -> name)
325: free_SNMP_ObjectName (v -> name);
326: v -> name = new;
327: }
328: else {
329: if ((tt = get_tcpent (ip = oid -> oid_elements
330: + oid -> oid_nelem - TT_SIZE, 1))
331: == NULL)
332: return NOTOK;
333:
334: jp = tt -> tt_instance;
335: for (i = TT_SIZE; i > 0; i--)
336: *ip++ = *jp++;
337: }
338: break;
339:
340: default:
341: return int_SNMP_error__status_genErr;
342: }
343:
344: switch (ifvar) {
345: case tcpConnState:
346: if ((i = tt -> tt_tcpb.t_state) < 0
347: || i >= sizeof tcp_states / sizeof tcp_states[0])
348: return int_SNMP_error__status_genErr;
349: return o_integer (oi, v, tcp_states[i]);
350:
351: case tcpConnLocalAddress:
352: netaddr.sin_addr = tt -> tt_pcb.inp_laddr; /* struct copy */
353: return o_ipaddr (oi, v, &netaddr);
354:
355: case tcpConnLocalPort:
356: return o_integer (oi, v, ntohs (tt -> tt_pcb.inp_lport) & 0xffff);
357:
358: case tcpConnRemAddress:
359: netaddr.sin_addr = tt -> tt_pcb.inp_faddr; /* struct copy */
360: return o_ipaddr (oi, v, &netaddr);
361:
362: case tcpConnRemPort:
363: return o_integer (oi, v, ntohs (tt -> tt_pcb.inp_fport) & 0xffff);
364:
365: case unixTcpConnSendQ:
366: return o_integer (oi, v, tt -> tt_socb.so_snd.sb_cc);
367:
368: case unixTcpConnRecvQ:
369: return o_integer (oi, v, tt -> tt_socb.so_rcv.sb_cc);
370:
371: default:
372: return int_SNMP_error__status_noSuchName;
373: }
374: }
375:
376: /* */
377:
378: static int tt_compar (a, b)
379: struct tcptab **a,
380: **b;
381: {
382: return elem_cmp ((*a) -> tt_instance, TT_SIZE,
383: (*b) -> tt_instance, TT_SIZE);
384: }
385:
386:
387: static int get_connections () {
388: register int i;
389: register unsigned int *cp;
390: register struct tcptab *ts,
391: *tp,
392: **tsp;
393: register struct inpcb *ip;
394: struct inpcb *head,
395: tcb;
396: struct nlist nzs;
397: register struct nlist *nz = &nzs;
398: static int first_time = 1;
399: static int lastq = -1;
400:
401: if (quantum == lastq)
402: return OK;
403: lastq = quantum;
404:
405: for (ts = tts; ts; ts = tp) {
406: tp = ts -> tt_next;
407:
408: free ((char *) ts);
409: }
410: tts = NULL;
411:
412: if (getkmem (nl + N_TCB, (char *) &tcb, sizeof tcb) == NOTOK)
413: return NOTOK;
414: head = (struct inpcb *) nl[N_TCB].n_value;
415:
416: tsp = &tts, i = 0;
417: ip = &tcb;
418: while (ip -> inp_next != head) {
419: if ((ts = (struct tcptab *) calloc (1, sizeof *ts)) == NULL)
420: adios (NULLCP, "out of memory");
421: /* no check needed for duplicate connections... */
422: *tsp = ts, tsp = &ts -> tt_next, i++;
423:
424: nz -> n_name = "struct inpcb",
425: nz -> n_value = (unsigned long) ip -> inp_next;
426: if (getkmem (nz, (caddr_t) &ts -> tt_pcb, sizeof ts -> tt_pcb)
427: == NOTOK)
428: return NOTOK;
429: ip = &ts -> tt_pcb;
430:
431: nz ->n_name = "struct socket",
432: nz -> n_value = (unsigned long) ip -> inp_socket;
433: if (getkmem (nz, (caddr_t) &ts -> tt_socb, sizeof ts -> tt_socb)
434: == NOTOK)
435: return NOTOK;
436:
437: nz ->n_name = "struct tcb",
438: nz -> n_value = (unsigned long) ip -> inp_ppcb;
439: if (getkmem (nz, (caddr_t) &ts -> tt_tcpb, sizeof ts -> tt_tcpb)
440: == NOTOK)
441: return NOTOK;
442:
443: cp = ts -> tt_instance;
444: cp += ipaddr2oid (cp, &ip -> inp_laddr);
445: *cp++ = ntohs (ip -> inp_lport) & 0xffff;
446: cp += ipaddr2oid (cp, &ip -> inp_faddr);
447: *cp++ = ntohs (ip -> inp_fport) & 0xffff;
448:
449: if (debug && first_time) {
450: OIDentifier oids;
451:
452: oids.oid_elements = ts -> tt_instance;
453: oids.oid_nelem = TT_SIZE;
454: advise (LLOG_DEBUG, NULLCP,
455: "add connection: %s", sprintoid (&oids));
456: }
457: }
458: first_time = 0;
459:
460: if ((tcpConnections = i) > 1) {
461: register struct tcptab **base,
462: **tse;
463:
464: if ((base = (struct tcptab **) malloc ((unsigned) (i * sizeof *base)))
465: == NULL)
466: adios (NULLCP, "out of memory");
467:
468: tse = base;
469: for (ts = tts; ts; ts = ts -> tt_next)
470: *tse++ = ts;
471:
472: qsort ((char *) base, i, sizeof *base, tt_compar);
473:
474: tsp = base;
475: ts = tts = *tsp++;
476:
477: while (tsp < tse) {
478: ts -> tt_next = *tsp;
479: ts = *tsp++;
480: }
481: ts -> tt_next = NULL;
482:
483: free ((char *) base);
484: }
485:
486: return OK;
487: }
488:
489: /* */
490:
491: static struct tcptab *get_tcpent (ip, isnext)
492: register unsigned int *ip;
493: int isnext;
494: {
495: register struct tcptab *tt;
496:
497: for (tt = tts; tt; tt = tt -> tt_next)
498: switch (elem_cmp (tt -> tt_instance, TT_SIZE, ip, TT_SIZE)) {
499: case 0:
500: return (isnext ? tt -> tt_next : tt);
501:
502: case 1:
503: return (isnext ? tt : NULL);
504: }
505:
506: return NULL;
507: }
508:
509: /* */
510:
511: init_tcp () {
512: register OT ot;
513:
514: if (ot = text2obj ("tcpRtoAlgorithm"))
515: ot -> ot_getfnx = o_tcp,
516: ot -> ot_info = (caddr_t) tcpRtoAlgorithm;
517: if (ot = text2obj ("tcpRtoMin"))
518: ot -> ot_getfnx = o_tcp,
519: ot -> ot_info = (caddr_t) tcpRtoMin;
520: #ifdef TCPTV_REXMTMAX
521: if (ot = text2obj ("tcpRtoMax"))
522: ot -> ot_getfnx = o_tcp,
523: ot -> ot_info = (caddr_t) tcpRtoMax;
524: #endif
525: if (ot = text2obj ("tcpMaxConn"))
526: ot -> ot_getfnx = o_tcp,
527: ot -> ot_info = (caddr_t) tcpMaxConn;
528: #ifdef TCPTV_REXMTMAX
529: if (ot = text2obj ("tcpActiveOpens"))
530: ot -> ot_getfnx = o_tcp,
531: ot -> ot_info = (caddr_t) tcpActiveOpens;
532: if (ot = text2obj ("tcpPassiveOpens"))
533: ot -> ot_getfnx = o_tcp,
534: ot -> ot_info = (caddr_t) tcpPassiveOpens;
535: if (ot = text2obj ("tcpAttemptFails"))
536: ot -> ot_getfnx = o_tcp,
537: ot -> ot_info = (caddr_t) tcpAttemptFails;
538: if (ot = text2obj ("tcpEstabResets"))
539: ot -> ot_getfnx = o_tcp,
540: ot -> ot_info = (caddr_t) tcpEstabResets;
541: #endif
542: if (ot = text2obj ("tcpCurrEstab"))
543: ot -> ot_getfnx = o_tcp,
544: ot -> ot_info = (caddr_t) tcpCurrEstab;
545: #ifdef TCPTV_REXMTMAX
546: if (ot = text2obj ("tcpInSegs"))
547: ot -> ot_getfnx = o_tcp,
548: ot -> ot_info = (caddr_t) tcpInSegs;
549: if (ot = text2obj ("tcpOutSegs"))
550: ot -> ot_getfnx = o_tcp,
551: ot -> ot_info = (caddr_t) tcpOutSegs;
552: if (ot = text2obj ("tcpRetransSegs"))
553: ot -> ot_getfnx = o_tcp,
554: ot -> ot_info = (caddr_t) tcpRetransSegs;
555: #endif
556: #ifdef tcpInErrs
557: if (ot = text2obj ("tcpInErrs"))
558: ot -> ot_getfnx = o_tcp,
559: ot -> ot_info = (caddr_t) tcpInErrs;
560: #endif
561: #ifdef tcpOutRsts
562: if (ot = text2obj ("tcpOutRsts"))
563: ot -> ot_getfnx = o_tcp,
564: ot -> ot_info = (caddr_t) tcpOutRsts;
565: #endif
566:
567: if (ot = text2obj ("tcpConnState"))
568: ot -> ot_getfnx = o_tcp_conn,
569: ot -> ot_info = (caddr_t) tcpConnState;
570: if (ot = text2obj ("tcpConnLocalAddress"))
571: ot -> ot_getfnx = o_tcp_conn,
572: ot -> ot_info = (caddr_t) tcpConnLocalAddress;
573: if (ot = text2obj ("tcpConnLocalPort"))
574: ot -> ot_getfnx = o_tcp_conn,
575: ot -> ot_info = (caddr_t) tcpConnLocalPort;
576: if (ot = text2obj ("tcpConnRemAddress"))
577: ot -> ot_getfnx = o_tcp_conn,
578: ot -> ot_info = (caddr_t) tcpConnRemAddress;
579: if (ot = text2obj ("tcpConnRemPort"))
580: ot -> ot_getfnx = o_tcp_conn,
581: ot -> ot_info = (caddr_t) tcpConnRemPort;
582:
583: if (ot = text2obj ("unixTcpConnSendQ"))
584: ot -> ot_getfnx = o_tcp_conn,
585: ot -> ot_info = (caddr_t) unixTcpConnSendQ;
586: if (ot = text2obj ("unixTcpConnRecvQ"))
587: ot -> ot_getfnx = o_tcp_conn,
588: ot -> ot_info = (caddr_t) unixTcpConnRecvQ;
589:
590: tcp_states[TCPS_CLOSED] = 1;
591: tcp_states[TCPS_LISTEN] = 2;
592: tcp_states[TCPS_SYN_SENT] = 3;
593: tcp_states[TCPS_SYN_RECEIVED] = 4;
594: tcp_states[TCPS_ESTABLISHED] = 5;
595: tcp_states[TCPS_CLOSE_WAIT] = 8;
596: tcp_states[TCPS_FIN_WAIT_1] = 6;
597: tcp_states[TCPS_CLOSING] = 10;
598: tcp_states[TCPS_LAST_ACK] = 9;
599: tcp_states[TCPS_FIN_WAIT_2] = 7;
600: tcp_states[TCPS_TIME_WAIT] = 11;
601: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.