|
|
1.1 root 1: #include <sys/param.h>
2: #include <sys/inet/ip.h>
3: #include <ipc.h>
4:
5: int printip();
6:
7: typedef struct {
8: int code;
9: char *meaning;
10: int (*action)();
11: int needid;
12: } Code;
13:
14: typedef struct {
15: int type;
16: Code *c;
17: } Msg;
18:
19: typedef struct {
20: int type;
21: int inuse;
22: int id;
23: } Client;
24:
25: /* Destination Unreachable Message
26:
27: 0 1 2 3
28: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
29: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30: | Type | Code | Checksum |
31: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32: | unused |
33: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34: | Internet Header + 64 bits of Original Data Datagram |
35: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36:
37: */
38:
39: Code unreachc[] = {
40: { 0, "net unreachable", printip, 0 },
41: { 1, "host unreachable", printip, 0 },
42: { 2, "protocol unreachable", printip, 0 },
43: { 3, "port unreachable", printip, 0 },
44: { 4, "fragment needed and DF set", printip, 0 },
45: { 5, "source route failed", printip, 0 },
46: { -1, 0, 0 }
47: };
48:
49: typedef struct {
50: u_char param[4];
51: struct ip ip;
52: } IpMsg;
53:
54:
55: /* Time Exceeded Message
56:
57: 0 1 2 3
58: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
59: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60: | Type | Code | Checksum |
61: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62: | unused |
63: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64: | Internet Header + 64 bits of Original Data Datagram |
65: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66: */
67:
68: Code timec[] = {
69: { 0, "time to live exceeded in transit", printip, 0 },
70: { 1, "fragment reassembly time exceeded", printip, 0 },
71: { -1, 0, 0 }
72: };
73:
74:
75:
76: /* Parameter Problem Message
77:
78: 0 1 2 3
79: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
80: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81: | Type | Code | Checksum |
82: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83: | Pointer | unused |
84: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85: | Internet Header + 64 bits of Original Data Datagram |
86: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87: */
88:
89: Code paramc[] = {
90: { 0, "parameter problem", printip, 0 },
91: { -1, 0, 0 }
92: };
93:
94: /* Source Quench Message
95:
96: 0 1 2 3
97: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
98: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99: | Type | Code | Checksum |
100: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101: | unused |
102: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103: | Internet Header + 64 bits of Original Data Datagram |
104: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105: */
106:
107: Code quenchc[] = {
108: { 0, "source quench", printip, 0 },
109: { -1, 0, 0 }
110: };
111:
112:
113: /* Redirect Message
114:
115: 0 1 2 3
116: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
117: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118: | Type | Code | Checksum |
119: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120: | Gateway Internet Address |
121: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122: | Internet Header + 64 bits of Original Data Datagram |
123: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124: */
125:
126: Code redirectc[] = {
127: { 0, "redirect datagrams for the network", printip, 0 },
128: { 1, "redirect datagrams for the host", printip, 0 },
129: { 2, "redirect datagrams for the type of service and network", printip, 0},
130: { 3, "redirect datagrams for the type of service and host", printip, 0 },
131: { -1, 0, 0 }
132: };
133:
134:
135: /* Echo or Echo Reply Message
136:
137: 0 1 2 3
138: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
139: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140: | Type | Code | Checksum |
141: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142: | Identifier | Sequence Number |
143: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144: | Data ...
145: +-+-+-+-+-
146: */
147:
148: int echo();
149: Code echoc[] = {
150: { 0, "echo", echo, 1 },
151: { -1, 0, 0 }
152: };
153: Code echorc[] = {
154: { 0, "echo reply", 0, 1 },
155: { -1, 0, 0 }
156: };
157:
158: typedef struct {
159: u_char id[2];
160: u_char seqno[2];
161: } EchoMsg;
162:
163: /* Timestamp or Timestamp Reply Message
164:
165: 0 1 2 3
166: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
167: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
168: | Type | Code | Checksum |
169: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170: | Identifier | Sequence Number |
171: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
172: | Originate Timestamp |
173: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174: | Receive Timestamp |
175: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176: | Transmit Timestamp |
177: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178: */
179:
180: Code timestampc[] = {
181: { 0, "timestamp", 0, 1 },
182: { -1, 0, 0 }
183: };
184: Code timestamprc[] = {
185: { 0, "timestamp reply", 0, 1 },
186: { -1, 0, 0 }
187: };
188:
189: typedef struct {
190: u_char id[2];
191: u_char seqno[2];
192: u_char orig[4];
193: u_char recv[4];
194: u_char xmit[4];
195: } TsMsg;
196:
197:
198: /* Information Request or Information Reply Message
199:
200: 0 1 2 3
201: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
202: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
203: | Type | Code | Checksum |
204: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205: | Identifier | Sequence Number |
206: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
207: */
208:
209: Code infoc[] = {
210: { 0, "info", 0, 1 },
211: { -1, 0, 0 }
212: };
213: Code inforc[] = {
214: { 0, "info reply", 0, 1 },
215: { -1, 0, 0 }
216: };
217:
218: Msg msgs[] = {
219: { 0, echorc },
220: { 3, unreachc },
221: { 4, quenchc },
222: { 5, redirectc },
223: { 8, echoc },
224: { 11, timec },
225: { 12, paramc },
226: { 13, timestampc },
227: { 14, timestamprc },
228: { 15, infoc },
229: { 16, inforc },
230: };
231:
232: typedef struct {
233: struct ip ip;
234: u_char type;
235: u_char code;
236: u_char cksum[2];
237: union {
238: IpMsg i;
239: EchoMsg e;
240: TsMsg t;
241: } u;
242: u_char buffer[4096];
243: } IcmpMsg;
244:
245: /*
246: * globals
247: */
248: char *av0;
249: Client clients[NOFILE];
250: fd_set cfds;
251: int debug;
252:
253: ding()
254: {
255: signal(SIGALRM, ding);
256: alarm(10);
257: }
258:
259: /*
260: * icmp mgr
261: */
262: main(ac, av)
263: int ac;
264: char *av[];
265: {
266: char *mtpt="icmp", *cp;
267: int i;
268: int ipfd, fsfd;
269: fd_set fds;
270:
271: av0 = av[0];
272: chdir("/cs");
273: for (i=1; i<ac; i++) {
274: if (av[i][0] == '-') {
275: for (cp=&av[i][1]; *cp; cp++) {
276: switch(*cp) {
277: case 'd':
278: debug = 1;
279: break;
280: case 'm':
281: if (i+1>=ac)
282: usage(av0);
283: mtpt = av[++i];
284: break;
285: default:
286: usage(av0);
287: }
288: }
289: }
290: }
291:
292: /*
293: * open the ip protocol
294: */
295: ipfd = open("/dev/ipicmp", 2);
296: if(ipfd < 0){
297: logevent("error opening ip device\n");
298: exit(1);
299: };
300:
301: /*
302: * plug ourselves into the file system
303: */
304: fsfd = ipccreat(mtpt, "");
305: if(ipfd < 0){
306: logevent("error mounting into fs\n");
307: exit(1);
308: };
309:
310: if(!debug)
311: detach(mtpt);
312:
313: /*
314: * clear out the clients
315: */
316: for(i=0; i<NOFILE; i++){
317: clients[i].id = i;
318: clients[i].inuse = 0;
319: }
320:
321: /*
322: * spin honoring requests
323: */
324: FD_ZERO(fds);
325: for(;;) {
326: int n;
327:
328: fds = cfds;
329: FD_SET(ipfd, fds);
330: FD_SET(fsfd, fds);
331: switch(n = select(NOFILE, &fds, 0, 10000)){
332: case -1:
333: logevent("select failed\n");
334: exit(1);
335: case 0:
336: continue;
337: }
338: signal(SIGALRM, ding);
339: alarm(10);
340: if(FD_ISSET(ipfd, fds)) {
341: readnet(ipfd);
342: n--;
343: }
344: if(n && FD_ISSET(fsfd, fds)) {
345: newclient(fsfd);
346: n--;
347: }
348: for(i = 0; n && i<NOFILE; i++){
349: if(FD_ISSET(i, fds)){
350: readclient(i, ipfd);
351: n--;
352: }
353: }
354: alarm(0);
355: }
356: }
357:
358: /*
359: * read an icmp message from the network
360: */
361: readnet(fd)
362: {
363: Msg *mp;
364: IcmpMsg m;
365: int n;
366: char fromsys[32], tosys[32];
367: u_char c[2];
368: Code *cp;
369:
370: if((n = read(fd, &m, sizeof(m))) > 0){
371: strcpy(fromsys, in_ntoa(m.ip.ip_src));
372: strcpy(tosys, in_ntoa(m.ip.ip_dst));
373: logevent("in %s -> %s, type %d code %d\n", fromsys, tosys,
374: m.type, m.code);
375: c[0] = m.cksum[0];
376: c[1] = m.cksum[1];
377: cksum(&m, n);
378: if(c[0] != m.cksum[0] || c[1] != m.cksum[1]){
379: fprint(2, "checksum error %.2x%.2x/%.2x%.2x\n", c[0],
380: c[1], m.cksum[0], m.cksum[1]);
381: return;
382: }
383: for(mp = msgs; mp->type >= 0; mp++){
384: if(mp->type == m.type){
385: for(cp = mp->c; cp->code >= 0; cp++)
386: if(cp->code == m.code)
387: break;
388: if(cp->code < 0)
389: fprint(2, "undefined code\n");
390: else if(cp->action)
391: (*cp->action)(fd, &m, n);
392: break;
393: }
394: }
395: if(mp->type < 0)
396: fprint(2, "undefined type\n");
397: } else {
398: logevent("error reading from network %d\n", errno);
399: exit(1);
400: }
401: }
402:
403: /*
404: * a call from a new client
405: */
406: newclient(fd)
407: {
408: int cfd;
409: ipcinfo *ipc;
410:
411: /*
412: * get the new call (protected by a timeout)
413: */
414: ipc = ipclisten(fd);
415: if(fd==0)
416: return;
417: cfd = ipcaccept(ipc);
418: if(cfd<0)
419: return;
420:
421: /*
422: * set up a new id (for echo/timestamp/etc)
423: */
424: clients[cfd].id += NOFILE;
425: clients[cfd].inuse = 1;
426: FD_SET(cfd, cfds);
427: logevent("new client %d %s!%s\n", cfd, ipc->machine, ipc->user);
428: }
429:
430: /*
431: * read an icmp message from a client (protected by an timeout).
432: * if this is a message that requires an id, put one in.
433: */
434: readclient(fd, ipfd)
435: {
436: IcmpMsg m;
437: int n;
438: char fromsys[32], tosys[32];
439: Msg *mp;
440: Code *cp;
441:
442: if((n = read(fd, &m, sizeof(m))) > 0){
443: strcpy(fromsys, in_ntoa(m.ip.ip_src));
444: strcpy(tosys, in_ntoa(m.ip.ip_dst));
445: logevent("out(%d) %s -> %s, type %d code %d\n", fd, fromsys,
446: tosys, m.type, m.code);
447: for(mp = msgs; mp->type >= 0; mp++){
448: if(mp->type == m.type){
449: for(cp = mp->c; cp->code >= 0; cp++)
450: if(cp->code == m.code)
451: break;
452: if(cp->code < 0)
453: fprint(2, "undefined code\n");
454: else {
455: if(cp->needid){
456: m.u.e.id[0] = clients[fd].id;
457: m.u.e.id[1] = clients[fd].id>>8;
458: }
459: ipsend(ipfd, &m, n, m.ip.ip_src,
460: m.ip.ip_dst);
461: }
462: break;
463: }
464: }
465: if(mp->type < 0)
466: fprint(2, "undefined type\n");
467: } else {
468: logevent("losing client %d\n", fd);
469: FD_CLR(fd, cfds);
470: close(fd);
471: }
472: }
473:
474: /*
475: * print a message with an ip body
476: */
477: printip(fd, mp, len)
478: IcmpMsg *mp;
479: {
480: }
481:
482: /*
483: * send an ip datagram
484: */
485: ipsend(fd, mp, len, src, dst)
486: IcmpMsg *mp;
487: u_long src;
488: u_long dst;
489: {
490: mp->ip.ip_dst = dst;
491: mp->ip.ip_src = src;
492: mp->ip.ip_len = len;
493: mp->ip.ip_hl = sizeof(struct ip)>>2;
494: mp->ip.ip_off = 0;
495: mp->ip.ip_ttl = 255;
496: mp->ip.ip_p = 1;
497: cksum(mp, len);
498: return write(fd, mp, len)!=len ? -1 : 0;
499: }
500:
501: /*
502: * echo a datagram
503: */
504: echo(fd, mp, len)
505: IcmpMsg *mp;
506: {
507: mp->type = 0;
508: if(ipsend(fd, mp, len, mp->ip.ip_dst, mp->ip.ip_src) < 0)
509: perror("sending echo");
510: }
511:
512: usage(name)
513: char *name;
514: {
515: fprint(2, "usage: %s [-d] [-m mount-pt]\n", name);
516: exit(1);
517: }
518:
519: /*
520: * internet checksum routine
521: */
522: cksum(mp, len)
523: IcmpMsg *mp;
524: {
525: u_char *cp;
526: u_short *sp;
527: u_long sum;
528:
529: sp = (u_short *)&mp->type;
530: len -= sizeof(struct ip);
531: mp->cksum[0] = mp->cksum[1] = 0;
532: for(sum = 0; len >=2; len-=2)
533: sum += *sp++;
534: if(len){
535: cp = (u_char *)sp;
536: sum += *cp;
537: }
538: while(sum & 0xffff0000)
539: sum = (sum & 0xffff) + (sum>>16);
540: sum ^= 0xffff;
541: mp->cksum[1] = sum>>8;
542: mp->cksum[0] = sum;
543: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.