|
|
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.