# /* genicmp.c * * Generate an icmp packet of the specified type and write it out * to the standard output (which is assumed to be redirected to * a file). Calling sequence: * genicmp * where type = "echo", "timestamp" or "ggp" (for ggp echo). */ #include #include "params.h" #include "extern.h" #include "ip.h" #include "icmp.h" #include "icmp_codes.h" #define INSZ 4 #define MYNET 022 #define MYSNET 012 #define MYRSD 0 #define MYHOST 010 extern caddr_t icmp_send_echo (); extern caddr_t icmp_timestamp (); extern caddr_t icmp_reply_echo (); extern caddr_t icmp_rpltm (); extern caddr_t ggp_send_echo (); extern caddr_t ggp_reply_echo (); main (argc, argv) int argc; char **argv; { unshort uid; unshort size; int stat; char fhost[INSZ]; if (argc != 4) { fprintf (stderr,"usage: genicmp \n"); exit (1); } icfd = fileno (stdout); ggfd = icfd; log = 0; setbuf (stdout, 0); if (!getomch (argv[2], &fhost)) { fprintf (stderr, "bad host address\n"); exit (1); } sscanf (argv[3], "%d", &uid); if (strcmp (argv[1], "icmpecho") == 0) icmp_send_echo (fhost, uid, &size, &stat); else if (strcmp (argv[1], "timestamp") == 0) icmp_timestamp (fhost, uid, &size, &stat); else if (strcmp (argv[1], "ggpecho") == 0) ggp_send_echo (fhost, uid, &size, &stat); else if (strcmp (argv[1], "icmperply") == 0) icmp_reply_echo (fhost, uid, &size, &stat); else if (strcmp (argv[1], "tmrply") == 0) icmp_rpltm (fhost, uid, &size, &stat); else if (strcmp (argv[1], "ggperply") == 0) ggp_reply_echo (fhost, uid, &size, &stat); else fprintf (stderr, "bad function code\n"); exit (0); } /* Parse foreign host number input as octal string */ getomch(name, paddr) char *name; char *paddr; { char tmp[INSZ]; register char *p; register int i, j; int n; paddr[0] = MYNET; paddr[1] = MYSNET; paddr[2] = MYRSD; paddr[3] = MYHOST; p = name; for (i = 0; i < INSZ; i++) { n = 0; while((*p >= '0') && (*p <= '7')) { n = ((n << 3) + (*p++ - '0')); if (n > 0377) return (FALSE); } tmp[i] = n; if (*p == 0) break; if (*p == ',') p++; else return (FALSE); } if (i == INSZ) return (FALSE); for (j = 3; j >= 0; j--) { paddr[j] = tmp[i]; if (--i < 0) break; } return (TRUE); } logdate () { } deq_timeout () { } caddr_t ggp_send_echo (fhost, uid, psize, pstat) /* Send a ggp echo request to the specified foreign host, using uid as * the transaction identifier. The pstat argument is a pointer to an * integer in which a termination code (system standard error code, or * as listed in "icmp_codes.h") will be returned. Similarly, psize * is a pointer to an integer in which the size of the transmitted * packet is returned. Returns a pointer to the generated echo packet * or NULL if an error occurs. * * Arguments: */ struct in_name *fhost; /* dest. host address */ unshort uid; /* unique transaction id */ unshort *psize; /* returned packet size addr */ reg int *pstat; /* status code address */ { reg caddr_t ppkt; /* ptr. to echo packet */ reg struct ggp *pggp; /* ptr. to ggp portion of packet */ unshort gglen; /* length of ggp data */ gglen = sizeof (struct ggp); if ((ppkt = in_alloc (gglen)) == NULL) { logdate (); printf ("out of space for packet, aborting!\n"); abort (); } pggp = in_find_data (ppkt, psize); pggp->gg_type = GG_ECHO; pggp->gg_code = 0; pggp->gg_seq = uid; pggp->gg_seq = short_to_net(pggp->gg_seq); /* byte swap if needed */ if (in_write (ggfd, ppkt, gglen, 0, fhost, FILL) <= 0) { *pstat = errno; if (log & LOG_ERR) { logdate (); printf ("net write error %d, trans = %d\n", *pstat, uid); } in_free (ppkt); return (NULL); } else { if (log & LOG_XMT) in_logpkt (ppkt, gglen, OUTPKT); *pstat = TSUCCESS; } return (ppkt); } caddr_t icmp_send_echo (fhost, uid, psize, pstat) /* Send an icmp echo request to the specified foreign host, using uid as * the transaction identifier. The pstat argument is a pointer to an * integer in which a termination code (system standard error code, or * as listed in "icmp_codes.h") will be returned. Similarly, psize * is a pointer to an integer in which the size of the transmitted * packet is returned. Returns a pointer to the generated echo packet * or NULL if an error occurs. * * Arguments: */ struct in_name *fhost; /* dest. host address */ unshort uid; /* unique transaction id */ unshort *psize; /* returned packet size address */ reg int *pstat; /* status code address */ { reg caddr_t ppkt; /* ptr. to echo packet */ reg struct icmp *picmp; /* ptr. to icmp portion of packet */ unshort iclen; /* length of icmp data */ iclen = sizeof (struct icmp); if ((ppkt = in_alloc (iclen)) == NULL) { logdate (); printf ("out of space for packet, aborting!\n"); abort (); } picmp = in_find_data (ppkt, psize); picmp->ic_type = IC_ECHO; picmp->ic_code = 0; picmp->ic_misc.ic_iseq.id_ident = uid; picmp->ic_misc.ic_iseq.id_seq = 0; picmp->ic_misc.ic_iseq.id_ident = short_to_net(picmp->ic_misc.ic_iseq.id_ident); picmp->ic_misc.ic_iseq.id_seq = short_to_net(picmp->ic_misc.ic_iseq.id_seq); picmp->ic_sum = 0; picmp->ic_sum = ~cksum (picmp, iclen >> 1, 0); if (in_write (icfd, ppkt, iclen, 0, fhost, FILL) <= 0) { *pstat = errno; if (log & LOG_ERR) { logdate (); printf ("net write error %d, trans = %d\n", *pstat, uid); } in_free (ppkt); return (NULL); } else { if (log & LOG_XMT) in_logpkt (ppkt, iclen, OUTPKT); *pstat = TSUCCESS; } return (ppkt); } caddr_t icmp_timestamp (fhost, uid, psize, pstat) /* Send a timestamp request to the specified foreign host, using uid as * the transaction identifier. The pstat argument is a pointer to an * integer in which a termination code (system standard error code, or * as listed in "icmp_codes.h") will be returned. Similarly, psize * is a pointer to an integer in which the size of the transmitted * packet is returned. Returns a pointer to the generated echo packet * or NULL if an error occurs. * occurs. * * Arguments: */ struct in_name *fhost; /* dest. host address */ unshort uid; /* unique transaction id */ unshort *psize; /* returned packet size addr. */ reg int *pstat; /* status code address */ { reg caddr_t ppkt; /* ptr. to timestamp packet */ reg struct icmp *picmp; /* ptr. to icmp portion of packet */ unshort iclen; /* length of icmp data */ iclen = sizeof (struct icmp); if ((ppkt = in_alloc (iclen)) == NULL) { logdate (); printf ("out of space for packet, aborting!\n"); abort (); } picmp = in_find_data (ppkt, psize); picmp->ic_type = IC_TMSTMP; picmp->ic_code = 0; picmp->ic_misc.ic_iseq.id_ident = uid; picmp->ic_misc.ic_iseq.id_seq = 0; picmp->ic_data.ic_time.tm_orig = (curtime % 86400L) * 1000L; /* convert time to ms. UT */ picmp->ic_misc.ic_iseq.id_ident = short_to_net(picmp->ic_misc.ic_iseq.id_ident); picmp->ic_misc.ic_iseq.id_seq = short_to_net(picmp->ic_misc.ic_iseq.id_seq); picmp->ic_data.ic_time.tm_orig = long_to_net(picmp->ic_data.ic_time.tm_orig); picmp->ic_data.ic_time.tm_recv = picmp->ic_data.ic_time.tm_orig; picmp->ic_data.ic_time.tm_trans = picmp->ic_data.ic_time.tm_orig; picmp->ic_sum = 0; picmp->ic_sum = ~cksum (picmp, iclen >> 1, 0); if (in_write (icfd, ppkt, iclen, 0, fhost, FILL) <= 0) { *pstat = errno; if (log & LOG_ERR) { logdate (); printf ("net write error %d, trans = %d\n", *pstat, uid); } in_free (ppkt); return (NULL); } else { if (log & LOG_XMT) in_logpkt (ppkt, iclen, OUTPKT); *pstat = TSUCCESS; } return (ppkt); } caddr_t ggp_reply_echo (fhost, uid, psize, pstat) /* Send a ggp echo reply to the specified foreign host, using uid as * the transaction identifier. The pstat argument is a pointer to an * integer in which a termination code (system standard error code, or * as listed in "icmp_codes.h") will be returned. Similarly, psize * is a pointer to an integer in which the size of the transmitted * packet is returned. Returns a pointer to the generated echo packet * or NULL if an error occurs. * * Arguments: */ struct in_name *fhost; /* dest. host address */ unshort uid; /* unique transaction id */ unshort *psize; /* returned packet size addr */ reg int *pstat; /* status code address */ { reg caddr_t ppkt; /* ptr. to echo packet */ reg struct ggp *pggp; /* ptr. to ggp portion of packet */ unshort gglen; /* length of ggp data */ gglen = sizeof (struct ggp); if ((ppkt = in_alloc (gglen)) == NULL) { logdate (); printf ("out of space for packet, aborting!\n"); abort (); } pggp = in_find_data (ppkt, psize); pggp->gg_type = GG_ERPLY; pggp->gg_code = 0; pggp->gg_seq = uid; pggp->gg_seq = short_to_net(pggp->gg_seq); /* byte swap if needed */ if (in_write (ggfd, ppkt, gglen, 0, fhost, FILL) <= 0) { *pstat = errno; if (log & LOG_ERR) { logdate (); printf ("net write error %d, trans = %d\n", *pstat, uid); } in_free (ppkt); return (NULL); } else { if (log & LOG_XMT) in_logpkt (ppkt, gglen, OUTPKT); *pstat = TSUCCESS; } return (ppkt); } caddr_t icmp_reply_echo (fhost, uid, psize, pstat) /* Send an icmp echo reply to the specified foreign host, using uid as * the transaction identifier. The pstat argument is a pointer to an * integer in which a termination code (system standard error code, or * as listed in "icmp_codes.h") will be returned. Similarly, psize * is a pointer to an integer in which the size of the transmitted * packet is returned. Returns a pointer to the generated echo packet * or NULL if an error occurs. * * Arguments: */ struct in_name *fhost; /* dest. host address */ unshort uid; /* unique transaction id */ unshort *psize; /* returned packet size address */ reg int *pstat; /* status code address */ { reg caddr_t ppkt; /* ptr. to echo packet */ reg struct icmp *picmp; /* ptr. to icmp portion of packet */ unshort iclen; /* length of icmp data */ iclen = sizeof (struct icmp); if ((ppkt = in_alloc (iclen)) == NULL) { logdate (); printf ("out of space for packet, aborting!\n"); abort (); } picmp = in_find_data (ppkt, psize); picmp->ic_type = IC_ERPLY; picmp->ic_code = 0; picmp->ic_misc.ic_iseq.id_ident = uid; picmp->ic_misc.ic_iseq.id_seq = 0; picmp->ic_misc.ic_iseq.id_ident = short_to_net(picmp->ic_misc.ic_iseq.id_ident); picmp->ic_misc.ic_iseq.id_seq = short_to_net(picmp->ic_misc.ic_iseq.id_seq); picmp->ic_sum = 0; picmp->ic_sum = ~cksum (picmp, iclen >> 1, 0); if (in_write (icfd, ppkt, iclen, 0, fhost, FILL) <= 0) { *pstat = errno; if (log & LOG_ERR) { logdate (); printf ("net write error %d, trans = %d\n", *pstat, uid); } in_free (ppkt); return (NULL); } else { if (log & LOG_XMT) in_logpkt (ppkt, iclen, OUTPKT); *pstat = TSUCCESS; } return (ppkt); } caddr_t icmp_rpltm (fhost, uid, psize, pstat) /* Send a timestamp reply to the specified foreign host, using uid as * the transaction identifier. The pstat argument is a pointer to an * integer in which a termination code (system standard error code, or * as listed in "icmp_codes.h") will be returned. Similarly, psize * is a pointer to an integer in which the size of the transmitted * packet is returned. Returns a pointer to the generated echo packet * or NULL if an error occurs. * occurs. * * Arguments: */ struct in_name *fhost; /* dest. host address */ unshort uid; /* unique transaction id */ unshort *psize; /* returned packet size addr. */ reg int *pstat; /* status code address */ { reg caddr_t ppkt; /* ptr. to timestamp packet */ reg struct icmp *picmp; /* ptr. to icmp portion of packet */ unshort iclen; /* length of icmp data */ iclen = sizeof (struct icmp); if ((ppkt = in_alloc (iclen)) == NULL) { logdate (); printf ("out of space for packet, aborting!\n"); abort (); } picmp = in_find_data (ppkt, psize); picmp->ic_type = IC_TMRPLY; picmp->ic_code = 0; picmp->ic_misc.ic_iseq.id_ident = uid; picmp->ic_misc.ic_iseq.id_seq = 0; picmp->ic_data.ic_time.tm_orig = (curtime % 86400L) * 1000L; /* convert time to ms. UT */ picmp->ic_misc.ic_iseq.id_ident = short_to_net(picmp->ic_misc.ic_iseq.id_ident); picmp->ic_misc.ic_iseq.id_seq = short_to_net(picmp->ic_misc.ic_iseq.id_seq); picmp->ic_data.ic_time.tm_orig = long_to_net(picmp->ic_data.ic_time.tm_orig); picmp->ic_data.ic_time.tm_recv = picmp->ic_data.ic_time.tm_orig; picmp->ic_data.ic_time.tm_trans = picmp->ic_data.ic_time.tm_orig; picmp->ic_sum = 0; picmp->ic_sum = ~cksum (picmp, iclen >> 1, 0); if (in_write (icfd, ppkt, iclen, 0, fhost, FILL) <= 0) { *pstat = errno; if (log & LOG_ERR) { logdate (); printf ("net write error %d, trans = %d\n", *pstat, uid); } in_free (ppkt); return (NULL); } else { if (log & LOG_XMT) in_logpkt (ppkt, iclen, OUTPKT); *pstat = TSUCCESS; } return (ppkt); }